Circle To Circle Collision Detection

Whilst it's true that XNA has functions for dealing with collision detection, the C# language in general doesn't, and since it's so very very simple you may as well make your own!

First let's get a few math bits and bobs out the way. The radius is simply the distance between the origin of a circle and the edge. The origin itself is the exact centre of a circle. It's this knowledge that allows us to precisely find if 2 circles have collided.

Despite the fact that circles seem like complex shapes, they are by far the easiest shape to deal with for collisions. It should be easy to visualise that if the distance between the origins of 2 circles is smaller than their combined radii, they are touching.

Let's say that we have 2 circles of radius 5m, and they are on a horizontal plane, 20m from each other. 20m is greater than 5m + 5m so there is no collision. But if they are 8m away, 8m is less than 5m + 5m so there is a collision.

Handling distances with an extra dimension is a little harder but it's very easy still. There is a simple formula created be a very clever man known as Pythagoras which allows us to find the distances between 2 points.

(1)
\begin{equation} sqrt( sqr(x) + sqr(y) ) \end{equation}

Where x and y are, in this case, the differences between the x and y values of the 2 circles.

So let's say we have a circle at (3,4) and a circle at (6,8). Bung that in the formula and we're good to go.

(2)
\begin{equation} sqrt( sqr(6-3) + sqr(8-4) ) = 5 \end{equation}

Fortunately, since we square the differences it does not matter if they are negative, so you can work out the difference by doing the 1st value - the 2nd or vice versa.

Now you have a very simple bit of maths to calculate the distance between the 2 points and then compare it to the combined radii. So how about some code?

int x1 = 3;
int y1 = 4;
int x2 = 6;
int y2 = 8;
int radius1 = 3;
int radius2 = 5;

//compare the distance to combined radii
if ( Math.sqrt( ( x2-x1 ) * ( x2-x1 )  + ( y2-y1 ) * ( y2-y1 ) ) < ( radius1 + radius2 ) )
{
Console.WriteLine("The 2 circles are colliding!");
}


Play around with the values and hopefully it'll all work. *Currently code is untested*

## Optimisation

There are a couple of optimisations we can make. Calculate a square root is a painfully slow trial and error process for a computer that will never find an exact value in most cases. Those more fluent in maths can probably see that we could instead square the combined radii and not square root the left hand side. This is considerably faster, more accurate and when you have hundreds of circles on screen it will make a noticeable difference.

Additionally we could make use of a couple of variables for the differences in co-ordinates instead of calculating it twice. So here's the revised code:

int x1 = 3;
int y1 = 4;
int x2 = 6;
int y2 = 8;
int radius1 = 3;
int radius2 = 5;

//compare the distance to combined radii
int dx = x2 - x1;
int dy = y2 - y1;
if ( ( dx * dx )  + ( dy * dy ) < radii * radii )
{
Console.WriteLine("The 2 circles are colliding!");
}


And a function of course :)

//Returns true if the circles are touching, or false if they are not
int circlesColliding(int x1,int y1,int radius1,int x2,int y2,int radius2)
{
//compare the distance to combined radii
int dx = x2 - x1;
int dy = y2 - y1;
if ( ( dx * dx )  + ( dy * dy ) < radii * radii )
{
return true;
}
else
{
return false;
}
}


~ knighty (Graeme Pollard - moc.liamg|33thgink#moc.liamg|33thgink)

page revision: 8, last edited: 11 Dec 2007 23:27