Actionscript 3 Physics
February 6, 2009 by: smonteThis tutorial is for anyone who wants to learn how to animate objects with the help of some simple physics. All done by Actionscript 3.0 of course.
1. Create a new document of size 400×400.
2. Draw a ball on the stage. Convert it into a movie clip (registration point in the center).
3. Give the ball an instance name of ”gameBall”.
4. Let’s set up the ball’s starting position. Type the following in the actions panel.
//Set the starting position of the ball to the center of the stage. gameBall.x = stage.stageWidth / 2; gameBall.y = stage.stageHeight / 2;
You should now have somewhat similar looking setup, if you’ll test your movie. Don’t worry if your colors are different. The ball could also be any size you want. My gameBall is 50×50.
5. Let’s start adding some movement to our ball. Type the following
//Declare variables needed for the physics (some are for later use). var speedY:Number = 0; var speedX:Number = 0; var radius:Number = gameBall.height / 2; var friction:Number = 0.98; //Acceleration variables var ax:Number = 0; var ay:Number = 0; var gravity:Number = 0.5; //Add event handler addEventListener (Event.ENTER_FRAME, enterFrameHandler); //This function is responsible for the whole animation in this movie. function enterFrameHandler (e:Event):void { //In each frame, add the necessary "forces" that moves the gameBall speedY += gravity; gameBall.y += speedY; }
Now our ball is falling as the gravity affects it. There is one problem though, the ball disappears as we reach the bottom. Let’s fix that.
6. Replace the enterFrameHandler with this new version
function enterFrameHandler (e:Event):void { //In each frame, add the necessary "forces" that moves the "gameBall" speedY += gravity; gameBall.y += speedY; //Let's check when the ball hits the bottom. if(gameBall.y + radius > stage.stageHeight) { //When we hit the bottom, reposition the ball to be exactly on the //bottom edge. Change the sign of the speedY so we go to the other direction. gameBall.y = stage.stageHeight - radius; speedY *= -1; } }
Now we have a bouncing ball!
7. Let’s allow the user to move the ball. Add the following code below the enterFrameHandler.
//Add event listeners for the user's key presses stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDownHandler); stage.addEventListener (KeyboardEvent.KEY_UP, keyUpHandler); function keyDownHandler (e:KeyboardEvent):void { switch (e.keyCode) { //User pressed the left arrow --> x acceleration negative case Keyboard.LEFT : ax = -0.5; break; //User pressed the right arrow --> x acceleration positivve case Keyboard.RIGHT : ax = 0.5; break; //User pressed the up arrow --> y acceleration negative (go up). Apply no gravity when up key down. case Keyboard.UP : gravity = 0; ay = -0.5; break; //User pressed the down arrow --> y acceleration positivve case Keyboard.DOWN : ay = 0.5; break; } } function keyUpHandler (e:KeyboardEvent):void { gravity = 0.5; ax = 0; ay = 0; }
Modify the enterFrameHandler, so that it looks like this.
function enterFrameHandler (e:Event):void { //In each frame, add the necessary "forces" that moves the "gameBall" speedY += gravity; speedY += ay; speedX += ax; gameBall.y += speedY; gameBall.x += speedX; //Let's check when the ball hits the bottom. if (gameBall.y + radius > stage.stageHeight) { //When we hit the bottom, reposition the ball to be exactly on the //bottom edge. Change the sign of the speedY so we go to the other direction. gameBall.y = stage.stageHeight - radius; speedY *= -1; } }
Easy, eh? I think we still have two issues to fix, the side boundaries and the friction.
8. To decrease the speed in each frame, we use the friction variable. Change the enterFrameHandler to the following
function enterFrameHandler (e:Event):void { //In each frame, add the necessary "forces" that moves the "gameBall" speedY += gravity; speedY += ay; speedX += ax; //Decrease the speed in each frame, so the ball won't bounce forever speedY *= friction; speedX *= friction; gameBall.y += speedY; gameBall.x += speedX; //Let's check when the ball hits the bottom. if (gameBall.y + radius > stage.stageHeight) { //When we hit the bottom, reposition the ball to be exactly on the //bottom edge. Change the sign of the speedY so we go to the other direction. gameBall.y = stage.stageHeight - radius; speedY *= -1; } //Check if the ball hits the top else if (gameBall.y - radius < 0) { gameBall.y = radius; speedY *= -1; } //Check the right edge if (gameBall.x + radius > stage.stageWidth) { gameBall.x = stage.stageWidth - radius; speedX *= -1; } //Check the left edge else if (gameBall.x - radius < 0) { gameBall.x = radius; speedX *= -1; } }
That’s the end of this tutorial. Play with this with different values to have your own “physical world”. If you have any questions, don’t hesitate to ask in the forum.
Final code
//Set the starting position of the ball to the center of the stage. gameBall.x = stage.stageWidth / 2; gameBall.y = stage.stageHeight / 2; //Declare variables needed for the physics (some are for later use). var speedY:Number = 0; var speedX:Number = 0; var radius:Number = gameBall.height / 2; var friction:Number = 0.98; //Acceleration variables var ax:Number = 0; var ay:Number = 0; var gravity:Number = 0.5; //Add event handler addEventListener (Event.ENTER_FRAME, enterFrameHandler); //This function is responsible for the whole animation in this movie. function enterFrameHandler (e:Event):void { //In each frame, add the necessary "forces" that moves the "gameBall" speedY += gravity; speedY += ay; speedX += ax; //Decrease the speed in each frame, so the ball won't bounce forever speedY *= friction; speedX *= friction; gameBall.y += speedY; gameBall.x += speedX; //Let's check when the ball hits the bottom. if (gameBall.y + radius > stage.stageHeight) { //When we hit the bottom, reposition the ball to be exactly on the //bottom edge. Change the sign of the speedY so we go to the other direction. gameBall.y = stage.stageHeight - radius; speedY *= -1; } //Check if the ball hits the top else if (gameBall.y - radius < 0) { gameBall.y = radius; speedY *= -1; } //Check the right edge if (gameBall.x + radius > stage.stageWidth) { gameBall.x = stage.stageWidth - radius; speedX *= -1; } //Check the left edge else if (gameBall.x - radius < 0) { gameBall.x = radius; speedX *= -1; } } //Add event listeners for the user's key presses stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDownHandler); stage.addEventListener (KeyboardEvent.KEY_UP, keyUpHandler); function keyDownHandler (e:KeyboardEvent):void { switch (e.keyCode) { //User pressed the left arrow --> x acceleration negative case Keyboard.LEFT : ax = -0.5; break; //User pressed the right arrow --> x acceleration positivve case Keyboard.RIGHT : ax = 0.5; break; //User pressed the up arrow --> y acceleration negative. Apply no gravity when up key down. case Keyboard.UP : gravity = 0; ay = -0.5; break; //User pressed the down arrow --> y acceleration positivve case Keyboard.DOWN : ay = 0.5; break; } } function keyUpHandler (e:KeyboardEvent):void { gravity = 0.5; ax = 0; ay = 0; }
Hi …thankU verymuch this post is extremely useful for me…thanku once again