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

How to go about this has me confused. Any thoughts?

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

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.

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.

Experts Exchange Solution brought to you by

Your issues matter to us.

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

Start your 7-day free trial
D4LyAuthor Commented:
Hi nifmcm-
I tried your suggestion, but the result unfortunately is that the balls grab each other more smoothly.

Check it out.

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



D4LyAuthor Commented:
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.

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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Adobe Flash

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.