collision:
Rect to Rect


A rectangle collides with another rectangle when the edges overlap on both the x and y axes. This is usually checked by comparing each of the four sides of one rectangle with the opposite sides of the other rectangle. 

This type of collision is commonly referred to as AABB (axis aligned bounding box) and it is the most widely used collision detection in games.

 

No Collision

 

PICO-8 Collision Function

function rect_rect_collision( r1, r2 )
  return r1.x < r2.x+r2.w and
         r1.x+r1.w > r2.x and
         r1.y < r2.y+r2.h and
         r1.y+r1.h > r2.y
end
 

Comparing Coordinates

First, we need an easy way to store the sides of a rectangle. We can do that with 2 tables that store separate X, Y, width, and height variables. Those tables (named r1for the first rectangle and r2 for the second) are what the above function expects.

They could be created like this:

--create object tables
r1 = { x=10, y=20, w=10, h=10 }
r2 = { x=50, y=60, w=15, h=15 }

Now we have two rectangles at their own coordinates of X and Y, and with widths of w and a heights of  h. To get the sides of  r1, we use a combination of these variables. For example, the right side of the rectangle is found with r1.x (left side) plus the width r1.w (See Table Shorthand).

--get sides out of rectangle table
r1.x         --left side
r1.x + r1.w  --right side
r1.y         --top side
r1.y + r1.h  --bottom side

Next, we want to compare the first rectangle's left and right sides with the second rectangle's right and left sides, and the first rectangle's top and bottom sides with the second rectangle's bottom and top sides. In expanded form, this check can be written as:

--compare r1 left with r2 right
if r1.x < r2.x+r2.w then ... end

--compare r1 right with r2 left
if r1.x+r1.w > r2.x then ... end

--compare r1 top with r2 bottom
if r1.y < r2.y+r2.h then ... end

--compare r1 bottom with r2 top
if r1.y+r1.h > r2.y then ... end

We can combine all of those checks at the same time using the and operator because it is only when all four checks are true that we know the two rectangles are overlapping:

--compare all 4 sides
if  r1.x < r2.x+r2.w
and r1.x+r1.w > r2.x
and r1.y < r2.y+r2.h 
and r1.y+r1.h > r2.y then
	print( "rectangles are overlapping" )
end

Understanding an Expanded Version

Now that we have two rectangles with coordinates and dimensions, and we know how to compare all 4 sides of the rectangles, we can put it all together into an expanded function like this:

--expanded example
function rect_rect_collision( r1, r2 )
	if  r1.x < r2.x+r2.w
	and r1.x+r1.w > r2.x
	and r1.y < r2.y+r2.h 
	and r1.y+r1.h > r2.y then  
		return true
	else
		return false
	end
end

This function has parameters (r1,r2) and it is expecting those to be objects with X, Y, W, and H keys

The function has one if statement that compares the opposite sides of the two rectangles. The and operator is used to make sure that all four of those checks are true before running the code inside: return true, which will send the value true back to where this function was called.

If any one of those checks is false, then the code after else will run instead, which will return the value false.

You can call this function in two ways to catch the returned true or false result:

--catch result in variable
is_colliding = rect_rect_collision( r1, r2 )

if is_colliding then
	print( "collided!" )
end

--directly inside of if statement
if rect_rect_collision( r1, r2 ) then
	print( "collided!" )
end

Note that these examples use the same argument names and parameter names just for the convenience of this tutorial, but to make the difference clear, this is how the parameters of the function still uses (r1,r2) but the arguments when calling the function could be any object table such as:

player = { x=10, y=20, w=8, h=8 }
enemy = { x=30, y=40, w=8, h=8 }

if rect_rect_collision( player, enemy ) then
	player_health = 0
end

(See more examples below in When to Use this?)


Understanding the Simplified Version

We can simplify and condense the expanded version down to a single line:

function rect_rect_collision( r1, r2 )
  return r1.x < r2.x+r2.w and r1.x+r1.w > r2.x and r1.y < r2.y+r2.h and r1.y+r1.h > r2.y
end

(This is the same function as under the interactive demo, but we removed the new lines.)

This works the exact same way as the expanded version because all the comparisons of the each side of the rectangles will result in either true or false the same way it does in an if statement. So we don't need the if statement at all.

The expanded function boils down to "if all checks true, return true, and if any are false, return false" which is an unnecessary step to explicitly return true or false since what we want to return is the same as the final result of the four comparisons.

So we can just return the result of the comparisons immediately in a single step and it does the same thing.



Rectangle to Rectangle Collision (or AABB Collision) is the most widely used form of collision detection in game development because of its simplicity and efficiency to know when two things of any size larger than a point are overlapping.

Most games simplify any complex shapes in their game to have rectangular hit boxes in order to make collision detection easy using this method. Here are some classic game examples and where they use rectangle to rectangle collision:

Legend of Zelda; Item Collection


Megaman; Moving Platforms

Mario Bros; Enemies


Bomberman; Explosion Attacks


Street Fighter; Multiple Hitboxes




Collision detection is often where a game feels good or bad. If your invisible rectangular hitbox leaves too much empty space, particularly at the corners, around your game object, then it could sometimes not even look like two things collided when this collision method says that they are. This is a frequent cause of player frustration and complaints.


In this example, the computer will say these fish collide and that could be game over.

So it is common to make the hitbox slightly smaller than the game object. This makes sure that the player will visually see the overlapping game objects, and sometimes even allow what looks like collision to pass undetected, which makes the game feel more relaxed and tolerant, which is appreciated by the player.





37

9 Apr 2025

Font