I can’t remember where I saw it, but at some point back in 2017 I became aware of a game jam game that featured an inventory system that stacked objects on top of a platformer protagonist. The catch was that with too many items, the player couldn’t actually get through spaces with low ceilings. Hilarious! (This is before anybody knew that stacking boxes on a character’s back would be the central premise of a AAA game that also had urine grenades.)
Combining those thoughts along with the concept of inventory-as-lives from the Sonic the Hedgehog games, I decided to build a simple game for Facebook Messenger. That game became Blob Catcher.
Building Blob Catcher
I’m not sure if I recommend this kind of thing or not . I wrote a lot of basic game engine stuff from scratch: Game loops, state/scene transitions, game object base classes that handled location and state, and even collision detection. Ultimately, though, I decided that I didn’t want to be in the game engine development business, abandoned the framework (whose name I cannot recall), and moved the project to Phaser.js instead.
The Core Design
The basics of gameplay are this:
- The player controls an object at the bottom of the screen that moves left and right
- The goal is to catch one type of falling object (in this case, the happy little blobs) while avoiding spikes
- The blobs would stack vertically, making avoiding the spikes more difficult
- The blobs would act as hit points, with the topmost blob falling off of the stack when the player hit a spike
- Blobs could be “collected” by touching a special object (in this case, a UFO)
- Collecting the blobs is the only way to increase score
- The value of blobs is non-linear based on the number of blobs collected at a time, incentivizing the player to try to risk having a much bigger stack of blobs when collecting, even skipping collectors sometimes, to increase the odds of a massive score increase
The last point is, in my opinion, the most interesting aspect of the design. It forces the player to make risk/reward tradeoffs and baits them into riskier behavior that they wouldn’t otherwise engage in if the blobs were always worth the same number of points.
To keep things simple, I assumed that everything would be separated into rows, which each row containing a blob and/or some spikes, with some rows containing now blobs and some rows containing no spikes. The UFOs would get their own rows and be bigger than everything else to reinforce their importance. The next step was to figure out the specifics:
- How big should the items on the screen be?
- How many items in a row?
- How far apart should a row of items be?
After a lot of experimentation, I settled on some numbers and a grid system that required items in the same row to be two grid spaces apart instead of just one.
(Also: All of the theming is based on whatever simple art I could get for free from OpenGameArt. Thanks, random people!)
Blob Catcher was always going to be an “infinite runner” style casual game, with an infinite procedural level that would speed up over time. The next step, then, was to create a procedural system to do this.
I won’t go into every detail here because the code is actually quite well-organized, labeled, and commented. Here’s a high-level summary:
- Store every possible row pattern that could spawn in an array
- Every N ticks (based on the current game speed, so the rows are always the same distance apart), grab a random row pattern
- Loop through the pattern and spawn a spike for every 1 that appears in the array and a blob for every 2 that appears in the array (spawn at X position i [array index] times 33 [grid size] plus 27 [x offset from the left side of the game bounds that the grid starts]
- Initialize all of those spawned objects so they start moving downward at the same speed of everything else
- If the countdown to a UFO appearing reaches zero, spawn a UFO at a random grid location instead and skip everything else
There’s an exception for the first three ticks, which always spawn the same items every game to help acclimate players, as a mini-tutorial:
- A specific pattern of spikes
- One blob
- A UFO
One Last Thing: Powerups
A lot of my time working on Blob Catcher once I switched to Phaser was at a short-lived local game development meetup. (Fun fact: This meetup was hosted by Colin Feo, who is now the CEO/founder of Windwalk Games!)
The people at the meetup played the game, and someone suggested I add special blobs to act as power-ups. Long story short, I did, and it worked out great.
There are four types of power-ups:
- Fire, which blows up all spikes on the screen
- Slow, which slows the game a bit to make things easier
- Shield, which adds a shield that protects from damage one time (again, Sonic the Hedgehog influence)
- Invincibility, which lasts a limited amount of time
The implementation and design of these power-ups is relatively straightforward, though I will add that the utility of Slow is dubious so when I recreated the game as Stranger Cubes I didn’t include it.
What is interesting about the power-ups is how they’re distributed.
Rather than rewrite this, I’ll just quote the comment from the code itself. (By the way, I think this is how code should be commented, even for solo developers. Because there’s no way I would have remembered this several years later!)
// Okay, here's how we're going to do this: // Take the frequency value of each blob type config and, // at the start of each level, get a random in between that value // and countdownRange value, and load it into this object. // Each tick, subtract 1 from every one except basic. // The first one to hit zero gets dropped and then re-rolled, // with basic being the backup if none get dropped. // This should ensure that everything drops at a relatively even // frequency with no dry spells and with a very very low chance // of the same powerup twice in a row.
Pretty cool, right? Basically, I wanted the power-ups to drop randomly, but not so randomly that it was possible to have streaks with too many or too few of any specific item.
Wait, does that say levels? Well, the procedural generator has the idea of a “level,” which is a chunk of generated content. After every “level,” the game speed is increased by a tiny amount. To compensate for the fact that the same amount of generated content will go by faster, the length of a level also increases in proportion with the speed. Pretty cool, right?
So, what happened to Blob Catcher? Well, I did initially release the game on Facebook’s Instant Games platform. It didn’t do particularly well – retention was poor. Acquisition was basically a black box; When the game went live, Facebook dumped tens of thousands of users into the game in just a few days (cool!), but almost nothing after that. At the platform documentation’s suggestion, I tried to add some Messenger integration for people to challenge each other with high scores, but it didn’t help much. And because Facebook’s analytics don’t really explain where users come from or how to get more of them (short of buying ads), there wasn’t really anything else I felt I could do with a ‘spare time’ project to improve the situation.
On the other hand, I did know that I could rebuild the whole game in Unity in a few days, which is what I did. I pushed the Unity version of the game out to iOS and Android for funsies, and that was that.
Well… sort of. My original vision for the game actually involved some kind of cool-looking abstract shapes (at least, that’s what I saw when I closed my eyes and thought about the game before I went to sleep), so my next project was to recreate the whole thing as Stranger Cubes. (Essay on that: Coming soon.)