In Part 3, we made an enemy chase the player. Which was nice, but nothing actually happened when the player was caught. Why not? Because we had no code to check for collisions! Let’s fix that.
Part 4: Collision check
What is a collision? Well, for the purposes of our game – and most games – it’s when two objects overlap. In our case, it’ll be our player sprite and our enemy sprite. That’s pretty simple to understand, but how do we code it?
Let’s look at the definition in plain English. Both sprites are 8 pixels wide, and we need to check if any part of each sprite is “inside” the area of the other. Things will be different for different sized sprites, but let’s keep it simple for now.
The player sprite’s four corners are:
And the enemy sprite coordinates are:
So when they overlap, all of the following must be true (follow along with two squares of paper if that helps!):
- The right edge of the enemy must be to the right of the left edge of the player (ex+8 > x), AND
- The left edge of the enemy must be to the left of the right edge of the player (ex < x+8), AND
- The bottom edge of the enemy must be below the top edge of the player (ey+8 < y), AND
- The top edge of the enemy must be above the bottom edge of the player (ey > y+8)
In PICO-8, that translates to:
if ex+8>x and ex<x+8 and ey+8>y and ey<y+8 then -- overlap else -- not overlap end
Let’s plan ahead a little, and assume we’re going to reuse the collision code for other things later on. After all, we might add more enemies, right? Let’s create a function to check collisions between two objects, using this code as the base. The function will return true if there’s a collision, and false if not:
function checkcol(ax,ay,bx,by) if bx+8>ax and bx<ax+8 and by+8>ay and by<ay+8 then return true else return false end end
Now we can send the coordinates of any two objects to that function and get a true or false in return. We’ll put a call to it in the _update() function (before we move anything), and stop the game if there’s a collision. Later, we can lose a life or something instead, but for now we’ll just stop().
-- check for collision if checkcol(x,y,ex,ey) then stop() end
Remember that “if checkcol(x,y,ex,ey) then” implies “if checkcol(x,y,ex,ey) == true”.
Here’s a catchup of all the code so far:
function _init() -- player start location x = 64 y = 64 -- enemy start location ex = 120 ey = 120 -- enemy "speed" d = 0.05 end function _update() -- check for collision if checkcol(x,y,ex,ey) then stop() end --[[ check button presses and screen edge btn(0) is left btn(1) is right btn(2) is up btn(3) is down ]] if btn(0) and x > 0 then x -= 1 end if btn(1) and x < 120 then x += 1 end if btn(2) and y > 0 then y -= 1 end if btn(3) and y < 120 then y += 1 end -- move enemy if x < ex then ex -= d end if x > ex then ex += d end if y < ey then ey -= d end if y > ey then ey += d end end function _draw() cls(2) -- clear the screen to mauve spr(1,x,y) -- draw sprite 1 at x, y spr(2,ex,ey) -- draw sprite 2 (enemy) at ex, ey end function checkcol(ax,ay,bx,by) if bx+8>ax and bx<ax+8 and by+8>ay and by<ay+8 then return true else return false end end
Pingback: How to make a PICO-8 game: Part 5 - deKay's Blog