In the previous tutorial, we made our player move around the screen. Next on our list is the ability to place totems (our towers) - a core gameplay element in a tower defense game!

Unlike the player, totems don’t exist at the start of the game. Also, there can be many totems on the screen at the same time! So for this to work, we’ll need to introduce two new concepts:

  1. Creating objects at runtime - while the game is in progress
  2. Updating and drawing multiple things at the same time

Creating the sprite

First things first, let’s draw the totem sprite. I created two frames, because I think having the towers move will make the game feel more alive.

Totem sprites

Draw the totem’s sprites on a new row of the spritesheet

Making totems

Before going further, let’s create a new editor tab for totems which will help us organise our code better. Click the + sign next to the editor tabs at the top of the screen. We’ll use this for all code related to totems.

First, let’s make a function make_totem. This will be similar to make_player except it will be used for… totems!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-- totems

function make_totem()
	return make({
		sprx=0,
		spry=12,
		sprw=10,
		sprh=10,
		anim={0,10},
		animspd=0.05,
		x=20,
		y=20,
		})
end

This should go at the top of our new editor tab. Note the comment at the top (-- totem) - if you hover over the top, this is the message that will be displayed as a tooltip. Handy if you can’t remember what you’ve used each tab for!

Remember to adjust sprx and spry for the coordinates you’ve used on the spritesheet.

Let’s also call this function from start_game, just to test that it’s working.

1
2
3
4
function start_game()
	init_globals()
	totem=make_totem()
end

And in _draw underneath where we draw the player sprite, so that we can see it. Note that we can reuse drawspr here!

1
2
3
-- in the _draw function
drawspr(p)
drawspr(totem)

Run the program. If it worked correctly, the totem sprite should appear in the top-left of the screen. However, this is still only drawing a single totem and we’re going to want many of them, so let’s fix that.

Drawing multiple sprites

In order to have multiple totems, we can’t have one variable for each totem because that would quickly get out of control. Instead, we can use the ever-versatile tables to store a list of all of the totems in the game. To start with, create an empty totems table inside init_globals.

1
2
3
4
5
6
function init_globals()
	_debug=""
	t=0
	p=make_player()
	totems={}
end

Replace the totem=make_totem() line from earlier with add(totems, make_totem()). This adds a new totem to our totems table.

Now, in order to draw it, we could use a simple loop like:

1
2
3
for totem in all(totems)
  drawspr(totem)
end

But there’s a neat trick to replace this when we want to call a function on each element in a table. We can replace drawspr(totem) with:

1
foreach(totems, drawspr)

Now the code should work as before. But notice the totem isn’t moving, because we haven’t used our animate() function on it yet. We can do that using the same technique - at the end of the _update function, just add:

1
foreach(totems, animate)

Run the program and you should see the totem moving.

Player summoning totems

Currently we’re using the default position of (20,20) to create the totem, but we want it to spawn at the player’s position. So create a new function called spawn_totem for this purpose:

1
2
3
4
5
6
function spawn_totem()
	local totem=make_totem()
	totem.x=p.x+2
	totem.y=p.y+2
	add(totems, totem)	
end

The +2 is just to center the totem at the player’s position. I found this through trial and error - sometimes it’s easier to just tweak things until they seem right.

Now we have all the pieces for totem-summoning, we just need to make it happen when the player presses a button. We can do this in the _update function using the if btnp(4) function. This checks if a button has been pressed and released. Note that we don’t use btn() here, because that would keep creating totems for as long as the button is held down!

1
2
3
4
5
-- in _update
	if btnp(4) then
		spawn_totem()
	end
	foreach(totems, animate)

Run the game, and hitting the z key (or the gamepad button for Pico-8’s O button) will spawn a new totem at the player’s position, each time it’s pressed!

Wrapping up

In this part of the tutorial we’ve discovered how to spawn new objects during the game’s runtime, and call the same function on multiple things at once. This is very useful for making a game dynamic and interesting. We’ll be able to use a similar technique for creating waves of enemies later on, in part 6 of this tutorial.