Undetected collisions in loop...?

Hello,

I’ve been experimenting with circle vs. circle collisons. Ive been using the code below to check for collisions and seperate the objects.

It works just fine, except in conditions where more than two circles are touching at the same time. For example, if three circles or more are colliding at the same time, they can sometimes overlap and then struggle to separate.

I think I know why this is happening. The code loops through the object array and checks for a collision between each object one at a time and alters their positions and velocities. The problem is that if it finds a collision between objects at the end of the array, the positions of the objects could be changed in such a way that they cause an overlap with an object that was checked earlier, for which no collision was detected. This new collision then goes undetected and this flaw is amplified when the loop runs again.

Does anyone know if there is a simple solution to this problem (maybe a recursive one?) or should I be looking a more robust grid based collision detection system?

Here’s the code I’m experimenting with if anyone is interested in this problem :slight_smile:

Thanks!


function circleCollision(circleOne:MovieClip, circleTwo:MovieClip):void
{
            //Find radius, x and y positions of circleOne
            var circleOne_Radius = circleOne.width/2;
            var circleOne_X = circleOne.x;
            var circleOne_Y = circleOne.y;

            //Find radius, x and y positions of circleTwo
            var circleTwo_Radius = circleTwo.width/2;
            var circleTwo_X = circleTwo.x;
            var circleTwo_Y = circleTwo.y;

            //Calculate the radii of both circles combined
            var totalRadii = circleOne_Radius + circleTwo_Radius;

            //Find the distances between the object on the xnd y axis
            var dx:Number = circleOne_X - circleTwo_X;
            var dy:Number = circleOne_Y - circleTwo_Y;
            var distance:Number = Math.sqrt(dx * dx + dy * dy);

            //Check wether objects are colliding
            if(distance < totalRadii)
            {
                //Find the amount of overlap between circles
                var overlap = totalRadii - distance;

                //Calculate normals
                var normalX:Number = dx / distance; 
                var normalY:Number = dy / distance;

                //Find the direction vector and use it to calculate the new velocities 
                var directionVector:Number = ((circleOne.vx - circleTwo.vx) * normalX) + ((circleOne.vy - circleTwo.vy) * normalY); 
                var newVx:Number = directionVector * normalX; 
                var newVy:Number = directionVector * normalY;

                //Move circleOne out of the collision
                circleOne.x += normalX * overlap;
                circleOne.y += normalY * overlap;
                
                //Apply new velocites to objects
                circleOne.vx -= newVx; 
                circleOne.vy -= newVy; 
                circleTwo.vx += newVx; 
                circleTwo.vy += newVy;
            }
        }

The objects are stored in an array called _thingsInTheGame. This is the loop that runs in an ENTER_FRAME event.


function onEnterFrame(event:Event):void
        {
            for (var i = 0; i < _thingsInTheGame.length - 1; i++)
            {
                var objectA:MovieClip = _thingsInTheGame*;
                for (var j = i + 1; j < _thingsInTheGame.length; j++)
                {
                    var objectB:MovieClip = _thingsInTheGame[j];
                    //Check for collision
                    circleCollision(objectA,objectB);
                }
            }
}