AS3: Billiard Game Physics
---------------
AS3: Main
---------------
Note: Before start reading the actual tutorial, I just want to leave clear that this will NOT teach you how to create a billiard game, only it physics and mechanics.
Check out the example I made below:
DEMO
Move the white ball with the arrow keys.
There are two necessary bases for create something like my demo example: Mass and Impulse.
Mass will measure how fast a ball will be able to speed up after collide. Impulse will create the collision based upon the balls's masses.
The impulse equation we are going to be using is:
J = - (1 + e) * ((v * n) + (v' * n'))
---------------------------------
1 + 1
-- --
M m
Where:
e = coefficient of restitution
v = ball A velocity
v' = ball B velocity
n = ball A normal vector
n' = ball B normal vector
M = ball A mass
m = ball B mass
If you are interested to know how to find out the equation above, just go here.
Before writing the function for colliding and separating the circles, here are the objects I added to each circle:
px : Number --> x coordinate
py : Number --> y coordinate
r : Number --> radii
vx : Number --> x velocity
vy : Number --> y velocity
m : Number --> mass
Then each frame I desaccelerate the ball's velocities with friction. That's all.
Ok. Finally for the function!
Since I already have the variables in the symbols objects, I only added two parameters, a and b (circle A and circle B respectively). Also, I made it a boolean function, this means that if true, the circles collide, if false, ignore.
function collideCircCirc(a:*,b:*):Boolean
{
// distances x,y
var dx:Number = a.px-b.px;
var dy:Number = a.py-b.py;
// distance squared, radii sum
var dl2:Number = dx*dx+dy*dy;
var dr:Number = a.r+b.r;
// if distance > pow radii, ignore
if(dl2>dr*dr) return false;
// mass a,b
var am:Number = a.m;
var bm:Number = b.m;
// inverse sum of mass
var m:Number = 1/(am + bm);
// distance non-squared, inverse of distance
var dl:Number = Math.sqrt(dl2);
var idl:Number = 1/dl
// normal vectors
var nx:Number = dx*idl;
var ny:Number = dy*idl;
// separation vector
var sd:Number = (dr-dl)*m;
// separation x,y
var sx:Number = nx*sd;
var sy:Number = ny*sd;
// separating circles
a.px += sx*am;
a.py += sy*am;
b.px -= sx*bm;
b.py -= sy*bm;
// velocity x,y
var vx:Number = a.vx-b.vx;
var vy:Number = a.vy-b.vy;
// dot product
var dot:Number = vx*nx+vy*ny;
// if dot is positive, collide
if(dot>0) return true;
// impulse and x,y
var j:Number = -(1+e)*dot*m;
var jx:Number = nx*j;
var jy:Number = ny*j;
// velocity change based upon the impulse and mass
a.vx += jx*am;
a.vy += jy*am;
b.vx -= jx*bm;
b.vy -= jy*bm;
return true;
}
Then you can update each frame with:
collideCircCirc(ball1,ball2);
or you can use an array and check for each circle removing the circle you are currently using.
If someone doesn't even know what I talked about (like Impulse, Mass, Vectors, Velocities, Normal Vector, etc...) I ask you or googling it or asking for your physics teacher.
I hope it helps someone.
Any doubts, just ask!