Anatomy of a Pico-8 RPG
Posted: August 20, 2021 Filed under: Patreon Leave a comment »A few days after the release of my dice I wanted to dive right back into game making. Specifically, I wanted to get back to work on Dusk Child 2, but some of the new pico-8 features I wanted to use to simplify making a multi-cart game were a little daunting to me so I instead started doodling concepts for other things, starting with the above RPG battle screen.
I posted about it on twitter, and then I cast a magic spell where I was only hypothetically working on a game like this. (“But Sophie, what?!?!” OK look, right, making an RPG is a bad idea, making one in pico-8 is a double-bad idea. I cannot justify working on something like this. BUT if I’m only hypothetically working on it, then I don’t have to feel guilty. And hypothetically if I finish it then I could release it, but hypothetically, if I can’t finish it then I don’t have to feel bad. Because I wasn’t ~really~ working on it. My logic is flawless as you can see.)
So yeah, consider this post a “how I would go about making such a thing, if I was to do it, which I’m probably not but 100% could be doing, wink wink.”
So once I had done some actual coding and made a working menu system and some basic battle stuff displayed I kind-of figured I could make such a game happen and so I got to work planning how the whole game could fit together.
STEP ONE: DATA
So a big part of the deal with pico-8 is how limited it is, I knew right away that the battle system itself would take up most of a cartridge, and if I wanted more to the RPG than that (menus, maps to explore, etc) then I would have to have multiple cartridges that all share the necessary game data. Pico-8 has a system for that conveniently called ‘cartdata’, but that too is limited – just 64 numbers.
So I made a new text document and started planning, I had to figure out what data was needed, and find a way to fit it into this little block (and in a way that didn’t use too many tokens or it might limit game features).
It took me a while to find a use for all these numbers that I liked but so far I’ve managed to use a little over half of them, what gets saved right now are:
- 3 Story flags (unused so far)
- Current Map
- Current Map ‘Stage’
- Player position X
- Player position Y
- Player facing direction
- Player character
- Money
- 5 Item IDs (what items you have)
- 5 Item Counts (how many items you have)
- 4 Playtime counters (Hours, Minutes, Seconds, 60ths of a second)
and also for each of the four main characters:
- Level
- Experience
- Hit Points
- Ability Points
- Weapon ID
I’ve been able to save cartdata slots by having a lot of values determined by other things. For example: A character’s Strength, Defence, Maximum HP, and Maximum AP are all determined by their current Level – so I don’t need to save those, so long as I have the character’s level these things can be calculated.
So, once I had an idea of how I would keep track of all the data that describes the player’s progress/status between cartridges, the next thing for me was to get started making systems.
STEP TWO: MAKING SYSTEMS
So including other scripts inside a script you are working on is a pretty common thing in programming, but it is actually petty new in pico-8, only being added in version 0.1.12. It is useful for a few things in pico-8 development, but for me the appeal is largely for how it can make multi-cart development easier.
See, if a game is made up of multiple cartridges, only one cart can be loaded at a time so each cart needs to have its own scripts. And there are likely to be a lot of common functions and data that you would want in each cartridge. Before, if you wanted to make a change to that then you would have to make the change in each and every cartridge’s scripts and hope that you hadn’t missed one or implemented something differently in one cart. But now you can just include whichever scripts are needed in each cart, and changing the source script will effect all of the carts.
This has already been incredibly useful for me; every cart includes some of the “gamedata.p8” systems that load and save data, and since I have changed that a few times to find the optimal cartdata slot usage, it has saved me making more changes than I need.
So for example, right now I have a “menusystem.p8” file that includes how to create, draw, and interact with multiple-choice menus. It is used in some carts (title, battles, party menu) but not others, the same code is copied to these carts when they are run/compiled.
I know I’m calling these “steps” and they kind of are in the order that I first started planning them, but I’m constantly making changes and refining each as I go. Anyway next is step three and that’s about deciding what cartridges you’ll have.
STEP THREE: DECIDING WHAT CARTRIDGES YOU’LL HAVE
So like all things pico-8, multi-cartridge games have limitations. For one you can’t run them on the pico-8 BBS, but for my RPG work the big one is that you are limited to 16 cartridges when compiling a game for people who don’t own the pico-8 console. (In theory I could make an RPG that used hundreds of cartridges but only people who own pico-8 could play it. Honestly that could be a cool thing but for now I’m trying to make a game for more people than just that).
16 cartridges might seem like a lot until you start seeing what can actually fit into one of them, and how much stuff is actually in an RPG of this type. My current plan (subject to change) is cartridges for:
- Title screen
- Credits/Ending
- Party Menu / Shop / Battle Victory
- Battle Cartridges
- Map Cartridges
I’ll adjust the amount of battle and map cartridges to best match the story and progression though the game once I really get into making that stuff but for now I have pencilled in three battle carts and ten map carts.
Obviously three types of battle and only ten locations would make for a relatively small (teensy tiny) RPG so each of those carts should be capable of having multiple types of battles (I have multiple enemy sprites in each, and formations of those enemies possible for each battle), and multiple locations for each map cart (perhaps using multiple parts of the map data, and or having compressed string data loaded into the map depending on the map stage. I want to have all kinds of locations, interiors, dungeons)
You might also note that the party menu, shop, and battle victory screen are all one cartridge. This saves a lot of space from other cartridges because there is a lot of common stuff between each of these things, and they all reasonably fit in a single cartridge.
STEP FOUR: NOT REALLY A STEP BUT THIS IS HOW SOME OF THE STUFF WORKS
So the battle system itself is fully turn-based. Each character takes a turn and then the enemies take their turns. This is repeated until only one side is left (or until you run away).
By having a very strict turn order like this without having to account for speed/initiative I can simplify a lot of the data (saving tokens!) and I can build unique gameplay from within the constraints – for example because Vian (the bird-person) is always the last party member to take a turn, they have an ability called “Again!” that lets the party immediately take another set of turns.
Each turn has several stages:
- Begin Turn
All characters are positioned correctly, the next turn-taker is selected, and their abilities are loaded into the menu
- Choose Action
If a player character, this is the menuing and targeting phase, if it is an enemy then the AI chooses an action and a target itself
- Cast (Perform Action)
The selected action is performed by the caster upon the selected targets. This happens in full and each animation is added to a list as appropriate.
- Animate
Animations in the list are played, and removed from the list when they are completed. Some actions will have added a “wait” to the animation list, which will prevent subsequent animations from playing until the previous ones have been completed.
- End Turn
Once the animations are all complete, turn-takers are checked to see if they are dead and, if so, are animated dying and removed from the turn list as appropriate. If there are no animations left, the turn really ends and we go back to the Begin Turn stage.
For map screens, I have a simple environment movement & drawing system. (draw the map around the player character, then draw all of the sprites from top to bottom to fake depth).
I also have a system similar to battle animations for events, so I can add things to a list of events (show a message, animate a character, open the shop menu, etc) and these events are played out in order each with their own logic and properties.
If you’re super focused on what I’ve said so far, you might notice that what I’ve mentioned of how I’m using cart data slots doesn’t have room for things to determine which menu (party menu, shop, battle victory) is displayed when loading the menu cart. This is because I don’t want the game to load into one of these things from the title screen, and also because there are other ways of passing information between cartridges.
When you use load() to load and run another cartridge, you can optionally pass along a string parameter, the menu system looks at this to decide which menu to display when it is first loaded.
Also, did you know you can import .png images into pico-8 cartridges’ spritesheets?
STEP FIVE: STORY
Ugh I don’t know I’m still figuring it out leave me alone! :p
That said I do have an idea of what the characters are about, where they are coming from, and where they might go. I’m just mostly going to keep working on this and see what happens. I don’t usually do too well planning everything way in advance anyway.
OK that’s pretty much where I’m at with this, if you’re a $5+ patron, you can check out a (very very very rough) build of this stuff from a week after I started, and this month I hope to have a MUCH better build featuring all this good stuff and hopefully even more!
Hope you’re well, I’m sorry for not posting stuff like this more often but it’s one of those tricky things where this takes a whole bunch of time that I could spend working on stuff, but I’ll try to do it more frequently! Thank you so much for your support <3
Oh, last minute update:
Here’s the spritesheets (as they are rn) for battles, field, and menus.