[Last Call] Learn how to a build a cloud-first strategyRegister Now


Colliding Balls help!

Posted on 2006-04-17
Medium Priority
Last Modified: 2008-02-01
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!!

Question by:D4Ly

Accepted Solution

nifmcm earned 672 total points
ID: 16475905
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.

Author Comment

ID: 16477227
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.
LVL 19

Assisted Solution

Montoya earned 664 total points
ID: 16477940
In the spirit of teaching you how to fish....





Author Comment

ID: 16478757
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.


Assisted Solution

muxxter earned 664 total points
ID: 16479893
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

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is intended to introduce all collision detection principles in flash, their strengths, weaknesses and workarounds. The main method for Collision Detection in flash is using hitTestObject. But unless you'll be pushing rectangular shapes without …
Here are some practices and techniques that can be adopted into your Flash/Flex application development process. Note: Not all "performance tips" provide an immediately-recognizable benefit.   This article does not include timing validation data,…
The goal of the tutorial is to teach the user how to use the auto adjust feature and what the different options do. When your video is not working right you can choose the auto adjust feature to help choose your settings.
The goal of the tutorial is to teach the user how to select which audio input to use. Once you have an audio input plugged into the laptop or computer, you will go into the audio input settings and choose which audio input you want to use.
Suggested Courses
Course of the Month18 days, 10 hours left to enroll

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question