Welcome to what can only be described as a fully functional accident running inside PICO-8.

You move. You shoot. Things fall from the sky. You survive purely out of stubbornness and the fact that the enemies are too confused to coordinate an actual attack pattern.

This is a top down shooter where everything technically works, nothing behaves politely, and the entire game loop was held together with determination, debug prints, and questionable decisions that somehow became features.

Enemies spawn from the void, drift downward like they forgot why they exist, and occasionally change identity just to keep things emotionally unstable. You shoot them, they respawn, and the cycle continues until either you win or your hands give up.

There is a health system. There is a score system. There is also a difficulty system that increases so slowly you will question whether it is doing anything at all.

It is not balanced. It is not polished. It is barely contained chaos.

But it is yours.

Made entirely in PICO 8, this project proves that yes, you can build a playable arcade shooter with nothing but tiny sprites, simple math, and refusal to quit.

 How to play

Move with arrow keys Z to shoot Do not get touched Pretend you are in control of the situation

 Features

A player that moves like it is slightly tired Enemies that respawn instead of learning Bullets that obey physics but not logic A score system that exists purely for motivation A health system that slowly teaches consequences Difficulty scaling so subtle it might be a myth

 This code is for you to see my bad code.

function _init()

 cls(5)

 bullets = {}

 enemies = {}

 x_position = 64

 y_position = 64

 x_movement = 0 

 y_movement = 0 

 bullet_speed = 3

 score = 0

 player_health = 3

 hit_timer = 0

 flash = 0

 diff = 1

 for i=1,3 do

  add(enemies, {

   x=flr(rnd(110)+10),

   y=flr(rnd(128)),

   spr=flr(rnd(3)+4)

  })

 end

end

function wrap(v) 

 if v > 128 then return 0 end

 if v < 0 then return 128 end

 return v

end

function reset_game()

 bullets = {}

 enemies = {}

 x_position = 64

 y_position = 64

 x_movement = 0 

 y_movement = 0 

 score = 0

 player_health = 3

 hit_timer = 0

 flash = 0

 diff = 1

 for i=1,3 do

  add(enemies, {

   x=flr(rnd(110)+10),

   y=flr(rnd(128)),

   spr=flr(rnd(3)+4)

  })

 end

end

function _update()

 if hit_timer > 0 then hit_timer -= 1 end

 if flash > 0 then flash -= 1 end

 if btn(0) then x_movement = -2 end

 if btn(1) then x_movement = 2 end

 if btn(2) then y_movement = -2 end

 if btn(3) then y_movement = 2 end

 if btnp(4) then

  add(bullets, {x=x_position, y=y_position-5})

  sfx(3)

 end

 diff += 0.0001

 if x_movement != 0 and y_movement != 0 then

  x_movement *= 0.7

  y_movement *= 0.7

 end

 x_position += x_movement

 y_position += y_movement

 x_movement = 0

 y_movement = 0

 x_position = wrap(x_position)

 if y_position < 0 then y_position = 0 end

 if y_position > 120 then y_position = 120 end

 for b in all(bullets) do

  b.y -= bullet_speed

  if b.y < 0 then

   del(bullets, b)

  end

  for e in all(enemies) do

   if abs(b.x - e.x) < 8 and abs(b.y - e.y) < 8 then

    score += 1

    

    e.x = flr(rnd(110)+10)

    e.y = -5

    e.spr = flr(rnd(3)+4)

    del(bullets, b)

   end

  end

 end

 for e in all(enemies) do

  e.y += 1 * diff

  if e.y > 128 then

   e.y = 0

   e.x = flr(rnd(110)+10)

   e.spr = flr(rnd(3)+4)

  end

  if hit_timer == 0 and abs(e.x - x_position) < 8 and abs(e.y - y_position) < 8 then

   player_health -= 1

   hit_timer = 30

   flash = 7

   sfx(2)

   if player_health <= 0 then

    reset_game()

   end

  end

 end

end

function _draw()

 if flash > 0 then

  cls(6)

 else

  cls(5)

 end

 spr(1, x_position, y_position)

 for e in all(enemies) do

  spr(e.spr, e.x, e.y)

 end

 for b in all(bullets) do

  spr(3, b.x, b.y)

 end

 print("score: "..score, 2, 2, 7)

 print("lives: "..player_health, 2, 8, 8)

end

Leave a comment

Log in with itch.io to leave a comment.