# Colliding Balls help!

I am working on something in which balls fall from the top of the stage and then bounce around, off the walls and one another. Each balls has a random size and mass defined at runtime, and all animation is scripted. My problem is on the collisions.

On the stage a clip runs a loop every frame going through each ball checking to see if a collision has been made with another ball. It seems that a collision is detected, processed, and the resultant velocities are applied to each ball properly, but because there is the possibility of overlapping at the time of the collision detection, the balls may be seen as colliding on the next frame as they try and move apart, resulting in another calculation. This causes the balls to just bunch up.

I seem to need some way to either

a) separate the balls properly when a collision is detected
b) make sure another collision calculation isn't processed until the distance between balls is greater than radius + radius2

I'll be more than happy to post my flash file for download if neccessary!!

-D4
LVL 9
###### Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Commented:
try the setInterval method instead of onEnterFrame... frames are too slow and possibly your app is running at only 12 per sencond, which would make it much slower... of course, if you don't have any frame based animation, you could just push that up and your check would be happening alot more... you'd need to change some vars like the speeds of balls moving etc... but your most stable bet is setInterval... with it, you can check for collision every millisecond if you want.

basic usage.
myInterval = setInterval(functionName, interval [, param1, param2, ..., paramN]);

where function does the check... interval is your milliseconds... params are optional stuff you'd be passing into your function.

when your need to get rid of the interval, use clearInterval(myInterval)... make sure the variable myInterval is accessible from whereever you clear it... i.e. don't make it local to one function and then clear it in another.

hope this helps.
0

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Author Commented:
Hi nifmcm-
I tried your suggestion, but the result unfortunately is that the balls grab each other more smoothly.

Check it out.

http://www.d4ly.com/ee/anim_03_b.swf

this is with setInterval at 1ms.
0
Process Improvement MgrCommented:
In the spirit of teaching you how to fish....

http://www.kirupa.com/developer/actionscript/multiple_collision.htm

Regards,

Montoya

0
Author Commented:
Iammontoya-
I'm not sure how that is supposed to help. My direction change calculations are a little more complex, but the basic idea is exactly the same as the link you've provided, but does not address my issue of balls against the wall or floor (since there is in fact no wall or floor in that example). I know how to 'fish', and have done my research...that's why I am here :) Perhaps a solution is out there, but I have yet to find it.

for(var i=0; i<maxBalls; i++){ //check collisions
bi = _root["ball"+i];
if(!bi)      continue;
for(var j=i+1; j<maxBalls;j++){
bj = _root["ball"+j];
if(!bj)      continue;
var xd = bi._x - bj._x; var yd = bi._y - bj._y;
var dr = Math.sqrt(Math.pow(xd,2) + Math.pow(yd,2)); //distance between balls
var rads = ((bi._width / 2) + (bj._width / 2)); //total distance between center points
var tm = (bi.code.mass + bj.code.mass)/2; //half of total system mass

if(bi.hitTest(bj)){ //check if balls are colliding
var nx = xd/dr; var ny = yd/dr; //normal vectors
var v0 = ( bi.code.vx * nx + bi.code.vy * ny );
var v1 = ( bj.code.vx * nx + bj.code.vy * ny );
var relv = v0 - v1; //relative velocity calculation
var vec0 = -bounce * relv; var vec1 = bounce * relv; //new vectors

bi.code.vx = (bi.code.vx) + nx * vec0 * bj.code.mass / tm; //set the resultant velocities
bi.code.vy = (bi.code.vy) + ny * vec0 * bj.code.mass / tm;
bj.code.vx = (bj.code.vx) + nx * vec1 * bi.code.mass / tm;
bj.code.vy = (bj.code.vy) + ny * vec1 * bi.code.mass / tm;
}
}
}

The math here works beautifully when the balls are both in the air. Its when one of the balls collides off of a wall or the floor that I run into some issues.

I've been thinking. I never have an issue with the ball getting caught up in the wall or floor itself. I believe this is because when the ball collides with a wall or floor it's position is reset to be completely inside the container, and then the new velocities are applied. Perhaps a solution would be to move the balls apart in the direction they will be traveling and _then_ apply the resultant velocities. How to do this is a bit unclear at this point, as well as how to deal with the walls and floor when moving a ball that is say, stationary on the ground.

Another thought would be to set a timer of some sort up, which would not allow for another collision calculation on the same 2 balls for a certain period of time, allowing them to move apart.

-D4
0
Commented:
I did something similar to this in my computer graphics class when I was an undergad. I did mine in C using OpenGL, but I use similar math (using a normal vector pointing from one mass to the other) to caculate the new velocity.

I too was having this problem of overlapping balls since the collision sometimes happened between frames. Although, my math didn't seem to care once they were moving in the correct direction, they would keep travelling in that direction.

Anyways, a simple fix I found was to look ahead one frame. Instead of checking collisions as they happen (or already happened) in this frame, I would see if any of them would collide in the next frame. If they were going to, I would set their nextFramePosition to exactly where the collision happens, and set the new velocity to that determined by your math equation.

This, I noticed, always made sure that the objects never overlapping, and no collision was calculated twice. Since in the next frame (the one you are now checking), the objects will be moving apart.

Hope this helps
MuXx
0