PICO-8: How do I shoot? Dynamic objects and tables

Shooting in Pico-8

PICO-8 is a small and sweet game engine aka fantasy console. This article explains how to add and remove objects like bullets to a game at playtime in PICO-8.

One question that I always get asked is: how do I add and remove multiple objects to a game dynamically. Stuff like projectiles, bullets or particles. No problem: I will show how to create objects on-the-fly in PICO-8.

BulletOne, BulletTwo, BulletThree, BulletFour

Probably the first idea is to make a new table for each object and saving it on a variable. We can just define a bunch of bullets and then set them when we press shoot.

local bulletOne = {
	x = 32, y = 32, 
	active = false, 
	draw = function(self)
		circfill(self.x, self.y, 7, 8)
	end
}

In our _draw callback we execute the draw() function of bulletOne: bulletOne:draw(). Making tables might be ok but having one variable for one object is very limiting. Is there a better way?

There must be a better way

Arrays can save you a lot of writing and duplicate code. Instead of using individual variables we can use a holding object.

bullets = {}
add(bullets, {
	x = 32, y = 32, 
	active = false, 
	draw = function(self)
		circfill(self.x, self.y, 7, 8)
	end
})

This way we can add as many objects to the bullets table as we like. And without creating a new variable every time.

Use PICO-8 iterators

How do we call the draw function for all the bullets in our _draw callback function? We use PICO-8 all() iterator function:

function _draw()
    for bullet in all(bullets) do
        bullet:draw()
    end
end

 

Additional: Global vs Local Variables

Global means that it can be accessed anywhere in your program. But there is also a table for the local scope. Local means that it is only accessible in the current part of your program. You can assign a variable to the local scope using the local keyword.