The question is clear. Character is stable on the stage and background and ground is moving. But when character hits the ground, it bounces again and again. Here is the code. how can i solve it? When i move the character its working perfect but when the moving object is ground bouncing problem happens.
here is the problem : http://www.swfcabin.com/open/1391814250
public function controller():void
{
if (rightKey || leftKey || jumpKey)
{
if (rightKey)
{
if (jumpWalk || canJump)
{
hero.gotoAndStop(2);
hero.scaleX = 1;
xSpeed -= speed;
}
}
if (leftKey)
{
if (jumpWalk || canJump)
{
hero.gotoAndStop(2);
hero.scaleX = -1;
xSpeed += speed;
}
}
if (jumpKey && canJump)
{
ySpeed += 15;
canJump = false;
}
}
else
{
hero.gotoAndStop(1);
}
if(!canJump){
hero.gotoAndStop(3);
}
ySpeed -= gravity;
if(ySpeed >10){
ySpeed = 10;
}
else if(ySpeed < -10){
ySpeed = -10;
}
if(xSpeed>10){
xSpeed = 10
}
else if(xSpeed < -10){
xSpeed = -10;
}
xSpeed *= 0.8;
level.x += xSpeed;
level.y += ySpeed;
}// controller function
public function loop(event:Event):void
{
controller();
while(level.hitTestPoint(hero.x , hero.y + hero.height/2 -1 - ySpeed , true)){
trace(ySpeed +"dasd");
ySpeed ++;
canJump = true;
} }
Here is what is happening now: when you are embedded in terrain, you are increasing the ySpeed -- the upward momentum -- until one 'tick' pulls the character out of the ground. But then the character is flying upward, because you increased their upward momentum. They still have that upward momentum until gravity pulls them back down, so they will keep 'bouncing'. To fix this, do the following:
Instead of ySpeed ++; in the main loop, try level.y++; This would represent pulling the hero out of the terrain when he is embedded (or actually pulling the terrain down, since your character is stationary), instead of changing his momentum to get him out.
You should also add ySpeed = 0; in there. That would represent losing all of your y-momentum when you hit the ground.
So your main loop would look like this:
public function loop(event:Event):void
{
controller();
while(level.hitTestPoint(hero.x , hero.y + hero.height/2 -1 - ySpeed , true)){
trace(ySpeed +"dasd");
level.y++;
ySpeed = 0;
canJump = true;
} }
Related
I'm very new to ActionScript3 and am making an asteroids-type game. Right now, the ship continues floating in a straight line when you let go of the movement buttons, and I want to be able to stop that from happening. I'm thinking either a dedicated button for braking, like the b key, or if the keys are not pressed to stop movement, whichever would be easier. Like I said I'm really new to AS3 so not even sure what part of my code is making them keep flying in a straight line. Here is the code to control movement for reference:
// register key presses
public function keyDownFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = true;
} else if (event.keyCode == 39) {
rightArrow = true;
} else if (event.keyCode == 38) {
upArrow = true;
//Add event listener for down arrow
} else if (event.keyCode == 40) {
downArrow = true;
// show thruster
if (gameMode == "play") ship.gotoAndStop(2);
} else if (event.keyCode == 32) { // space
var channel:SoundChannel = shootSound.play();
newMissile();
} else if (event.keyCode == 90) { // z
startShield(false);
var channel:SoundChannel = shieldSound.play();
}
}
// register key ups
public function keyUpFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = false;
} else if (event.keyCode == 39) {
rightArrow = false;
} else if (event.keyCode == 38) {
upArrow = false;
//Add listener for down arrow
} else if (event.keyCode == 40) {
downArrow = false;
// remove thruster
if (gameMode == "play") ship.gotoAndStop(1);
}
}
// animate ship
public function moveShip(timeDiff:uint) {
// rotate and thrust
if (leftArrow) {
ship.rotation -= shipRotationSpeed*timeDiff;
} else if (rightArrow) {
ship.rotation += shipRotationSpeed*timeDiff;
} else if (upArrow) {
shipMoveX += Math.cos(Math.PI*ship.rotation/180)*thrustPower;
shipMoveY += Math.sin(Math.PI*ship.rotation/180)*thrustPower;
//Added down arrow movement to allow player to move backwards
} else if (downArrow) {
shipMoveX -= Math.cos(Math.PI*ship.rotation/180)*thrustPower;
shipMoveY -= Math.sin(Math.PI*ship.rotation/180)*thrustPower;
}
// move
ship.x += shipMoveX;
ship.y += shipMoveY;
I agree that there is a little logic problem in your code. Your ship will move on 'til
judgement day because the two variables responsible for the speed of it's motion - shipMoveX
and shipMoveY - aren't automatically degraded over time.
Now there are literally thousands of ways of how this could be achieved but let's keep things
simple.
You are using a class variable called thrustPower - make sure to set it to 0.1 and that the value of both shipMoveX & shipMoveY is 0.
Additionally add these class variables:
private var thrustHorizontal:Number = 0;
private var thrustVertical:Number = 0;
private var speed:Number = 0;
private var maxSpeed:Number = 5;
private var decay:Number = 0.97;
Replace the moveShip function with this:
public function moveShip(timeDiff:uint):void
{
thrustHorizontal = Math.sin(Math.PI * ship.rotation / 180);
thrustVertical = Math.cos(Math.PI * ship.rotation / 180);
// rotate and thrust
if (leftArrow)
{
ship.rotation -= shipRotationSpeed * timeDiff;
}
else if (rightArrow)
{
ship.rotation += shipRotationSpeed * timeDiff;
}
else if (upArrow)
{
shipMoveX += thrustPower * thrustHorizontal;
shipMoveY += thrustPower * thrustVertical;
}
else if (downArrow)
{
shipMoveX -= thrustPower * thrustHorizontal;
shipMoveY -= thrustPower * thrustVertical;
}
if (!upArrow && !downArrow)
{
shipMoveX *= decay;
shipMoveY *= decay;
}
speed = Math.sqrt((shipMoveX * shipMoveX) + (shipMoveY * shipMoveY));
if (speed > maxSpeed)
{
shipMoveX *= maxSpeed / speed;
shipMoveY *= maxSpeed / speed;
}
ship.x += shipMoveX;
ship.y -= shipMoveY;
}
As you can see, there is this new if-block:
if (!upArrow && !downArrow)
{
shipMoveX *= decay;
shipMoveY *= decay;
}
Here we're handling the case, if the player neither pressed up nor down and multiply
the spaceships horizontal/vertical speed by decay. If you scroll back a bit, you notice
it's value is 0.97.
You can generally say, if you multiply a positive number x by 0 < y < 1, x will become smaller.
So if you're spaship is currently moving horizontally at 3 pixels per frame (shipMoveX=3 ; shipMoveY=0)
it will become 2.91 the next frame. The next frame it will be 2.8227, then 2.738019 ... and so on before it will finally reach zero in infinity.
I am making a platformer game in Flash (AS3) and the code I have below works. I want my character to jump high enough to allow it time to reach a platform. The only problem with code below is the speed at which it jumps up and down and the height of the jump. Tthe space bar is what triggers the function to run.
Please help as I would much appreciate it! :)
Player.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed);
function fl_MoveInDirectionOfKey(event:Event)
{
if (spacePressed){
var gravity:Number = 9.8;
var jumping:Boolean = false;
var jumpVar:Number = 0;
if(jumping != true)
{
jumpVar = -70;
jumping = true;
}
if(jumping)
{
spacePressed = false;
Player.y += jumpVar;
jumpVar += gravity;
}
Player.addEventListener(Event.ENTER_FRAME, drop);
function drop(event:Event)
{
Player.y -= jumpVar;
jumpVar -= gravity;
if(Player.y > 350){
Player.y = 350;
}
}
Player.removeEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
Player.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
/*var frameNumb:Number = 0;
Player.addEventListener(Event.ENTER_FRAME, jumpup);
spacePressed = false;
function jumpup(event:Event)
{
while(frameNumb < 30){
spacePressed = false;
Player.y -= 1;
frameNumb += 0.5;
}
Player.removeEventListener(Event.ENTER_FRAME, jumpup);
Player.addEventListener(Event.ENTER_FRAME, jumpdown);
function jumpdown(){
while(frameNumb > 0){
spacePressed = false;
Player.y += 1;
frameNumb -= 0.5;
}
}
}*/
}
if (leftPressed)
{
Player.x -= speed;
Player.gotoAndStop("left");
}
if (rightPressed)
{
Player.x += speed;
Player.gotoAndStop("right");
}
}
Thanks
Your use of 9.8 for gravity is meters-per-second-per-second. Since drop() is executed every frame, you're going to get some serious fast-forward gravity, unless the program is doing only 1 FPS. So, assuming you want more fluidity than 1 FPS, consider doing
jumpVar += gravity/fps;
However, to get the exact velocity required to lift you to a height, I think the calculation is...
initialVelocityInMetersPerSecond = Math.sqrt( 2 * gravity * metersToJump )
So instead of jumpVar = -70, you would do something like...
// get posititive distance since we'll use to get a square root
var metersToJump:Number = Player.y - platform.y;
jumpVar = -Math.sqrt( 2 * gravity * metersToJump );
...and then in the ENTER_FRAME handler...
Player.y += jumpVar / fps;
jumpVar += gravity / fps;
From your example it's not the case, but if you place the platform below the Player, it won't work as you can't get the root of a negative number!
In my example code I am not fixing the height of the platform, so how you decide on the target platform is a completely separate matter.
I have some code whereby I want a symbol (just a square atm) to bounce around inside the stage. Occasionally however, it gets stuck on the edges. Any advice on how to fix this?
Everything else works fine, including the inertial motion.
package {
import flash.display.MovieClip;
import flash.events.*
import flash.ui.Keyboard
public class Unit extends MovieClip {
var velocityX:Number = 1;
var velocityY:Number = 1;
var accellerationX:Number = 1;
var accellerationY:Number = 1;
var bounciness:Number = 1;
var maxSpeed:Number = 10;
public function Unit(){
Key.initialize(stage);
addEventListener("enterFrame", move);
}
private function move(e:Event){
accellerate()
if ((this.x<10)||(this.x>780)){
velocityX *= -1;
if (velocityX>0){
velocityX -= bounciness;
}
if (velocityX<0){
velocityX += bounciness;
}
this.x += velocityX;
}
else{
this.x += velocityX;
}
if ((this.y<10)||(this.y>520)){
velocityY *= -1;
if (velocityY>0){
velocityY -= bounciness;
}
if (velocityY<0){
velocityY += bounciness;
}
this.y += velocityY;
}
else {
this.y += velocityY;
}
}
private function accellerate(){
if (Math.abs(velocityY) < maxSpeed){
if (Key.isDown(Keyboard.UP)){
velocityY -= accellerationY;
trace("Accellerating UP");
}
if (Key.isDown(Keyboard.DOWN)){
velocityY += accellerationY;
trace("Accellerating DOWN");
}
}
if (Math.abs(velocityX) < maxSpeed){
if (Key.isDown(Keyboard.RIGHT)){
velocityX += accellerationX;
trace("Accellerating RIGHT");
}
if (Key.isDown(Keyboard.LEFT)){
velocityX -= accellerationX;
trace("Accellerating LEFT");
}
}
if (Key.isDown(Keyboard.SPACE)){
velocityX = 0;
velocityY = 0;
}
}
}
}
Your problem is like the following:
if ((this.x<10)||(this.x>780)){
velocityX *= -1;
You toggle the volocityX, but what is likely happening is on the next frame, it still meets the if condition (hasn't moved far enough the other direction) so it's just going back and forth every frame from -1 to 1.
Do something like this instead:
if(this.x < 10 && velocity == -1) velocity = 1; //If it's near the left edge, and still moving to the left, change direction
if(this.x > 780 && velocity == 1) velocity = -1;
This way, you are only flipping the direction when it's going the wrong way.
Repeat for the velocityY stuff
So I am currently trying to do a game which is almost like a maze.
The problem is with the wall collision, once the character hits a wall, I can't get him out anymore, he gets "stuck" no matter what direction I try to take him after the collision.
One of the solutions I was thinking would be to whenever the character hits the wall, to "back him up", so that there is no more collision detected. However, when I do that, he goes through the wall in a strange way.
Here is my code so you guys can have an idea of what I'm doing:
function keyPressed(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = true;
if(char.hitTestObject(test))
{
leftHit= true;
} else {
leftHit = false;
}
}
if (event.keyCode == Keyboard.RIGHT)
{
rightArrow = true;
if(char.hitTestObject(test))
{
rightHit= true;
} else {
rightHit = false;
}
}
}
function keyReleased(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = false;
}
if (event.keyCode == Keyboard.RIGHT)
{
rightArrow = false;
}
}
function walking(event:Event):void {
if (rightArrow) {
if(rightHit)
char.x -= speed;
else
char.x += speed;
}
if (leftArrow) {
if(leftHit)
char.x += speed;
else
char.x -= speed;
}
}
A big part of this code I actually got from another person asking the same question. Even doing what was suggested in the other topic, the problem still remains.
Thank you very much for any help!
As requested, here is my solution:
if (rightArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x+speed, MovieClip(root).char.y, true))
{
MovieClip(root).char.x += speed;
x = x-speed; //moving the background
}
}
if (leftArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x-speed, MovieClip(root).char.y, true))
{
MovieClip(root).char.x -= speed;
x = x+speed; //moving the background
}
}
if (upArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x, MovieClip(root).char.y-speed, true))
{
MovieClip(root).char.y -= speed;
y = y+speed; //moving the background
}
}
if (downArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x, MovieClip(root).char.y+speed, true))
{
MovieClip(root).char.y += speed;
y = y-speed; //moving the background
}
}
It's been a while so some of this stuff I really don't remember, but from what I can see, I check if adding the speed of my character will make it become collided with the wall. If that happens, I do not move the character even if I do seemingly have enough space. I think that is pretty much it.
Hope it helps.
I'm moving an HSlider thumb via the accelerometer. The following code works fine. The problem, though, is that as I keep tilting the device, xSpeed continues to increment. This means that when I now tilt it the other way, the thumb doesn't move for a while -- since, depending on how long I was holding tilted in that intial direction, xSpeed has been going up and up.
So this works, but with the abovementioned flaw:
private function readAcc(e:AccelerometerEvent):void
{
xSpeed -= e.accelerationX * 4;
myHSlider.dispatchEvent(new FlexEvent("valueCommit"));
myHSlider.value += xSpeed;
}
But what I want to do is to stop incrementing xSpeed once the hSlider.value == either the minimum or the maximum. Sounds simple, but when I put in if statements, they prevent the thumb from moving at all:
private function readA(e:AccelerometerEvent):void
{
if(h.minimum < h.value && h.maximum > h.value)
{
xSpeed -= e.accelerationX * 4;
h.dispatchEvent(new FlexEvent("valueCommit"));
h.value += xSpeed;
var lastSpeed:Number = xSpeed;
}
else if (h.value == h.minimum || h.value == h.maximum)
{
xSpeed = lastSpeed;
h.dispatchEvent(new FlexEvent("valueCommit"));
h.value += xSpeed;
}
}
What should the logic be to make this work?
Thanks.
Perhaps your slider value is exceeding the min or max limits when you add (or subtract) xSpeed. Check for this, and subtract if the value is too high, or add if the value is too low.
// EDIT: Code modified to reflect most recent comment
if(h.minimum < h.value && h.maximum > h.value)
{
xSpeed -= e.accelerationX * 4;
var lastSpeed:Number = xSpeed;
}
else if (h.value <= h.minimum )
{
xSpeed = 2;
}
else if ( h.value >= h.maximum )
{
xSpeed = -2
}
h.value += xSpeed;
h.dispatchEvent(new FlexEvent("valueCommit"));
OK, have figured this out and wanted to share it. The key is not to mess with setting the hslider's h.value. Rather, just set the x of the thumb, and let the value take care of itself. The accelerometer event calls a handler; in that handler create a moveThumb() function which will adjust that x. Then, from within the moveThumb() function, dispatch the valueCommit event so that the hslider will respond.
private var xSpeed:Number;
private function accUpdateHandler(e:AccelerometerEvent):void
{
xSpeed -= e.accelerationX;
moveThumb();
}
private function moveThumb():void
{
var newX:Number = h.thumb.x + xSpeed;
var newY:Number = h.thumb.y + ySpeed;
if (newX < 0)
{
h.thumb.x = 0;
xSpeed = 0;
}
else if (newX > h.width - h.thumb.width)
{
h.thumb.x = h.width - h.thumb.width;
xSpeed = 0;
}
else
{
h.value += xSpeed;
}
h.dispatchEvent(new FlexEvent("valueCommit"));
}