"Imprisoned beneath the earth...only your wit, guile and a plasma pistol for company. However will you escape?"
25 levels of mind-bending physics-puzzle-platforming fun!
This is actually a remake of a Flash game I made back in 2011-2012, which you can play here. I even remade the original music in glorious 4-channel chiptune (I got the original music from the Newgrounds Audio Portal and it's since been deleted. Wish I could find the original artist!)
I made a post before about porting a physics library called bump to PICO-8; this is the first project I've made using it in earnest. I mentioned concerns in that thread about token pressure from including the library. In the end, the greatest strain on token count was representing levels in code (the game doesn't actually run while unminified); I had to get creative with string encoding and other tricks to make it all fit (8191/8192 tokens!). I wrote a pretty ropey python script for converting multiple Tiled tmx files into generated lua code (you can find the script here). I encoded the tiles as PICO-8-compatible hex strings (this meant that the data just needed to be copied into a reserved section of the map when loading a level); the rest was encoded as structures of entity types, co-ordinates and properties (e.g. switch colours, platform directions).
Previously when making games in LOVE2D, I made use of a simple 2D axis-aligned physics library called bump.lua. I especially enjoyed the versatility (e.g. different collision types and outcomes based on custom filtering) and the simple, intuitive API. I wanted to see how effectively it could work in PICO-8, so I forked it.
The main obstacle to running bump was that PICO-8 has no access to the math lua module and uses 16-bit ints, so all math.floor etc. calls were replaced with their PICO-8 equivalents. math.huge did not have a standard PICO-8 analog, so the 16 bit int max (32767) was hardcoded instead. Likewise, PICO-8 lua does not parse 10e-10 style numbers, so DELTA was changed to a regular decimal value. In addition, PICO-8 does not have access to the table module, so a separate sort function was added to replace table.sort.
I also deleted portions of the library that I didn't consider necessary for my own uses to save on tokens and characters:
- bounce and touch collision types
- anything involving querying segments (note: querying rects and points are unchanged)
- all sanity checks and assertions that bump would normally make e.g. assertIsPositiveNumber or assertIsRect. While these are useful for debugging and avoid weird inconsistent states, they eat up precious tokens. I've used bump enough in other games to feel comfortable enough without these safeguards.
- public bump.rect and bump.responses tables. I honestly never used them anyway.
What's left is still a robust physics library for rectangles and points. Here's a quick demo platformer using bump.
Naturally, the primary concern with any library in PICO-8 is tokens and characters. Here's what it clocks in at:
I haven't quite figured out just how big that footprint is. Obviously 32.3% is a sizeable number of tokens to give away, but, like I mentioned, bump's interface is pretty simple, which saves tokens later down the road (every attempt to move an object within the world can use as few as 11 tokens). In addition, it's possible to go back and delete more from the library before releasing if the functionality is unused (e.g. for the demo above, anything involving querying the world is unused and could be deleted). I'm sure bump would be overkill for any game that doesn't require anything beyond simple collision detection with overlapping rectangles, but I'm optimistic it could still be beneficial for more complex use cases. I plan to find out.
A bog standard minigolf game with 4-player pass-and-play multiplayer
I heard about PICO-8 literally years ago and completely forgot about it until last weekend. Downloaded it and spent the week having a great time getting to grips with it. 16 Greens is the first 'proper' game I've made so far.
- I tried to lean into the 'PICO-8 way' as much as possible; usually I'd make maps in Tiled and import them into whatever game I'm making, but since PICO-8 has a specific cart block for map data, I figured it was best to use that instead (I still used Tiled, I just wrote a python script to convert tmx files into PICO-8 map data). For this game, since I wanted each hole to be a full screen, this limited me to 16 holes, but I figured this would help me preserve precious tokens and characters. In hindsight, I actually seriously underestimated just how many tokens and characters PICO-8 affords you; I ended up under 50% of the token limit and didn't even use 20% of the character limit (after minifying). I'll try storing map data in code in future (especially since string encoding doesn't eat up many tokens).
- Minifying helped with the character count significantly (~12k minified vs. ~32k unminified), although obviously did nothing for tokens. That said, if I start storing more map and graphics data in code, then character count will become more important, so I'll stick with minifying for future carts (I used luamin).