AS3: Circle-Circle Collision Detection
----------------------
AS3: Main
----------------------
Have you ever wanted to create collisions between circles without using HitTestObject and stuff? So this is the right tutorial for you! This tutorial will cover how to detect when two circles are colliding (independent of their diameters, radii and coordinates) and how to prevent them from entering into each other.
Here it is an example of what I am going to be showing:
EXAMPLE
Drag the circles.
I think that is much better we discuss how we are going to make it before begin to code.
Distances
Imagine you have two circles A and B colliding, add a point in the center of the circles and draw a line across them. You will notice that this line is the sum of their radii. Now, push off the circles away and you will see that there is no collision but we still have that line we talked about. This means that something must be only happening while it is less or bigger than the sum.
r.a + r.b
We can call this line as the distance between the center points of the circles. To calculate distances you basically separate them in two components x and y, for each coordinate and later join them in a single formula, the Pythagorean theorem squared, which would be the true distance or resultant distance.
d.x = circleB.x - circleA.x
d.y = circleB.y - circleA.y
d.r = sqrt(d.x ^ 2 + d.y ^ 2)
Right so we can say that if the distance is less than the sum of radii, the circles are colliding, else, anything is happening.
I posted a diagram below the post, so you can see what I am talking about.
if(d.r < r.a + r.b)
Force:
The first part of the problem is solved. The second step is how to prevent a circle from entering into each other. It is evident that the distance can never be less than the sum of radii, so the force would be just the difference.
force = d.r - ( r.a + r.b )
So if d.r = 0, force = - sum of radii. Constant.
The force vary according to the coordinates of the current dragged circle because the distance is not constant, so we can make a ratio of the current distance by the total distance and multiply it by the force.
f.x = force * ( d.x / d.r )
f.y = force * ( d.y / d.r )
Finally is just sum the circle's positions according to the force x and y components.
Now it is totally done.
Further notes:
If you would like to apply the color change and the rotation of the smaller circle while colliding you can create an uint variable called col and set it to 0xff0000 (red color in hexadecimal) if the circles are intersecting and 0 (black color) if false, then during an update (an enterFrame handler for example) you just set the color in the lineStyle of the circles with col.
Also, if you would like to keep the circle inside the another circle, then is just make the opposite, if distance > difference of radii, force is distance subtracted from the difference.
Rotation:
The rotation is just the inverse tangent of the product between the force components and the force. (In degrees).
degrees = 180 / pi
1 / tan( ( f.x * force) / ( f.y * force ) ) * degrees
The function:
Now we will apply everything we talked about in a function called circleCircleIntersection. To have a collision we need at least two circles, so we will set circleA and circleB as the function parameters.
function circleCircleIntersection(circleA:*,circleB:*):void
{
var d:Object={};
d.x=circleB.x-circleA.x; // distance x
d.y=circleB.y-circleA.y; // distance y
d.r=Math.sqrt(d.x*d.x+d.y*d.y); // resultant distance
var r:Object={};
r.a=ra; // radii A
r.b=rb; // radii B
if(d.r<r.a+r.b) // if distance < sum of radii
{
r.sum=r.a+r.b; // radii sum
var f:Object={};
f.r=d.r-r.sum; // force
f.x=d.x/d.r; // force x
f.y=d.y/d.r; // force y
// moving the ball away
circleA.x+=f.x*f.r;
circleA.y+=f.y*f.r;
// the angle for rotation
var angle:Number=Math.atan2(f.x*f.r,f.y*f.r);
circleA.rotation=-angle*deg; // angle in degrees
col=0xff0000; // red color
}else{
col=0; // black color
circleA.rotation=0; // reset the rotation
}
}
Then to call the function you can add it to an ENTER_FRAME event like this:
circleCircleIntersection(circle1,circle2);
If you are having issues, you can download my file here.
I hope you have understand. Any questions just ask!