Practical 2D collision detection – Part 1

Collision detection is a fascinating, yet almost entirely overlooked and oversimplified aspect of game making.

In my experience making games, I have found that collision detection, and subsequent collision resolving is quite tricky to get right. I would like to share a few practical pointers I find useful, so you can get started with your own collision framework.

For these articles, we will be working on 2D collisions, that is collisions that can be represented with 2D shapes in a 2D environment. Don’t let the 2D fool you though; a lot of 3D games can be created with a 2D collision environment, as long as collisions can be thought of in only two dimensions.

For example, side scrollers can benefit from XY-only collisions. While top-down games like racing, strategy or even some simulation games can use XZ-only collisions.

When we talk about collisions, there are two elements to consider. collision detection and collision resolution.

Collision detection consists of deciding whether or not two objects are colliding. Collision resolution consists of reorganizing colliding objects so they are not colliding anymore.

Even though detection and resolution are closely related, the algorithms and results for both detection and resolution are wildly different. It is in fact very common to use detection but not resolution for things such as triggers (for example, detecting when a player enters a room).

In this article, I will focus on collision detection. We will consider resolution in a future article.

Collision detection is a geometric problem: Given two shapes, decide whether they overlap or not. The complexity of the solution depends on what kind of shapes we are talking about.

So let’s start with the simplest shapes: two circles.

A large white circle, and a small yellow circle, just hangin’ out.

Each circle can be represented as three numbers: the center coordinates for X and Y, and a radius:

public class CollisionCircle
{
    public float X { get; set; }
    public float Y { get; set; }
    public float R { get; set; }
    public CollisionCircle(float x, float y, float r)
    {
        X = x;
        Y = y;
        R = r;
    }
}

Two circles collide when the distance between the two centers is less than or equal than the sum of their radii. We can do this with Pythagoras:

public class CollisionCircle
{
    public float X { get; set; }
    public float Y { get; set; }
    public float R { get; set; }

    public CollisionCircle(float x, float y, float r)
    {
        X = x;
        Y = y;
        R = r;
    }

    public static bool IsCollision(CollisionCircle a, CollisionCircle b)
    {
        float deltaX = a.X - b.X;
        float deltaY = a.Y - b.Y;
        float distance = (float)Math.Sqrt(deltaX * deltaX - deltaY * deltaY);
        float sumOfRadii = a.R + b.R;
        if (distance <= sumOfRadii)
            return true;
        return false;
    }
}

I don’t want to talk much about optimization, but in here, we can save ourselves the costly square root at line 18, by simply comparing the squared distance with the square of the sums of the radii. The result would look like this:

public class CollisionCircle
{
    public float X { get; set; }
    public float Y { get; set; }
    public float R { get; set; }

    public CollisionCircle(float x, float y, float r)
    {
        X = x;
        Y = y;
        R = r;
    }

    public static bool IsCollision(CollisionCircle a, CollisionCircle b)
    {
        float deltaX = a.X - b.X;
        float deltaY = a.Y - b.Y;
        float distanceSquared = deltaX * deltaX - deltaY * deltaY;
        float sumOfRadii = a.R + b.R;
        if (distanceSquared <= sumOfRadii * sumOfRadii)
            return true;
        return false;
    }
}

So far, so good. On the next article, we’ll figure out how to do collision detection with other kinds of shapes.

Credits

I worked for Sega from 2010 to 2015. Most of the games I worked on at first were mobile games with no credits screen, or a credits screen hidden under some menu that nobody ever watched.

Starting in late 2013, I started working on console games, which do have credits at the ending, and they actually list me!😜

It’s really awesome to see your own name on a game that you worked on. So just for bragging, I’ll post screenshots of places where my name appears in this page Project Diva F 2nd (2014): Development Support. Watch at 4:54

Also in the English version, watch at 0:56

(video is no longer available)

Phantasy Star Nova (2014): Programming. Watch at 11:23

7th Dragon III: code VFD (2015): Programming Team: Graphics. Watch at 4:42. Also in the end credits, but I still can’t find a video of that.