I’m trying to code a tiny city builder for the PICO-8 fantasy console.
In 2020, I discovered the fantasy video game console PICO-8 and started writing a game for it. I continued its development in 2021, but got stuck some time after. Essentially, the game idea I had was too ambitious for what I actually could accomplish myself at the time. My programming skills haven’t improved a lot, but I still very much want to learn and I’m itching to use PICO-8, which is such a lovely little piece of software. So when a new game idea came around, I decided I would try again.
So here we are. Meet 𝔗𝔦𝔫𝔶𝔥𝔬𝔩𝔡, a city/town builder for the PICO-8 system. As with my first attempt, I can’t promise that this will ever reach a workable state, but I’m giving it my best. The design of this new game is a lot more in line with what people usually do with PICO-8 games, so it should be somewhat more achievable than my last attempt. But there are still many challenges inherent in the design, as it should be. Solving these problems is why I am doing this, after all. Solving problems has always been the best motivation for me to learn things like this.
So what am I trying to do? My idea is to design a classic city builder – meaning a game that is more about its inherent simulation, about building and trying out things, rather than about winning – but within the unique constraints presented by PICO-8’s design. As far as I know, nobody has done quite like what I’m imagining for PICO-8 yet. Although Picopolis, a demake of Sim City by former Minecraft lead developer jeb, comes close:
But since I do have my own ideas on how I want my city builder to look and play, I didn’t spent a lot of time looking at how jeb did things. After all, my goal here is to try out things, make mistakes and learn from them.
I envision 𝔗𝔦𝔫𝔶𝔥𝔬𝔩𝔡 to be a town builder, rather than a city builder. In the game, you will build a small medieval village, trying to provide your villagers with everything they need to live. As more and more people move in, you will need to build houses for them and their needs will grow. They will generate taxes, which you can spend on specialised buildings. Eventually, you will be able to build a castle and fortifications. In the later game, this will become necessary, as increased wealth of your settlement will attract raiding parties that will ransack your settlement and steal some of your gold.
Here are my initial design notes on the concept:
There is no way to win the game. The goal is simply to experiment and to build your ideal town. Although the money counter can of course serve as a sort of high score, the game is much more about letting the simulation run and seeing your village evolve.
Progress So Far
The game will include a fixed map. You can pick any part of the map to build on, provided it is passable terrain. Different terrain features can be used to supply your village: Trees can be harvested for wood, there are ore deposits that you can mine and some buildings, like the water mill, need to be build near water to work. You can also plant grain and cultivate livestock to feed your people. There are six resources in the game: People, Food, Wood, Stone, Metal and GP (Gold Pieces). These things are interdependent on each other and govern how much your settlement can grow. You can see statistics for these resources in the screenshot below on the main status bar of the game. This also includes a date display to show how much time has elapsed. In the screenshot, it’s currently the 21st of September 1465. To keep things simple, all months in the world of 𝔗𝔦𝔫𝔶𝔥𝔬𝔩𝔡 uniformly have 30 days.
That’s pretty much all I have nailed down about the game mechanics so far. I’ve spent most of my time working on the game up to this point on designing its look and working on the UI. I’ve also included a nifty title screen and the beginnings of a state machine to handle menus and such.
The title screen is actually encoded as a string, so as not to use valuable sprite real estate. Of course, I couldn’t have designed a system to do something like that myself. Luckily, PICO-8 has an amazing community which freely shares ideas and code. So I ended up using JadeLombax’s String-Based Graphics Rendering System to encode and decode my image.
You can run that cartridge in PICO-8 to encode an image that you’ve imported and then to copy the resulting string into your own PICO-8 code. The cartridge also includes code that you can then use in your program to decode this string and display the image on the screen:
-- jadelombax's string-based rendering system
x+=len if(x>mw) x=x0 y+=1
It’s pretty clever stuff! And it saves me from having to give up parts of my game map for the intro screen (or possibly menu graphics, if I want to use those later).
So as it stands right now, the game has an intro screen that loads into the map. There’s some UI, but that isn’t functional yet. You can move the cursor around and it changes colour over terrain that’s impassable or things like buildings (this is will be useful later to show that you can’t build on these tiles).
I will now need to implement a menu that allows you to build things like buildings. My planned control scheme for this game is that you’ll move the cursor around with the directional buttons (LRUD) and then you can bring up the build menu with X. From there you can choose what building to build (X) or you can back out with O. Back on the map, O is used to bring up a more detailed statistics UI that also pauses the game.
After this, I will have to implement actually keeping track of objects in the game world like buildings. For this, I will need classes. Later, I also want to spawn little people that you can see walking around, which will involve me having to learn about pathfinding, specifically the A* algorithm. Apparently, there are implementations for PICO-8 already (original, optimised single-function).
And then, we need a lot of game logic to run the actual simulation. And probably a lot of optimisation and fine tuning of it. I will keep you updated here on how it goes. If you want to follow along while flail around in Lua, the project’s up-to-date code is up on GitHub.