Workpad
August 17th, 2024

Project Seed - A Pico-8 Prototype

Sidetracks

Oof, another long stretch between updates. This has not been a productive winter.

Much of the project I've been writing about here are, shall we say, "on ice". UCL is still being used for the project it's been built for, but there's been no further work done on it recently. I think we can safely say Photo Bucket is dead, at least for now. Blogging Tool and that interactive fiction project is still ongoing, but both are running on a slow burn. I was hoping to get the fiction thing done by the end of winter, but it's likely that timeline will slip. Maybe some time in spring.

What have I been doing in the meantime? Watching YouTube videos on old DOS games, actually. Hardly an activity worth writing about here. But it did get me wanting to try working on a game again. And I did get an idea for one while watching videos of someone going through a collection of shovelware titles.

This project is designated the codename "Project Seed". I'm going to be a little cagey about the details, at least for now. But I will say that I'm planning to use Pico-8 for this. I bought a license for Pico-8 about 2 years ago (oof, did not expect it to have been that long ago) and I watched a few videos on how to use it, but I didn't have a good idea for a project then. It is a fascinating bit of software, and I know it's quite popular amongst hobbyists. One thing I like about it is that the games made with it are not expected to have great art. As someone who can't draw to save himself, this works in my favour. So don't expect anything resembling Celeste from me! 😄  Pico-8 also targets HTML5, which works for me.

Anyway, I have this idea, and I thought about starting a prototype to see how it feels. I downloaded Pico-8, spun up a new project, and started drawing some of the graphics. I've got the bare minimum so far: a user-controlled paddle, called the "basket"; a laser bullet, and a thing that needs to be shot.

The first few sprites. Must say I really like the Pico-8 pallette.
The first few sprites. Must say I really like the Pico-8 pallette.

Next was coding up the Lua code. Using the Pico-8 builtin editor was fine for a bit, but I eventually switch to Nova just for the screen size. I am still trying to adhere to the whole retro-style approach to Pico-8. The code I write is still bound to the 8192 token limit, and I'm trying to avoid using too much virtual memory, capping elements to only a handful. But, yeah, using Nova to write the logic is so much better.

Anyway, the first milestone was allowing the player to move the basket around and shoot laser bullets. Then it was to get one of the shootable items moving across the field. The idea is that the player will need to fire the laser to hit the shootable item. When it's hit, it begins to fall, and the player needs to catch it in the basket.

Shooting the laser and catching the item in the basket.
Shooting the laser and catching the item in the basket.

This took about an hour or so, and already the glimpse of the core game mechanics are starting to show through. They're just ridiculously primitive at this stage. I mean, the item really shouldn't fall through the basket like that. But given that it's a prototype, I'm okay with this so far.

Next experiment was spawning multiple items onto the field. This got off to an interesting start:

An "item" train.
An "item" train.

But adding a bit of randomness to the Y position and the spawn delay managed to make things a little more natural again:

A more natural item spawner.
A more natural item spawner.

One thing I'm considering is whether to add some randomness to the item X velocity, and even have items move from right to left. But this will do for now.

At this stage, items were just being added to an array, which grew without bounds, and were not being released when they left the screen. Obviously not a good use of memory (even though this is running on an M2 Mac Mini and not retro hardware from the 1980's, but that's hardly the point of this exercise). Furthermore, the player is only able to shoot one bullet at a time, and those bullets weren't being released either. So I set about resolving this, trying to do so in the spirit of a Pico-8 game. I've setup a fixed Lua array, which will grow up to a max size, and added a simple allocator which will search for an empty slot to put the next item in.

function next_slot(tbl,n)
  if \#tbl < n then
    return \#tbl+1
  else
    for i = 1,n do
      if tbl[i] == nil then
        return i
      end
    end
  end
  return nil
end

This makes releasing items really easy: just set that slot to nil. It does mean that I can't use ipairs to iterate over items, though. Instead I have to use the following construct:

for i,item in pairs(items) do
  if item then
     -- Do thing with item
   end
end

It's here that I wished Lua had a continue statement.

I used this for both the item and bullets: there can now be up to 8 items and 4 bullets on the screen at a time. After making those changes, the prototype started to play a little better:

So, a good start. But there are definitely things need to be fixed. The basket needs to be wider, for one. It's fine for the prototype, and I'm okay with it the collision being pretty lenient, but it's too narrow to make it fun.

But the biggest issue is that the collision logic sucks. Bullets are flying through the items, and items are falling through the basket. I'm using a point-in-rectangle approach to collision detection, with a few probing points for each item, but they obviously need to be adjusted.

So collision is what I'm hoping to work on next. More on this when I get around to it.