How to make a PICO-8 game: Part 4

How to make a PICO-8 game: Part 4

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

 

0 Comments

  1. Pingback: How to make a PICO-8 game: Part 5 - deKay's Blog

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.