Optimal Play Should Not Be lame
Sanguinite’s inception sprung from this one liner in my head: What if my childhood favorite game Solar Jetman had procedural levels? I actually re-played the entirety of Solar Jetman at some point after starting work on Sanguinite. It’s a great game and really sucked me in as a kid, but adult Wheffle noticed a lot of flaws that would need to be addressed if I used the game as a template.
The Completionist’s Struggle
One of the first things I noticed while replaying Solar Jetman was the fact that I felt bad if there was any loot left on the map when I selected “blast off” to go to the next level. Anything less than the complete strip-mining of a planet was sub-optimal, especially considering I was trying to save credits for that sweet Italian Racing Jetpod.
This is totally fine in some games that are more slow-paced and hand-crafted to reward exploration with neat secrets and Easter eggs, but in this case it isn’t ideal.
Personally I don’t like to be stressed out or bored doing something tedious while I’m gaming, but I also often feel a need to play optimally. It’s frustrating not to be able to play optimally and have fun at the same time. Since there was no time limit and you could re-fuel and re-arm your pod at the mothership for free as many times as you like, I felt obligated to scour the map for every last treasure, which unfortunately wasn’t always a great time.
At first the shuttle in Sanguinite functioned similarly to the mothership in Solar Jetman, offering free refuels, repairs, and re-arming. However, after I realized the completionist issue, I experimented with just not offering any in-situ servicing for your drones. The difference was immediate and clear: now you have to pick and choose where to explore and what you can haul back to the shuttle based on your limited fuel, ammo, and armor. Once you run low on these resources, it feels satisfying to be able to say “I did my best” and slam the launch button even when there are still goodies laying around in some deep godforsaken crevice.
This became a theme throughout development. The way the game is designed, I was worried about accidentally creating an un-fun or tedious “optimal” path at any point during a playthrough, and so I am always trying to sniff out and fix any offending design quirks.
The “Orbit -> Mission” Loop
Games are loops, and loops within loops. Some are small and fast, like “look for bullets -> dodge bullets -> repeat”. Others are very big and long, like “start a game of civ -> win/lose -> repeat” (well, sometimes that particular loop is very short for me).
The base loop that Sanguinite started development on was the “orbit -> mission” loop. I found that it was important to keep that loop moving at a good pace and not let the player get stuck in one phase too long. But I also wanted each phase to be meaningful.
The first issue I noticed was that it was “optimal” to play every single mission that came along. As soon as you left one mission, you could launch a shuttle to the next. That was ludicrous, so I added shuttle servicing time between missions. It felt a lot better to have time to chill in orbit and finish projects, and now there was an added layer of having to pick and choose which missions you wanted to take.
On the other side of the loop, it was pretty easy to get stuck in a mission for a very long time at first. Part of the problem was the unlimited fuel/ammo/health issue that I talked about previously. But I wanted a little bit more of a nudge to get the player to not linger too much, especially later on in the game when you can bring lots of drones and equipment that make it easier to stay longer.
I don’t much like strict time limits, like the clock in the early Mario games that would just straight-up kill you when it ran out. Instead, I opted to take a leaf out of Deep Rock Galactic’s book and implement a version of their “swarm” system. If you stay in a mission long enough, enemy reinforcements appear and attack you. The timer gets shorter after each swarm until you are under constant assault, prompting the player to get the hell out.
The “Transit -> Planet” Loop
There’s always a bigger fish, and the big fish that eats the “Orbit -> Mission” loop is the “Transit -> Planet” loop. When the player has collected enough fuel from mission sites, they can leave the orbit of their current planet and choose the next one. The ship’s fuel depletes to zero and the process starts over.
If you haven’t guessed it yet, there’s a lingering problem here. In the early stages of implementing this system I realized that the player could loiter at a planet indefinitely (infinite missions are generated while the player is in orbit) and there wasn’t much of a reason to leave a planet. Why not just stockpile resources and finish every lab project on world 1?
For a game with a set number of hand-crafted levels this isn’t really a problem. I may in fact switch tracks later on and generate a limited number of missions per planet that you can strip-mine and be done. That would involve adjusting a few other systems as well to match with that new approach, so for now we have to try to incentivize the player to move on while presented with infinite levels.
The solution I came up with here was a version of the mission’s swarm system. If you loiter at a planet long enough (riling up the natives as you complete missions), ancient machines and creatures will begin to wake up and your ship will get attacked by an alien warship.
This event spawns a special mission indicator and a countdown timer telling you how long you have to complete the event mission before the warship “comes within firing range” and blows you up. The event mission has you landing on the outer hull of the alien ship with the shuttle and infiltrating the interior with your drones to blow up critical systems (obviously this is the most reasonable option, since your expedition is peaceful and your ship is unarmed).
I said earlier I don’t like time limits, and perhaps I broke that rule a little bit with this event countdown. However, at the time of writing I haven’t made a final decision on what to do when the countdown runs out. We could just kill the player, but I was thinking about implementing a hit point system for the player’s ship and simply deducting a chunk and reseting the countdown when it reaches zero. Forceful nudges rather than a game-ending body slam.
Once you finish the special event mission (which actually has objectives, unlike normal surface missions) the event will disappear, but more ships will spawn at increasingly faster rates.
Along with the warship event, missions continue to increase in difficulty without necessarily increasing in reward. I’m also planning on implementing special surface missions involving orbital defense batteries that start to show up the longer you loiter. Hopefully these systems are enough to keep the player moving along and progressing.
Limiting Hard Barriers
Another theme for this article could have been something revolving around my dislike for deliberate hard barriers. This is the third time I’ve brought up Mario-esque time limits, but I really do feel there are more elegant solutions out there. Even some older games would spawn a floating axe or invincible monster when your timer ran out rather than just instantly kill you.
I’d much rather incentivize intended behavior rather than punish unintended behavior.
Optimally the player should feel like your game’s intended behavior was their decision. “Wow the danger level is ramping up here, one more crate and I’d better leave” is a much more positive thought to have than “my timer is running out, I’d better drop what I’m doing” or worse… “How did I die? Oh, I forgot about the timer.” Something like the swarm system creates a flexible barrier that allows the player to push against it for fun. If they want to try and get that ore crate in the middle of a huge swarm, that’s fine! If they die, they’re more likely to have a laugh about it.
Not only is it important to identify and address un-fun or tedious optimized paths in your game, I believe it’s just as important to solve them in dynamic ways rather than with lazy barriers. Your poor compulsive min/max’ing players will appreciate it.