Skip to main content

It's time again for PiCoSteveMo

· 5 min read
beho

It's November again, which can mean only one thing. That's right, it's time to make a janky PICO-8 game with a tenuous connection to a Stephen King work.

https://itch.io/jam/picostevemo-4

My idea this year is to make a truck game around the unusual spelling in the title of the novel Pet Sematary.

I haven't touched PICO-8 in this time so I'll try to make a summary of the tricks I learned last year.

Starting a new project

If you want your cart project to live somewhere other than in PICO-8's memory files, you can make a symlink to some other part of your hard drive.

On linux, pico-8 carts live in ~/.lexaloffle/pico-8/carts and I want to my cart to live in ~/src/wet-semantary.

First in the PICO-8 console, create a new cart

-- in PICO-8 save a fresh new cart
save wet-semantary

Then in a bash terminal we can make a link

# in a bash shell move the cart to the repo
mkdir ~/src/wet-sementary
mv ~/.lexaloffle/pico-8/carts/wet-semantary.p8 ~/src/wet-semantary/

# set up a symlink to PICO-8 carts directory
ln -s ~/src/wet-semantary ~/.lexaloffle/pico-8/carts/wet-semantary

# verify that it worked
ls -al ~/.lexaloffle/pico-8/carts

Then you can access this new folder from PICO-8.

-- in PICO-8 again load the cart
load wet-semantary/wet-semantary.p8

Once the cart is loaded you're ready to start jamming. Run the cart with RUN or ctrl+R.

Using a separate lua file for source

If you're like me and not hardcore enough to use the PICO-8 editor, you also may want to have a separate lua file for your source code.

If it's not there already, add a __lua__ block like this between the pico-8 cartridge\\version 43 section and the __gfx__ section.

__lua__

#include main.lua

This will import source code from the main.lua file.

Adding text the top of your cartridge file

Whilst we're talking about that lua block, you can add comments to the top of it and they will appear on your cartridge png when you export it

__lua__
--wet semantary
--by beho ♥ https://beho.dev

#include main.lua

PICO-8 methods

You mean you don't have this PICO-8 cheat sheet as your desktop background already?

If you get lost, you can also search the manual.

Here are more or less all the methods I used last year:

Drawing​

-- clear the screen with colour n
cls(n)

-- outline of rectangle (x, y, w, y) with border radius r and colour n
rrect(x,y,w,h,r,n)
-- fills a rectangle (x, y, w, y) with border radius r and colour n
rrectfill(x,y,w,h,r,n)

-- draw sprite number n to (x,y), has optional scaling parameters
spr(n, x, y)
-- draw from sprite map source rectangle (sx, sy, sw, sh) to (x, y)
sspr(sx, sy, sw, sh, x, y)

-- draw an image to (x, y) from tile map source rectangle (sx, sy, sw, sh)
map(x, y, sx, sy, sw, sh)

-- draw text on the screen at position (x, y) with colour n
print("⬅️", x, y, n)

-- change the transparency colour in the sprite editor
-- helpful if you want to paint things black
palt(11, true); -- 11=extremely bright green
palt(0, false); -- 0 =black

Input​

-- if button 4 is pressed (and released, fires once)
if btnp(4) then
-- do things
end

Sounds​

-- make crazy little noises
ErrorSound = "\as6x1g0g-0"
print(ErrorSound)

-- play music track n
music(n)
-- fade music track n in with over 6,000ms
music(n, 6000)

Iteration​

-- iterate over a range
for i = 1, 4 do CloneGuest(Options[i])); end -- four guests

-- iterate over a list
for option in all(Options) do
-- option.things
end

Time​

-- time since the game started
t()

-- check how much time has happened since a previous measurement
if t() - PartyStart < 3 then
end

Scene management

You don't need scene management to have a good time now, but I know I will want it eventually.

Inspired by system for managing states you can assign your update and draw hooks to variables:

-- empty global variables which will be populated with
-- update and draw methods for scenes
Update = nil
Draw = nil

function _init()
-- the initial state
PartyInit()
end

function _update()
Update()
end

function _draw()
Draw()
end

(The methods that start with an _ here are the entrypoints that PICO-8 uses to control your game.)

Then you can switch to other scenes by updating these global variables.

function TitleSceneInit()
Update = TitleSceneUpdate
Draw = TitleSceneDraw
end

function TitleSceneUpdate()
-- update logic
end

function TitleSceneDraw()
-- draw logic
end

Centered text

I made this helper function:

-- print text (somewhat) centered at (x,y)
function PrintCentered(text, x, y, color)
-- print offscreen so we can measure the width
local w = print(text, 0, -8)
print(text, x - ceil(w / 2), y, color)
end

Animation

I used this implementation of smooth step.

-- (time, start, end)
function SmoothStep(t, s, e)
s = s or 0
e = e or 1
t = mid(1, t)
return s + (e - s) * t * t * (3 - 2 * t)
end

This will return a value between 0 and 1 that represents how far time has progressed from value start to end.

I used this for example to animate the logo sliding down from the top of the screen:

logoOffset = SmoothStep((t() - 3 - TitleStart) / 3, -8 * 9, 0)
map(16, 0, 8 * 3 + 6, 8 * 4 + logoOffset, 8, 5)

OK that's enough yapping, I need to start working on my new game now.