Mail Man: Fury Road

About

Mail Man: Fury Road is my second full Pico-8 game. It’s an infinite runner of sorts, where you deliver packages to mailboxes at high speed in order to keep your vehicle charged as long as you can.

Process/design notes

Compared to Fishin’, Mail Man was a much more difficult game to finish—its first lines of code were written well over two months ago. Granted, I wasn’t exactly working on it consistently over that entire span, but considering the itty-bitty scope of the finished product, it really was a slog.

I don’t think that time was wasted, exactly; in fact, in hindsight I’m quite happy to have spent as much time as I did. Because while it was slow-going, and while I spent many frustrated nights just staring at my half-finished game and hating it for being half-finished, I’m not sure I can get this sort of on-the-fly game design experience any other way. You see, Mail Man started its life as a game called Ridin’ (noticing a naming pattern yet?), and all I knew about Ridin’ when I started developing it was that it would involve ridin’ a motorcycle through a desert. So in my first weekend working on it, I drew the player character, coded up a player controller (almost the exact same one that ended up in the final game), and then had no clue what I was supposed to do next. I had started what I thought was a game but was really nothing at all yet. It had no challenge or goal or feedback or reward. And no matter how many times I said, “But what’s the game though?” while pacing around my apartment, my wife wouldn’t give me the answer.

This feeling was not great. It felt bad! I spent time coding and drawing things that made no sense or didn’t feel right or weren’t any fun, and then I threw those things away. I replayed the same mediocre early version of this game over and over and over again, waiting for it to feel like something I liked. I filled a few pages of a notebook with a brainstorm of ideas for how to move forward, possible questions and themes and enemies and obstacles. I looked up other driving-themed Pico-8 games for inspiration and then became briefly, stupendously depressed when I saw how good Pico Racer was.

There’s no magic bullet that got me out of this rut. I mostly just kept trying new things until something felt right to me, and then repeated until another thing felt more right. At some point I had a gut feeling that the player should have a good reason to use more buttons than just the arrow keys, which led me to think about Mario Kart-style projectiles. An aesthetic desire to make the game non-violent funneled me into the vague idea of throwing Things at Receptacles, and my recent attempt to play Death Stranding is probably to blame for whole package-delivery theme. The end result isn’t great by any means, but it’s a noticeable step up in scope and polish from my last game, and most importantly to me, I think it actually feels pretty good to play. GoodFeel™ is an elusive thing to capture, and I’m gosh darn fired up to have made a game that has even a little bit of it.

Some technical tidbits

The craft-minded of my many, many avid readers should continue onwards to to learn about a few technical aspects of Mail Man: Fury Road that may be of interest.

The dust trail

One of the first things I wanted to nail was the dust trail behind the bike—with limited visual skills/tools at my disposal, I knew this would be essential for creating a sense of movement and physicality. Plus I’ve been wanting to take a run at something like this ever since I played Sable. Because it would have to react dynamically to the player’s movement, and because I wanted it to feel at least partially noisy, I knew I’d need to build the trail procedurally rather than as a fixed set of sprite animations. Big picture, this is as simple as maintaining an array of discrete particle objects and, on fixed time units, doing each of the following:

  1. Adding a new particle immediately below the player character
  2. Moving each existing particle downward at a rate that matches the player’s upward velocity
  3. Culling any particles that have left the viewport
    1. Note that there’s a more optimal way to do this! We could instead loop the culled particles back around to the front of the array so that our program doesn’t have to do as much dynamic memory management. I didn’t do this, because my game is fast enough, but it’s something I’d reach for if it weren’t.
  4. Drawing all remaining particles with some dynamic size that grows as they approach the bottom of the screen

Use basically any shape for your “particle” in step 4 and you’ve got a pretty decent trail behind your moving player! In my case, I gave circles and custom sprites a try, but they didn’t have enough time on screen to read properly, so I went with simple horizontal lines. To create a sense of dissipation around the edges and make them feel more organic, I added a bit of randomness to the rate at which they grew, and gave each one a 5% chance of also drawing a couple of spare pixels past its outer edges. In a slower-paced game, or one where the player can look more closely at what’s happening, I would 100% have to get way more clever than this, but this ended up being quite nice in my opinion.

Math for low-res screens

Fractions were probably the most annoying thing I had to contend with throughout development. In case you didn’t notice, Pico-8’s screen is rather small. Relative to basically any other modern screen, it’s ridiculously easy to see each individual pixel onscreen, even when they’re moving. A consequence of this is that the margin between smooth movement and choppy movement is very small—something that moves one or two pixels every frame will look just fine, but something that moves one pixel for 4 frames and two pixels every fifth frame will look awful.

I had problems like this for probably half of the time this game was in development. Movement looked jittery and playing the game for longer than 15 seconds gave me a headache. I had to do a pretty rigorous debug session to find the root cause, which was that my global movement speed variable was being clamped incorrectly. When the player’s speed exceeded its max integer value, I was simply not accelerating it any more, when I should have been actively resetting it to the exact value I wanted. As a result, all my objects were moving at a speed of something like 1.067 pixels per frame instead of exactly one pixel per frame, which would cause each one to periodically lurch downward whenever the fractional component of its position added up to a bonus pixel. Truly an unmitigated disaster.

Unfortunately, this same issue with fractional movement makes it basically impossible for me to make the player’s speed dynamic. I was hoping to do something like this to increase the difficulty as players make it farther into the desert, but increasing speed by anything less than a full pixel per frame is a recipe for nausea, while increasing the speed by an entire pixel per frame is way too intense. So I suppose our lonely delivery person will just have to bike at a constant rate until he’s ported to a more mainstream platform.