Flash & Swish  Home Flash & Swish Flash Tutorials Physics in Flash - Gravity
rss

Physics in Flash - Gravity

Author: Craig Smith More by this author


The Movie

Download Flash File

Every story has to start somewhere, and in this story we begin with our good friend Sir Isaac Newton. Newton's theories have been, and are still the primary theories studied to understand the way things happen around us. In this series of tutorials we are going to explore various aspects of physics and how they can be represented in your flash applications. We begin with gravity.

The algorithms and ideas covered in this tutorial are simplified somewhat and, although it may horrify some of you out there who have studied Newtonian physics in depth, there is a good reason for this. To fully implement Newtonian physics to create a highly realistic simulation would require explaination of some complex topics far far beyond the scope of this tutorial.

StepSetting up the Scene

Start with a new file with dimensions of 400 x 300. Now draw a circle in the middle of the stage with a radius of 16. Believe it or not, this is all the designing you'll need to do. The stage should now look like the following image:

Picture 1

Step Before we go to work on the ball and assigning actions, there are a few global variables that we need to set. In the context of a physics simulation, these variables are the environmental properties of the world in which we are setting the simulation. For example, in this tutorial we will be defining gravity, restitution and friction. Add the following code to the first frame of the _root timeline:

var gravity:Number = 1; 
var restitution:Number = 0.6; 
var friction:Number = 0.9; 

stop();

StepNow let's go to work on the ball. First convert this circle to a Movie Clip symbol, giving it the name Ball_MC and setting its registration point to the centre. Now for the code... To start off, attach the following code to the movie clip instance to setup some initial variables.

onClipEvent(load) { 
  var vel:Object = { x: 0, y: 0 }; 
  var pos:Object = { x: _x, y: _y }; 
  var old:Object = { x: _x, y: _y }; 
  var radius:Number = this._width 2; 
  var movie:Object = { width: 400, height: 300 }; 
  var dragging:Boolean = false; 
}

These variables should be pretty self explanatory. vel is an Object storing the horizontal and vertical velocity of the ball, and pos is another Object containing the current position of the ball.

StepA good practice to follow when implementing physics (in any programming language, not just ActionScript) is to store an object's x and y position in seperate variables and edit these values each frame when calculating where the ball should be moved to. Then the very last 2 lines of code of each frame should update the ACTUAL position of the object to be equal to the newly calculated values.

This technique is one I believe in, hence it will appear in all the tutorials. Below is the block of code which handles the movement of the ball each frame and should be added to the ball MovieClip after the onClipEvent(load) code:

onClipEvent(enterFrame) { 
  vel.y += _root.gravity; 

  pos.x += vel.x; 
  pos.y += vel.y; 

 / Now update the ACTUAL position of the ball... 
  _x = pos.x; 
  _y = pos.y; 
} 

And that is it! That's all the code you need to make an object the subject of gravity. But you didn't think I've leave it there did you?

If you're on the 'ball' (sorry, I just couldn't resist it) then you'l probably have previewed the movie to find that the ball quickly drops of the bottom of the stage to never be seen again! Bit boring isn't it?

StepBouncy, Bouncy...

What we need is some way of stopping the ball leaving the bottom of the stage. What we need is a floor!

For simplicity we'll use the bottom of the stage as the floor. Now because this is a very simple application of gravity, there's no real need for an elaborate collision detection system. Instead, each frame, before the actual position of the ball is updated, we'll perform an if statement to determine whether the ball has left the stage, and if so, take appropriate action.

Before we consider the code to test for and handle collisions, lets think about what actually happens when an object collides with a surface shall we? As you'll know from observations in real-life, when a ball bounces off the floor it doesn't return to the same height. The reason for this is that when an object bounces off say the floor, it loses some of it's energy, which is seen as a reduction in the speed of the object. This leads us on to Newton's Law of Restitution. Without boring you with lots of mathematical theory, the equation governing restitution is:

Picture 5

The coefficient of restitution for an object will depend upon the material the object is made from and will always be a value between 0 and 1. A value of 0 would prevent the object from bouncing at all whereas a value of 1 would cause the object to continue to bounce forever

Add the following code before the actual co-ordinates of the ball object are updated:

// Has the ball left the bottom of the stage?... 
if( pos.y + radius > movie.height ) { 
  pos.y = movie.height - radius; 
  vel.y *= -_root.restitution; 
} 

What this code does it to check whether or not the the bottom edge of the ball is below the bottom edge of the stage. If it is, it sets the y co-ordinate of the ball so that it is just touching the floor. It also reverses the vertical velocity of the ball and multiples it by the coefficient of restitution to reduce the speed of the ball accordingly.

With all this code in place, the ball will now bounce when it hits the bottom of the stage, coming to rest after a few bounces. Great, we're getting ther, but it's still a bit boring. The ball comes to rest after a few seconds, and that's your lot. Time for a bit of interactivity I think!

StepWouldn't it be cool if it were possible to pick up the ball and throw it around? Well you're in luck, because that's what we're going to do now!

First things first, we need to alter the Ball_MC symbol a little. Select the symbol instance on stage and hit Ctrl+E to edit the instance. Now select the yellow ball and its outline and convert it to a Button symbol, calling it Ball_Button. With this newly created instance of the button selected, give it the following actions:

on(press){ 
  startDrag(this,false,16,16,384,284); 
  dragging = true; 
} 
on(release, releaseOutside){ 
  stopDrag(); 
  dragging = false; 
} 

Throw that ball around

What this code does is to allow the ball movie clip to be dragged around the stage by the mouse. The problem with this it that while ever we are dragging the ball, the code we assigned to the ball to be executed each frame is dragging the ball downwards. The solution to this is to use a variable (dragging) to keep track of whether or not the ball is currently being dragged and only apply gravity if it is not.

This requires a few changes to the code contained within the Ball_MC instance. We need to put all of the code inside the onClipEvent(enterFrame) function inside an if statement which tests for the dragging variable being false. This function should now look like the following:

onClipEvent(enterFrame) { 
  if(!dragging) {

   / Actions to apply gravity here... 

  } 
} 

Getting very close to our goal now, we realise that this doesn't quite give us the throwing action we desire. Instead, we can only pick up the ball and drop it from anywhere on the stage. To allow the user to actually throw the ball around, we need to extend the if(!dragging) statement to contain an else section of code which is executed while ever the ball is being dragged. What this code does it to calculate the horizontal and vertical speeds of the ball based on the speed the mouse is being moved:

onClipEvent(enterFrame) { 
  if(!dragging) { 

   / Actions to apply gravity here... 

  } else { 
    old.x = pos.x; 
    old.y = pos.y; 
    pos.x = _x; 
    pos.y = _y; 
    vel.x = ( pos.x - old.x ) 2; 
    vel.y = ( pos.y - old.y ) 2; 
  } 
} 

StepWhere'd it go?

Now those of you that are more alert may see a couple of problems that will arise from allowing the user to throw the ball around.

Firstly, It could be thrown off the stage to the left or the right and never be seen again, and secondly, it will never come to rest when it has stopped bouncing. Instead it'll just slide across the floor!

Let's tackle problem number one first. The solution is to add 2 more if statements similar to the one that checks for the ball leaving the bottom of the stage, but this time to cause the ball to bounce off the sides of the stage:

... 
if( pos.x + radius > movie.width ) { 
  pos.x = movie.width - radius; 
  vel.x *= -_root.restitution; 
} 

if( pos.x < radius ) { 
  pos.x = radius; 
  vel.x *= -_root.restitution; 
} 
... 

And now for problem #2, which can be solved with one line of code. All that is needed is to apply some friction to the ball whenever it is in contact with the floor. To do this, add the follwing line of code to the if( pos.y + radius > movie.height ) block of code:

// Has the ball left the bottom of the stage?... 
if( pos.y + radius > movie.height ) { 
  pos.y = movie.height - radius; 
  vel.y *= -_root.restitution; 
  vel.x *= _root.friction; 
} 

StepConclusion

And with those minor additions of code our gravity simulation is complete! To summarise, this tutorial was only a brief introduction into implementing basic gravity in flash. This movie will now be the basis of some of the following tutorials which will explore ways in which this physics engine can be extended and improved upon.



Author's URL: www.spoono.com

Rate this Material: Bad 1 2 3 4 5 Excellent
print this page tell a friend subscribe to newsletter subscribe to rss

Add comments to "Physics in Flash - Gravity"