This is an introductory tutorial on collision detection and physics. Creating 2D physics is often daunting to the beginner flash programmer but as you will soon see it is really not that hard so long as you break everything down into small steps. Here we are going to create a world and populate it with a realistic bouncing ball:
The concepts required here may look daunting but all that needs to be required are the following:
Velocity
Wall Collision Detection
Friction
Gravity
Defining the world
Lets start off by defining our bounds and our world as a class like so:
Here we start with a World class that contains a backing sprite and a Ball Sprite which we have placed in the middle of the bounds. This tute is all about creating some realistic movement based on basic physics so lets get the ball to move.
Velocity
Within the physical world moving objects have a velocity which represents a distance moved over time. In Actionscript, we have a frame ticker which represents time so once every frame we can add the velocity to the coordinate position of our sprite to give the appearance of movement. Velocity in physics is given as a vector but in Actionscript we can provide it as two separate values for each coordinate. Lets add velocity to our ball:
class Ball extends Sprite
{publicvar vx:Number = 0; // velocity xpublicvar vy:Number = 0; // velocity ypublicvar radius:Number = 20; // circle radiuspublicfunction Ball(rad:Number){// Apply params
radius = rad;
// Draw Ball
graphics.lineStyle(1,0xAAAAAA);
graphics.beginFill(0xA9C065);
graphics.drawCircle(0,0,radius);
graphics.endFill();
// Add Listeners
addEventListener(Event.ENTER_FRAME, onFrame);
}privatefunction onFrame(e:Event):void{// Apply Velocity to Position
x += vx;
y += vy;
}}
Notice nothing much has happened. Our Ball is still sitting in the center of the stage and not moving. The reason it isn't moving is because we have given it an initial velocity of 0 for both the x and y directions. Lets give this a number value of lets say 5. Add the following to our World class:
Bingo! the ball is moving but it is hardly realistic. Firstly the ball leaves the bounds almost immediately so we need to provide some collision detection and to constrain it to the given bounds.
Wall Collision Detection
Let's add the following handler and variable to our Ball class:
This is going to listen for when we add our ball to the world and at that instance get the properties of our world and apply them to the ball animation.
now add the following to our frame routine:
privatefunction onFrame(e:Event):void{// Use a temp var for x and y to increase performancevar tx:Number = x;
var ty:Number = y;
// Collision Detection with right wallif(tx + vx > bounds.right - radius){
tx = bounds.right - radius;
vx *= -1;
}// Collision Detection with left wallif(tx + vx < bounds.left + radius){
tx = bounds.left + radius;
vx *= -1;
}// Collision Detection with floorif(ty + vy > bounds.bottom - radius){
ty = bounds.bottom - radius;
vy *= -1;
}// Collision Detection with ceilingif(ty + vy < bounds.top + radius){
ty = bounds.top + radius;
vy *= -1;
}// Apply Velocity to tx and ty
tx += vx;
ty += vy;
// Render the change
x = tx;
y = ty;
}
Lastly we need to alter our World class to provide us with the bounds property containing the bounds to constrict the ball to. So lets move our backing instance to become a private instance variable and access its getBounds method for the bounds of the world.
class World extends Sprite
{
...
privatevar backing:Sprite;
...
publicfunctionget bounds():Rectangle
{return backing.getBounds(this);
}}
Within the frame script we are now checking to see if the object has moved beyond the boundary given by the bounds Rectangle. If the bounds have been exceeded for any given direction the direction is reversed based on the boundary exceeded.
Here we also use a temporary variable to make it so that x is only set at the end of the frame script and is only necessary for performance reasons but is a good habit to get into since it is good to keep data and render separate.
The Flash plugin is required to view this object.
So now we have our ball flying away within our bounding box but the movement doesn't look particularly real as we haven't added any of the common physical forces to our object such as friction or gravity.
Adding Friction
To add air friction we simply need to multiply the velocity by a given amount between 0 and 1 every frame ie:
// Air Dampening
vx *= .99;
vy *= .99;
This leaves us with something that looks like the following:
The Flash plugin is required to view this object.
Gravity
The last thing to do is add gravity to simulate the natural pull towards the ground by simply adding to the downward velocity every frame:
// Air Dampening
vx *= .99;
vy *= .99;
// Gravity
vy += 1;
// Apply Velocity to tx and ty
tx += vx;
ty += vy;
// Render the change
x = tx;
y = ty;
After moving the gravity and friction properties to belong to the World we are left with the following full source code:
package
{import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Rectangle;
[SWF(width="530", height="397", frameRate="30", backgroundColor="#EEEEEE")]publicclass BallWorld extends Sprite
{publicfunction BallWorld(){var world:World = new World(530,397);
addChild(world);
}}}import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
class World extends Sprite
{privatevar backing:Sprite;
publicvar friction:Number;
publicvar gravity:Number;
publicfunction World(w:Number, h:Number){
friction = 0.95;
gravity = 1;
backing = new Sprite();
backing.graphics.lineStyle(1,0xAAAAAA);
backing.graphics.beginFill(0xFFFFFF);
backing.graphics.drawRect(0,0,400,300);
backing.x = w/2 - backing.width/2;
backing.y = h/2 - backing.height/2;
addChild(backing);
var ball:Ball;
ball = new Ball(20);
ball.x = w/2;
ball.y = h/2;
// Initial Velocity
ball.vx = 5;
ball.vy = 5;
addChild(ball);
}publicfunctionget bounds():Rectangle
{return backing.getBounds(this);
}}class Ball extends Sprite
{publicvar vx:Number = 0; // velocity xpublicvar vy:Number = 0; // velocity ypublicvar radius:Number = 20; // circle radiusprivatevar bounds:Rectangle;
privatevar friction:Number;
privatevar gravity:Number;
publicfunction Ball(rad:Number){// Apply params
radius = rad;
// Draw Ball
graphics.lineStyle(1,0xAAAAAA);
graphics.beginFill(0xA9C065);
graphics.drawCircle(0,0,radius);
graphics.endFill();
// Add Listeners
addEventListener(Event.ENTER_FRAME, onFrame);
addEventListener(Event.ADDED, onAdded);
}privatefunction onAdded(e:Event):void{var world:World = parent as World;
bounds = world.bounds;
friction = world.friction;
gravity = world.gravity;
}privatefunction onFrame(e:Event):void{// Use a temp var for x and y to increase performancevar tx:Number = x;
var ty:Number = y;
// Collision Detection with right wallif(tx + vx > bounds.right - radius){
tx = bounds.right - radius;
vx *= -1;
}// Collision Detection with left wallif(tx + vx < bounds.left + radius){ tx = bounds.left + radius; vx *= -1; }// Collision Detection with floor if(ty + vy > bounds.bottom - radius){
ty = bounds.bottom - radius;
vy *= -1;
}// Collision Detection with ceilingif(ty + vy < bounds.top + radius){
ty = bounds.top + radius;
vy *= -1;
}// Air Dampening
vx *= friction;
vy *= friction;
vy += gravity;
// Apply Velocity to tx and ty
tx += vx;
ty += vy;
// Render the change
x = tx;
y = ty;
}}
As you can see by adding gravity we substantially increase the reality factor of the motion.
Introduction to collision detection & 2D physics
This is an introductory tutorial on collision detection and physics. Creating 2D physics is often daunting to the beginner flash programmer but as you will soon see it is really not that hard so long as you break everything down into small steps. Here we are going to create a world and populate it with a realistic bouncing ball:
The concepts required here may look daunting but all that needs to be required are the following:
Defining the world
Lets start off by defining our bounds and our world as a class like so:
The Flash plugin is required to view this object.
Here we start with a World class that contains a backing sprite and a Ball Sprite which we have placed in the middle of the bounds. This tute is all about creating some realistic movement based on basic physics so lets get the ball to move.
Velocity
Within the physical world moving objects have a velocity which represents a distance moved over time. In Actionscript, we have a frame ticker which represents time so once every frame we can add the velocity to the coordinate position of our sprite to give the appearance of movement. Velocity in physics is given as a vector but in Actionscript we can provide it as two separate values for each coordinate. Lets add velocity to our ball:
Notice nothing much has happened. Our Ball is still sitting in the center of the stage and not moving. The reason it isn't moving is because we have given it an initial velocity of 0 for both the x and y directions. Lets give this a number value of lets say 5. Add the following to our World class:
Which gives us this:
The Flash plugin is required to view this object.
Bingo! the ball is moving but it is hardly realistic. Firstly the ball leaves the bounds almost immediately so we need to provide some collision detection and to constrain it to the given bounds.
Wall Collision Detection
Let's add the following handler and variable to our Ball class:
This is going to listen for when we add our ball to the world and at that instance get the properties of our world and apply them to the ball animation.
now add the following to our frame routine:
Lastly we need to alter our World class to provide us with the bounds property containing the bounds to constrict the ball to. So lets move our backing instance to become a private instance variable and access its getBounds method for the bounds of the world.
Within the frame script we are now checking to see if the object has moved beyond the boundary given by the bounds Rectangle. If the bounds have been exceeded for any given direction the direction is reversed based on the boundary exceeded.
Here we also use a temporary variable to make it so that x is only set at the end of the frame script and is only necessary for performance reasons but is a good habit to get into since it is good to keep data and render separate.
The Flash plugin is required to view this object.
So now we have our ball flying away within our bounding box but the movement doesn't look particularly real as we haven't added any of the common physical forces to our object such as friction or gravity.
Adding Friction
To add air friction we simply need to multiply the velocity by a given amount between 0 and 1 every frame ie:
This leaves us with something that looks like the following:
The Flash plugin is required to view this object.
Gravity
The last thing to do is add gravity to simulate the natural pull towards the ground by simply adding to the downward velocity every frame:
After moving the gravity and friction properties to belong to the World we are left with the following full source code:
As you can see by adding gravity we substantially increase the reality factor of the motion.
The Flash plugin is required to view this object.