Dynamic Circle/Circle Collision Detection in ActionScript 3
collision detection demo click and drag to move a circle or its velocity vector
source
INTRODUCTION
Determining whether 2 circles are colliding is one of the simplest types of collision detection. You simply evaluate the sum of the circles’ radii and the distance between them. If that sum is greater than the distance, the circles in question are coincident. This call is made at each time step in a simulation.
This works well in most cases and is most often optimized to evaluate the square of the sum of the radii and the square of the distance between circles- which offers the same response without an expensive square root call.
THE PROBLEM
But what if our circles are moving really fast? At the beginning of the interval they may not be colliding and likewise at the end; but it’s quite probable that at some point within that interval, the circles do collide.

THE SOLUTION
We can evaluate as many as 2 possible collisions (given constant velocity)- their initial collision and the moment at which they are adjacent again (if they passed through each other without effecting each other’s movement). There aren’t necessarily 2 solutions; and the second solution does little good for us here anyway. So we’re left wanting to derive:
(A) if the circles will collide in a given interval and if so,
(B) when they first collide in relation to that interval.
This solution is presented in Real-Time Collision Detection by Christer Ericson. He does a much better job of explaining the following derivation than I can, but here we go anyway!
DERIVATION
Because we’re presuming constant velocity over the interval 0 ≤ t ≤ 1, the position of a circle is equal to:

Where X is its current position and v, velocity. So at the beginning of the interval, the circle’s position is equal to X + v * 0 = X, and X + some portion of v for any t value greater than 0. What we need is a function of t that evaluates the distance between the 2 circles according to this parameterization:

Where
and 
When f is equal to the sum of the 2 circles’ radii, the circles are coincident:

Where r is respective radius. Evaluating distance means we need to compute a square root, which as mentioned above is undesirable. We can square both sides of the equation instead:

The square of the sum of vectors expands into dot products just like a scalar polynomial expands into multiplications:

Moving all terms to the left side, and naming each constant based on its relationship with t in agreement with the equation’s quadratic nature, we have:

Where

and

Which is a quadratic equation where b is known to be a multiple of 2. Its roots are:

EFFICIENCY CONSIDERATIONS
Every calculation requires processing and ActionScript is certainly not the exception! We want to organize our detection method such that nothing is defined/calculated before it is necessary. If we can eliminate the possibility of collision before defining a variable- we should! It’s a common mistake to solve without consideration of the algorithm’s real job- to offer an answer to our collision query as quickly as possible. And that’s the driving force here.
IMPLEMENTATION
This example utilizes CircleParticles with public properties representing radius, position and velocity. The Collision type takes 2 of these CircleParticles at instantiation. Its method detect evaluates collision over the interval implied by these CircleParticle’s velocities.
Given collision, it sets a time variable (t) to the point at which in that interval collision first occurs. A basic understanding of vector arithmetic and quadratic equations should be sufficient to wholly understand this function:
/** * Detects whether 2 {@link CircleParticle} instances will collide within an implicit timestep of 1 * * Given collision, {@link #t} is set to the percentage of the interval at which collision occurs. * ie: 0 if collision occurs at the beginning of the interval and 1.0 at the end of the interval * * The event of collision is given by the quadratic equation ax^2 + 2bx + c = 0 offers the resolution: * x = ( -b - Math.sqrt( b^2 - ac ) ) / a, the smaller of 2 possible roots * * Note that we return from the algorithm before declaring/defining any unnecessary variables * * * @return {@code true} if collision is detected, {@code false} otherwise * */ public function detect() : Boolean { //difference vector of the 2 circles' positions var cDiff:Vector = c2.position.getDifference( c1.position ); /** * {@code c} the squared distance between circles minus the squared sum of their radii * this offers a means to check for intersection at the start of the interval * without making an expensive square root call * * ie: if the sum of the circles' radii squared > the distance between them squared, * they are overlapping * */ var c:Number = cDiff.dot( cDiff ) - ( c1.radius + c2.radius ) * ( c1.radius + c2.radius ); if( c < 0 ) { //initial overlap condition- return with time 0 t = 0; return true; } //difference between circles' velocities var vDiff:Vector = c2.velocity.getDifference( c1.velocity ); var a:Number = vDiff.dot( vDiff ); if( a < Collision.OMEGA ) return false; //circles not moving relative each other var b:Number = vDiff.dot( cDiff ); if( b >= 0 ) return false; //circles moving apart var d:Number = b * b - a * c; if( d < 0 ) return false; //no solution to the quadratic equation- circles don't intersect //evaluate the time of collision t = ( -b - Math.sqrt( d ) ) / a; return t <= 1; }
NOTE: While there is not a single trigonometric function call in this detection method, some of its assertions are based on the law of cosines.
REACTION
So, assuming collision at exactly halfway through the interval, our Collision’s t property is set to 0.5. We can now move on to react to the collision.
The idea or our Collision’s react method is to take our knowledge of the moment of collision within the interval and apply that to our CircleParticles. We first move the circles along their velocity vectors scaled by the collision interval. We then calculate the transfer of momentum along the axis of collision and move the circles from their position at collision along their new velocity vectors by the remainder of the interval:
/** * Reacts to a collision between {@link #c1} and {@link #c2} at specified time {@link #t} * * * We project the ghost particles along the velocity vector of c1 and c2 by * t * circle.velocity. * (Description is outdated- needs updating) * Then we normalize the collision vector and amplify by the magnitude of the * opposing circle's velocity to obtain each ghost's velocity. Their velocities * are then multiplied by 1 - t to give us each reaction vector in reference to the * remaining span of the interval. * * * @param g1 ghost particle representative of {@link c1} at moment of collision * @param g2 ghost particle representative of {@link c2} at moment of collision * */ public function react( g1:CircleParticle, g2:CircleParticle ) : void { //assign the position at percentage t along each velocity vector to each ghost g1.position = c1.position.getSum( c1.velocity.getProduct( t ) ); g2.position = c2.position.getSum( c2.velocity.getProduct( t ) ); //difference vector between circles at time of collision var cDiff:Vector = g2.position.getDifference( g1.position ); //normalized var collisionNormal:Vector = cDiff.getUnit(); //relative velocity of circles var relativeVelocity:Vector = c1.velocity.getDifference( c2.velocity ); //coefficient of restitution range of 0 - 1.0 //0 is completely inelastic (lump of clay) and 1 is purely elastic (superball) var restitution:Number = Math.sqrt( c1.elasticity * c2.elasticity ); //the impulse created at collision- //this is given by the following equation (j is used to represent impulse) //j = -( 1 + e )vAB . n / n . n( 1 / mA + 1 / mB ) //where e is the coefficient of restitution, vAB is the relative velocity //n is the collision normal and mA/mB are the respective masses of the different circles // "."s represent the vector dot product var impulse:Number = collisionNormal.dot( relativeVelocity.getProduct( -( 1 + restitution ) ) ); impulse /= collisionNormal.dot( collisionNormal.getProduct( 1 / c1.mass + 1 / c2.mass ) ); //scale each impulse along the collision normal by the circles' respective masses var reactionA:Vector = collisionNormal.getProduct( impulse / c1.mass ); var reactionB:Vector = collisionNormal.getProduct( -impulse / c2.mass ); //Multiply this by the the remainder of the interval (1 - t) g1.velocity = c1.velocity.getSum( reactionA ).getProduct( 1 - t ); g2.velocity = c2.velocity.getSum( reactionB ).getProduct( 1 - t ); }

I’m trying to develop a 3D physics engine, and so far this is the best material I’ve found. I’m currently more interested in collision detection than reaction at the moment (haven’t got that far yet), and I’m trying to understand the equation you’ve used. I can see it obviously measures distance between the two objects and the answers that the quadratic function returns is time when distance is 0, but could you please explain how this equation came to be? I would like to try to expand this to a 3 dimensional equation taking in to account acceleration and possibly different shapes.
Also, should line 25 in the react function read: var cDiff:Vector = d2.position.getDifference( d1.position );
You’re right brendan, it should be g2.position.getDifference( g1.position ); (which can be disregarded altogether as of 09.30.07)
There should be no need to extend it to a 3D model with circles, however- the Vector operations should be the same. Since you’re considering expanding the idea to other shapes it would suit you well to look into raycasting which would offer a more generic starting point. In regard to the equation relating to detection- as you pointed out, we’re phrasing the equation such that the distance between the circles (minus the sum of their radii) is 0 at an unknown time, t. distance( t ) = 0 = at^2 + 2bt + c. a is the dot product of the relative velocity and itself. b is the dot product of the relative velocity and the relative position. c is the dot product of the relative position and itself. It should make sense then that there are 3 possible outcomes-
This page has a nice table in regard to these 3 scenarios. For more information on this I refer you to Christer Ericson’s fantastic Real Time Collision Detection, from which this algorithm is largely derived.
i’ll provide a physically realistic react method ASAP since you’ve found this useful.
I’m trying to port this code to C++, and I’m wondering what Collision.OMEGA is. Is that some constant? Thanks for the guide!!
Hi Elliot,
It’s just an arbitrarily defined constant meant to leave room for numerical rounding errors. If the dotted relative velocity (in this case defined as the difference between 2 and 1) is less than 0, the circles are moving apart from each other. Because this is just a computationally inexpensive early-out for the algorithm, it’s a bit safer to leave a margin for error.
This sort of constant is most often named EPSILON.
Here’s the whole source in case you missed the link above.
But that’s not the quadratic formula!
This is the quadratic formula:
http://en.wikipedia.org/wiki/Quadratic_equation#Quadratic_formula
i don’t know what you’re saying, Multihunter. ax^2 + 2bx + c = 0 is a quadratic equation… its roots are (-b +/- sqrt(b^2 – ac))/a
The quadratic formula is
//since your only doing the lesser of the two
X = (-b – sqrt(b^2 – 4ac)) / 2a
On the example you are missing the “4ac” but have “ac”
So that is what MultiHunter is saying.
It is the exact same equation, where it is known that b is a multiple of 2. Because of this, the solution reduces to (-b +/- sqrt(b^2 – ac))/a.
EDIT: I’ve added a derivation of this equation- hopefully that will add some clarity!
This has been bugging me for a few days so I need to ask :p. How do you actually know that b is multiple of 2 here? And if you know that b is multiple of 2, how do you actually reduce the equation at this state (-b +/- sqrt(b^2 – ac))/a?
cheers
@Patrick Corander
if you look at the derivation above, you’ll see that the equation equals at^2 + 2bt + c = 0. the generic form of this equation is at^2 + bt + c = 0, so in this case we know that the second term happens to be a multiple of 2. here’s how i solved for t:
at^2 + 2bt + c = 0
at^2 + 2bt = -c
t^2 + t(2b/a) = -c/a
t^2 + t(2b/a) + b^2/a^2 = -c/a + b^2/a^2
(t + b/a)^2 = -c/a + b^2/a^2
t + b/a = sqrt( (b^2 – ac)/a^2 )
t + b/a = sqrt( b^2 – ac )/a
t = (-b +/- sqrt( b^2 – ac ))/a
Would you mind explaining how you would change the code to allow for decremental velocities?
For example, imagine friction comes into play, and the velocity of each circle will reduce by 0.1 each frame.
How would you account for that?
For those that are interested, I have solved the problem above by adding vDiff.multiply(0.9); just after vDiff is calculated in the detect function.
I now have a new question: I have a problem when the two circles are added whilst overlapping each other. A collision is detected, but there are insufficient velocities to move them apart, so they just sit there.
I have attempted several solutions in terms of re-positioning the circles, but this causes problems when you add more than two circles to the mix.
The ideal solution would be for the circles to gradually move apart from one another, but sadly my maths abilities are not good enough to figure that one out.
Hopefully someone can help…?