How to make a PICO-8 game: Part 5

Score!

Now that things can collide and the player can effectively die (see last time), the next job is to score some points. Doing this is surprisingly easy, and so this lesson is going to be very short.

Part 5: Score!

For the purposes of this game, simply staying alive is how you score points. Maybe we’ll add bonus points or something later, but for now, the player will get one point for every frame they stay alive.

We need to do three things: set an initial score, update that score, and draw the score on the screen. Hopefully you can see where this is going.

In _init(), we’ll initialise the score to zero:

Then, in _update(), we’ll increment it (so it goes up by one point each time _update() is called. We’ll do that at the end of _update() in case we die that frame:

And finally, we’ll draw this on the screen in – you guessed it – _draw(). We need to draw it after we clear the screen with cls (or we won’t see it), but it’s an artistic choice as to whether our sprites are “on top” of the score, or the score is “on top” of the sprites.

Of course, we could have a status area on the screen for this (where the gameplay area won’t encroach), but for now we’re keeping it simple. Let’s print it at 100,0 so it’s in the top right but has space to allow for multiple digits in case we’re that good, and in colour 7 (white):

And that’s literally all there is to it.

I said it was going to be short! Let’s catch up with the code so far:

 

How to make a PICO-8 game: Part 4

Crash! But not that sort of crash.

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:

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:

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().

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:

 

How to make a PICO-8 game: Part 3

Chase me.

Last time, we got a square moving round the screen and accounted for bumping into the walls. This time, we’ll give old Squarey a reason to move around – something to chase him. Or her.

Part 3: Chase me

Right back at the start, we created an extra sprite to use as an enemy – Sprite 2. We’ll make use of that now.

Firstly, we need an initial position for our enemy. As we’re using x and y for the player, let’s use ex and ey for the enemy, and start it in the bottom right of the screen. 120, 120 perhaps. We’re also going to assign a speed to it – how far it moves each frame – and call it d (for distance, in pixels). We put these assignments in our _init() function:

We also need to display this enemy on the screen, so in the _draw() function, remembering the enemy sprite is in slot 2, we can use:

All this does so far, though, is show a square in the bottom right. We still need to make it move, and to do that we need to check where it is in relation to the player. In English, we want this:

“If the player is to the left of the enemy, move the enemy left”

“If the player is to the right of the enemy, move the enemy right”

That is, if x is less than ex then the player is to the left, and if x is greater than ex then the player is to the right. We can do the same for up and down with y and ey.

So how do we make it move left? Decrement ex. Right? Increment ex. Up? Decrement ey. Down? Increment ey. And how much do we increment or decrement by? Our variable d. Easy! Let’s do the if checks in _update(), after we’ve moved the player:

Now run the code, and watch how the enemy chases the player. Very, very slowly. Have a play with the value of d in the _init() function to see how this changes the speed of the enemy – try 0.1 or 1 instead of 0.05, for example.

Chase me!

Obviously, the game is very easy at this point, and not least because nothing happens if the enemy catches you. Why not? Because we’ve not coded any collisions yet! That’s what we’ll do next time. For now, here’s all the code so far, with some additional annotations so we’ll remember what everything does:

How to make a PICO-8 game: Part 2

I like to move it.

In the last chapter, I showed you the very basic task of putting a sprite on the screen. That’s all very well, but a bit less interactive than most games are. In this chapter, let’s make it move.

Part 2: Move the player

The first task here is to make PICO-8 check to see if the player is pressing any of the direction keys. You can do this by making use of the btn() function.

The arrow keys (or joypad d-pad, depending how you’re playing the game) are referred to by the numbers 0 to 3. The left key is 0, right is 1, up is 2 and down is 3. If you check to see, for example, if btn(0) is true, then you’re checking to see if the player is pressing left.

You’ll recall that the coordinates of the player sprite on the screen are stored in the variables x and y. To physically make the sprite move left, you need to make the value of x smaller, and to move it right you have to make it larger – remember that the left of the screen is 0, the right is 127. Let’s make it move by one pixel at a time for simplicity’s sake. Ignoring up and down for the moment, this code in the _update() function will do that:

In plain English, this reads as:

“If the left key is being pressed, then decrease the value of x by 1”

“If the right key is being pressed, then increase the value of x by 1”

You could be a little more verbose and use the longer forms if you wish:

When you do a check on a function, looking for a “true” is implied, and I prefer the shorter form of the increment and decrement command, but both work. Just note that when you assign a value to a variable you use one equals sign (=), but when you do an “if” check, you use two (==).

Run your code now, and see how the sprite moves left and right as you press left and right. Magic!

Of course, this only deals with left and right. Let’s add the code for up and down, using btn(2) and (3) and changing y as appropriate:

Now, you’d think that was the end of it, but there’s a flaw here. You may have noticed that the sprite can move off the screen where you can’t see it. That in itself isn’t necessarily a bad thing, but for the purposes of this game we don’t want that to happen.

To fix it, we need an additional check for “screen edge detection”. When moving left, we need to make sure that x is only decremented when x is already greater than 0. Similarly, we can only move up if y is greater than 0.

For the right and bottom edges, it’s slightly more complicated. Although the edges are at 127 pixels, our sprite’s x and y values refer to the top left corner of the sprite, which is 7 pixels before the right and bottom edges of the sprite – the sprite is 8×8 pixels, remember. Instead of then checking to see if the sprite is at 127 pixels, we need to check for 120.

We can add this check at the same point we check for a button press by modifying the “if” statements. For example:

If we finish this off to include up and down, we can complete our code (for now!):

Next time, we’ll add an enemy to chase the player!

How to make a PICO-8 game: Part 1

Let’s Make A Game.

Since I’m now teaching people how to make programs in PICO-8, I thought I might as well put my teaching notes here for others who may find them useful.

A few caveats:

I am not an expert. Yes, there are better ways of doing some of what I’m explaining (and some of the improvements will come in later parts of the “course”), but my “class” consists of children, some of whom will have no coding experience past Scratch so bear that in mind. In particular, I will be using longhand for variables, and objects/classes will be used later on, to keep things readable, simple, and followable. Followable is definitely a word. Also, this won’t teach you how to use PICO-8 itself, just how to program with it. There’s a manual for that.

The game we’re going to create is very simple. There are two sprites, and one sprite is player controlled and chased by the other sprite. That’s it. Told you it was very simple.

Parts of a PICO-8 Game

There are three main functions to deal with in a basic PICO-8 program: _init(), _update() and _draw(). Note the underscores – without them your program won’t work.

_init()

This is called at the start of your program when you run it. Unless called again, it runs only once. It’s here where you put all your setup stuff, variable initialisation, and so on.

_update()

This is called over and over again, 30 times a second. In here you put your “game logic”, updating variables such as object locations, checking for collisions, increment the score, and so on.

_draw()

This function is where all the drawing on the screen takes place. So you’d print the score, draw the sprites, and so on in the _draw() function. It is also called 30 times a second if it is possible to do so – if the code is taking to long to run it may drop  _draw() calls so that _update() has time to run properly.

Just a few things to mention before I show you any code:

Firstly, comments in the code (that is, notes to you rather than actual code) are either lines starting

which comments out that line, or

which comments out everything until

Secondly, it’s good practice to give all your functions and variables useful names. PICO-8 does have a character limit so you may need to make them shorter and therefore less useful in the future, but not yet!

Finally, indent your code. When you open a function, a loop, an if/then or anything like that, indent everything in it. It makes it a lot easier to read.

If you follow these three rules, your code will be nice and readable – important if you come back to it weeks or months later, or give it to someone else, but also it helps a lot when things aren’t working as you’d expect.

Part 1: Put some stuff on the screen

First off, we’ll need a sprite to act as the player. We’ll just draw a blank square for now in the sprite editor, and use the sprite slot 1 to store it. We won’t need it yet but lets also create an enemy sprite the same only a different colour in slot 2.

Two basic sprites

Now, in the code editor, lets put the three basic functions I mentioned above:

We’ll choose now what the start coordinates of the player sprite are. The PICO-8 screen is 128×128 pixels, with the top left of the screen at 0,0, and the bottom right at 127,127. The middle will be roughly 64,64 then. We’ll call the x and y coordinates of the player, well, x and y. Why not?

Since they’re being initialised, we put these in _init():

At this point, we’re not going to move it about, but we do need to draw it. Usually in a PICO-8 game, you’ll want to clear the screen at the start of each draw frame, so we’ll make use of the cls() command to do that. We can choose what colour to clear the screen to by putting the colour number in cls(). You can use this palette to chose one:

cls(2) will clear the screen to a sort of purpley mauve, for example.

Then we’re going to draw the player sprite on the screen at 64, 64 – now known as x and y. This is done with the spr() command, and the coordinates refer to the top left corner of the sprite. We also need to tell spr which sprite to use, in this case the player sprite, which is sprite number 1.

And there we go:

Best. Game. Ever.

Next time, I’ll show you how to make the thing move around the screen, but for now, here’s all the code so far:

Making audio work on a Steam Link and a Mac

I could just turn the volume up really high and listen through the ceiling.

Yes, it’s another Steam Link post. You see, having had some success with streaming Windows to the Steam Link, I thought I’d have a proper go and making Mac streaming work. And I’ve managed it! Eventually. Apple: “It just works!”. Pff.

Firstly, and not related to the audio issue mentioned in title of this post, I found a small utility to stop my iMac from deciding to go to sleep while playing. As it did. And that was annoying. It’s called Owly, and is free. It sits in the menu bar, and you can click it to disable all sleeping, and click again to enable sleeping. There’s options to prevent sleeping for a certain number of hours or minutes too, in case you’re likely to forget to turn it back on.

Anyway, that was an aside. To the matter at hand!

After setting the Steam Link up to talk to my Mac, and configured for my controller, TV, and so on, I discovered that sound wasn’t being streamed. It’d play in the Steam Link menus and startup screen, but not in Steam itself. Only it was – on the Mac.

I trawled the Steam forums, where the issue comes up a lot, but the solution is always the same: use the Steam Beta and it’ll force some drivers to install on the Mac. Thing is, that was the issue back in 2015 and I’ve done that already.

Turns out, after much fiddling, very easy to fix. If the Steam Link itself is set to use 5.1 audio, or “auto detect”, then sound plays through the Mac. Set it to stereo, and it works. OK, in stereo, but at least that’s something. Mini Metro doesn’t need surround sound anyway.

Still, it means I don’t need to boot into Windows quite so much to play Steam games now.

Configuring Spotify to use less disk space

Download ALL the things. But nobody knows why.

When my PC hard drive reached critical capacity last week, and I was figuring out where all the space had gone, I found one of the major bit-thieves was Spotify. This folder (in Windows 7 at least):

had grown to be over 12GB. 12GB! For a streaming service where everything is online? That can’t be right. Even more odd is how this folder isn’t even the Spotify cache folder, which by default is here:

and for me was only a gig in size. The user interface for Spotify does let you reconfigure the location of this Storage folder, so you can move it to another drive to make a bit of space, but this doesn’t help with the larger issue of the Data folder – which can’t be configured like this.

Luckily, there is still a solution. Firstly, close Spotify completely (making sure it’s not still running in the system tray), then go to this folder:

Note that’s the Roaming folder, not the Local folder where the Data and Storage folders are. In here, there’s a file called “prefs”. Open this in a text editor – Wordpad is better than Notepad because the file contains UNIX style carriage returns and Notepad doesn’t cope well with them.

At the end of the file (although it doesn’t seem to matter where, so long as it’s on a line by itself, add this:

1024 is the maximum size, in megabytes, you want to give over to this cache. So for 1GB, use 1024. For half a gig, 512, and so on. I’m sure you can figure that bit out for yourself!

Save the file, making sure your text editor doesn’t add a rogue file extension when you do so, and then go back to the Data folder mentioned earlier and delete the contents. No, really. It’s fine. Or move them somewhere if you’re scared.

Open up Spotify again, and if it’s all working, you’re set! It isn’t clear why this folder fills up when there’s a perfectly good folder already there for caching purposes, but at least there’s a way of stopping it growing out of control.

Fitting a backlit screen to an original Game Boy

Blue is the warmest colour.

I bought a somewhat yellowed old Game Boy, along with a kit containing a new shell, buttons and some bits to make a backlight for the screen, from someone who I suspect intended to combine them all himself but perhaps didn’t feel up to the task.

He should have tried a little harder, as it wasn’t nearly as difficult as it seemed at first, and the finished product is pretty awesome. So awesome, in fact, that my daughter wanted to play a pile of old Game Boy games on it.

I won’t go into how I assembled it all here, as the guy who sells the kits has an excellent video guide to doing it:

Anyway, that’s how to do it, and this is how things went for me:

I didn’t choose the blue version of the light (there are a variety of different options), but I think it looks pretty good. One of the first titles I tried was Pokémon Blue, so it was appropriate!

Now I’ve done it once, I really want to do another. The previous owner of this one’s shell overtightened the screws causing those white pimples on the front, and although they gave me a bivert kit (to improve the contrast on the screen) it’s the bare chip version which is somewhat tricky to fit. I have another Game Boy I can use, which is missing the screen bezel and is also yellowed, and you can now get a simpler bivert kit which is much easier to install.

I just need to choose the colour scheme I want for the new one!