If you're anything like me, the idea of adding some simple physics to your next game is freaking exciting... though a little intimidating. Unfortunately I lost my Math mojo around year 10 when girls and football stole the spotlight.
I recently purchased "Physics for Game Programmers" looking for some easy answers. It's a great book (highly worth buying) but a little heavy on theory and light on code examples. I was specifically after information on ball-ball reactions and angular momentum though it left me feeling like I should've paid a little more attention in class. Admittedly, I haven't gone through the book chapter by chapter (this probably would solve my problem) but who has time for that?!
In a bid to start giving back to the Flash community, here's a headstart down the track to create realistic looking Billiard/Pool Ball physics in Actionscript.
Let me preface the following information by stressing that by no means am I a physics guru (nothing has changed since grade 10) , I expect you to be at least an intermediate Actionscripter and familiar with basic game-orientated trigonometry to keep up. If you have questions, post comments here and I'll answer them as best I can... if I can! The second disclaimer is that I'm still quite new to Flash. The way I do things may be a little unconventional but they've worked for me so far. Let me know if you think there's a better way to play.
Step 1 - The ball symbol
Firstly, open Flash and set the frame rate to 30 fps. Draw a circle on the stage with a width and height of 100 pixels and convert it to a symbol with its registration point in the middle. Name it anything you like but make sure you 'export for ActionScript' and type "Ball" as the identifier and "Ball" in the "AS 2.0 class:" field.
Once you've done that you can delete it from the stage - just make sure that it's still in your library.
Step 2 - the Ball class
Next step is to sort out the code that makes your ball movieclip behave like a ball. Time to ask yourself what a ball needs to work... are you thinking yet? I'm not going to help you if you're not thinking! Here's the minimum you'll need for the class:
- variables to hold information describing the current state of the ball (x/y position, radius and mass)
- variables to hold the temporary positions of balls whilst we're looking for collisions
- functions to move and draw the ball
- function to deal with the ball if it is heading off the stage
- function to see if this ball is hitting any other balls
- function to determine how the balls react when they hit
A point to note is that you want to make sure that you only check for collisions between each pair of balls once - ie. 3 balls = 3 collision checks each frame. Seems obvious though rookies often forget to implement this.
Follow this link to see my basic Ball class: Ball.as
For those that just want the good stuff... here's the code that deals with the reaction between the balls...
-
function ballBallReaction(b1:Ball, b2:Ball, dist:Number, xdiff:Number, ydiff:Number):Void {
-
// params
-
// b1 - first ball in collision
-
// b2 - second ball in collision
-
// dist - distance between the middle of the two balls
-
// xdiff - diff between balls on the x axis
-
// ydiff - diff between balls on the y axis
-
-
// This function is where the billiard goodness takes place.
-
// It's physics madness... I'll explain the bits I think I understand
-
-
// find the angle between the balls
-
var angle = Math.atan2(ydiff, xdiff);
-
-
var cosa = Math.cos(angle);
-
var sina = Math.sin(angle);
-
-
// find the current linear momentum on each axis for each ball
-
// I think this rotates the coordinate system so that we can
-
// determine a 2 dimensional collision
-
var vx1p = cosa * b1.xmov + sina * b1.ymov;
-
var vy1p = cosa * b1.ymov - sina * b1.xmov;
-
var vx2p = cosa * b2.xmov + sina * b2.ymov;
-
var vy2p = cosa * b2.ymov - sina * b2.xmov;
-
-
// P = momentum?
-
// V = velocity?
-
var P = vx1p * b1.mass + vx2p * b2.mass;
-
var V = vx1p - vx2p;
-
-
vx1p = (P - b2.mass * V)/(b1.mass + b2.mass);
-
vx2p = V + vx1p;
-
-
// tell each ball how fast they're going on each axis
-
b1.xmov = cosa * vx1p - sina * vy1p;
-
b1.ymov = cosa * vy1p + sina * vx1p;
-
b2.xmov = cosa * vx2p - sina * vy2p;
-
b2.ymov = cosa * vy2p + sina * vx2p;
-
-
// Work out the where the balls are colliding along the
-
// "Line of Action" so that we can project them far enough
-
// away from each other to no longer intersect
-
var diff = ((b1.radius + b2.radius) - dist) / 2;
-
-
var cosd = cosa * diff;
-
var sind = sina * diff;
-
-
// update their temporary positions
-
b1.tempx -= cosd;
-
b1.tempy -= sind;
-
b2.tempx += cosd;
-
b2.tempy += sind;
-
}
Step 3 - Growing some balls...
So lastly we need a way to populate the Stage. While I'm here... if you haven't got SEPY Actionscript editor yet, go get it. It will save you lots of time and free you from the horror that is the Flash IDE.
Go to the first frame in your .fla file and type
-
#include "main.as"
Now get your SEPY on and make a file called, you guessed it, "main.as". If this is new to you then you owe me a coke... I've just saved you a billion hours.
In the main file we need:
- An array to keep track of all of the balls on the stage
- A function to create a new ball
- A function to iterate through the ball array on every frame, moving each ball (which also looks for collisions) and then renders them to the screen.
Here's what I had in my main file: main.as
If you're just interested in how I got the Ball out of the library and onto the Stage with the class attached, here it is:
-
function newBall(howMany:Number):Void {
-
// creates a new ball on the stage and adds it to the end
-
// of the allBalls array
-
-
for (var i = 0; i <howMany; i++) {
-
allBalls.push(this.attachMovie("Ball", "ball_" + ballCounter++, this.getNextHighestDepth(), getStartPosition())
-
.init(allBalls.length, this));
-
}
-
}
The trick resides in the .init() which returns a reference to our new Ball. I remember being pretty impressed when I figured this out for the first time. "this" in the code snippet above refers to the root movieclip.
Step 4 - Watch in awe!
So if all goes to plan you should end up with something like this.
Here's the .zip of everything you see here: Ball_tutorial.zip
Conclusions
This is by no means a comprehensive tutorial, simply the kind information I was looking for a few weeks ago. If this scratches your physics itch then my work here is done.
There are plenty of resources for ActionScript physics online... Kirupa.com has a great forum which helped me out here quite a bit. Also make sure you check out TONYPA's vector tutorials.
Please let me know if you find this information useful... and make sure you send links to your work through to me! For me, this is the first tiny step towards the holy grail that is Pinball!
Cheers.







