Collision Detection Methods

Posted on 5 March 2010 by mike

I've had a few queries about collision detection recently so I decided to share some code I've used to detect collisions between two circles as well as rectangles vs circles.

I will be doing a tutorial on this as soon as possible, but for the moment this code could be useful.

In SLQ I am using AABB (Axis Aligned Bounding Boxes) for the collision checks. Each entity is responsible for providing its collision bounds as a CGRect. Its then a simple process of checking each entities CGRect against another using the CGRectIntersectsRect method.

Whilst this is fine for rectangles, what about if you want to use a circle as bounds for your entity. You may either have a circular shape you want bounds for, or you want to rotate your entity and not have to worry about rotating the bounding box in which case circles are useful.

There are no methods available within Cocoa Touch to check if a circle has intersected with a rectangle or if a circle has intersected with another circle. For this you need to create your own methods and the methods I use for these checks are shown below.

This first method can take a CGRect structure and a Circle structure, listed later in this post and check if they intersect. If they do then YES is returned.


static inline BOOL RectIntersectsCircle(CGRect aRect, Circle aCircle) {

float testX = aCircle.x;
float testY = aCircle.y;

if (testX < aRect.origin.x)
testX = aRect.origin.x;
if (testX > (aRect.origin.x + aRect.size.width))
testX = (aRect.origin.x + aRect.size.width);
if (testY < aRect.origin.y)
testY = aRect.origin.y;
if (testY > (aRect.origin.y + aRect.size.height))
testY = (aRect.origin.y + aRect.size.height);

return ((aCircle.x - testX) * (aCircle.x - testX) + (aCircle.y - testY) * (aCircle.y - testY)) < aCircle.radius * aCircle.radius;
}

The next method can be used to check if two circles are intersecting and again respond with YES if they are.

static inline BOOL CircleIntersectsCircle(Circle aCircle1, Circle aCircle2) {
float dx = aCircle2.x - aCircle1.x;
float dy = aCircle2.y - aCircle1.y;
float radii = aCircle1.radius + aCircle2.radius;

return ((dx * dx) + (dy * dy)) < radii * radii;
}

Both of these are designed to be quick and so don't use the expensive sqrtf function. The structure I'm using to define a circle is shown below.

typedef struct {
float x;
float y;
float radius;
} Circle;

Once I've finished with the book, I'll do a proper tutorial on this stuff and show how it can be used. I'm also planning on introducing a physics engine, something like Box2D or Chipmunk to show how they can be used in general and how their more advanced collision detection can also be used.

Hope you find this useful.

Mike

blog comments powered by Disqus