## Collision Detection – Circles, Rectangles and Polygons

So you’re making a game and you want to check if your character has bonked an enemy. This calls for collision detection algorithms. Surely you could use a framework like Box2D to do all the collision detection for you.. well yes, you could and it would work pretty darn good. But if you don’t really need all the physics processing that comes with Box2D then you’re adding a lot of bloat to your game when it could be done with some nice algorithms shown in this guide.

### Circle vs Circle

So how do we detect of 2 circles are colliding? Well, lets take a look at 2 circles colliding and see what we can tell:

If you look at this image you can see the radius of circle 1 (the red line) and the radius of circle2 (the blue line) when both circle touch create a line between the centers of both circles. Any further apart and they would not be touching and any closer and they would be inside each other. This works for any angle too.

So now we know if the distance between the circles is smaller than the combined radius of both circles then the circles are colliding. So how do we work out the distance between the 2 circles? If we draw a line on the x axis from 1 circle to the other and one on the y axis we get this:

Oh look, a triangle…. and not just any triangle, a right angled triangle. Now we have a right angled triangle we can use Pythagorean theorem to work out the distance. The Pythagorean theorem states that the hypotenuse (the side opposite the right angle) is always the square root of side 1 squared + side 2 squared. For us to get the x axis length values we would take the absolute value(non negative) of circle 1’s x position – circle 2’s x position this gives us one side of the triangle. Now we do the same on the y axis using circle’s y position – circle2’s y position. The code for this is:

1 2 |
float sidea = Math.abs(circle1.x - circle2.x); float sideb = Math.abs(circle1.y - circle2.y); |

Now we square the side values

1 2 |
sidea = sidea * sidea; sideb = sideb * sideb; |

Now we get the square root

1 |
float distance = (float) Math.sqrt(sidea+sideb); |

We now have the distance between the 2 circles. The last thing is to compare it to the sum of the circle’s radii..(radiuses?!?)

1 2 3 |
if(distance < circle1.radius + circle2.radius){ //We are colliding } |

To make this more useful we can put it all in one method so all we have to do is ask is circle1 touching circle 2 and that is done with this method.

1 2 3 4 5 6 7 8 9 10 11 |
public boolean isCirclesColliding(Circle cir1, Circle cir2){ float sidea = Math.abs(cir1.x - cir2.x); float sideb = Math.abs(cir1.y - cir2.y); sidea = sidea * sidea; sideb = sideb * sideb; float distance = (float) Math.sqrt(sidea+sideb); if(distance < circle1.radius + circle2.radius){ return true; } return false; } |

### Rectangle vs Rectangle

A rectangle in computing usually refers to a shape with 4 corners and 2 parallel sides and is a common shape for use in collision detection due to its simplicity to make and detect collisions with. Rectangles are often used to define a collision boxes for entities that don’t require precise detection. So how do we check if 2 rectangles are colliding? we check to see if 2 of the sides fall in between the other rectangle. Lets take a look at two rectangles about to collide:

Here you can see 2 rectangles that have not collided yet. You can see by the dotted lines that neither the bottom nor right edge fall inside the other rectangle. This says the rectangle is not colliding.

Now you can see that one side of each rectangle is inside the other and this means.. well, it means nothing they still haven’t collided only one side of each is inside and for a collision 2 sides must be inside the other rectangle.

A collision has happened and both sides of each rectangle are inside the other rectangle. O.k. so now we know how to check if a rectangle is in a rectangle but how do we do this in code?

First, we must find out where the sides of the rectangle are and we do that using the width, height and position of the rectangle. In our example we will be using the position as the bottom left corner but you could use the center of the rectangle with a little extra math. So first we need to get the position of all sides:

1 2 3 4 |
int topEdge1 = rectangle1.position.y + rectangle1.height; int rightEdge1 = rectangle1.position.x + rectangle1.width; int leftEdge1 = rectangle1.position.x; int bottomEdge1 = rectangles.position.y; |

We do the same for rectangle 2 and then we compare using the following code:

1 2 3 4 5 6 |
if( leftEdge1 < rightEdge2 && rightEdge1 > leftEdge2){ // An edge of rectangle 1 is inside rectangle 2 } if( bottomEdge1 < topEdge2 && topEdge1 > bottomEdge2 ){ // Either the top or bottom is inside rectangle 2 } |

Now we can tell when 2 sides are inside another rectangle we just need to combine them in a single function we can call whenever we need to:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public boolean isRectanglesColliding(Rectangle rec1, Rectangle rec2){ int topEdge1 = rec1.position.y + rec1.height; int rightEdge1 = rec1.position.x + rec1.width; int leftEdge1 = rec1.position.x; int bottomEdge1 = rec1.position.y; int topEdge2 = rec2.position.y + rec2.height; int rightEdge2 = rec2.position.x + rec2.width; int leftEdge2 = rec2.position.x; int bottomEdge2 = rec2.position.y; if( leftEdge1 < rightEdge2 && rightEdge1 > leftEdge2 && bottomEdge1 < topEdge2 && topEdge1 > bottomEdge2){ return true; } return false; } |

### Simple Polygon vs Polygon (convex)

So we covered circles and rectangles but how about polygons. Polygons don’t have a set radius or a set width and height so we can’t use the previous methods. Let’s take a look at some polygons that are colliding and see what we can tell about polygon collisions.

From this image you can see that if a convex polygon is colliding then at least 1 of the corners(vertices) is inside the other polygon. So if we check to see if a corner point is inside the other polygon we know they are colliding There are some edge cases where the points do not fall within the other polygon however this is not covered in this guide as it is only an introduction to collision detection. So how do we check if a point is inside a polygon? We simply draw a line from the point to somewhere external to the polygon.

In the image above you can see we have drawn 3 dashed lines. 2 of the lines start inside the concave polygon and those have cross the polygon border an odd amount of times whereas the line that starts outside the polygon crosses the border an even number of times. By checking if a line we draw from the point crosses the polygon border an odd amount of times we will be able to tell if a point is inside a convex or concave polygon. Note: We will only checking for convex polygons with our code however, I just wanted to show that this line method works for both types when checking points.

#### Breaking up the polygon

In order to start drawing imaginary lines through our polygon, we need to first break the polygon up into segments. Each segment will be a pair of corners which will be one border of the polygon like the green line in the image below:

We first need to iterate through all the vertices. In this tutorial our polygon vertices are stored as an array of floats. In the image above the red arrow shows the order the vertices are stored. So our array of vertices for this pentagon shape would be {1,0,0,3,3,6,6,3,5,0} which equates to {x1,y1,x2,y2,x3,y3,x4,y4,x5,y5}. So to loop over these values we will use this for loop:

1 2 3 4 |
final int numFloats = vertices.length; // 2 for every corner = 10 for pentagon for (int i = 0; i < numFloats; i += 2) { //i += 2 as there are 2 values per corner // do some coding here } |

Now we have a loop we can work out the formulas.

From the image above you can see that our first vertex is x1 and y1 and then the next vertex is x2 and y2. This is due to the order the vertexes are inside the float array. Now we have the vertex values we need to get the gradient ( the slant of the line between the two vertex points ). With the gradient we can find out the length of d by multiplying the gradient by the distance down the line to the point. This gives us the x position of Px.

Now we have the x position of Px we can see if the point we are checking is directly left of this border line. If Px is left of this line then we can say we have found 1 of the points where our imaginary line crosses a border and can increment an intersect counter.

So how do we put all this into a function?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public boolean contains (float x, float y) { final float[] vertices = getTransformedVertices(); // get the vertices final int numFloats = vertices.length; // get the amount of vertices int intersects = 0; // counter for times line crosses for (int i = 0; i < numFloats; i += 2) { float x1 = vertices[i]; // set first vertex.x float y1 = vertices[i + 1]; // set first vertex.y float x2 = vertices[(i + 2) % numFloats]; // set second vertex.x float y2 = vertices[(i + 3) % numFloats]; // set second vertex.y // (point is between y1 and y2) && (point) < (( gradient) * (distance) + vertex.x) if (((y1 <= y && y < y2) || (y2 <= y && y < y1)) && x < ((x2 - x1) / (y2 - y1) * (y - y1) + x1)) intersects++; } return (intersects & 1) == 1; } |

We have a function to check if a point is in a polygon and it can be used for every vertex in a polygon to allow us to check if a polygon is in a polygon. So if all 5 points of a pentagon are not inside a polygon then we know the polygons are not colliding and if at least one point is inside then we know the polygon is colliding. The code for that is:

1 2 3 4 5 6 7 8 9 |
final int numFloats = vertices.length; boolean isColliding = false; for (int i = 0; i < numFloats; i += 2) { float x = vertices[i]; float y = vertices[i + 1]; if(polygon.contains(x,y)){ isColliding = true; } } |

#### Why can’t we use this method to check concave polygons?

Concave polygons can have parts that extrude out and allow vertices to completely go through another polygon and this stops our function from returning true as we’re only checking if points are inside a polygon. If you need to check convex polygons I recommend using the separating axis theorem method.

### Shape A vs shape B

Checking for one shape versus another is a little more complex than what we’ve been doing before. First you need to be able to know what shapes are colliding then use an appropriate algorithm. This however is outside the scope of this tutorial and we will only be going over how to check for collisions between set shapes. We will go over Circle vs Polygon, Circle vs Rectangle and Rectangle vs Polygon.

### Rectangle vs Polygon

We have already covered how to check if a polygon is inside another polygon and we broke it into parts and checking each corner of the polygon as a point. A Rectangle is just a polygon with 4 corners. We can reuse the code we made for the polygon vs polygon code. We just need to get the rectangle corners from the height, width and position of the rectangle. An that is done with this code:

1 2 3 4 5 6 7 8 9 |
x1 = square.x y1 = square.y x2 = square.x+height; y2 = square.y+height; x3 = square.x+height+width; y3 = square.y+height+width; x4 = square.x+width; y4 = square.y+width; float[] verts = {x1,y1,x2,y2,x3,y3,x4,y4}; |

Now you can iterate over them like you did with the polygon’s vertices.

### Circle vs Polygon

This is where things get complicated. An explanation as simply as possible is…. you take a single border of a polygon, get its width and height and turn it into a vector (value stating direction). Next, you get a vector to represent a line to the centre of the circle. Normalize this value and find the dot product between this line and the first line. This will give us 0 or less when the circle is closest to the start of the line , line length or more when closest to the end of the line and a value between 0 and line length when closest to a middle part of our polygon border line. Now we get the x and y position closest to the circle centre, square them and compare vs the square of the circle radius. If the radius squared is less than the squared x y position of the closest point it is colliding.

That’s quite a lot to take in so we’ll break it down into smaller portions. The first thing we are doing is finding the vector of the line between the two points of the polygon. Shown in the image below:

In the image, the solid green line is the vector we are checking. We get the width of the line by removing the x value for the first point from the x value of the second point( the top point is first due to the ordering of the vertices in the float array for the polygon) This gives us negative 1. Next we get the y value be removing the y value of the start point from the end point. This gives us negative 2, so our border line is now represented as a vector of (-1,-2).

Now we need to get the vector for the circles center from the start point. This is done by removing the circle x from the start x and the circle y from the start y. In the image you can see the dotted red line which represents our new vector and and equates to (0,-1). Now we have 2 vectors which we will use to get the length and the dot product. The length we will store for later and can be worked out manually by getting the square root of w*w + h*h. The dot product is a measurement of the similarity of 2 vectors. If 2 vectors are pointing in the same direction the dot product will be 1, if the two vectors are opposite then the dot product will be -1 and a right angle would be 0. This is true in maths however in programming the dot product will not range from -1 to +1 instead it will range from -line length to +line length but 0 will always represent a 90 degree angle.

First we get the length of the line in the image above:

1 |
float l = borderVector.len(); // this is about 2.23 |

Now the dot product:

1 2 3 4 5 |
// this work out to be (-0.44,-0.89,0) float borderVectorNormal = borderVector.nor(); // this works out to be 0.8944273 float dotProduct = circleVector.dot(borderVectorNormal); |

If we look at the image above we can see that if the dot product is below 0 the circle center would be in the top right quarter. If the dot product is bigger than the line length then the circle would be in the lower left quarter. Now we have the dot product and it is less than the line length of 2.2 but more than 0. Now we know the center of the circle is in the lower right quarter and is closest to a point on our polygon border.

Now we need to find out which point that is. We already have all the variables we need from the previous calculations; the dot product and the normalized borderVector. To get this point we just need to scale the borderVectorNormal by the dot product and add those to the start.x and start.y

1 2 3 4 |
// scale the normal by the dot product to get position on the polygon border pointOnLine.set(borderVectorNormal.scl(dotProduct)); // add to our start vector outputVector.set(pointOnLine.x + start.x, pointOnLine.y + start.y, 0); |

The output vector now contains the x and y position on the polygon border that our circle center is closest to.

The final calculation checks if the circle is close enough to be considered colliding using the euclidean distance:

1 2 3 |
float x = center.x - outputVector.x; float y = center.y - outputVector.y; return x * x + y * y <= squareRadius; |

As you can see from the formula and image above we use the x and y value to create a triangle and then work out the hypotenuse length. Then we check if the hypotenuse is smaller than the radius to check if the circle is colliding.

So now we can check if a circle is colliding with a single border line from our polygon but only when the circle is closest to the border line. we haven’t done any checks for when the circle is closest to the start or end point of our line. This function below does contain those cases and can be used to check if a circle intersects a polygon border line:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public static boolean intersectSegmentCircle (Vector2 start, Vector2 end, Vector2 center, float squareRadius) { tmp.set(end.x - start.x, end.y - start.y, 0); // holds polygon line vector tmp1.set(center.x - start.x, center.y - start.y, 0); // holds start to circle center vector float l = tmp.len(); // the euclidean length of line :(w * w + h * h) squared float u = tmp1.dot(tmp.nor()); // the dot product for these 2 vectors if (u <= 0) { // circle center is closest to start tmp2.set(start.x, start.y, 0); // set point to start point } else if (u >= l) { // circle is closest to end tmp2.set(end.x, end.y, 0); // set point to end point } else { // circle is in between tmp3.set(tmp.scl(u)); // scale the normal by the dot product to get position on border tmp2.set(tmp3.x + start.x, tmp3.y + start.y, 0);// set point to position on line closest to circle center } // check if circle radius is longer than the line from our position on line to circle center (true for collisions) float x = center.x - tmp2.x; float y = center.y - tmp2.y; return x * x + y * y <= squareRadius; } |

We now need to check each line in our polygon to check collisions for all sides. We can reuse our loop we used for checking polygon vs polygon collisions. So our finished code looks like this:

1 2 3 4 5 6 7 8 9 10 11 |
public boolean contains (Polygon poly, Circle circ) { final float[] vertices = poly.getTransformedVertices(); // get the vertices final int numFloats = poly.vertices.length; // get the amount of vertices for (int i = 0; i < numFloats; i += 2) { Vector2 start = new Vector2(poly.vertices[i],poly.vertices[i + 1]); Vector2 end = new Vector2(poly.vertices[(i + 2) % numFloats], poly.vertices[(i + 3) % numFloats]); Vector2 center = new Vector(circ.x, circ.y); float squareRadius = circ.radius * circ.radius; return intersectSegmentCircle (start, end, center, squareRadius); } |

### Circle vs Rectangle

Checking a rectangle against a circle is the same as checking a polygon against a circle we just need to convert the corners to vertices like we did for the Rectangle vs polygon answer.

1 2 3 4 5 6 7 8 9 |
x1 = square.x y1 = square.y x2 = square.x+height; y2 = square.y+height; x3 = square.x+height+width; y3 = square.y+height+width; x4 = square.x+width; y4 = square.y+width; float[] verts = {x1,y1,x2,y2,x3,y3,x4,y4}; |

This however is quite expensive and another method is available if the rectangles are never rotated and always align with the x and y axis shown in the next section.

### Circle vs Rectangle (Axis Aligned)

To check if an axis aligned rectangle is colliding with circle you can inflate the rectangle with the radius of the circle and then check if the circle center lies within this area.

In the image above you can see 3 circles all colliding with a rectangle from the sides and on the corner. All of them have their center within our inflated rectangle. So how do we create this in code?

The first thing we need to do is get the distance the circle is from the rectangle for each axis.

1 2 |
distance.x = abs(circ.x - rect.x); // circle is x away from rectangle center on horizontal axis distance.y = abs(circ.y - rect.y); // circle is y away from rectangle center on verticle axis |

If you look at the image above you can see that the rectangle width(RW) plus the circle radius(CR) gives us our outer bounds for the circle collision anything that is bigger than this is not going to be colliding and can be excluded from any further calculations. (All of our circles pass this test)

1 2 |
if (distance.x > (rect.width/2 + circ.r)) { return false; } // too far on x axis if (distance.y > (rect.height/2 + circ.r)) { return false; } // too far on y axis |

Now we check if the circle center is inside rectangle or the red areas of the image above using the following code:

1 2 |
if (distance.x <= (rect.width/2)) { return true; } if (distance.y <= (rect.height/2)) { return true; } |

The red and purple circle have been detected by this and are considered to be colliding, the blue isn’t inside these and will be caught by the next check.

Now we have to check the corners to check if the circle centers lie with in them. In order to do that we have to get the euclidean distance from the center of the circle to the center of the rectangle.

1 |
cDist_sq = (distance.x - rect.width/2)^2 + (distance.y - rect.height/2)^2; |

finally we check if the radius squared is smaller or equal to the euclidean distance. This captures our final circle and concludes all the phases of checking collisions.

1 2 3 4 |
if((cDist_sq <= (circ.r^2)){ //collision detected return true; } |

So our final code for checking collisions between Circles and axis aligned rectangles is:

1 2 3 4 5 6 7 8 9 10 11 12 |
bool intersects(Circle circ, Rectangle rect) { distance.x = abs(circ.x - rect.x); distance.y = abs(circ.y - rect.y); if (distance.x > (rect.width/2 + circ.r)) { return false; } if (distance.y > (rect.height/2 + circ.r)) { return false; } if (distance.x <= (rect.width/2)) { return true; } if (distance.y <= (rect.height/2)) { return true; } cDist_sq = (distance.x - rect.width/2)^2 + (distance.y - rect.height/2)^2; return (cDist_sq <= (circ.r^2)); } |

### Notes.. and why I use Libgdx.

I prefer to use a framework such as Libgdx to create my games and thought it would be good to show you how all these collision detections would be done when using the Libdx framework. Nearly all of the collision detection methods shown above can be done in libgdx using the Intersector class.

**Circle vs circle**

1 |
Intersector.overlaps(circle1,circl2); |

#### Rectangle vs Rectangle

1 |
Intersector.overlaps(rectangle1,rectangle2); |

#### Polygon vs Polygon

1 |
Intersector.overlaps(polygon1,polygon2); |

#### Rectangle vs polygon

1 2 3 4 5 |
Polygon poly = new Polygon(new float[] { 0, 0, rect.width, 0, rect.width,rect.height, 0, rect.height }); poly.setPosition(rect.x, rect.y); if (Intersector.overlapConvexPolygons(poly, p)){ // collision } |

#### Circle vs polygon

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public boolean contains (Polygon poly, Circle circ) { final float[] vertices = poly.getTransformedVertices(); // get all points for this polygon (x and y) final int numFloats = vertices.length; // get the amount of points(x and y) // loop through each point's x and y values for (int i = 0; i < numFloats; i += 2) { // get the first and second point(x and y of first vertice) Vector2 start = new Vector2(vertices[i],vertices[i + 1]); // get 3rd and 4th point (x and y of second vertice) (uses modulo so last point can use first point as end) Vector2 end = new Vector2(vertices[(i + 2) % numFloats], vertices[(i + 3) % numFloats]); // get the center of the circle Vector2 center = new Vector2(circ.x, circ.y); // get the square radius float squareRadius = circ.radius * circ.radius; // use square radius to check if the given line segment intersects the given circle. return Intersector.intersectSegmentCircle (start, end, center, squareRadius); } } |

#### Circle vs rectangle

1 |
Intersector.overlaps(circle,rectangle); |

As you can see the amount of coding needed is considerably less when using Libgdx.

In the Circle vs Circle collision shouldn’t the code be

if(circle1.radius + circle2.radius > distance){

return true;

}

If circle1.radius + circle2.radius is less than distance the collision would always return true until there actually was one.

You are correct, I have now fixed this in the post. Thanks for pointing this out.

No worries great tutorial!

I don’t think it’s apparent that the Circle — Rectangle method will give correct results, namely the corners. Could you provide some additional information?

so for the x and y values for the circle and rectangle, is it the top-left corner or middle?