Design Dive: Dome Keeper

I discovered the game Dome Keeper in October of 2022. It’s a Godot game, and it had a cool premise—tower defense mixed with resource mining in a sci-fi atmosphere—so I bought it. Since then, I’ve played Dome Keeper on a near-daily basis, and I haven’t gotten tired of it yet.

Why do I like it so much? I decided to analyze the gameplay and try to figure that out. If I can understand why I like playing a particular game, that will help me figure out how to better design my own games.

I decided to focus on two categories: the gameplay of Dome Keeper itself, and the “environment” surrounding how and when I play Dome Keeper. Both impact my overall feeling for the game and why it’s so much fun for me to play.

I totally didn’t get distracted playing Dome Keeper while writing the blog post, I was doing field research!

The Gameplay

There are three parts to Dome Keeper’s gameplay: mine digging, resource management, and monster fighting. Additionally, there are a number of “rush moments” where these three systems come together to create awesome moments.

All runs start with carving out your initial tunnel.

Mine Digging

Digging a mine is simple: move down below the dome and start drilling into the nearest block (if you’re the Engineer character, anyway). This feels like digging mines in Minecraft (another activity I’ve done a lot). Why do I like it? I think it has to do with being able to structure a plan for what an “ideal” mine shaft looks like and then imprint that pattern onto the pixelated rock tiles.

I’ll be ignoring the Assessor character for this post because I almost solely play as Engineer; it just fits my preferred style of play better.

I’m not content with just digging tunnels, though; I need a goal in doing so. That objective is finding new resources: iron, water, and cobalt. These resources all contribute to improving my capabilities (more on that in a bit), so they have endogenous value within the game. Because of that value, they’re worth finding, so it gives me a small burst of dopamine when I find them. The way I dig my tunnels allows me to ensure I don’t miss finding anything.

I don’t know why digging optimal patterns to find resources is so soothing to me…but it is.

Finding iron, water, and cobalt is only part of the mining story; I also have to carry those resources back through the mine shafts to my dome, where they are processed for use. At the beginning, the game limits how many resource units I can carry, resulting in a cap to how quickly I can mine. Over time, I can upgrade this carry limit, so the efficiency improves. That visible sense of progress feels good as I play, and it further feeds into the value resources have.

There’s other things which can be found underground, too. The other main discoverable items are gadgets, which you have to dig out and carry back to your dome. Once there, they provide some beneficial functionality, including the ability to teleport between your base and a movable portal (Teleporter), a gravity lift which pulls resources in it up to the dome (Lift), and high-powered explosives you can drop to destroy lots of rocks at once (Blast). There are also other minor things to discover under the rocks which aren’t directly part of the dome, like a small creature that ferries one resource at a time, a seed which you can plant on a resource to create a “tree” growing that resource, and a device that, when activated with two iron cubes, gives you X-ray vision to see through two layers of rock. These things add a touch of surprise when you come across them in your digging, and the variety which can be found keeps things interesting.

I’m not sure what this called, but picking it up gives you a massive speed boost. That’s fun to randomly find!

Finding resources and helpful items is only one facet of Dome Keeper’s gameplay. Once you bring those things back to your base, you need to do something with them.

Once your resources have been brought back for processing, you get to choose where to spend them. There are multiple things you can upgrade, and making the right choices about which upgrades to get when is important.

Resource Management

You are underpowered when you start a new run of Dome Keeper; it takes quite a few hits for your drill to break apart the rock, and even longer when that rock contains a resource. The first thing I always do is to mine enough iron to increase my drill’s power so I can dig faster. Immediately this provides visible feedback in the form of faster digging, and passive feedback in that I can get future upgrades sooner. This kind of tangible feedback feels great, and it keeps building up with each upgrade you purchase.

The upgrade UI is nice and clean, so it’s obvious what you’re getting and what it leads to in the progression tree.

I didn’t have to choose upgrading the drill first, though; I could also have chosen to upgrade my mining speed, or the power of the laser weapon on my dome, or even the ability to see how much time I have before monsters come within firing range of the dome. There’s a plethora of choices to make, and strategizing to buy upgrades at the right time in order to maximize my chances of survival is enthralling. Even choices which feel worthless (like buying an indicator that tells me how many waves I’ve survived) feed into the thrill of strategic decision making; by having some options that are obviously worthless, it gives me the thrill of knowing I’m making a correct choice by avoiding them.

The dome and the keeper aren’t the only things to upgrade, either. The gadgets you find buried under the dome also have their own small upgrade tree, which makes them even more fun to use. Some of the upgrades improve efficiency, like adding additional orbs to the Lift to bring more resources back faster. Others change gameplay entirely, like the Teleporter gaining the ability to teleport resources and providing an alternate means of getting resources back to your base. As I play, I also develop partiality towards certain gadgets based on how I like to play (teleporter and lift are go-to gadgets) while others have less value (like the probe and the Drillbert robot). If I bring back a gadget and it turns out to be something I don’t want, I get to choose to shred it for cobalt, which helps prevent me from feeling like I brought back something worthless.

Spending resources on upgrades is important for improving my ability to mine more effectively. Just as important, however, is improving the ability to defend my dome.

Turns out we weren’t alone, after all.

Monster Fighting

The final element of Dome Keeper’s gameplay trifecta is base defense. Every so often, monsters will approach from across the surface of the planet you’ve landed on and attempt to destroy your dome. Losing your dome means losing the game, so you have to prevent this from happening at all costs. Fortunately, this part of gameplay feels fun, and the combat introduces further opportunities for strategic thinking.

Firing a laser feels so darn fun! It’s a straightforward beam of light that melts the health of any monster it hits for as long as you keep it trained on said monster. The effects feel nice and juicy, from the wavy effects of the beam to the small particles that shoot from along the beam trail, from the satisfying shoom sound of the laser to the small controller rumble that happens while I’m opening fire.

Over time, bigger and bigger monsters approach, in greater numbers, so you must upgrade in order to survive. The laser can be made more powerful, and the dome can be improved with greater health and resistance to damage. These upgrades cost the same resources that you use to build up your mining efficacy, so there is a constant tug and pull of when to upgrade your mining to get resource faster and when to upgrade your defense so you can continue to survive.

Time to upgrade my laser. That means it’ll be awhile before I can afford upgrading other things, but I need to start killing monsters faster to reduce time to kill, and with it base damage.

There’s even strategic gameplay in the moment to moment of battle. You can’t move your laser instantaneously, so where you move it to impacts how much damage you take. If you move it to the side with fewer monsters, then that’s more damage coming your way before you can shift the laser back to the other side. If you take enough damage, you need to pop out of laser mode to make repairs (done simply with a payment of cobalt), so you need to make sure you stay on top of how much health you have.

A recent update to Dome Keeper added an upgrade that automatically fixes your dome when it runs out of health, if you have the resources to afford it. It’s something I always get because of how convenient it is, but having it definitely removes a lot of that tension which previously came from managing health in battle.

Overall, fighting the monsters feels good, and figuring out the optimal times to upgrade and the best battlefield tactics for minimizing damage feels continuously interesting. The best moments of Dome Keeper, however, come from when these three tenets of gameplay interact with one another to create thrilling results.

I like to keep my laser in the center of the dome prior to starting the battle, so I can pivot quicker to whichever side spews monsters first.

Rush Moments

I’ve already explored some of the ways Dome Keeper’s systems come together to create good gameplay, but there are some more subtle thrills to be had.

While you’re mining underground, you have to keep a constant eye on the monster proximity countdown. Come back too early, and you’ve wasted precious time you could’ve spent doing more digging; come back too late, and you’re going to take some hits and get behind in your defense. If you get things exactly right and dash back into the base just as an attack wave starts, it creates an incredible rush.

Even in failure to calculate things correctly, it still results in powerful feelings, from the panicked adrenaline burst as you scramble back to the tune of the proximity alarm’s beeping to the relief you feel as you exterminate the last monster in a wave with a sliver of health remaining, able to fight another day. Importantly, you aren’t left with the taste of defeat from these moments; you feel as though some bad decision you made was your near downfall, and formulate solutions to prevent yourself from falling into the same bad situation again.

Whoops, didn’t play that one right. I’ll do better on the next one.

Finally, reaching an endgame moment provides its own thrill. Whether it’s the relic from Relic Hunt mode, to making the decision that you have enough score to trigger the sendoff in Prestige mode, reaching the end goal feels powerful in that the end is in sight, if only you can hold out and play well just a few moments longer. It can even turn into a bit of mastery, where you know you can win right now, but choose to try and play as long as you can, betting on being able to squeak out a win just before becoming overwhelmed.

My Environment

The gameplay itself is enjoyable, but just as important for me is how well it fits my lifestyle. I don’t get much time to play games, I don’t enjoy spending lots of time learning how to play them, and short and sweet games usually don’t feel cool enough for me to enjoy playing them. Dome Keeper manages to hit a sweet spot for all three of those metrics, and I’ll explain how.

Hmm…find resources more easily, or improve my base defense? Or, perhaps, take the cobalt to repair my base? Choices, choices.

Time Spent

I don’t have much spare time. In addition to spending 40 hours a week doing my day job, I spend at least 16 hours a week on developing my own games, and at least half of the remaining time in various family activities. I simply don’t have time anymore for epic games that cost me dozens of hours of gameplay, like I did as a teenager and in my early twenties.

The gameplay of Dome Keeper is such that I can easily fit a meaningful gameplay session in roughly 20 minutes. It doesn’t feel like I’m hard pressed to end the session, either; a full cycle takes roughly 2-3 minutes, so it’s not hard to find a natural stopping point.

I do confess to sometimes finding it hard to stop because of that “just one more thing” mentality, though. Gotta find out what that gadget is before I quit my session, right?

Completing a full round of Dome Keeper takes, at most, a couple of hours. That’s enough time for me to finish a run at least once each week. Game completion gives me a great sense of resolution, even if said run ends in defeat. Comparatively, games with a massive story and lots of content can easily take me months to reach a completion point, and playing the same game that long without resolution leaves me feeling frustrated. Thus, Dome Keeper’s short run time is something I enjoy a lot.

As someone who has a life to live and games to develop, it’s easier for me to enjoy games that have short core sessions and modest run times; in those regards, Dome Keeper’s timing fits my sweet spot almost perfectly.

Don’t mind me, I’m just hauling some iron.

Simplicity

Similarly to how I have less time to play games, I have less time to understand the complexity of a game’s loop. If something takes a lot of time for me to learn, I have a lot less fun playing it; at the same time, if the gameplay is too simple, then it’s boring. Once again, Dome Keeper manages to hit a perfect balance for my tastes.

Having only a small number of resources to manage helps keep the complexity down. The fewer compounding interactions I have to keep track of, the easier it is for me to understand those resource interactions. I think the number three, in particular, is just right. Having only two resources would make for not much challenge at all, and having more than three, while not impossibly complex, would add more information for me to comprehend, and make the game slightly more difficult to get into.

Relic found! Time to dig it out and bring it back to the base…

Speaking of complex interactions, Dome Keeper has a lot of them. It may not be obvious at first, though, because those complexities arise from the combination of simple interactions. Buying a drill upgrade? Easy to understand the value. Buying a more powerful laser? Also easy to understand. But what if you only have the resources to buy one upgrade or the other? Less powerful drill means it’ll take longer to get more resources for upgrading, but less powerful laser means you might not have enough firepower to prevent the next wave from doing a lot of damage. Those two simple interactions (upgrading the drill and the laser) combine to form a complex strategic decision, one that changes from run to run depending on the situation I’m in. I love simple ideas that combine to form deep strategies, and Dome Keeper is full of such interactions.

Playing the game almost feels like routine to me at this point. That may sound like a weird thing to speak of in a positive light, but it makes sense for someone in my position. A routine is something I can measure myself against easily to see how well I’m doing. Following the patterns I’ve established are good feels rewarding when I carry them out with maximal efficiency. Finally, that comfy feeling of following a routine is a pleasant break from the stressful challenges I face in my day job, game development efforts, and family life.

Dome Keeper may seem like a simple game to play, with not much time spent doing it. For me, that’s a good combination, and everything feels just complex enough that I don’t get bored of playing it the way that I do.

One sec, trying to survive the final fight.

Fun Atmosphere

Finally, the style Dome Keeper is presented in appeals to me. The pixel art is crisp, and easy to read, so it doesn’t take me much effort to read the information I need; it also conveys a good sci-fi atmosphere without needing too much detail. The sound design is great, from the tings of the drill to the crumbling of the rocks to the screams of the monsters as they die. And the music is chill enough to fit well in the background and not pull me out of my mine-digging reverie.

Conclusion

I like Dome Keeper a lot. In studying the game, I’ve realized that its gameplay is a great fit for my interests, and the way it fits into my busy lifestyle makes it easy for me to make small amounts of time to play it.

As a game designer, still working on crafting an enjoyable game, these insights are valuable to keep in mind. I don’t want to design another Dome Keeper, but understanding why I enjoy that game so much aids my own efforts to create games that, hopefully, are just as enjoyable.

The aftermath of the final battle. I survive, victorious once again.

Anchors and Margins and Containers, Godot My!

Note that the title’s joke only works if you use the correct pronunciation of Godot. 😉

As much as I’ve loved using Godot over the years, one of my biggest pain points had been grappling with positioning UI nodes. I work as a web developer for my day job, so I work regularly with CSS. Compared to that, Godot’s UI didn’t feel intuitive, and anything more complex than full-screen positioning frequently resulted in nodes placing themselves in ways I didn’t expect, and it felt like I spent hours duct-taping an interface together. I scoured whatever documentation I could get my hands on, but nothing seemed to help much in the end.

Recently, however, I’ve had some tremendous breakthroughs in my understanding of how Godot’s UI positioning system works. The result is that I now understand that Godot’s UI is actually very simple to use, almost brilliantly so. Suddenly, I was able to put together complex UI scenes easily, and comprehend why my UI looked the way it did. Given all the frustration I’ve felt over the years, these realizations have felt almost miraculous.

I wanted to codify my newfound knowledge in this blog post. Not only will this be a reference I can look back on to refresh my memory, it will help people struggling with Godot’s UI to gain the perspective I have, and thus make UI work a breeze instead of a hurricane.

This is not a tutorial on how to make good UI, but an explanation of how Godot positions UI nodes. That said, I made a Godot project to help illustrate my points, and I’ve made it available for you to download and reference for your own edification.

The project was originally created in Godot 3.5, but I tested opening it in 4.0 and nothing seems to have changed for the worse. The UI around anchors/margins is different, as called out on Twitter by Jaysen Huculak, but the underlying principles are still the same.

Anchors

Let’s start with the first of the foundational elements of UI positioning: Anchors.

Anchors control the boundaries of where a node and its content are drawn on the screen. The unit of measurement is literally, that: a unit, from 0 to 1. What is the unit’s reference? The parent node’s size, which starts from the pivot (which is the 2D coordinate where the node is “located” in UI coordinate space) and extends across horizontal and vertical axes to the full size of the parent node. 0 means you are at the start of the axis (horizontal for left/right, vertical for top/bottom) and 1 means you are at the end of the axis.

That’s tricky to parse with words alone, so let’s look at some images to illustrate how this positioning system works.

Note that this is the Godot 3.5 interface. In Godot 4.0, these properties are nested under the Layout dropdown section.

The above is a simple Control node that is the child of another node that fills the entire viewport. Note that all the anchor values have been set to 0. Correspondingly, the node’s size is also zeroed out, so you can’t see anything of that node’s contents.

If you create a Control node with Godot’s editor interface, it will not look like this despite also having 0’s set for the anchors. I’ll explain why later in the article.

Let’s see what happens when we set the right and bottom values to 1 (or 100% of the parent’s size horizontally and vertically).

Suddenly, our node stretches fully across the available viewport space. By setting right to 1, we told Godot to expand the right edge of the node all the way across the parent node’s bounding rectangle, across the horizontal axis; it’s the same story with setting bottom to 1, but on the vertical axis of the bounding rectangle, instead.

Just for fun, let’s change the left and top values to 0.5 and see what happens.

Now our Control node looks like it’s in the lower-right corner of the viewport. Essentially, we told Godot to move the left and top edges of our node 50% away from the parent’s pivot origin.

I’m not showing this in the screenshots, but I placed a ColorRect within the Control to make it more obvious how much space it’s taking up. It’s essentially just filling whatever space our Control node is, and isn’t needed in any functional way.

Anchors are just one part of Godot’s UI placement equation. Another critical part of that equation is Margins.

Margins

Margin controls the amount of spacing used from the specified edge. Where Anchors are placed using percentile units, Margins use pixel units.

Let’s take another example Control node, with anchor values right and bottom set to 1.

Currently, the viewport is completely filled. Let’s try adding some margin around the Control so that there’s 16px of space around it.

…wait, that doesn’t look right. There’s 16px of space around the top and left of the Control, as we expected, but the bottom and right sides got pushed outside of the viewport’s visible area.

Why did that happen? It’s simple: Godot doesn’t treat margin as distance into the bounding rectangle. Instead, Margin gets applied along an axis of direction; positive margin is to the right/bottom of the specified edge, while negative margin is to the left/top of that edge.

This is different from how margins work in CSS, and is a big reason why I misunderstood Godot’s UI for so long.

To get the spacing effect we want, we need to apply negative margin values to the bottom and right margins.

That’s more like it.

Just for fun, though, what if we wanted to have our Control’s width exceed the bounding rectangle of the containing node? Simple, we just make the left and top margins negative, and the right and bottom margins positive.

Earlier, I glossed over the fact that creating a new Control node in Godot’s editor doesn’t actually create a node with no size, despite anchors being set to 0. That’s because Godot defaults the new Control’s right and bottom margins to 40px, which results in giving them a default rect_size of Vector2(40, 40). I don’t know of official documentation explaining why, but my guess is that this is to try and minimize confusion around why new controls have no size.

Wait, what’s rect_size? How is that related to margin values? Good questions!

How Anchors and Margins Impact Other Control Properties

While Anchors and Margins are the core aspects that determine a node’s position and size, they do so in coordination with other node properties. Changing the anchors and margins of a node will usually automatically adjust these tangential properties, and vice versa.

Let’s go over what these properties are.

Rect Size

The rect_size property is the actual size of the control node. This can be set directly, but often this gets readjusted based on the settings of the anchors and margins. The important thing to remember is that this value always represents the node’s actual size in-game.

Rect Position

rect_position is the point where the control “is” in the game’s UI space (aka it’s point of origin). Like rect_size, this can be set manually, and is also automatically adjusted based on interactions with anchors and margins.

See how the right margin for this control is 80, but the left margin is -20. This makes the control’s size 100 (80 + 20) and its X coordinate -20.

Rect Min Size

The rect_min_size property forces Godot to never shrink this particular node below the specified size. Unlike rect_size and rect_position, this is never adjusted automatically by Godot. It’s useful for when you absolutely need to have a control not shrink below a certain size, but be careful: it’s easy to abuse this property to hack around badly-set UI properties. (I certainly used it this way!)

Layout Presets

At this point, if you’ve worked with Godot’s UI before, you may have realized something: “This feels awfully similar to what happens when I use the Layouts button!”

That’s because those Layouts are nothing more than common presets for the anchor and margin values. For example, “Full Rect” is the exact same thing as setting top and left anchors to 0, right and bottom anchors to 1, and all margins to 0. Meanwhile, the “Center” preset sets all anchors to 0.5 (aka 50%) and then automatically calculates the margin values such that they are half of the node’s minimum size, resulting in a centered node.

This is the same 100×60 rectangle from the previous image, but with the center preset applied. Note the difference in not just anchor and margin values, but the rect_position as well.

The presets specified were common enough that Godot’s developers decided to make a convenient way to set them, but it can be confusing when you try to use them without understanding how the underlying system works. I’ve definitely had confusion about why a previously “centered” control wasn’t updated automatically when I did something which changed the node’s size. The reason why is because the presets don’t automatically update in response to changes; they just act on whatever you have architected at the time they get used. Thus, if I change something which affects the node’s size, I need to reapply the “Center” preset to get the node to look centered again.

Child Control Nodes

What happens if you change anchors and margins for a child node? Exactly the same thing as changing those values for its parent! All the examples I’ve used to this point have had nodes be children to a root node that matches the size of the viewport, but the viewport itself is completely irrelevant to the sizing of nodes. If you have a sized control, and adjust the anchor and margin values of its children, they will fit within that parent control’s space.

This control has it’s anchors and margins set relative to the viewport-filling parent…
…while its child’s anchors and margins are relative to its own bounding rectangle, instead.

That’s incredibly powerful and predictable, to have a UI system which functions the same for every Control-based node in Godot.

Well, almost all nodes…

Container Nodes are Exceptions

There is a class of node in Godot called a Container. Container nodes themselves can be sized with anchors and margins, just like any other node. However, the children of container nodes get automatically sized and positioned by that container’s internal logic, ignoring (and overwriting) any manually-set size and position values.

You can position and size container nodes within control nodes via the editor…
…however, if you try to change the anchors, margins, or rect_size of nodes within a Container-based node, those values will be automatically adjusted by the container node.

There are multiple kinds of Container nodes, each with their own internal logic for how children size and position are handled. To give a few examples:

  • HBoxContainer aligns its children horizontally.
  • VBoxContainer aligns its children vertically.
  • GridContainer aligns its children within a set grid of columns.
  • CenterContainer centers all direct children to its own center.

Godot’s documentation does call out this behavior, and the layout presets are disabled when working within container nodes (the latter behavior to prevent developers from using them in places where they simply won’t work). If you hadn’t understand how the UI system works overall, like me, then these explanations and behaviors may have felt more like descriptions rather than elucidations.

Size Flags

You do still have some control over the placement and sizing of nodes within a Container, through size flags. Size flags have four types of behavior, for both horizontal and vertical axes (all of which can individually be turned on or off).

fill causes the node to fill the space given to it. That space is governed by both the parent container’s size and the node’s own calculated size.

expand causes the node to fill any space within the parent container not already used by another node. If neighboring nodes are not set to expand, they get pushed by ones that do. If adjacent nodes both expand, they split the space between them.

shrink center causes the node to occupy only its minimum possible size, while also centering its own position relative to its neighbors and its parent container.

shrink end is the same as shrink center, but with the position at the end of the available space instead of the center.

Not setting any of the above flags makes the node act as though a shrink begin property existed.

Here, the first and last child nodes only have their fill flags set. The second and third child both expand horizontally, while the third child also shrinks to center vertically. (Since there are no child nodes of fixed size for that third child, a minimum height of 10px needed to be set)

The important thing to remember with positioning nodes within containers is to not worry about getting the nodes in a specific position or size, but to get them aligned according to whatever ratio you’re trying to achieve. The advantage of this approach is that you can place container nodes anywhere within the UI, and they will automatically take care of placing and sizing their children to match that same ratio.

Why Won’t My Control Node Behave in a Container

Have you ever tried to put a Control node in a Container node and it behaved like this?

You might need to squint to see the white text that’s out of place.

At first glance, it seems like the Container isn’t size-managing the Control, but that’s not actually the case. The truth is that Control nodes, by default, do not adjust themselves based on the size of their own children. (In other words, Control nodes are not Containers!) In fact, the Control node is resized by the Container, but since the Control isn’t expanding to the size of its children its own size is getting set to 0.

There are two ways to get more expected behavior. One is to put a rect_min_size on the Control node so there is something for the Container to resize.

The other way is to use the Control node’s size flags.

Which one should be used? It will depend on the effect you’re trying to achieve. If you just need the node to occupy space, a rect_min_size should do the trick. For more dynamic size adjustment, changing the size flags works best.

Conclusion

This is how Godot’s UI sizing and positioning system works: Anchors, Margins, and Containers. Now that I understand this, I’ve had a much easier time crafting UI that is placed exactly how I want it to be. The system is simple, but until I grokked how it works it felt confusing and unintuitive.

Hopefully, this post helps you better understand Godot’s UI as well!

I used this color palette for the ColorRect nodes I used for visualization throughout the examples. It doubles as a nifty display of what you can accomplish with Godot’s UI!

Postmortem: Belle Bubb’s Sand-Witch Shop

Rebecca and I have spent the last half year working on the same game: Dice Tower (the full release). We hit a milestone of getting the game ready enough to show at a local playtest livestream, and I really wanted to take a break from Dice Tower development. The two of us decided to participate in another game jam; it would let us try making something different, and possibly something that would be worth continuing after Dice Tower was finished.

Participating in more game jams was something we’d intended to do after GMTK Game Jam last year, but we spent so much time focused on Dice Tower that we never made time for it.

After some research into game jams happening at the time, we chose to enter Godot Wild Jam 54. It’s a game jam where only Godot engine-made games were allowed, so we’d get a chance to see other games made in that engine. It was a smaller size game jam than others we’d entered in the past, so the odds that people would play our game (and leave feedback) was higher. Finally, the length of the jam was nine days, and we thought that would allow us to better fit jam work in alongside our normal day job and family responsibilities without taking too much time off.

The game we created was Belle Bubb’s Sand-Witch Shop, and it was about working in a sandwich shop making “cursed sandwiches” (fitting the jam’s theme of “curses”) through 2D drag-and-drop gameplay. Sadly, we were unable to finish the game due to a convergence of multiple major issues; that said, those issues provided great insight into how to get better at making games, so I don’t think our efforts were wasted.

I’ll identify what those issues were, explain why they were problematic, and explain how I’m going to learn from them to become a better game developer.

Even though our game was incomplete, we still uploaded what we had to the jam anyway, so we could get feedback.

Issue: Isolated Tests

The gameplay for Belle Bubb’s Sand-Witch Shop involved doing new kinds of things that I was less familiar with, like drag and drop mechanics, evaluating what constituted a “sandwich”, and having ingredients that could interact with one another both during sandwich assembly and during sandwich consumption (aka “eating”). I chose to try and build each system in isolation and test that each worked well enough before moving on to others.

Creating all the systems in isolation meant there was no gameplay loop for the majority of the game’s development, so there couldn’t be any testing around whether the game was actually fun. Sure, dragging ingredients around and having them interact with one another was cool, but without evaluating them it was just an aimless sandbox experience. Testing the systems independently also meant I couldn’t see how well they’d interface with one another. This had catastrophic consequences when I encountered fatal issues with those systems once they were brought together.

Lesson Learned: No More Isolated Tests

I like making isolated tests because it’s simpler for me to wrap my head around them; I also don’t have to immediately worry about making them work as part of a whole. However, this is twice now that waiting to integrate systems until later in the project has resulted in slower progress. The jam version of Dice Tower was able to recover from this; Belle Bubb’s Sand-Witch Shop was not. Therefore, for games I’m working on the future, I need to build all the systems together at once. That should help me identify integration problems much sooner, and come up with better fixes for them.

Gameplay was to drag ingredients from their containers onto the sandwich being assembled on the countertop. The taste profile on the right would update as each ingredient was added to the sandwich.

Issue: Badly-Designed Resource System

The foundation of evaluating the sandwich structure was a system that made heavy use of Godot’s customizable Resource nodes to store data in complex ways. This was somewhat similar to resource-based work that I’d created for Dice Tower, so I thought it wouldn’t be too much work to do the same kind of thing here. The architecture I came up with involved having the Ingredient resource store references to its UI model, and then the UI model also referencing its own Ingredient resource.

This dual-reference approach led to horrible issues with resource uniqueness. I was treating each Ingredient resource as a unique entity, but Godot treats resources as shared entities; anything holding a reference to a resource refers to the same instance of that resource. Since each ingredient, in design, could have its own unique set of curses and effects, I had to do a lot of duplication when creating new Ingredients and assigning them to models. This created all kinds of bugs where the stored data on a model or resource didn’t match what the game systems expected, and the massive amount of nesting took hours for me to debug.

All that stemmed from one complex resource system. I built multiple such architectures, and then had them all reference each other… The bugs stemming from that hell were the reason we wound up not being able to fully complete the game.

Lesson Learned: Don’t Abuse Resources

Working with Godot’s resources allows for creating powerful customizable systems, but it is incredibly easy to abuse that power to the point of making things insanely difficult to troubleshoot. I need to not use resources so much for the data solutions. At the very least, I need to minimize how much nested resource storage I’m doing, and make sure the architectures I’m coming up with aren’t fatally flawed before building on top of them.

Bringing in a cursed ingredient had an effect on ingredients around it. For instance, the tomatoes were cursed to repel lettuce.

Issue: Too Much Undetected Complexity

I had no idea how complex the game we were trying to make actually was. To illustrate, these are the features which we managed to get into the game. At the time of planning, I thought they were simple:

  • Sandwiches have ingredients
  • Ingredients have curses
  • Curses have effects
  • Ingredients can also have effects
  • The same effects can be assigned to both curses and ingredients
  • Ingredients have individual tastes
  • Sandwich ingredients are combined together to form a recipe
  • They also come together to form the actual sandwich
  • Both of these have a “taste profile” that is the amalgamation of all ingredient tastes
  • They also have an “effects profile” that is the amalgamation of all curse and ingredient effects
  • Recipe and food need to be compared to each other to determine if they are “close enough”
  • All of the above needs to be represented in-game and in UI

That wasn’t even the full scope of what we had originally planned to put into the game. Other ideas include:

  • Randomizing which ingredients have what curses
  • Getting paid for making sandwiches
  • Using earned money to choose what ingredients to buy
  • Having a story about how you sold your soul to keep your sandwich shop alive
  • Post-sandwich order review that included descriptions of what effects your curses had

That was a lot of complexity. It didn’t feel that way at the beginning because I didn’t think things through. The further we got into making the game, the more I realized the amount of effort needed to make all these systems and interactions work was insane.

And, because I waited so long to bring systems together, I didn’t experience this revelation until it became too late to pivot to something simpler.

Lesson Learned: Work Through Systems Implications in Advance

I need to have much better insight ahead of time where potential complexities will arise. The best way I can think about doing that is diagramming them somewhere, on paper or in a whitescreen board app, so I can visualize what systems need to interact with one another. If there’s too much complexity, then it’s a clear sign that I need to scale things back. I’ve been worried in the past that this will make the process take longer, but the consequence of not trying to do so is having things take longer anyway and not realize it until it’s too late.

Other ingredients had effects that could cancel out curses. The cheese, in this instance, cancelled out any Repulsive curse on any other ingredient.

Issue: There Was No Planned Endgame

We came up with an idea for interesting gameplay, but had no concept of what the goal of the game was going to be. I kept putting a pin in it to “come back to” after the other systems were developed. Since none of the other systems were ever fully completed, we never got a chance to figure out what happens at the end.

Lacking this conceptualization of the player’s goal contributed to the underestimation of how much work was needed. There was no way to test the player could play through a core gameplay loop because we didn’t know what said loop was beyond “make a sandwich”. Without that guiding star, it was too easy to fall into a pattern of perfecting the systems with no plan for whether those systems would work well together to create a satisfying resolution.

Lesson Learned: Define the Goal at the Outset

Knowing what the player’s in-game goal is from the beginning not only gives a development target to shoot for in terms of minimum viability, but it also makes it clear what systems really need to be kept to make a fun gameplay experience. That doesn’t mean the goal has to be immutable; in fact, the goal will likely need to be simplified further as development roadblocks cut into available development time. If the goal is known in advance, though, then figuring out how to juggle all the necessary concerns should become much simpler.

To build a sandwich, you would have to account for the curses each ingredient had. You would then have to be careful to make sure the taste profile of those combined ingredients fit close enough to the profile of the sandwich recipe.

Issue: I Was Overworked

As mentioned previously, we’d spent a long time before this working on Dice Tower. In that entire time, I hadn’t really taken a break, and this caught up with me during the jam.

I’m no stranger to pushing through burnout—I don’t think I’ve ever fully recovered from burning myself out nearly a decade ago—but I underestimated how much easier it is to work through burnout when on a consistent, slow grind. When I needed to work fast and come up with good ideas quickly, my brain refused to cooperate. That’s one of the reasons I didn’t have a good grasp on how complex the ideas were: I couldn’t think far enough ahead to evaluate the consequences of those ideas, so I instead ignored that part of the process to work on the next thing necessary. The consequence of working through major burnout was significantly slowed progress, much too slow for a game jam. Subsequently, since I fell behind pace, I didn’t give myself time to rest during the jam, which only further exacerbated the mental problems I was dealing with. It was a nasty negative feedback loop.

Lesson Learned: Take a Break!

I’m bad at taking time off to actually take time off. I also know that it’s easier for me to push through tiredness and make progress if I do it consistently. But there’s a limit to how much grind I can endure, and I need to respect that. At the very least, I should take some time off from game development and other project work prior to starting a new game jam, to give myself time to recharge properly. That should hopefully make it easier for me to work and plan properly, and thus also make it easier to not feel like I’m falling behind, resulting in pacing my work schedule appropriately.

There were lots of possibilities to work with, both for ingredients and for effects.

Conclusion

I entered a game jam with the intent of working on a different project which might become future inspiration. Instead, I endured an experience that revealed multiple flaws with how I approach game development. Though the experience was painful, the lessons I learned from it are valuable, and that makes me glad for having gone through it.

Lest this postmortem post make it seem like the entire project was a disaster, let me highlight some of the things that did go right:

  • People liked messing around with making the sandwiches, so there is an idea there which might be worth future exploration.
  • While the resource system was buggy, it did allow for relatively easy creation of ingredients, curses, and effects.
  • Of all the things that got cut, at least sound and music weren’t among them this time!

Our focus is going back to Dice Tower, but we definitely intend to enter game jams more frequently in the future. Even when the projects don’t succeed in being good games, they succeed in being great teachers.

…and that’s a wrap! (Please clap.)

Postmortem: Dice Tower

This July, Rebecca and I took part in Game Maker’s Toolkit Game Jam 2022 (an annual game jam hosted by the creator of YouTube channel Game Maker’s Toolkit, Mark Brown), making a game called Dice Tower in only fifty hours. It was our first game jam in a long time, having spent the last three years focusing (and failing) on making our “first big release”. Those fifty hours proved to be an intense, fulfilling experience, and I want to examine how things went. I’ll start with the goals that Rebecca and I made, continue into what happened during the jam, and conclude with whether I felt our goals were met and what we’ll do in the future.

Our Goals

First and foremost, Rebecca and I wanted to actually release the game! Our last jam effort, Rabbit Trails, never saw the light of day because we didn’t get the build submitted in time, and we were determined to avoid making that mistake again.

I wrote briefly about this experience as part of my retrospective on 2019.

To that end, we explicitly wanted to scope our game small enough that it had a realistic chance of being completed by jam’s end. Further supporting that goal, we also decided that we would avoid trying to come up with something “clever”; we would be fine with coming up with feasible and fun ideas, even if they might be ideas that other people were likely to come up with. Finally, we determined that we would specifically make a 2D side-scrolling platformer, because that was the genre we were most familiar with; we didn’t want to waste time figuring out how to do a genre that we lacked experience in making.

Based on what had happened in previous jams, we had a few other goals we wanted to meet. Given that our previous games felt bland, we wanted to make sure whatever we made felt more polished and juicy, thereby increasing how good it felt to play. Previous jams had left us feeling burnt out and exhausted, and, while that is a traditional hallmark of game jams, we strongly wanted to avoid feeling that way at this jam’s end, so we made plans to limit how many hours we’d work per day so that we’d have time to relax and get our normal amount of sleep.

Separate from the in-jam goals, we had one ulterior objective: we wanted to see if the idea we came up with was good enough to develop further into a small release. The game we’d been working on, code-named “Squirrel Project”, was still very much in the early prototyping stage; we’d built and tried a lot of things, but made little progress in actually putting together a full game experience. Both of us felt concerned with how much time we were taking in making a “small game”, so we were interested in seeing if doing game jams might give us smaller concepts that would be easier to develop and release quickly. This jam would serve as a proof of concept for this theory.

Day One (Friday, 7/15/22)

The day of the jam arrived. Our son was off spending the weekend with relatives, we’d prepared our meal plan for the next couple of days, and I’d taken time off from my day job. We sat around my laptop, awaiting Mark Brown’s announcement of the theme. At noon, the video was released, and we saw the theme emblazoned on the screen:

Roll of the Dice

Initial Planning

I hated the theme at first impression. One of my takeaways from working on Sanity Wars Reimagined (our first-ever full release) was that working with randomness in game design was hard, and now we had a game theme which strongly implied designing a game focusing around randomness. In my mind, it would be harder to design a game around dice that wasn’t random in some way. Concerned now with whether we would have enough time to make a good game, I started brainstorming ideas with Rebecca.

We spent that first hour working out an idea; the first idea we hit upon wound up dominating the rest of our brainstorming session, to the point that we didn’t seriously entertain anything else. The game would be a rogue-lite platformer, where you moved to various stations and rolled dice to determine which ability you got to use for the next section of gameplay. Throughout the level would be enemies that you could defeat to collect more dice, which would then give you a better chance to roll higher at the ability checkpoints, thereby increasing your odds of getting the “good” abilities.

I intentionally wanted to minimize the randomness of our game so that players felt they had some level of control over the outcomes of dice rolls, and I liked the idea of using dice quantity to achieve this outcome. The more dice you add to a roll, the more likely you are to get certain number totals. This is known as a probability distribution.

At the end of that hour, we formally determined that this was the idea we wanted to work with. Rebecca started crunching out pixel art, and I got to work making a prototype for our envisioned mechanics.

That Old, Familiar Foe

The next few hours of my life were spent working on the various elements that would serve as a foundation for our mechanics. I threw together some simple dice code, along with dice containers that could roll all the dice they were given. I also pilfered my player character and enemy AI code from Squirrel Project, to jumpstart development in those areas.

But something happened as I started trying to work out how I was going to make the player’s abilities work: my brain began to freeze up. This was a frighteningly familiar sensation: I’d felt this way near the end of developing the original Sanity Wars (for Ludum Dare 43). Dark thoughts started clouding my mind:

There’s not enough time to make this game.

You’re going to fail to finish it, just like your last game jam.

Is what you’re feeling proof that you’re not really good enough to be a game developer?

Slowly, I forced myself to work through this debilitating state of mind. After several more hours, I came up with a janky prototype for firing projectiles, and a broken prototype for imparting status effects on the player (like a shield). It occurred to me that if I was having this much trouble making something as simple (cough cough) as player abilities, then how was I going to have time to fix my glitchy enemy AI, and develop the core mechanic of rolling dice to gain one of multiple abilities, and make enough content to make this game feel adequate, let alone good. Oh, and then there was still bugfixing, sound and music creation, playtesting…

It finally hit me: This idea wasn’t going to work. There was simply too much complexity that was not yet done, and I was struggling with the foundational aspects that needed to be built just to try out our idea. There was no way I would be able to finish this vision of our game on time.

My mind in shambles and my body exhausted, I shared my feelings and concerns with Rebecca, and she agreed that we needed to pivot to a new idea. We tried to come up with something, but we were both too tired to think clearly. Therefore, we decided to be done for the evening, get some supper, and head to bed.

Note the lack of planned relaxation time.

As I lay in bed, I fretted about whether we could actually come up with a new idea. That first idea was by far the best of what few ideas we’d been able to come up with during our brainstorming session; how were we going to suddenly come up with an idea that was good enough and simpler? With these worries exhausting my mind, I fell asleep.

This is the first thing I made, a simple test with a dice container and N number of dice. It felt oddly satisfying to keep pressing the “Roll Dice” button.

Day Two (Saturday, 7/16/22)

The next morning, at 6am, I woke up, took a shower, and played a video game briefly. This was my normal morning routine during the workday, and I was determined to keep to it. At 7am, I grabbed a cup of coffee and sprawled out on the couch, pad of paper and pen resting upon an adjacent TV tray, prepared to try and come up with a new idea.

Rebecca joined me at 7:30am, after she did her own waking routines.

The New Idea

I wrote down the elements we already had: Rebecca’s character art and tileset from her previous day’s work, some dice and dice containers, and a player entity that was decently functional as a platformer character. If our new idea could incorporate those elements, then at least not all of yesterday’s work would go to waste.

After thinking about it for a long while, I hit upon an idea: what if you rolled dice to determine how much time you had to complete a level? As you moved through each level, you could collect dice and spend them at the end-of-level checkpoints to increase your odds of getting more time to complete the next level. If that were combined with a scoring system involving finding treasure collectibles that were also scattered throughout each level, then there’d be potentially interesting gameplay around gambling how many dice you’d need to collect to guarantee that you had enough time in each level to collect enough treasure to get a high score.

I pitched the idea to Rebecca, and after some discussion about that and a few other ideas, we decided this was the simplest idea, and therefore had the best chance of being completed before the deadline. Fortunately, this idea also did successfully incorporate most of the elements that we’d worked on yesterday, so we didn’t have to waste time recreating assets. On the other hand, this idea needed to work; there was likely not going to be any time to come up with another plan if we spent time on this one and it failed.

Our idea and stakes in mind, Rebecca and I once more commenced our work.

Slogging Through the Day

I created various test scenes in Godot. Slowly, I began to amass the individual systems and entities that I’d eventually put together to form the gameplay. Throughout the day, I felt very sluggish and lethargic mentally; this was likely a side effect of the burnout I’d put myself through yesterday. I kept reminding myself that some amount of progress was better than none at all, but it still didn’t feel great.

By the start of that evening, I had a bunch of systems, but nothing that fully integrated them. Taking a break, I went outside for a walk and some breaths of fresh air. As I trod the trails in our neighborhood, I worked out the game’s next steps. I reasoned that if I continued to put each system and entity together in isolation and test them, I stood a realistic chance of running out of time to put everything together into a cohesive game. Therefore, I decided to forgo this approach, and simply put everything together now, and build the remaining systems as I went along. This flew in the face of how I traditionally prefer to program things, but I resolved to set aside my clean code concerns and focus simply on getting the game working.

This might look like a game level, but it was really just a single test scene that I was throwing my creations into. There was no logic connecting any of these things together to form a gameplay loop.

The Late Evening Dash

Not long after I returned from my walk, it became 7pm. This was the twelve-hour mark, and in our pre-jam plans I’d determined that I wouldn’t work more than twelve hours on Saturday. Yet I still didn’t have much that was actually put together. I was now faced with a conundrum: should I commit to stopping work now, and risk not having enough time tomorrow to finish the minimum viable product?

Ultimately, I decided that I would try to get an MVP done tonight, or at least keep working until I felt ready to stop. Three hours later, while that MVP was still incomplete, I had put together the vast majority of what was needed to make the game playable: a level loading system, the dice-rolling checkpoints, dice collection (though said dice weren’t yet connected to the checkpoints), the level timer and having it set from rolling the checkpoint dice, rudimentary menu UI, and player death. At this point, I felt that continuing to work would just cut into my sleeping time, and I was still determined to get a proper amount of sleep. At the least, those few hours had produced enough progress that I felt confident that I could finish things up tomorrow morning.

I quickly prepared for bed, and after watching some YouTube to wind down I fell asleep.

One of three tutorial levels I’d created that night. This one is to teach the player that they can pick up dice; when they advance to the next checkpoint, they’ll see that newly-collected die in their dice pool, and hopefully make the connection between the two actions without having to explicitly spell it out.

Day Three (Sunday, 7/17/22)

That morning, I woke up at 6am, as usual, but this time I skipped all of my morning routine save the shower. By 6:30am, I was at my computer and raring to go.

Blazing Speed and Fury

The first thing I did was export the game as it currently was. I’d been burned enough times by last-minute exports that I was determined to make sure that didn’t bite me in the butt this time. Fortunately, this time there were no export-specific crashes or bugs, so I resumed work on the game proper.

For the next several hours, my mind singularly focused on getting this game done. I finally made the checkpoints accept the dice you collected, thus completing the core loop of rolling dice to determine the time you had to make it through the level. I added game restart logic, added transition logic for when the player was moving between levels, added endgame conditions and win/loss logic, and fix various bugs encountered along the way. I also realized that I wouldn’t have time to implement a scoring system, so I unceremoniously cut it from the MVP features.

Cutting the scoring system also meant cutting the third tutorial level, which would have taught the player about the treasure collectible. Additionally, it would’ve served as a prelude to the intended tension of collecting treasure to increase your score and collecting enough dice to have more time in the next level.

Around noon, I finally had the game fully working. I could boot the application, start a new game from the main menu, play through all the designated levels, and successfully reach the victory level to win the game (or run out of time and lose). If nothing else, we at least had a playable game!

Final Push

The game jam started at noon on Friday, and as it was now noon on Sunday that meant 48 hours had passed. Thankfully, the jam had a two-hour grace period for uploading and submitting games to Itch.io. That meant I had less than two hours to jam as much content and polish into the game as I could before release!

I blazed my way through creating six levels, spending less than an hour to do so. Of course, that meant I had little time to balance the levels properly, beyond ensuring they could be completed in an average amount of time. One thing I did spend time on was adding the various pieces of decorative art Rebecca made to each level. It might seem frivolous to add decorations, but I think having a nicely-decorated level goes a long way towards breaking up level monotony and sameness, and honestly it didn’t take that long for me to add those things.

After a few trials, I hit upon a solution for balancing the randomness for the dice checkpoints: I’d give the player six free seconds at the start of each level, and a single die at each checkpoint (in addition to the ones collected through gameplay). As I playtested the level, that at least felt long enough that, using probability curves, the average player could have a decent chance of finishing each level.

Intentionally, I chose to not focus at all on adding sound effects and music. My reasoning went thusly: players would probably prefer to have more content to play through than have sound and music with very little content. It made me remorseful, because sound can make an okay game feel great, but there just wasn’t enough time to do a good job of it, so I decided it was better to just cut audio entirely.

Finally, at 1:30pm, I looked at what we had and determined it was good enough. Rebecca had been working on setting up our Itch.io page, and I gave her the final game build export to upload to the store page. We submitted the game just in the nick of time; shortly after our submission was processed, Itch.io crashed under the weight of thousands of last-minute uploads. While this server strain prevented us from adding images for our game page (we got them in later), at least we already had the game uploaded and submitted, so we weren’t in danger of missing the deadline.

Rebecca and I looked at each other. We’d done it! We’d successfully made a game and submitted it! We spent the rest of the afternoon out and about on a date, taking advantage of our last bits of free time before returning to parenthood the next day.

Feedback

Over the next week, our game was played and rated by people. We received multiple comments about how people enjoyed the core idea, which was encouraging.

A couple of our friends from the IGDA Twin Cities community took it upon themselves to speedrun our game. This surprised me, because I thought the inherently random nature of our game would be a discouragement from speedrunning. They told me they enjoyed it a lot, however, and over the course of that week they posted videos of ridiculously speedy runs and provided good feedback.

By happenstance, the Twin Cities Playtest session for July was that same week, so Rebecca and I submitted Dice Tower to be played as part of that stream. Mark LaCroix, Lane Davis, and Patrick Yang all enjoyed the game’s core concept, and gave us tremendous feedback on where they felt improvements could be made, as well as different directions we could go to further expand and elaborate on the core mechanic. It was a great session, and we are greatly indebted to them for their awesome feedback.

After the play-and-review week had passed, Mark Brown made his video announcing the winners of the jam, and we got to see our final results online (we did not make it into the video, which only featured the top one-hundred games).

For a game jam with over six thousand entries, we did surprisingly well, placing in the top 50% in overall score. Our creativity score was in the top third, which pleased me greatly; it felt like further validation that our core concept was good enough to build on.

Reflection

I want to circle back to those goals Rebecca and I set before the jam, and see how we did in meeting them. There were a couple of other takeaways I had as well, which I’ll present after looking at the goals.

Did We Meet Our Goals?

First and foremost, we wanted to release a game, and we did! That was huge for us, given our last effort died in development. In particular, to release this game after the mental fracturing I endured on Friday night, and having to pivot to a new idea, shows that, perhaps, we’re decent game developers, after all.

Did we scope our game properly? At the beginning, no, definitely not. Fortunately, we recognized this (albeit after spending a day on it), and decided to change to a more feasible idea. Even though we had to cut scope from the new idea as well, the core was small enough that we were able to make it in the time allotted. It gives us a new baseline for how much work we can fit in a given amount of time, which should serve us well in future endeavors.

It’s a similar story for our theme interpretation. Our first idea seemed simple, but turned out to be complex under the hood, as it’s a lot of work to not only add lots of different player abilities, but game entities (such as enemies) to use those abilities on. In hindsight, I laugh at how we thought that kind of game was feasible in 48 hours, with not nearly enough foundation in place beforehand. That said, once again, we pivoted from the complex to the simple, and the new theme interpretation was simple enough to be doable.

Ironically, I thought this would be a common enough idea that plenty of other people would do it, but I actually never encountered a mechanic similar to this during my plays of other jam games, and multiple people commented on the novelty of the idea. Perhaps our focus on coming up with a good idea instead of a unique one managed to get us the best of both worlds!

We stuck to our guns and made a 2D side-scrolling platformer, even though at times I felt like that made it more difficult to find a good theme interpretation. Because we knew how to work in that genre, it made our mid-development pivot possible; I don’t think we could have been successful in doing that if we’d tried to make something unfamiliar to us. Additionally, I think using a genre where dice are less commonly used led to coming up with something more unique than we might’ve if we’d done an RPG or top-down game (two genres I thought would be easier fits for the theme).

One area we did miss on was making this a polished release. The missing audio was sorely felt. That said, I really like the art that Rebecca came up with, especially the decorations, and I don’t regret the decision to cut sound in favor of making levels and placing her doodads. Honestly, despite the missing audio, the fact that this game was fun and playable made this jam release feel more polished than our previous jam efforts.

That dice banner and the dice family portraits were particularly fun to place throughout the levels.

A big success we had was in self-care management. Even though we didn’t stick to the maximum hours per day we set before the jam, we took care to make sure we got enough sleep each night. The end result is that this is the first jam we’ve done that both of us didn’t feel utterly spent at the end of it. That allowed us to enjoy a lovely afternoon and evening together as a couple, and we didn’t feel totally shot for days thereafter. I think that also helped us have the energy needed to push us through to the finish line.

One final goal remains to be evaluated: was our game good enough to base a future release upon? The answer is “yes”. Based on the enthusiastic feedback we received, plus our own thoughts about where the concept could go, we’ve decided to put Squirrel Project aside and focus on making a full, but small, release out of Dice Tower. With some more features and polish, and maybe a dollop of background story to tie things together, we think Dice Tower could make a good starting point for our first paid release.

Additionally, we plan to take part in future game jams, and further explore the concept of making quick games to find small ideas with good potential.

Other Takeaways

There were some additional things we learned from the jam. These emerged as byproducts of the things we tried during the jam.

Our initial thoughts were that we’d spend our brainstorming session coming up with multiple ideas, and then make small prototypes for each of them and decide which of them was the one we wanted to make. It didn’t turn out that way; both our first and second attempts settled early on a single idea, to the point where we didn’t really have many other ideas that we seriously considered. I think that perhaps that’s just how Rebecca and I work; it’s easier for us to jump into an idea and try it rather than piece a bunch of ideas together and flesh all of them out on paper. Perhaps in our next jam, then, we’ll deliberately settle on an idea right away and just go for it, making explicit allowance for pivoting if it starts feeling like too big an idea to work with.

Personally, I also learned that I need to let go of trying to test every little thing in isolation. That may be a good approach for building long-lived, stable systems, but for something as volatile as game prototyping it just slows the process down too much, with no game to show for it. By putting things together as early as possible, it makes things feel more real because it is the real game! I’ll keep this in mind for future projects, to just make a go of it right off the bat, and save my efforts to make things nice and tidy for when the ideas are codified and made official.

Conclusion

Ultimately, I’m glad Rebecca and I decided to participate in GMTK Game Jam 2022. It feels exhilarating to not only finish a game in that short amount of time, but to defeat some of my internal demons from previous jams in the process. We feel more confident in our ability to develop and release games, and we’re excited to tackle making the full release of Dice Tower.

It’ll be interesting to compare this postmortem with the postmortem for whatever that game becomes!

In the meantime, though, feel free to try out our jam release of Dice Tower and let us know what you think!

Dice Tower (Game Jam version) released!

Over the last three days, PixelLunatic and I worked on a game for Game Maker’s Tool Kit Game Jam 2022. Our entry is Dice Tower, and you can play it here!

Keep in mind that this is a game jam game, so this is far from perfect (for example, there is no audio), but we think the end result would up being pretty fun to play! We might decide to develop this further in the future, though we haven’t officially committed to doing so yet.

Enjoy!

How Donkey Kong Country 2’s Movement Feels Amazing (Part 3)

This is Part 3 of a 3-part series. Check out all the parts here!

Part 1: Here!
Part 2: Here!
Part 3: This post.

As a child, I loved to play Donkey Kong Country 2: Diddy’s Kong Quest; as an adult in my early thirties, I still love playing it. One of the reasons, among many, why is the game’s character movement feels almost perfect. Never do I feel as though I can’t adequately control Diddy or Dixie Kong as I navigate them through many levels of perilous adventure. As a game designer, I found myself wondering: what is it, exactly, that makes me love DKC2’s movement so much?

To answer that question, I’ll take a close look at the action verbs DKC2 employs related to the player characters. It’s not just a matter of analyzing the actions and movements in and of themselves, however; the level and enemy design of DKC2 are intentionally crafted to augment those basic and special actions. As is undoubtedly true for many games, it is the whole package together which creates that feel I love so much.

In the first part of this blog series, we looked at the many abilities and forms of movement the Kongs can do; in the second part, we examined the design of the levels those actions are performed in, and how it compliments them. Now, we’ll look at the final segment of the movement equation: the foes the Kongs must fight throughout the levels. We’ll review the types of enemies that get included in the game, relative to how you are expected to deal with them; next, we’ll examine a few foes that implement some special mechanics on top of their base type; finally, we’ll look at a few levels to see how enemies are placed to take advantage of the Kongs’ movement, their movement, and the level’s design to create compelling, challenging gameplay experiences.

Kantankerous Kharacteristics

When asked about what kinds of enemies are present in Donkey Kong Country 2, one might say “there’s some ground enemies, flying enemies, swimming enemies, some bosses”. That isn’t wrong at all, but I want to approach this from a different perspective; I want to examine enemies by how they are designed to be defeated. This approaches helps us focus on what moves you need to employ to defeat a baddie, which makes it well-suited for this design dive.

Basic Baddies

Many of the baddies are designed to be beaten with one or more of the regular moves in the Kongs’ arsenal. Some specifically protect themselves against particular kinds of moves, forcing you to be more strategic about how you approach them. Let’s break those types down.

Stomp Enemies

As is true in many platforming games, there are many baddies which can be defeated by jumping on their heads and knocking them off the stage; I’ll call this “stomping”. It’s usually pretty obvious which foes can be stomped; they lack any sort of visible protection to their heads which might discourage you from jumping upon them. That doesn’t mean all stompable enemies are the same; there’s plenty of variety to enemy widths, which affects how easy it is to land within their hurtbox. For example, Sneeks and Flitters have quite wide hurtboxes (and they are visually long-looking characters to communicate this), making them relatively easy to land on; other foes, like the Klomp, stand upright and present a smaller hurtbox, and thus are more of a challenge to land on precisely.

I use the term “hurtbox” to mean the collision area where contact results in hurting the entity possessing it.

Stompable enemies are sometimes placed in such a way that you can chain jumping on multiple of them in a row. As discussed before, this is used in some places as the required means of progressing through the level, but it’s also included in less critical areas as a fun thing to do. Jumping as you land on top of an enemy provides a boost to your jump height, which adds to the thrill of the action. Since jumping on enemies is a core part of the game, adding elements like this to increase the fun factor goes a long way to making the game feel good to play.

Spin Enemies

The spin move is also usable as an attack, careening into enemies to knock them away. Unlike falling on a baddie from above, using a spin requires knowing how much time you spend in the spin animation before breaking out into a run, as otherwise you’ll instead run into the enemy (and thus take damage and lose the Kong you control). This makes the spin attack more challenging to pull off, but subsequently it feels a little more satisfying to use than a simple jump attack.

When you successfully spin into a baddie, it actually resets the spin to the initial frame of the spin move; since the camera stops moving forward as part of this, it adds some weight to how the spin attack feels, contributing to the fun of using it. To compliment this, some parts of the game place multiple enemies close enough to each other that you can easily spin through the entire group, which is tremendously entertaining!

This is actually something I don’t think is done as well in Donkey Kong Country: Tropical Freeze. There’s been a lot of times in that game where I’ve tried to pull off a spin attack through a group of enemies that seem close enough to spin fully through, only for my spin to come up short in the middle of the combo through no perceived fault of my own. It makes it such that I trust the use of that attack less than the jump. That’s a shame, since I think DKC games are at their best when the player is able to use both forms of attack equally well.

Many of the ground baddies which can be stomped on can also be spun into; some, however, specifically prescribe whether or not the spin attack should be used. The Spiny is designed to resemble a porcupine, bristling with sharp quills all over its body except for the exposed head area; spinning into this foe from the front is thus strongly encouraged. The Klampon, an alligator-esque foe with big, nasty teeth, communicates the opposite; spinning into those jaws means your death, so you must instead stomp them. This adds a level of depth beyond simply defeating these baddies; you need to understand what they are vulnerable to and specifically use the move which targets that vulnerability.

Protected Enemies

There are a few foes which are explicitly immune to the spin and stomp attacks the Kongs possess, meaning you can only defeat them with a projectile or an animal buddy’s attack. As mentioned in previous parts, that means when you are given access to a projectile or a buddy, you’ll need to keep them around long enough to deal with any protected enemies in your path.

What if you don’t have a projectile or an animal buddy? Then these protected baddies become obstacles which you must avoid. There are plenty of places in the game where this is what you are expected to do. For example, many climbing sections are littered with Zingers, forcing you to climb quickly or make well-timed jumps to avoid their patrols. On the ground, protected foes are often placed in ways that force you to perform a clever move (like a spin jump) to get through (or, alternatively, to access some form of reward that you’d otherwise have to pass on).

Enemies which are protected from spins and stomps are given a visual design that communicates this. The hornet-like Zinger is covered in sharp, triangular stingers, making it quite clear that death awaits those who try to spin or jump into it. Klubba is big and muscular, and the Kongs simply don’t have enough mass to do any damage to him; instead, when you try to jump on or spin into him, you bounce off him, and he turns red, making the next time you touch him cause damage. Kutlass sports a pair of oversized cutlass swords, and carries them in such a way that it makes it clear that he can cut you down from any angle you choose to try and attack. Identifying which enemies are protected from spins and stomps is an important part of gameplay, and forces clever use of your moves to either avoid them or keep projectiles and animal buddies alive long enough to get to those baddies and defeat them.

Komplex Kharacters

We’ve examined the basic archetypes of enemies by how they are intended to be defeated. There are a few special cases which differ enough from the basic types, which we’ll look into now.

Ranged Enemies

Most of the baddies in DKC2 use their brawn to try and hurt you, but a few fellows got the clever idea of shooting projectiles at you, instead. That forces you to keep your eyes peeled for when such baddies appear in the level, and react quickly to the projectiles they shoot at you to avoid them. Sometimes, these ranged foes are positioned such that they shoot projectiles through an area of the level you must pass through to make progress, requiring you to time your moves to the pattern of the projectiles so you pass while the baddie is reloading. Thanks to how responsive your basic movement is, dodging the projectiles, while a challenge, is rarely a frustration.

Even within the ranged archetype, there is variety to be found in what projectiles they shoot. The Kannon baddie (not to be confused with the samely-named Kannon that shoots you into bonus areas) sometimes shoots simple wooden barrels, which you can bounce on top of if you aim your jumps correctly; this is used in some levels as a required means of progression, bouncing across from barrel to barrel over a gap until you get to the other side. Other times, they fire iron cannonballs which hurt you irregardless of how they touch you, and you must simply avoid them. The Krook, meanwhile, fires its metal hook hands when you pass within line of sight; the twist is that those hooks function like boomerangs, returning to the Krook after reaching maximum distance, forcing you to not only keep an eye for the initial shot, but be prepared to avoid the projectile as it traverses its return trajectory. Finally, the Kloak hovers around and is capable of throwing many kinds of projectiles, from barrels and chests to Spinies and Zingers; sometimes, if you wait long enough and dodge the projectiles, a Kloak will throw out some form of goodie, like a banana coin or a chest with a 1-up balloon, so it’s not always in your best interests to kill them right away.

Swimming Enemies

While swimming, the Kongs cannot jump, spin, or throw; this makes all the foes underwater a protected enemy, because touching them means death. Thus, underwater sections tend to evoke avoidance gameplay, where you swim carefully through rooms of patrolling baddies. Not every foe is content with simply patrolling, however; the Lockjaw, an orange piranha, will charge towards you if it catches you within its line of sight, while the Shuri, a spinning starfish, will wait for you to enter an area, then attempt to launch themselves in your general direction. The Puftup, a bloated pufferfish, will sometimes explode when you get within range, launching its sharp spikes in predetermined directions and forcing you to dodge to avoid them.

Both the Shuri and the Puftup also have variants which simply patrol an area, so you have to identify which variant you’re facing when they appear on-screen!

A lot of times, in swimming levels, Enguarde the swordfish is hidden somewhere, and using him makes the underwater sections far easier. Instead of having to avoid every enemy you see, you can instead line up Enguarde’s sword bill to stab them and take them out. As mentioned before, it’s a reward for players who explore levels carefully and check the nooks and crannies for hidden passages.

Bosses

Boss fights are the apex stage of every world, the final challenge that you must overcome to progress to the next world area. All bosses are immune to stomps and spins, being vulnerable only to projectile attacks. Often, the projectiles you need aren’t immediately available to you, requiring you to wait for them to appear. These big baddies aren’t content with sitting around and letting you get those projectiles freely, however; they have many forms of attack in their arsenal to use on you. These attacks are patterned, so you can learn how a boss is going to attack you and develop strategies for dodging them. Even when you acquire the projectile, however, you still have to aim correctly to get the projectile to hit the baddie, or you’ll have wasted your shot and made the boss fight take longer, increasing the odds that you’ll make a mistake and take a hit.

The stages you fight each boss on ask for the use of different abilities as part of the pattern avoidance. Krow, the foe of the first world, flies around the stage and tries to drop eggs on you, some of which can later be picked up and thrown back at him. Kudgel, the gatekeeper of World 3, jumps around the stage and tries to land on top of you; when he hits the ground, anything standing on it is paralyzed, so you not only have to run around to avoid getting landed on, you also have to jump in the air to get off the ground to avoid being unable to respond to his next jump. To fight King Zing, the defender of the fourth world, you transform into Squawks and must not only dodge the king’s flight path, you must hit a specific part of his body (the tail stinger) with your egg projectiles in order to cause damage. Even though the underlying pattern of dodge-the-boss-until-you-can-use-your-projectile is the same for all boss stages, the different takes on that pattern keep the gameplay fresh and interesting, while requiring you to make good use of your movement to win.

This was a notable issue with bosses in the original Donkey Kong Country, where nearly every boss had to be fought in the exact same way, by simply jumping on them.

Special Shenanigans

There’s more to a good foe than simply meandering around a level. A few simple stooges like that are useful for establishing a baseline to gameplay, but often, as game designers, we want to make enemies that take expected archetypes and add an unique twist for the player to deal with.

Donkey Kong Country 2 does this with many of its foes; even though the baddies can be classified into a small set types of how they can be beaten, most still get one or more unique traits that make it more interesting to deal with them beyond a simple spin or stomp. We’ll examine a small subset of DKC2’s roster of baddies, observing the mechanics which make them function and how they engage with the moves given to the player.

Neek

We’ll start with the humble Neek. A small, bandana-bearing vulture, Neek hovers at a predetermined area in the level and waits for you to get near. Once you enter his threat radius, he lets out a screeching cry and dives down a planned flightpath, starting with an arced curve and flattening out into a straight line. You need to quickly predict where that flight path is going, and whether you’re in it. If you are, you’ll need to duck or jump to get out of the way. If you want to remove the Neek, you can jump up and stomp on its head as it flies by.

As far as special mechanics go, this one is relatively simple. Even so, it adds an element of intrigue to how you plan to deal with him. Until you enter the threat radius, he doesn’t move, so you can’t wait him out; on the other hand, since it won’t attack right away, you have time to prepare for your reaction. While all Neeks perform some form of dive and flatten out maneuver, the angles involved can vary with each Neek, so you have to figure out quickly what kind of pattern it’s going to adopt. Thus, even though the dive isn’t that complex a behavior, the Neek’s simple mechanic is still enough to provide interesting, fun gameplay.

Click-Clack

A small, yet oversized, dung beetle, the Click-Clack has a small hitbox to accompany its tiny frame. This makes it so that you have to be more precise with your jumps in order to land on them. Additionally, when you jump on one, it flips onto its back instead of becoming defeated; you’ll also get knocked back a little bit. If you ignore that Click-Clack, it’ll revive and move around faster than before; only a second jump will dispatch it for good. On the other hand, while it’s flipped over, you can pick it up and throw it as though it were a projectile (although throwing it down to the ground will cause it to revive). Finally, if you spin into it, you defeat it instantly.

There’s all sorts of interesting gameplay that arises from the Click-Clack’s mechanics. The knockback force you experience when you jump on a Click-Clack can make the stomp a little risky; that force could push you into another enemy, or into a pit. Spinning into it, where you have room to do so, is certainly the safest way to dispatch them. On the other hand, it can be used as a projectile; if you’re about to face a horde of enemies, particularly ones that are protected from your other attacks, it’s well worth your while to stomp on a Click-Clack for the purpose of carrying it around as ammunition (or a shield, since holding projectiles protect you from damaging attacks to your front). You can’t sit around and wait while it’s on its back, however; you have to decide whether you’re going to kill it or carry it, or it’s just going to get up again, and since it now moves faster it’ll will be more deadly to deal with.

If you look at the Click-Clack in terms of how it is beaten, it’s a spinnable, stompable foe. The small hitbox and unique mechanics around what happens when you stomp on it make it a much more interesting, versatile foe to fight than it might otherwise be.

Klobber

The Klobber is a Kremling that hides in normal-looking barrels. When you get close enough to it, the Klobber will pop up and try to run into you, knocking you around if it succeeds in doing so. The fact that baddies in barrels exist means you have to be cautious whenever you see a barrel; is it only a barrel, or is a Klobber hiding within? Oftentimes, Klobbers are placed around other enemies or hazards, making it easy for you to get shoved into a source of damage.

How do you stop the Klobber? You have to leap into the air and stomp on its head; spin attacks do nothing against it. Once it’s been stomped, it hides inside its barrel for awhile before popping back out to charge after you anew. The only way to prevent it from returning is to pick it up and throw it into something and break, or offscreen into the bottomless void. You don’t need to throw it right away, though; you can carry the Klobber’s barrel around, and it functions exactly like a regular barrel. Like the Click-Clack, that makes the Klobber a source of projectiles, making it worthwhile to deal with one.

There’s more than one kind of Klobber, too. Different-colored Klobbers have different effects when they hit you. The green Klobber just knocks you around; the yellow Klobber steals bananas from you, which disappear if you wait too long to recollect them; the black Klobber takes away life balloons, which float away if you leave them alone. The red Klobber hides in TNT barrels—with the special name Kaboom—and blows up if it runs into you. These increasingly deadly side effects heighten the stakes of engaging with them; be careless, and you could lose valuable life-giving resources (or, in the case of Kaboom, your life).

Kutlass

Finally, we’ll bring up Kutlass. We’ve briefly mentioned it already; it’s the double-cutlass-wielding Kremling. Those oversized swords, as mentioned before, make it clear that jumping on the Kutlass is a suicidal maneuver. What about spinning into it from behind? It’s too smart; as soon as you get close, it’ll turn to face you and charge at you. If you don’t move out of the way, those massive cleavers will come down on your Kong’s head and take them out of the picture. The only option you have, if you don’t have a projectile, is to dodge out of the way. When you do this, the force of Kutlass’ swing gets its cutlasses stuck into the ground for a few moments, exposing an opportunity to strike and defeat it, either by stomp or spin.

This enemy is an unique blend of the protected and basic types, and this makes it interesting to engage with. You need some amount of space where you can get near the Kutlass without getting immediately into its threat radius; otherwise, you have nowhere to dodge when it swings the swords at you. Even if you do have enough room to dodge, you have to react quickly, making the Kutlass a test of how well you’ve mastered using your movement over the course of playing the game.

Level Design Kase Studies

Having baddies, no matter how interesting they may be, is nothing without creating level designs that take advantage of how they behave, just like having good movement is nothing without a level design that makes those moves fun and entertaining. As with many other aspects, Donkey Kong Country 2 does a great job with enemy placements in its levels, starting with simple schemes to ease new players in and ramping up to complex challenges that truly test a player’s mastery of their moves.

There are a total of 40 levels in the game, each with enough depth to go many thousands of words into. For the sake of brevity, however, we’ll restrict our gaze to portions of a few levels. Even these microcosmic glimpses should prove illuminating as to how well DKC2 uses enemies in its level design.

Pirate Panic

We’ll begin at the beginning: the first level of the game, Pirate Panic. As is typical of the first level of many games, Pirate Panic is designed to introduce you to the many mechanics you’ll be using for the rest of the game. Fittingly, the first enemy you come across is a Sneek, who is easy to jump on and moves slowly; he’s just begging for you to jump on him or spin into him.

Having the first enemy you encounter be simple, easy, and uncomplicated gives the player less to worry about. The Sneek isn’t going to suddenly rev up speed and charge into you, or jump super high out of nowhere; he’ll just keep moving your way until you either deal with him with your moves or let him run into you. It’s a great way to introduce the basic moves to you.

You encounter a pair of Sneeks as your next foes; you’ve already learned how to deal with one, so now the game asks you to deal with two of them. Hopefully, knowing what to do, this proves to be an easy task for you.

Afterwards, the next foe you see is the plodding Klomp. This is a new baddie, with a differently-shaped profile (and hurtbox), but the way you deal with him is the same as how you dealt with the Sneek; the jump just needs to be a little bit higher. Alternatively, if you’ve happened to learn how to hold down the Y button to run, you’ll pick up a crate projectile right before you see the Klomp. It’s not far-fetched to think from there that you might be able to throw this at the Klomp, or even hold it to run into him.

This Klomp is also on top of a row of platforming barrels, so you could even choose to run underneath him if you don’t feel like engaging him. It’s also an introduction to enemies on different height levels, something you’ll encounter often throughout the rest of the game.

Once you pass the Klomp, the next baddies you have to contend with are a row of Sneeks, but this time there’s a twist: the foes are advancing beneath a bunch of stacked platform barrels (so named to distinguish them from projectile barrels). If you try to jump on them, you’ll most likely land on top of a barrel instead of the Sneeks, avoiding them entirely. If you just want to progress, that might be good enough; for many players, though, it’s irking to leave any foe undefeated, if it was within their power to handle. That row of barrels serves as a discouragement against jumping, in that case. The way to defeat these Sneeks is spinning into them; hitting the first one will result in demonstrating the fun art of spinning through all the nearby enemies, exposing a new strategy for you to use and cementing it in your brain with a rush of fun gameplay.

By now, you’ve had multiple chances to practice your basic moves. The rest of Pirate Panic continues in much the same way, introducing slightly more challenging scenarios and foes, giving you a great taste of the gameplay to come.

Lava Lagoon

Next, we visit Level 3 of World 2, Lava Lagoon. This is the first time a level gimmick gets introduced: the water is, literally, lava, and you must jump on the back of an all-powerful, almighty seal named Clapper to convince him to turn this lava into water, making it safe for you to traverse. You can’t stay in the water too long, however; after a brief period of time the water will start heating up, until it once again becomes lava.

If Clapper is powerful enough to turn lava into water, why doesn’t he help the Kongs out in more substantial ways? Good question.

The way this level gimmick is introduced is clever. You are presented with a small branching path. At the start of this fork sits Clapper, waiting for you. The path above is patrolled by a Klampon; the path below is lava-logged and, at the moment, impassible. Earlier in the level, you had to contend with a Sneek approaching you from a higher platform, so that jump to the upper platform feels dangerous. Meanwhile, Clapper the seal is barking at you, and, given how often jumping on things solves problems in this game, you’ll probably feel inclined to do the same here, just to see what happens. Thus, you discover Clapper’s magical powers of liquid and temperature transmutation, making the lower path accessible to you. It is far easier to swim through this area, so you’ll likely take it over the upper path.

This fork in the road thusly introduces the level’s gimmick to you in an intuitive way, inviting you to figure it out on your own. Even if you ignore Clapper entirely and brave the upper platform, it’s not a big deal; you’ll soon reach a point where you cannot progress further without using Clapper. Seeing him multiple times increases the odds that you’ll engage with him and figure out his shtick.

One other thing that underwater path teaches you: that you’ll have swimming enemies to contend with underwater, as a lowly Flotsam patrols the floor of the lower path. It’s easy enough to swim above him, but it prepares your expectations for what kind of gameplay is to come.

The rest of Lava Lagoon is an increasing progression of a simple pattern: introduce lava-water sections that you need to cool down with Clapper, then travel through before the water heats back up to the point of damaging temperatures. In each water section, you have a cadre of underwater foes to swim past and dodge; the combinations become trickier and trickier to navigate the deeper you get into the level, ending with a mad dash through a maze of puffing Puftups (the non-exploding kind) to make it to the end of the level before you run out of time. For good measure, you also get tossed a Klobber at the level’s end that you have to avoid or defeat, lest it push you back into the lava. Overall, the level is a good example of taking a level gimmick, teaching you how it works, and ramping up the challenge of that gimmick through good enemy placements.

Bramble Scramble

As you progress further into the worlds and levels of Donkey Kong Country 2, the challenges the game puts before you becoming increasingly more difficult. I think Level 3 of World 4, Bramble Scramble, is a quintessential example of the game giving you a great challenge to put all your skills to the test. This level is oriented both around climbing on ropes and flying with Squawks.

In the other two levels we’ve discussed, the opening enemy was something simple and easy to deal with. Not here; your first foe is a Krook, and you encounter him the moment you move forward in the level, needing to deal with his hook shot right away. Even if you beat him, though, he’s right on the edge of a thicket of brambles, so you have to be careful that your jump doesn’t lead you to fall into them. After a long jump to the next safe wooden platform, you’re faced with a tall, thorny vine, with a Zinger hovering on the other side waiting to sting you upside the face, assuming you manage to fly over the thorns without getting your Kongs’ butt pricked along the way. You get one DK barrel to try and take out the Zinger, and if you succeed your passage over the thorns is a little safer. The shot isn’t easy to make, however, and you only get one chance; the game is testing you to see how skilled you’ve gotten with your aim.

Skip past a climbing section patrolled by Zingers and a Krook, and another jumping section where you need to use running jumps to have any hope of making it between platforms, and you’ll encounter your first Squawks section. First, you ascend upwards, with a few Zingers floating off to the side which you can use as target practice for your egg shot. You’ll need it, too, because the next section is flooded with flying Flitters. Normally, these blue dragonflies are relatively harmless, but in such large swarms, you’ll quickly get overwhelmed if you don’t fire away your egg bullets to take them out. The eggs aren’t fired in a straight line, either, so you have to remember how the egg trajectory is arced and use that to guide your aim. While doing all that, you must also avoid flying into the brambles above and beside you as you move through the area.

Thankfully, while flying with Squawks you can rest on flat stretches of bramble without taking damage. Given how difficult it is to shoot down the Flitter swarm and keep yourself up in the air, this section might be where you learn this ability!

Eventually, you get to the no-Squawks sign and the halfway barrel, where the next climbing section starts. First, you climb upwards into the face of a squadron of waiting Neeks. Almost immediately after you see them, they dive bomb across your path. If you jump, you fall back down to the ground, so you have to shimmy up and down the rope to keep out of their way. At the top of the rope is a junction with a horizontal rope, allowing you to continue onward. Here, however, you encounter a Kannon firing a rapid burst of cannonballs; you cannot pass yet, as the rate of fire is too fast. Instead, you must wait until there is a short pause in fire, then dash across as quickly as you can before the Kannon begins firing anew.

You continue across the path of ropes, and soon you end up on another horizontal rope, square in the path of another Kannon. You don’t see the Kannon on screen, but you can hear him open fire, and soon you’ll see a cannonball flying across the length of rope, straight at you! Luckily, there’s some gaps in the brambles above that give you just enough room to jump up into in order to avoid the shot. You must advance down the rope to the next safe jumping zone, before another cannonball comes screaming across the screen to take you down. Do this a few more times and you’ll finally get close enough to the Kannon to take him out and end the threat for good.

There’s plenty more challenge left in this level, but there’s one more pattern I want to look at. At several junctions throughout this level, you’ll encounter a group of Zingers. Some of them will be red, meaning they are immune to your egg shot, while one or two will be normal yellow Zingers. With all the Zingers alive, the passage through will be near impossible; you need to shoot down the yellow Zingers to clear your path enough to make it through with relative ease. It’s a great way of presenting players with a simple, yet meaningful strategic choice that yields a tangible reward.

Castle Crush

Our final foray will be into the realm of World 6, Level 3, named Castle Crush. This is another gimmick level. This time, the floor is rising up beneath your feet, and you’ll quickly find yourself running out of head room! To stay alive, you need to keep your eye atop the screen to see where in the ceiling the continuation paths are, and position yourself to be under them before the floor smashes you into the ceiling.

I wasn’t intending for most of these examples to be Level 3s, but that’s how it shook out. 😛

As if that weren’t time pressure enough, the foes populating this level will do their best to come at you from nearly out of nowhere and force you to make quick decisions on how you’re going to handle them. The first enemy you encounter is, once again, a Sneek, dropping down on you from above; a quick and easy enemy to defeat that you’ve, by now, beaten dozens and dozens of times. It also introduces you to a pattern that will be very common in this level: small alcoves containing enemies that drop on you from above.

The next baddie you encounter is a Spiny, also falling down from above. You must defeat him with a spin attack, but you have to time it right; spin too early and you’ll finish the attack animation before the Spiny gets close enough to take damage, resulting in the Spiny landing right on top of you. Some time later in the level, you’ll encounter Klampons dropping in on you from above as well. These you cannot deal with by spin attack, so you must allow them to fall and land, then quickly jump in the air to stomp on them before they close in on you in the tight quarters you keep.

Eventually, shortly before the halfway point, you get introduced to a long hallway that contains both a Spiny and a Klampon. The Spiny is first; if you spin into him, you’ll wind up near where the Klampon patrols, so you’ll have to be careful to ensure you stop your spin in time to get airborne and stomp the Klampon. This section is specifically designed to introduce you to this particular pairing: Spiny and Klampon. It keeps it spaced wide enough that you have a good chance of surviving the encounter while teaching you how difficult it is to deal with both these foes in the same area.

Sure enough, later on in the level, you encounter your first section where a Spiny and a Klampon patrol right next to each other. The Spiny leads, with the Klampon right behind. You now have a difficult choice to make: do you try and leap over the Spiny to jump on the Klampon and defeat him first, or do you instead spin into the Spiny and try to jump right before your spin carries you into the Klampon’s gnashing teeth? Both maneuvers are equally challenging, and with the rising floor you are forced to decide quickly, lest you get squished. It’s one of the most challenging parts of the game, and it feels awesome to correctly execute whichever decision you made.

There are plenty more sections in Castle Crush where the Spiny and Klampon patrol is used. There is even one section where you have alternating Spinies and Klampons dropping on you from above, forcing you to time your attacks so you spin into the dropping Spiny, then quickly jump to stomp on the Klampon before the next Spiny falls onto your lap. All this challenge, and this is only one single part of the many myriad challenges Castle Crush throws your way. By the time you finally ascend to the top of the level and stomp that exit target, you’ll feel exhausted, yet exhilarated at having gotten through.

Kong-clusion

Whew! At last, we’ve made it to the end, not just of Part 3, but this entire series!

In this part, we dove headlong into examining the enemy design and how it was created with the aim of players using their fine-tuned moves on them. The ways each enemy can be defeated provides a framework for understanding what an enemy means in the context of the moves the player can do, from the basic stompable, spinnable baddies to the foes which embody special protections and attacks. Even enemies sharing the same defeat type can have differences in gameplay by exhibiting one or two special behaviors on top of that. Finally, each level in the game, of which we examined several, is tailored to take these enemies and place them in locations that make optimal use of what they do, all in the aim of providing a fun, challenging experience for the player.

Over this entire blog series, I’ve shown why Donkey Kong Country 2’s movement is special. The moves themselves are finely tuned and feel great to perform, and there’s a great many ways to modify the basic movement to provide fun gameplay variety. Every level is designed to take full advantage of these great movement mechanics, rewarding both skillful play and observant exploration. In each level lives enemies that are designed to make using your moves to conquer them, whether by defeating them or avoiding them, fun and exciting.

In short, I think Donkey Kong Country 2’s movement feels amazing. It’s why I loved playing the game as a kid, and it’s why I keep coming back to playing it, nearly thirty years after it was released. Nothing else I’ve played comes close to how this game feels.

As a game designer, it is my hope that I’ll one day get to make a game that pays homage to the movement mechanics of this game. After writing all these blog posts, I’ve certainly squirreled up enough techniques and ideas to take inspiration from!

How Donkey Kong Country 2’s Movement Feels Amazing (Part 2)

This is Part 2 of a 3-part series. Check out all the parts here!

Part 1: Here!
Part 2: This post.
Part 3: Here!

As a child, I loved to play Donkey Kong Country 2: Diddy’s Kong Quest; as an adult in my early thirties, I still love playing it. One of the reasons, among many, why is the game’s character movement feels almost perfect. Never do I feel as though I can’t adequately control Diddy or Dixie Kong as I navigate them through many levels of perilous adventure. As a game designer, I found myself wondering: what is it, exactly, that makes me love DKC2’s movement so much?

To answer that question, I’ll take a close look at the action verbs DKC2 employs related to the player characters. It’s not just a matter of analyzing the actions and movements in and of themselves, however; the level and enemy design of DKC2 are intentionally crafted to augment those basic and special actions. As is undoubtedly true for many games, it is the whole package together which creates that feel I love so much.

In the previous part, we took a look at the specific actions the Kongs can make, from walking and running to jumping and throwing, as well as the various special forms of movement, like climbing and swimming, and the animal buddies which modify how basic movements work. The actual abilities are only part of the overall story, though; just as critical as how you can move is where you can move. Without level design that compliments the possible actions you can take, a game won’t be as fun as it could be.

Exploration Evaluation

There are 40 regular levels, excluding boss stages. Many challenging sections are included in those levels, often increasing in difficulty as you progress from the early stages to the later ones. While some stages involve special gimmicks, a lot of times the challenge is derived simply from taking the actions you are familiar with and asking you to execute them well to progress. Let’s break down some of the ways this is accomplished.

Basic Navigation

First of all, because the Kongs’ movement is so well-tuned, it’s fun on its own to just move your Kong throughout the level. The short accelerations make the movement feel more smooth while not taking away from your control, like sometimes happens when using long acceleration times. The minimal jump scaling gives you just the right amount of height, and the timing on how much you scale seems perfectly balanced so that you can get the exact jump height you want. The spin move feels fluid and lasts just the right length of time so that you don’t feel like you lose control when you use it. All in all, simply moving through the level is fun.

Beyond moving around, the level structure itself is used to make it easy to figure out where you need to go. In many cases, you are asked to move right (for horizontal levels) or up (for vertical levels). By employing a consistent pattern for where you are expected to move, it makes it hard to get yourself lost in any given level. Some levels are “square”, and in these you start traversing from right to left (or, sometimes, right to left); you eventually reach a vertical section of the level, either up or down, and you then traverse the horizontal plane in the opposite direction from which you came, until you reach the next horizontal section. There are a few cases where this formula is played with, for the sake of variety, but it is never done in a confusing way; you still always know where you should be going.

This is an underrated part of feeling good about your movement; even if it’s fun to move your character around, it’s a lot less fun to not know where you need to go to make progress, and getting lost repeatedly is quite the powerful buzzkill. By making it hard to get lost in any given level, Donkey Kong Country 2 removes a potential source of frustration, and thereby makes everything feel more fun.

Collectibles

Each level also contains sections that have goodies in them, places you are meant to discover and be rewarded for the effort of doing so. Some of these are sprinkled through the course of the main path. Oftentimes, though, these goodie sections are placed in locations that go against the grain of expectations, such as to the left of the level start. A lot of times, these places aren’t particularly hard to reach, and they are intended to reward you for exploring outside of the conventional expectations.

Sometimes, though, collectibles are placed in ways that challenge you to show mastery of your moves. Kong letters are often used in this way, being positioned in such a way that picking them up involves doing some difficult maneuver, like spinning off a platform and jumping at just the right time to both collect the letter and avoid falling to your death.

The ultimate collectible is the DK Coin (also known as a Hero Coin). These big, shiny coins, with the letters “DK” embossed on them, are used as an ultimate test of movement, observation, and/or timing. There isn’t a gameplay advantage to collecting them; your reward is the thrill of finding the coin and procuring it through perilous platforming and top-notch timing.

Checkpoint Barrels

Each level in Donkey Kong Country 2 has a single checkpoint barrel, roughly halfway through the level. When a checkpoint barrel is broken, if you die later on in the level you will start the level from this checkpoint barrel’s location instead of the beginning of the level.

How does this tie into movement, precisely? It adds a reprieve from having to play perfectly without dying; if you had to play an entire level without any checkpoints, it would make the game more difficult and tense to play, and thus it would be harder to justify using difficult action sequences later on in the stage. By only having one checkpoint, levels have a clear first-half/second-half dynamic that often allows for introducing level gimmicks and gameplay in the first half, and following them up with more challenging versions of those mechanics in the second half; having more checkpoints would either make individual sections feel too short, and thus not interesting enough, or too difficult, making the whole level feel more like a slog. One checkpoint barrel per level feels like just the right amount, to me.

That analysis on checkpoint segments applies to the 3D Donkey Kong Country games, which use multiple checkpoints per level. It’s one of the reasons I prefer the older games to the modern ones.

Finding Bonus Areas

Each level contains at least one bonus area to find. These bonus areas have entrances that are hidden or obscured in a few different ways. The most obvious ones are bonus barrels, which function like blast barrels that shoot you into the bonus area; while a few are placed in obvious locations, most of these bonus barrels are placed such that they either aren’t visible or are placed in difficult to reach locations, requiring skill to reach. Some bonus areas have entrances which are hidden inside of the level walls, and you need to use a barrel or Rambi’s charge move to break open the entrance.

The final way to enter bonus areas is through Kannons, which require being loaded with cannonballs in order to shoot the Kongs into the bonus area. Whenever you find a cannonball, it always means there’s a Kannon to find in the level, and vice versa, which adds an element of expectation to the gameplay; finding the cannonball first means you need to ensure you keep hauling the cannonball with you until you can reach the Kannon, often requiring agile platforming to avoid dropping it into a chasm; finding the Kannon first means you need to search the level for the corresponding cannonball, and then bring it back to the Kannon.

The ways required to get to bonus areas often involve challenging bits of action use. For instance, a bonus barrel that is too high to jump to means you need to either have both Kongs, so you can team throw into it, or you need to have an animal buddy that can be used to maneuver the required vertical distance (such as Rattly’s jump or Squitter’s platform webs), and consequently that means you need to play well enough to keep your partner or animal buddy around long enough to reach the bonus barrel’s location. Same is true for bonus entrances hidden behind walls; you need to lug a projectile around, or find Rambi and ride him to the bonus area entrance, so that you have something to open the wall with. With projectiles, in particular, that will mean not using them on other baddies along the way, lest you sacrifice your only means of breaking open the wall. Such gameplay subtly adds difficulty in executing moves you are already familiar with, rewarding partaking in these optional challenges with the right to enter a bonus area.

Bonus areas themselves often have gameplay that challenges your mastery of the game’s movement mechanics, but since these are the same as what you encounter in normal level gameplay, just harder, I won’t go into detail on them.

End Level Targets

To wrap up our look into Donkey Kong Country 2’s level navigation, let’s investigate the end-of-level mechanic that is used. It consists of a target and pole, akin to hammer games you might see at a fair or carnival. The mechanics of how it works matches those counterparts as well: if you hit the target with enough force, you cause the barrel on the pole to shoot up and knock down the reward on the top; otherwise, it simply gives a lackluster bump as the Kongs scamper off stage. What reward you get is randomized between 3-4 options of differing value, from single bananas to banana coins to extra life balloons (and, in a few cases, Kong letters or Hero Coins).

Simply jumping from ground level onto the target isn’t enough to claim the reward; you need to find a height tall enough to jump from, or you need to find a blast barrel that will shoot you into the target. While it’s usually pretty obvious where you’ll need to go to get the necessary force to break the target, it’s still a small test of observational skills nonetheless.

Most of the challenge of these end-level targets, however, comes from timing your jump or blast to coincide with when the reward you want to claim appears. The cycle time is relatively short, so usually waiting to launch at the target until your desired reward is displayed results in not hitting the target until the next reward has been cycled in. Thus, you need to pay attention to the pattern to figure out when the reward you want appears in the cycle of items, and then launch shortly after the prior reward appears, ensuring that you’ll arrive on target at the correct moment.

There’s usually no threat of death during these sections, so it’s merely a matter of finding the right place to launch from, and then timing it right to get the reward you intend. It’s a simple little challenge, adding a less tense form of skillful challenge to wrap up the more difficult sections of level preceding it.

Platforming Perils

There’s more to Donkey Kong 2’s level design than just navigating the levels. Often, you the player are given challenging sequences to get past as part of level progression, using both the regular movements given to you and special movement mechanics. The degree of challenge expected from each varies, generally starting with simple asks in the first worlds, to downright difficult sequences in the final worlds. Let’s examine the various ways the game presents these challenges to you.

Level Architecture

Oftentimes, the challenges are introduced through the level’s architecture. A frequent case is the use of gaps between platforms, where you must often use running jumps or spin jumps to get enough speed to clear the gaps. The ground heights themselves are varied throughout an individual level, and those too can be used to introduce challenge, such as having to time your jump onto a higher or lower platform while avoiding a baddie shooting projectiles across that plane.

Speaking of enemy placements, those too are used to introduce platforming challenges. For instance, you’ll be asked sometimes to navigate a huge platform gap by jumping on the backs of flying enemies; failure to do this successfully results in falling downward, often to your death. Even when it isn’t required as part of level progression, jumping off of enemies is also used as a means to access goodie areas or bonus entrances.

The responsiveness and control make it feel as though you can easily pull off whatever moves you need to; there are rarely any sections that are so maddeningly precise that you have to spend an hour or more just to execute the moves needed. That doesn’t mean the challenging sections of the game are easy to pull off; you still need to be precise with your button presses. Rarely, however, will you find yourself stuck on a level section because the actions needed to get past it are borderline impossible.

There are a few exceptions. Looking at you, Animal Antics!

Climbing Sections

Ropes restrict your movement to specific planes, and enemies are placed along the ropes to force you to jump across with good timing to get past them. Taking away some of your freedom of movement makes it clear what you need to do to move on. Sometimes, you encounter “rope net” sections which give you climbing ability across both vertical and horizontal planes, at the expense of reduced horizontal climbing speed; these are a great mechanic to take the rope climbing experience and introduce a different flavor of it.

Another climbing mechanic is the use of hooks. These objects hold your Kong in place when you jump into them, until you jump away from them. Unlike ropes, hooks are all about asking you to move aerially, and oftentimes multiple hooks are placed in succession, requiring you to jump from hook to hook to continue onward. It’s a bit of a combination between jump movement and rope movement.

Blast Barrel Sections

Blast barrels, unlike their projectile counterparts, are not thrown. Instead, you jump into one of these barrels, and while in the barrel your normal movement is taken away. By “firing” the blast barrel (by tapping the jump button), you are launched out of the barrel’s open top, regaining air movement shortly afterwards. With your normal movement taken away, you instead need to rely on aiming the barrels in the correct direction before blasting out.

There are many kinds of blast barrel to play with throughout the game. Some let you rotate the barrel by pressing the directional buttons. Some spin automatically, requiring you to time your blast right when the barrel is facing the direction you want to go. Some don’t rotate at all; these are often aimed straight up, and are meant for you to use your aerial control after being fired to get where you need to go. Alternatively, they can be aimed in a fixed direction, with baddies between you and the next section, again making it a matter of timing to blast yourself out when the enemy is not in the line of fire. Occasionally, you’ll encounter automatic blast barrels, that shoot almost as soon as you jump into them; these are most often used to take you through a predetermined sequence of barrels, or to get you out of one level area to the next one.

There are a few levels which introduce special blast barrel mechanics. Timed barrels are regular blast barrels that automatically fire after an on-barrel timer expires, giving you a short amount of time to align the barrel correctly before getting shot into an enemy or abyss. Tracker barrels, instead of rotating the barrel, instead let you move the barrel itself across the level, and you’ll need to use them to get across dangerous sections of the level before blasting out. Kong Blast Barrels, marked with Diddy or Dixie heads, will only operate if the Kong you currently control matches the head shown on the barrel, requiring you to keep that Kong alive in order to use them.

Why use blast barrels at all, when you have normal movements that feel great to use? An obvious answer is to provide another change of pace to level mechanics, which in general helps with preventing things from getting too stale. Also, since barrels fire the Kongs at high velocities, it adds a speed thrill to the game while controlling it enough to not make it maddening; if this fast speed was your default movement speed, it would be very hard to control what you were doing. Finally, it provides a new way to take skills you’ve needed to use through normal movement (such as timing moves to defeat or avoid enemies) and gives you a new context to use them in. These things combine to make blast barrels interesting and fun, good qualities to add to any game!

Animal Buddy Sections

Some levels give you access to an animal buddy, and while you have the animal buddy you have to use its different movement to get through the level. Oftentimes, the level is designed with this in mind. For example, when having Rattly, the levels subsequently are designed with vertical traversal and jumping as central components for sections of that level. You usually don’t need to use the animal buddy for the entire level, however, and signposts with “no animal” signs tell you at what point the animal buddy will be taken away from you; crossing this signpost causes the animal buddy to disappear in a poof of clouds, along with some reward for keeping the animal buddy up to that point in the level.

Not all levels with animal buddies require you to use them to get through the level. Sometimes, the animal buddies are hidden somewhere in the level, and usually not in obvious places. In cases like these, you can beat the level without them, although doing so is usually more difficult; having the buddy makes the level easier to beat, but places a challenge on locating the animal buddy in the first place. This encourages you to search around to see if there are hidden or obscured level sections that would lead you to finding an animal buddy. This reveals another function of the no-animal signposts: if you see one for a particular animal buddy that you don’t currently have, that’s a sign that one was hidden somewhere in the level for you to find.

Some levels do require the animal buddy to proceed. Most of the time, in these cases, you’ll jump into a special Animal Barrel that transforms the Kongs into the animal buddy pictured on the side. The levels which do this are subsequently designed with far more challenging sections that can only be defeated through good use of that animal buddy’s movements and skills. By forcing you to become the animal buddy, you’re prevented from getting yourself in a position where you lose the animal buddy in a level section that requires their movements to get past. It’s a great way of employing user experience to enhance the level design.

Level Gimmicks

Some levels have their own special mechanics that you have to deal with. For example, in one level, the level is filled with lava, until you jump on Clapper the Seal, who temporarily transforms that lava into water which can be safely traversed. Another level has a wind mechanic, where every so often the wind blows strongly enough to affect all Kong movement, forcing you to have to plan your jumps when the wind is blowing in the direction you want to move. Yet another level features a rising floor, forcing you to make quick decisions about where to go and how to defeat enemies, before running out of room and getting crushed. Most of the time, such gimmicks are only used in that specific level.

How do these gimmicks impact movement? It’s a clever way to test your knowledge and mastery of the various movement mechanics you’ve been introduced to. By adding a special mechanic that changes normal level gameplay, you need to understand how these gimmicks impact your abilities. In cases where your movement itself is directly affected by the gimmick, you also need to apply that understanding to counteract the gimmick’s impact to continue making progress through the level.

Beyond mechanics, special level gimmicks help those levels feel more memorable!

Camera Concoctions

A critical, yet often overlooked, aspect of movement is the game’s camera. After all, it’s a lot harder to make precise movements if the camera isn’t framing the action well! Thankfully, Donkey Kong Country 2’s camera is well designed to enable making your movements with confidence that you won’t get screwed over by it. It’s also used as a way to focus your attention on where you need to be going, as well as hiding goodie sections and bonus areas.

Framing

Let’s start with looking at the basic camera framing. When moving through a horizontal stage, the camera is placed mostly behind you, leaving you a little sight of what’s happening behind you, but giving most of its real estate on the challenges that are immediately in front of you, the direction you need to be going. If you turn around and move leftwards in a horizontal level, however, the camera position shifts to put the Kongs at the center, giving you more sight into what’s happening behind you, without making it feel like this is the “correct” direction to be moving in. It’s one way the game helps prevent you from getting lost in a level.

What about vertical or square levels, where progression can include moving leftwards or rightwards? Here, the camera sits in such a way that you can see more of the area in the direction the Kongs are facing than the direction behind them. This is a good compromise, though it does sacrifice some of the camera’s ability to tell the player where to go. Such instances are usually paired with level design that doesn’t let you move too far in a horizontal direction, however, so if you do end up accidentally backtracking, you won’t lose much time over it before figuring it out and turning to go the correct way.

A technique that is also used is placing sections of level that are impossible to navigate backwards through once you go through them. There are also a few instances where the camera itself is prevented from moving backwards, forcing you to keep moving in the intended level direction.

Motion

Something that isn’t immediately obvious, until you start paying attention to it, is that the camera’s vertical height is precisely controlled. Depending on where you are in the level, the camera’s vertical height is fixed at a predetermined coordinate; as you move through the stage horizontally, the camera’s height is automatically adjusted depending on the height of the terrain you are walking across. When you reach vertical level sections, or swimming and flying areas that involve vertical movement, then the camera follows the player’s movement.

There are certain areas of a level where the camera’s vertical and horizontal movement are stopped. In cases like these, it makes it clear where the intended progress of a level is, and it also prevents the camera from clipping too far off the edge of a level (a place you don’t need to see to make any gameplay decisions). Interestingly, this technique is sometimes used to obscure entrances to goodie or bonus areas, requiring you to watch carefully for telltales signs (such as the lone banana near the edge of the screen) and rewarding you for your observational skills.

Importantly, the camera does not move vertically to follow Diddy and Dixie when they jump. This allows you to not lose sight of the ground, and anything on it you might be jumping towards or away from. It is a subtle way of allowing you to maintain precise control over where you are moving. If this camera mechanic weren’t in place, it’d be easy for enemies to drop out of frame while you’re in mid-air. That would make it much harder to plot your movements, since you’d have to rely on memory to know where you should and shouldn’t jump. It’s a crucial component to making the Kongs’ movements feel good.

Aspect Ratio

A huge difference with Donkey Kong Country 2, compared to modern platformers, is the use of the squarish 4:3 aspect ratio. This was how most TVs were built back in the days when this game was released, so that was the only supported resolution the game had. Unlike the rectangular 16:9 aspect ratio, which is what computer monitors and TVs commonly use these days, 4:3 gives you much less horizontal screen real estate, so there’s less room to tell you what’s coming up.

Having to account for this limited width of frame has a lot of influence on the game’s design. For example, rarely do you see long and wide sections of challenging gameplay, and the times you do encounter them are specifically designed with the obscured view in mind, forcing you to react quickly to what you see as the camera reveals what’s coming next; consequently, you need to know your movement well so you don’t have to think about what to do when you see the next challenge in frame; you can just instinctively react to it. We don’t often think of aspect ratio as a part of the game designer’s arsenal, but the limited nature of the aspect ratio in DKC2 is clear evidence that it does, in fact, play an important part of how a game’s design feels.

To Be Kong-tinued

In this part, we examined many different ways the level design of Donkey Kong Country 2 takes the movement mechanics of the player and provides exciting, challenging ways to use them. We also examined the various special forms of gameplay, which either incorporate special movements or enhance the challenge of your regular movements. Finally, we took a look at how the game’s camera itself plays an important role in how the movement feels. No matter how good a game’s character feels to move, without good level design those good movements won’t feel as fun as they could be.

There is one more component that makes the movement feel good: the enemy design. In the final part of this three-part series, we’ll examine the baddies of Donkey Kong Country 2 and how they, too, play a crucial role in making the movement feel good. Stay tuned!

This is Part 2 of a 3-part series. Check out all the parts here!

Part 1: Here!
Part 2: This post.
Part 3: Here!

How Donkey Kong Country 2’s Movement Feels Amazing (Part 1)

This is Part 1 of a 3-part series. Check out all the parts here!

Part 1: This post.
Part 2: Here!
Part 3: Here!

As a child, I loved to play Donkey Kong Country 2: Diddy’s Kong Quest; as an adult in my early thirties, I still love playing it. One of the reasons, among many, why is the game’s character movement feels almost perfect. Never do I feel as though I can’t adequately control Diddy or Dixie Kong as I navigate them through many levels of perilous adventure. As a game designer, I found myself wondering: what is it, exactly, that makes me love DKC2’s movement so much?

To begin answering that question, I’ll take a close look at the action verbs DKC2 employs related to the player characters. It’s not just a matter of analyzing the actions and movements in and of themselves, however; the level and enemy design of DKC2 are intentionally crafted to augment those basic actions. As is undoubtedly true for many games, it is the whole package together which creates that feel I love so much.

To break this lengthy dissertation into digestible chunks, this will be a three-part series. We’ll open up with a look at the basic movements and abilities of the Kongs themselves, as well as some special moves that are used to spice up the normal gameplay. After that, we’ll examine how the levels are designed to take advantage of the basic and special moves. Finally, we’ll look at the enemy designs and how those compliment the basic moves and abilities as well.

Kong Kapabilities

To begin this design dissection, we’ll look at the many forms of movement present for the Kongs in DKC2. First up: the core action verbs. Each Kong possess a base set of moves that you’ll be employing throughout the majority of the game.

Walk and Run

You have two basic ground movements, one for walking, and one for running. Diddy’s speed is slightly faster than Dixie’s, for both walking and running, but both feel fast enough that I don’t feel particularly disadvantaged when using the slower Kong. The actual movement speeds themselves feel just right to me; I’ve never found myself wishing that I could move faster or slower.

Triggering the run and walk actions are simple: hold the Y button and a direction to run in said direction; don’t hold Y, and that same directional input is a walk. Personally, I always appreciate it when games give me the ability to walk when I want to, even if most of the time I’m probably going to run. Having an easy-to-use slow option gives me that more precise control when I feel like I need it.

For 3D games, having easy walking also lets me get more immersed in the fantasy of inhabiting a character in a world. No one runs all the time in real life!

Accelerating from a standstill to a walk is near-instantaneous, which further helps with making the Kongs easy to control, but there is just enough acceleration that you don’t feel the characters instantly transition from idle to walk. Running, on the other hand, only happens after you press the Y button, which triggers the controlled Kong’s spin move before transitioning to the run. That animation helps convey a reason for why the character is suddenly transitioning to a run speed, while also giving you an attack move which is easy to trigger. If you were holding Y and start moving from idle, though, you just accelerate briefly into the run speed; again, just enough acceleration to make it not instantaneous, but short enough that it doesn’t impact your control over the character.

Speaking of spin maneuvers…

Spin

Both Kongs have a spinning maneuver, but each does it differently. The execution of both spin maneuvers result in the same outcome, however: pressing the Y button causes the Kong to perform a spinning attack move, which is capable of defeating most ground enemies; if Y is still held, then any directional ground movement will subsequently result in the Kong moving at a running speed.

As mentioned, the Kongs each have their own spin on the spin maneuver. Diddy’s is a cartwheel, looking quite acrobatic, while Dixie’s is a body spin, twirling her pony tail (termed by the game as a “helicopter spin”). Interestingly, Diddy’s cartwheel looks like a more natural action than Dixie’s, which can contribute to his move feeling faster than Dixies, but in fact both spin at the same speed and move the same distance, which means you aren’t disadvantaged when faced with level sections which ask you to use the maneuver.

Dixie’s helicopter spin serves a second purpose while in air: pressing Y while in midair causes Dixie to spin constantly, giving her a slower fall speed, and thereby giving the player greater control over where they want to land. Diddy does not have this ability, which helps give both Kongs distinct roles: Dixie is useful for air control, while Diddy is useful for moving more quickly.

Jump

An essential ingredient to most 2D platformers is the jumping action, and both Diddy and Dixie are more than capable of performing this function. Pressing the B button causes the selected Kong to jump into the air, up to approximately three times their own height. Tapping B causes a short jump, while holding B slightly longer results in a higher jump. While it may seem pointless to have this scaled jumping, having some control over your jump height makes you feel more in control than you would if you only had a single jump height.

There is more to the feel of the jump than the upward movement. Running and jumping allows you to cover more horizontal distance than walking and jumping, providing more encouragement to run through the levels. While in the air, you have full control over horizontal direction, giving you the ability to precisely place where you want to land and making air control feel responsive. When you fall, you accelerate to a constant speed, which you maintain until you hit the ground (or the enemy on it), which makes it easier to predict where your jumps will land.

Interestingly, it seems that your fall speed is the same as your jump speed; it takes the same amount of time to fall from the apex of your jump as it does to jump up to it. However, if you are moving in a horizontal direction while in midair, it seems to slightly increase the amount of time the Kong stays at the apex of the jump. This is something I only noticed when going through my recorded footage frame-by-frame to try and get ballpark estimates, but now that I think about it, this gives you a little more time to figure out where you want to land before you start falling. It’s a clever design, one that I hadn’t thought about before.

Most enemies can be defeated by jumping on them, and this jump attack is something you’re going to do a lot throughout the course of the game. The game encourages you to do this by giving you a greater jump height when you jump off the top of an enemy than when you jump from the ground, allowing you to cover greater distances. Even if you don’t actually jump off the enemy, landing on one grants you a small bounce acceleration that still lets you move up and onward. These movements help make bouncing off an enemy feel good.

The spin moves also have a role to play in performing jumps. While spinning off of a ledge, you can press the jump button (B) to cause the Kong to jump while in mid-air. This allows the Kong to cover more horizontal distance than they’d be able to cover by simply running and jumping. The timing on this is fairly forgiving; the game doesn’t want to impede you from pulling this maneuver off.

Duck

It’s easy to forget about the ability to duck, as it’s a passive move compared to walking, running, spinning and jumping. This move causes your Kong to duck down and hold still, effectively decreasing their vertical hitbox size by about half. This is used to less effect than other moves, but there are still places that will require you to duck under passing enemies, so it has a part to play in the movement design.

Team Throw

Finally, you can pick up your partner to put them on your Kong’s shoulders, then subsequently throw them by pressing Y (the normal throw button). If you hold the up direction as you throw, this results in launching your partner up into the air in a slow, controllable way; without this, your partner Kong is simply thrown to the ground, remaining where they fell until you come back for them (or they go off-screen, in which case they run back to you automatically). The horizontal throw can also be used to defeat enemies that could be defeated with normal attacks.

Special Skills

Now that we’ve discussed the basic Kong moveset, let’s examine cases where the game modifies these default maneuvers to introduce other forms of gameplay. These serve as an occasional change-up to how the game flows. Just as with basic movement, the feel of these special movements is important.

Climbing

Throughout various levels, ropes are placed, which the Kongs can climb when you leap into them. While on a rope, your movement is restricted to a single plane, either horizontal or vertical (depending on which way the rope faces). Diddy and Dixie’s different movement speeds factor here as well, with Diddy being able to traverse ropes slightly faster than Dixie.

Keeping the rope climbing speeds fast, close to their walking speeds, means that it doesn’t feel like the game slows down during the climbing sections, so they still feel good to move around on. This, in turn, makes it fun to navigate through the various challenges the designers place along the paths the ropes and chains force you to traverse.

Swimming

In some levels, there are water sections that the Kongs can swim in. Jump and spin attacks can’t be performed underwater, so the gameplay changes from defeating enemies to avoiding them. While underwater, you are able to move in all directions, but you sink downward unless you tap the B (jump) button to swim upward.

Like the climbing sections, your movement speed underwater is close to your regular movement speed, although the requirement of tapping the B button makes swimming more skillful than simple navigation; you have to time button presses to keep yourself afloat while swimming past enemies. Unlike the climbing sections, swimming sections allow you unrestricted horizontal and vertical movement, adding yet another flavor of movement variety to break up the rote platforming that dominates most of the game.

Flying

Some levels give you access to the Squawks animal buddy, a parrot that grants the Kongs the ability to fly. The flying sections are similar to swimming sections; you can move in all directions, but have to continuously tap B to move up or you float back down to the ground.

The similarity in how swimming and flying sections work from a movement standpoint allows for the designers to reuse player expectations for how those mechanics work, and avoid having to teach yet another new mechanic.

Speaking of animal buddies…

Animal Buddies

These are animals that the Kongs can ride (or, in some cases, transform into), and using an animal buddy changes what moves the player can perform. With all the animal buddies, there are similar base movement motions: there is a slower “normal” speed, and then a faster “running/swimming/flying” speed when moving while holding down Y. Beyond that, however, each animal introduces different changes to the movement equation.

Animals can be accessed in two ways. One is through a crate, in which case the Kongs ride the animal. While riding the animal, taking damage causes the Kong to fall off and the animal to run away; you can also choose to dismount the animal willingly. The other is by transforming into the animal itself. Dismounting the animal is no longer an option, so you are stuck with that animal’s movement changes. Usually, transformed mode is given when the level’s design explicitly requires that particular animal’s movements to progress through the level.

Either way, at some point in the level you’ll reach a “no-animal” sign, which removes the animal buddy and gives you some kind of reward. By giving an end to the animal buddy use, this allows for only having some parts of the level be designed around the use of the animal, and in some cases even have multiple animals within the same level. It makes the animal buddies another tool in the player’s movement arsenal.

Let’s take a look at the animals and what their movements add to the gameplay.

Rambi

A rhinocerous that gives you a faster running speed. Rambi is impervious to damage when jumping on enemies or running into them with its horn, only being vulnerable to attacks from behind (and certain projectiles). Holding down A prepares an even faster run in the direction Rambi is facing, plowing through enemies and breaking through hidden entrances to bonus areas.

Riding Rambi makes you feel almost invincible, so you feel more willing to move fast and make risky decisions. Enemies are mostly no longer a challenge for you. These things combined make Rambi feel amazing to use. To account for this, oftentimes Rambi’s location in a level is hidden, making finding him a reward for looking around the levels, rather than blazing through them.

Enguarde

A swordfish that gives you full movement control underwater. No longer do you need to tap B to stay afloat; Enguarde hovers in place when idle, and moves in whatever direction you input. The sharp-looking bill on its face can defeat any underwater enemy, and clearing enemies makes the underwater sections that much easier.

Having Enguarde removes a lot of the challenge from swimming movement, which means riding Enguarde feels similar to riding Rambi, in that you feel more free to move where you please, with ease. Since Enguarde makes underwater movement and gameplay much easier, his locations, like Rambi’s, are hidden well in the level, so that finding and using him is a reward for good exploration.

One could think of Enguarde as the underwater version of Rambi.

Squawks

As mentioned, Squawks is a parrot that gives you the ability to fly in a stage. Unlike Enguarde, you don’t get to hover in place when idle, so there is still challenge involved with using the bird. Squawks also has a ranged attack, hurling eggs out of its mouth in a parabolic trajectory when the Y button is pressed.

Unlike Enguarde, who generally makes level movement easier, Squawks requires more care to ride. Any contact with an enemy damages Squawks, so you are required to be careful as to where you fly. The egg projectiles don’t fly straight, so aiming them to hit enemies, while maintaining flight, is in and of itself a challenge for the player. As such, Squawks is often placed in locations that are easier for the player to find.

Squitter

Squitter gives you the ability to shoot webs. Pressing Y delivers an attack web which can defeat any non-invulnerable enemy; you can control the arc of the shot by holding up or down on the direction input after the attack web has been fired. Pressing the A button (or, alternatively, either the L or R buttons) shoots a slow-moving platform web. Pressing the platform web button again after firing deploys the web platform, giving you something to stand on in mid-air. These platforms disappear after a short period of time, however, so you need to move quickly. Unlike other ground animals, Squitter cannot defeat enemies by jumping on them, so you need to keep away from foes and blast them from afar.

From a design standpoint, Squitter is a massive change to your movement toolset. Riding him takes away your ability to jump on enemies, but gives you an infinite amount of projectiles, making you adopt a long-ranged approach to defeating enemies. Creating platforms at will allows you to avoid hazards, pitfalls, and enemies that would otherwise prove difficult or impossible to overcome; they also provide an interesting way to add more vertical movement to the regular platforming action.

Rattly

This snake has an extremely high jump, allowing you to reach higher platforms than you could with the Kongs by themselves. Holding down A charges Rattly to make a super-jump, similar to how holding A charges Rambi to make a super run. Rattly defeats any enemy that it jumps on, except for ones that are invincible. Interestingly, when Rattly moves along the ground, movement consists of small jumps that result in a lurching style of movement; this is perhaps an encouragement to move by pressing the jump button, which feels more fun to do.

Rattly is all about the jump. He can jump on nearly anything and live, and, since your spin attack is taken away while riding him, you are strongly encouraged to jump on foes in your path. The high jump allows for adding taller sections to levels that take advantage of that bigger jump height.

I am leaving out Glimmer and Clapper because they do not change your movement mechanics.

Careening in Carts

Three levels let you ride in carts. While in a cart, the Kongs move in a consistent rightward direction at a controlled speed (you can go faster by holding the forward directional input, and slower by holding back). Depending on the level, jumping will either cause both Kong and cart to jump, or just the Kong. With the consistent movement, beating these levels is about reacting to upcoming threats quickly; you aren’t given time to ponder your next action. This can be frustrating while learning the level, but it results in satisfying rushes once you consistently react correctly to the level’s challenges.

What does this sudden change in movement bring to the design table? The rush of speed, for one. It’s fun to move fast through a level, much faster than you normally get to move. Along with that speed comes reduced amounts of time to react to level hazards. You can’t stop to figure out how to get past those hazards, either; you’re hurtling at them at high velocity, and you have to make quick choices about how to get past them. This is hard, but exhilarating, and they add a health dash of experiential spice to the movement gameplay.

These cart levels are ones I loved playing as a kid. That said, I think it’s good that there aren’t many of these kind of levels, as the high tension throughout would make level to level gameplay far more exhausting if that was the majority of the action.

Tossing in Throwable Objects

One final Kong ability remains: throwing objects. Both Kongs are capable of picking up and holding barrels and other objects placed throughout the level by holding the Y button; releasing the Y button causes the Kong to throw the projectile, which will defeat any enemy that it touches along the flight path. Aside from certain animal buddies, this is the only ranged attack you have access to in the game.

In many cases, the objects will break on impact, whether with the world or an enemy, making them a single-use resource. This forces you to consider carefully when you encounter a projectile to throw; should you use it now, on the nearest enemy, or should you try to hold on to it to use on some future part of the level with a more difficult obstacle, or a bonus area entrance? Your movement isn’t impeded while holding a barrel, so you still have the same level of control that you do normally; however, since objects break on contact, and you are forced to throw the object when you jump on an enemy, holding on to a projectile you wish to keep intact transforms the gameplay from defeating enemies to avoiding them until such time as you wish to use the projectile. This is a great way to subtly introduce a change in gameplay.

Interestingly, I always thought in my mind that you moved slowly while holding on to a barrel, but in testing I found that this is actually not true; you still move the same amount regardless of whether you’re holding an object or not. This is an interesting psychological effect; I wonder if the designers intended it, or if it was just a byproduct of our expectations for movement with held objects.

What if you don’t want to hold the projectile right now, but still need to keep it around? You can hold down and release Y to set the object back down on the ground, where it will wait for you to collect again. If you move far enough to cause the object to go off-screen, however, it resets its position back to where you found it; while this was probably something introduced by the technological limitations of the SNES days, rather than a design decision, it’s something you still have to consider when setting the object down.

The way in which Diddy and Dixie throw projectiles differs for each. Diddy picks up objects with his hands and throws them in a flat, shallow arc that is almost effectively a straight line; Dixie picks up objects with her ponytail (boy, her hair can really defy the laws of physics, can’t it) and throws them with a more pronounced arc. Because her hair is on her head, the release point of projectiles Dixie throws is higher than Diddy’s, resulting in making it easier to hit enemies that are up in the air. Both Kongs are able to jump while holding objects, which provides additional control over where the projectile is thrown. Since Diddy’s throw starts lower to the ground, jumping and throwing is almost essential when throwing with him to get good distance. Giving the two Kongs different throwing styles further differentiates between using the two Kongs, making it useful to have both around to switch up which one you use for a given situation.

There are many kinds of objects the Kongs can throw throughout their journey. Each kind of object provides different characteristics that affect player strategy for using them.

Barrels

This is the bread and butter projectile of the game: a simple, metal-banded wooden barrel. You can throw it normally, which will fling the barrel forward and cause it to break on impact with the ground (plowing through however many enemies were in its way), or you can heave it upwards into the air, which will cause it to land softly enough to not break on impact, and subsequently will roll along the ground (and through enemies) until it hits a wall or falls off a ledge.

Crates

Crates, on the other hand, are square projectiles that clearly communicate that they won’t roll. They also break on impact, regardless of how you throw them, making them a much more limited resource.

Buddy Barrel

The buddy barrel contains your partner Kong, if you lost them at some point during gameplay, and when the barrel breaks open you get your partner back. Interestingly, the buddy barrel’s impact mechanics are similar to the crate, in that it breaks immediately on impact with the ground or with an enemy, so when there is no Kong in the barrel the two objects are pretty much the same, functionally.

Cannonballs

These spheres of solid metal do not break on impact with anything, but they also do not roll when they hit the ground. Because of their indestructible nature, they are useful as reusable projectiles or shields for as long as you can keep from throwing them into a pit.

Chests

Chests break only on impact with enemies (or bonus area entrances), and they contain some form of beneficial pickup (or “goodies”) which gives you something of value, from banana bunches to life balloons (extra lives) to Kong letters, and everything in between. Since they don’t break on hitting the ground, you pretty much have to use them on enemies, which means you’ll have to find an enemy to use it on or you won’t be able to break it.

TNT Barrels

The holy hand grenade of DKC2, these explosive barrels are capable of destroying any enemy in a fiery explosion. This explosion has a small radius that will destroy any other enemies it touches. This barrel is often the only means you are given to deal with invulnerable enemies, which means being given one can be a sign that such an enemy is coming up.

To Be Kong-tinued

We’ve taken a deep look into the movement of Donkey Kong Country 2. From the simplest, basic moves to the variations introduced by special abilities, controlling the Kongs feels tight, responsive, and fun. But having characters that move well is only part of the gameplay story; the environments the Kongs move through and the enemies they fight contribute just as much to the feel of the movement as the movement itself.

In the next part of this series, we’ll take a dive into the level design of Donkey Kong Country 2, and see how much it impacts how the movement feels. Stay tuned!

This is Part 1 of a 3-part series. Check out all the parts here!

Part 1: This post.
Part 2: Here!
Part 3: Here!

Postmortem: Sanity Wars Reimagined

After seven months of development, Rebecca (PixelLunatic) and I have released Sanity Wars Reimagined! Along the way, we learned a lot, lessons we hope to apply to future games we develop. In this article, I want to dig a little bit into what we learned, from what we were initially trying to do to where we wound up, and the various lessons learned and mistakes made along the way.

You can check out Sanity Wars Reimagined on Itch.io!

This project started with a discussion Rebecca and I had about where things were from a long-term standpoint. For the past few years, we’d attempted, and abandoned, various prototypes, and it seemed like we were still far off from actually releasing a product. At the time, I had just come off of a month-long project exploring the creation of game AI; my intent was to start another project aimed at making improvements to the dialogue system. During our discussion, however, Rebecca pointed out that, while our ultimate goal was to make games and sell them, we had a bad habit of not committing to anything long enough to get it released. What’s more, she was concerned that this pattern of starting and abandoning projects wasn’t good for our morale.

She was right to be concerned about this; I’d felt that making an actual release was still a point far off in the distance, and this was making it easier for me to accept the idea of working on non-release projects, to “gain experience”. How would we ever learn how to improve, though, if we never got our projects to a releasable, playable state? Only two of our game jam games and one of our prototypes had ever been given to other people to play, so we had very little feedback on where we needed to improve. I realized that we couldn’t keep waiting to release something until “we got better”; we needed to make something and release it, however bad it may be.

We decided that we would start with a small project, so that it would take less time to get it to a releasable state. To that end, we determined that the project should be a remake of our first jam game, Sanity Wars. By remaking a game that was already released, we thought, we could focus on actually building the parts needed to make the game work; since I’d made those things work previously, we would hopefully avoid the pitfall of trying to create mechanics that were beyond our current skill to implement, or would take too much time to build. Why Sanity Wars? Out of all the previous jam games we’d made, it seemed like the most successful one, so we thought we could just add some polish, redo the art (since Rebecca did not do the original’s art), and it would be fine.

With that, our next project was set: Sanity Wars Reimagined. We would stay faithful to the mechanics of the original, aiming only to remake them in Godot, as this would be quicker than trying to iterate and make new mechanics. I would also take the opportunity to try and make systems that would be reusable in future games; ideally, we would treat Sanity Wars Reimagined as a foundation that we would directly expand upon for the next game. Since the original Sanity Wars was done in three full days, I thought this project wouldn’t take long to complete. Accounting for our busy adult schedules, I estimated the work would take two weeks to complete; at most, a month.

It didn’t take two weeks. It didn’t take a month. It took seven months before we finally released Sanity Wars Reimagined on Itch.io. Along the way, we made significant modifications to the core mechanics, removing multiple parts that were considered essential to the original Sanity Wars; even with those changes, the end result was still not that fun (in our minds). There were many times during the development period where it felt like it was going to drag on and on, with no end in sight. All that said, I still think Sanity Wars Reimagined was a successful release.

Why do I think that? To answer that question, I want to examine what technologies we developed during the project, what mistakes we made, and what we plan to do to improve things for our next project.

Technologies Developed

A lot of what I made from a code standpoint was able to be imported back into my boilerplate Godot project, which will then be available from the start when I clone the Genesis boilerplate to make any future game project. In doing so, I’ve hopefully decreased the amount of development time needed for those projects.

Genesis is name of a tool I created in NodeJS that lets me keep a centralized Godot boilerplate template and create new projects from that boilerplate using simple commands in a command line interface. To give a non-technical summary, it allows me to quickly create and update new Godot projects that include common code that I want to reuse from project to project.

Here are some of the things that I’ll be able to make use of as a result of the work done for Sanity Wars Reimagined:

Resolution Management

There is a lot to consider when supporting multiple resolutions for a game, especially one that uses a pixel art aesthetic. I was already aware of this before committing to figuring out a solution for Sanity Wars Reimagined, but I underestimated just how much more there was to learn. The good news is that I created a solution that not only works for Sanity Wars Reimagined, but is generalized enough that I can use it as the starting point for future games.

I’ll talk in brief about some of the struggles I had to contend with and what I did to solve them.

For starters, when working with pixel art, scaling is a non-trivial issue. Because you are literally placing pixels in precise positions to render your art aesthetic, your scaling must always keep the same aspect ratio as your initial render; on top of that, it must specifically be increased in whole integer factors. This means you can only support a limited number of window sizes without messing up the pixel art. That plays a huge factor in determining what your base size is going to be; since most monitors use a 1920px by 1080px resolution size, your base needs to be a whole integer scale of 1920×1080, or else the game view is not going to actually fill the whole screen when it is maximized to fill the screen (aka fullscreen).

The way fullscreen modes are typically handled for pixel art games, when they attempt to handle it at all, is to set the game view to one of those specific ratios, and letterbox the surrounding area that doesn’t fit cleanly into that ratio. That is the approach I chose for my fullscreen management as well.

Godot does give you the means to scale your game window such that it renders the pixel art cleanly, and you can also write logic to limit supported resolution sizes to only those that scale in whole integers from the base resolution. However, there is a catch with the native way Godot handles this: any UI text that isn’t pixel-perfect becomes blurry, which isn’t a great look to have. I could have switched to only using pixel-perfect fonts, but that wasn’t the look I wanted the game UI to have. After spending a lot of time experimenting with ways to handle this in Godot’s settings, I determined that I would have to create a custom solution to achieve the effect that I wanted.

I wound up talking to Noel Berry (of Extremely OK Games) about how Celeste handled this problem, as its crisp UI over gameplay pixel art was similar to what I was hoping to achieve. He told me that they actually made the UI render at 1920×1080 at default, and then scaled the UI up or down depending on what the game’s current resolution was. This inspired me to create a version of that solution for Sanity Wars Reimagined. I created a UI scaling node that accepts a base resolution, and then changes its scale (and subsequently the scale of its child and grandchild nodes) in response to what the game’s current resolution is. It took a lot of effort, but in the end I was able to get this working correctly, with some minor caveats*.

* I’ll be coming back to these caveats later on in the article, when I discuss mistakes that were made.

Overall, I’m very pleased with the solution I developed for resolution management in Sanity Wars Reimagined, and ideally this is something that should just work for future pixel art-based games.

Screen Management

Another system I developed for Sanity Wars Reimagined is a screen management system that supports using shaders for screen transitions. Although my boilerplate code already included a basic screen manager that was responsible for changing what screens were being currently portrayed (MainMenuScreen, GameScreen, etc.), a significant flaw it had was that it didn’t provide support for doing screen transitions. This was going to be a problem for Sanity Wars Reimagined, as the original game had fade transitions between the different screen elements. I thus set out to refactor my screen management to support doing transitions.

In the original Sanity Wars, the way I accomplished the fade was through manipulating the drawn image in the browser’s canvas element (as the original game was built using HTML/JavaScript, the technologies I was most familiar with at the time). It was hardcoded to the custom engine I’d built, however, and there wasn’t a direct way to achieve the same effect in Godot. It’s possible I could have made the fade transition, specifically, work by manipulating the screen node’s modulation (visibility), but I didn’t feel comfortable making direct changes to node properties for the sake of screen effects, especially if I wanted to have the ability to do other kinds of transitions in the future, such as screen slides or flips; anything more complex than that would be outright impossible through mere node property manipulation.

My focus turned towards experimenting with a different approach, one based on using Godot’s Viewport node to get the actual render textures, and then manipulating the raw pixels by applying shaders to the render images of the outgoing screen and the incoming screen. Viewports were something I hadn’t had much experience with, however, so I wasn’t certain if the idea I had would actually work. To prove the concept, I spent a weekend creating a prototype specifically to test manipulating viewport and their render textures. The approach did, in fact, work as I envisioned (after a lot of research, trial, and error), so I proceeded to refactor the screen management system in Sanity Wars Reimagined to use this new approach.

When referring to screens here, I’m not talking about physical monitor screens; it’s a term I use to refer to a whole collection of elements comprising a section of the game experience. For instance, the Main Menu Screen is what you see on booting up the game, and Game Screen is where the gameplay takes place.

Overall, the refactor was an immense success. The fade effect worked precisely the way it did for the original Sanity Wars, and the system is flexible enough that I feel it should be easy enough to design new screen transition effects (in fact, I did create one as part of making the LoadingScreen, transitioning to an in-between screen that handled providing feedback to the user while the incoming GameScreen prepared the gameplay). Should I want to create different visual effects for future transitions, it should be as simple as writing a shader to handle it. (Not that shaders are simple, but it is far easier to do complex visual effects with shaders than with node property manipulation!)

Automated Export Script

After realizing that I needed to export game builds frequently (more on that later), I quickly found that it was tedious to have to work through Godot’s export interface every time I wanted to make a build. On top of that, Godot doesn’t have native build versioning (at least, not that I’ve found), so I have to manually name each exported build, and keep track of what the version number is. Needless to say, I wondered if there was a way I could automate this process, possibly through augmenting the Genesis scripting tools to include a simple command to export a project.

I took a few days to work through this, and in the end I managed to create functionality in my Genesis scripting tool that did what I wanted. With a simple command, godot-genesis export-project "Sanity Wars Reimagined" "Name Of Export Template", Genesis would handle grabbing a Godot executable and running a shell command to make Godot export the project using the provided export template, and then create a ZIP archive of the resulting export. The name of the export was the project name, followed by a build number using the semantics I chose (major.minor.patch.build). By providing a -b flag, I could also specify what kind of build this was (and thus which build number to increment). It works really well, and now that exports are so easy to do I am more willing to make them frequently, which allows me to quickly make sure my development changes work in the release builds.

Other Features and Improvements

There are many other features that were created for Sanity Wars Reimagined; to save time, I’ll simply give brief summaries of these. Some of these were not generalized enough to be ported back into the Genesis boilerplate, but the experience gained from creating them remains valuable nonetheless.

Generators

These nodes handle spawning entities, and I made the system flexible enough that I can pretty much generate any kind of object I want (though, in this case, I only used it to spawn Eyeballs and Tomes).

RectZone

This is a node which let me specify a rectangular area that other nodes (like Generators) could use to make spatial calculations against (aka figure out where to spawn things).

PixelPerfectCamera

This is a Camera node that was customized to support smoothing behavior rounded to pixel-perfect values. This helps reduce the amount of visual jitter that results from when a camera is positioned between whole integer values.

The reason this happens is because pixels can’t be rendered at fractional, non-integer values, so when a pixel art game asset is placed such that the underlying pixels don’t line up to a whole integer, the game engine’s renderer “guesses” what the actual pixel color values should be. This is barely noticeable for high-resolution assets because they consist of a huge number of pixels, but for something as low-resolution as pixel art, this results in visual artifacts that look terrible.

UI Theming

I finally took a dive into trying to understand how Godot’s theme system works, and as a result I was able to create themes for my UI that made it much simpler to create new UI elements that already worked with the visual design of the interface. I plan to build on my experience with UI themes for future projects, and ultimately want to make a base theme for the Genesis boilerplate, so I don’t have to create new themes from scratch.

State Machine Movement

I converted my previous Player character movement code to be based on a state machine instead of part of the node’s script, and this resulted in movement logic that was far simpler to control and modify.


As you can see, there were a lot of features I developed for Sanity Wars Reimagined, independent of gameplay aspects. A large part of what I created was generalized and reusable, so I can put the code in future projects without having to make modifications to remove Sanity Wars-specific functionality.

Complications

No human endeavor is perfect, and that is certainly true for Sanity Wars Reimagined. In fact, I made a lot of mistakes on this project. Fortunately, all of these mistakes are things I can learn from to make future projects better. I’ll highlight some of these issues and mistakes now.

Both Rebecca and I learned a lot from the mistakes we made developing this project, but I’m specifically focusing on my mistakes in this article.

New Systems Introduced New Complexities

The big systems I added, like Resolution Management and Screen Management, added lots of functionality to the game. With that, however, came gameplay issues that arose as the result of the requirements integrating with these systems introduced.

Take ScreenManager, for example. The system included the ability to have screens running visual updates during the transition, so the screen’s render texture didn’t look like it was frozen while fading from one screen to the next. By creating this capability, however, I needed to modify the existing game logic to take into account the idea that it could be running as part of a screen transition; for instance, the player character needed to be visible on the screen during the transition, but with input disabled so the player couldn’t move while the transition was running.

Another issue the ScreenManager refactor created had to do with resetting the game when the player chose to restart. Before, screens were loaded from file when being switched to, and being unloaded when switched from, so restart logic was as simple as using node _ready() methods to set up the game logic. After the refactor, this was no longer true; to avoid the loading penalty (and subsequent screen freeze) of dealing with loading scenes from file, ScreenManager instead kept inactive screens around in memory, adding them to the scene tree when being transitioned to and removing them from the scene tree when being transitioned from. Since _ready() only runs once, the first time a node enters the scene tree, it was no longer usable as a way to reset game logic. I had to fix this by explicitly creating reset functions that could be called in response to a reset signal emitted by the controlling screen, and throughout the remaining development I encountered bugs stemming from this change in game reset logic.

ResolutionManager, while allowing for crisp-looking UI, created its own problems as well. While the UI could be scaled down as much as I wanted, at smaller resolutions elements would render slightly differently from how they looked at 1920×1080. The reason for this was, ironically, similar to the issues with scaling pixel art: by scaling the UI down, any UI element whose size dimensions did not result in whole-number integers would force Godot’s renderer to have to guess what to render for a particular pixel location on the monitor. Subsequently, some of the UI looked bad at smaller resolutions (such as the outlines around the spell selection indicators). I suspect I could have addressed this issue by tweaking the UI design sizes to scale cleanly, but my attempts to change those values resulted in breaking the UI in ways I couldn’t figure out how to fix (largely due to my continued troubles understanding how to create good UI in Godot). In the end, I decided that, with my limited amount of time, trying to fix all the UI issues was less important than fixing the other issues I was working on, and ultimately the task was cut during the finishing stages of development.

I’m guessing most people won’t notice, anyway, since most people likely have the game at fullscreen, anyway.

Complexities arising from implementing new systems happened in other ways throughout the project as well, although the ones stemming from ScreenManager and ResolutionManager caused some of the bigger headaches. Fixing said issues contributed to extending development time.

Designing for Randomization

One of the core mechanics of Sanity Wars (original and Reimagined) is that all the entities in the game spawn at random locations on an unchanging set of maps. At the time I created the mechanic, my thought was that this was a way to achieve some amount of replayability, by having each run create different placements for the tomes, eyeballs, portals, and player.

Playtesters, however, pointed out that the fully random nature of where things spawned resulted in wide swings of gameplay experience. Sometimes, you got spawns that made runs trivially easy to complete; other times, the spawns made runs much more difficult. This had a negative impact on gameplay experience.

The way to solve this is through creating the means of controlling just how random the processes are. For example, I could add specific locations where portals were allowed to spawn, or add logic to ensure tomes didn’t spawn too close to portals. Adding controlled randomness isn’t easy, however, because by definition it means having to add special conditions to the spawning logic beyond simply picking a location within the map.

The biggest impact of controlled randomness wasn’t directly felt with Sanity Wars Reimagined, however; it was felt in our plans to expand directly off of this project for our next game. Given that random generation was a core element of gameplay, that meant adding additional elements would also need to employ controlled randomness, and that would likely result in a lot of work. On top of that, designing maps with randomness in mind is hard. It would likely take months just to prototype ideas, let alone flesh them out into complete mechanics.

This aspect, more than anything else, was a huge influence in our decision to not expand on Sanity Wars Reimagined for the next project, but to concentrate on a more linear experience. (More on that later.)

Clean Code

If you’re a programmer, you might be surprised at seeing “clean code” as a heading under complications. If you’re not a programmer, let me explain, very roughly, what clean code is: a mindset for writing code in such a way that it is easy to understand, has specific responsibilities, and avoids creating the same lines of code in different files; through these principles one’s code should be easier to comprehend and use throughout your codebase.

Under most circumstances, writing clean code is essential for making code not only easier to work with, but faster to develop. So how did writing clean code make Sanity Wars Reimagined more complex?

Simply put, the issue wasn’t strictly with adhering to clean code principles in and of themselves; the issue was when I spent a lot of time and effort coming up with clean code for flawed systems. Clean code doesn’t mean the things you create with it are perfect. In fact, in Sanity Wars Reimagined, some of the things I created wound up being harmful to the resulting gameplay.

A prime example of how this impacted development is the way I implemented movement for the Eyeball entity. I had the thought of creating a steering behavior-based movement system; rather than giving the entity a point to navigate to and allowing it to move straight there, I wanted to have the entity behave more like real things might move (to put it in very simple terms). I then spent a long time creating a locomotion system that used steering behaviors, trying to make it as clean as possible.

In the end, my efforts to integrate steering behavior movement were successful. There was a huge flaw, however; the movement hampered gameplay. Steering behaviors, by design, are intended to give less-predictable behavior to the human eye, which makes it harder to predict how the eyeball is going to move when it isn’t going in a straight line. This style of movement also meant the Eyeballs could easily get in a position where it was difficult for the player to hit them with the straight-line spirit bullet projectile, which was specifically intended for destroying Eyeballs. Since steering behaviors work by applying forces, rather than explicitly providing movement direction, there wasn’t an easy, feasible way for me to tweak the movement to make it easier for the player to engage with Eyeballs.

In addition to making Eyeballs less fun to play against, the steering behaviors also made it hard to make Eyeballs move in very specific ways. When I was trying to create a dive attack for the Eyeball, I literally had to hack in movement behavior that circumvented the steering behaviors to try and get the attack to visually look the way I wanted to; even then, I still had a lot of trouble getting the movement to look how I felt it should.

How did clean code contribute to this, precisely? Well, I’d spent a lot of time creating the locomotor system and making it as clean an implementation as I possibly could, before throwing it into the gameplay arena to be tested out and refined. If there had been time to do so, I likely would have needed to go back and refactor the Eyeball movement to not use steering behaviors; all that work I’d spent making the steering behavior implementation nice and clean would’ve gone to waste.

Don’t get me wrong; writing clean code is very important, and there is definitely a place for it in game development. The time for that, however, is not while figuring out if the gameplay works; there’s no sense in making something clean if you’re going to end up throwing it out shortly thereafter.

Playtesting

I didn’t let other people playtest the game until way too late in development. Not only did that result in not detecting crashes in release builds, it also meant I ran out of time to properly take feedback from the playtests and incorporate it back into the game.

For the first three months of development, I never created a single release build of Sanity Wars Reimagined. I kept plugging away in development builds. The first time I attempted exporting the project was the day, no, the evening I was scheduled to bring the game to a live-streamed playtest session with IGDA Twin Cities. As a result, it wasn’t until two hours before showtime that I found out that my release builds crashed on load. I spent a frantic hour hack-fixing the things causing the crashes, but even with that, the release build still had a major, game-breaking bug in it: the testers couldn’t complete the game because no portals spawned. Without being able to complete the game, the testers couldn’t give me good feedback on how the game felt to them. From that point onward, I made a point of testing exports regularly so that something like that wouldn’t catch me off-guard again.

The next time I brought the game out for playtesting was in the middle of January 2022, three months after the first playtest. At that point, I’d resigned myself to the fact that Sanity Wars Reimagined didn’t feel fun, and was likely going to be released that way; my intent with attending the playtest was to have people play the game and help me make sure I didn’t have any showstopping bugs I’d need to fix before release. What I wasn’t expecting (and, in retrospect, that was silly of me) was that people had a lot to say about the game design and ways it could be made more fun.

To be honest, I think I’d been stuck so long on the idea that I wanted to faithfully recreate the original game’s mechanics that I didn’t even think about making changes to them. After hearing the feedback, however, I decided that it would be more important to make the game as fun as I could before release, rather than sticking to the original mechanics.

That playtest, however, was one and a half weeks before the planned release date, meaning that I had very little time to attempt making changes of any significance. I did what I could, however. Some of the things I changed included:

  • Removing the sacrifice aspect of using spells. Players could now access spells right away, without having to sacrifice their maximum sanity.
  • Giving both the spells dedicated hotkeys, to make them easier (and thus more likely) to be used.
  • Adding a countdown timer, in the form of reducing the player’s maximum sanity every so often, until the amount was reduced to zero, killing the player. This gave players a sense of urgency that they needed to resolve, which was more interesting than simply exploring the maps with no time constraints.
  • Changing the Eyeball’s attack to something that clearly telegraphed it was attacking the player, which also made them more fun to interact with.
  • Adding a scoring system, to give the player something more interesting to do than simply collecting tomes and finding the exit portal.
  • Various small elements to add juice to the game and make it feel more fun.

Although we did wind up extending the release date by a week (because of dealing with being sick on the intended release week), I was surprised with just how much positive change I was able to introduce in essentially two and a half weeks’ worth of time. I had to sacrifice a lot of clean code principles to do it (feeding into my observation about how doing clean code too early was a problem), but the end result was an experience that was far more fun than it was prior to that play test.

I can only imagine how much more fun the game could’ve been if I’d had people involved with playtesting in the early stages of development, when it would’ve been easier to change core mechanics in response to suggestions.

Thanks to the IGDA Twin Cities playtest group, and specifically Mark LaCroix, Dale LaCroix, and Lane Davis, for offering many of the suggested changes that made it into the final game. Thanks also to Mark, Lane, Patrick Grout, and Peter Shimeall for offering their time to playtest these changes prior to the game’s release.

Lack of a Schedule

I mentioned previously that I’d thought the entire Sanity Wars Reimagined project wouldn’t take more than a month, but I hadn’t actually established a firm deadline for when the project needed to be done. I tried to implement an approach where we’d work on the project “until it felt ready”. I knew deadlines were a way that crunch could be introduced, and I wanted to avoid putting ourselves in a situation where we felt we needed to crunch to make a deadline.

The downside, however, was that there wasn’t any target to shoot for. Frequently, while working on mind-numbing, boring sections of code, I had the dread fear that we could wind up spending many more months on this project before it would be finished. This fear grew significantly the longer I spent working on the project, my initial month-long estimate flying by the wayside like mile markers on a highway.

Finally, out of exasperation, I made the decision to set a release date. Originally, the target was the middle of December 2021, but the game wasn’t anywhere near bug-free enough by that point, so we pivoted to the end of January 2022, instead. As that deadline approached, there were still dozens upon dozens of tasks that had yet to be started. Instead of pushing the deadline out again, however, I went through the list to determine what was truly essential for the game’s release, cancelling every task that failed to meet that criteria.

Things that hit the cutting room floor include:

  • Adding a second enemy to the game, which would’ve been some form of ground unit.
  • Refactoring the player’s jump to feel better.
  • Fixing a bug that caused the jump sound to sometimes not play when it should.
  • Adding keyboard navigation to menus (meaning you had to use the mouse to click on buttons and such).
  • Create maps specifically for the release (the ones in the final build are the same as the ones made for the second playtest).

It’s not that these things wouldn’t have improved the game experience; it’s just that they weren’t essential to the game experience, or at least not enough to make it worth extending the release date to incorporate them. By this point, my goal was to finish the game and move on to the next project, where, hopefully, I could do a better job and learn from my mistakes.


These are far from the only complexities that we had to deal with during Sanity Wars Reimagined, but they should serve to prove that a lot of issues were encountered, and a lot of mistakes were made. All of these things, however, are learning opportunities, and we’re excited to improve on the next project.

Improvements for Next Time

There’s a lot of things that I want to try for the next project; many of them serve as attempts to address issues that arose during the development of Sanity Wars Reimagined.

Have A Planned Release Date

I don’t want to feel like there’s no end in sight to the next project, so I fully intend to set a release date target. Will we hit that target? Probably not; I’m not a great estimator, and life tends to throw plenty of curveballs that wreak havoc on plans. By setting an end goal, however, I expect that it will force us to more carefully plan what features we want to try and make for the next game.

In tandem with that, I want to try and establish something closer to a traditional game development pipeline (or, at least, what I understand of one), with multiple clearly-defined phases: prototyping, MVP, alpha, beta, and release. This will hopefully result in lots of experimentation up front that settles into a set of core mechanics, upon which we build lots of content that is rigorously tested prior to release.

Prototype Quickly Instead of Cleanly

Admittedly, the idea of not focusing on making my code clean rankles me a bit, as a developer, but it’s clear that development moves faster when I spend less time being picky about how my code is written. Plus, if I’m going to write something, find out it doesn’t work, and throw it away, I want to figure that out as quickly as possible so I can move on to trying the next idea.

Thus, during the prototyping phase of the next project, I’ll try to not put an emphasis on making the code clean. I won’t try to write messy code, of course, but I’m not going to spend hours figuring out the most ideal way to structure something. That can wait until the core mechanics have been settled on, having been playtested to confirm that said mechanics are fun.

Playtest Sooner Rather Than Later

The feedback I received from the final big playtesting session of Sanity Wars Reimagined was crucial in determining how to make the game more fun before release. For the next project, I don’t want to wait that long to find out what’s working, what’s not, and what I could add to make things even more fun.

I don’t think I’ll take it to public playtesting right away, but I’ll for sure reach out to friends and interested parties and ask them to try out prototype and MVP builds. It should hopefully be much easier to make suggested changes during those early stages, versus the week before release. With more frequent feedback, I can also iterate on things more often, and get the mechanics to be fun before locking them down and creating content for them.

Make a Linear Experience

After realizing how much work it would be to try and craft a good random experience, I’ve decided that I’m going to purposely make the next game a linear experience. In other words, each playthrough of the game won’t have randomness factoring into the gameplay experience. This may be a little more “boring”, but I think doing it this way will make it easier for me to not only practice making good game design, but make good code and good content for as well.

Will it be significantly less fun than something that introduces random elements to the design? Maybe, maybe not. We’ll find out after I attempt it!


Those are just a few of the things I intend to try on the next project. I don’t know if all of the ideas will prove useful in the long run, but they at least make sense to me in the moment. That’s good enough, for now. Whatever we get wrong, we can always iterate on!

Conclusion

That’s the story of Sanity Wars Reimagined. We started the project as an attempt to make a quick release to gain experience creating games, and despite taking significantly longer than planned, and the numerous mistakes made along the way, we still wound up releasing the game. Along the way, we developed numerous technologies, and learned lots of lessons, that should prove immensely useful for our next project. Because of that, despite the resulting game not being as fun as I wish it could’ve been, I consider Sanity Wars Reimagined a success.

What’s next for Rebecca and I? It’ll for sure be another platformer, as that will allow us to make good use of the technologies and processes we’ve already developed for making such games. I fully expect there will be new challenges and complications to tackle over the course of this next project, and I can’t wait to create solutions for them, and learn from whatever mistakes we make!

Sanity Wars Reimagined released!

The game PixelLunatic and I have been working on for the past seven months, Sanity Wars Reimagined, has been officially released! Download it here.

It’s been a long seven months, working on this game, and while there’s still plenty of things that could be improved, overall I’m pleased with how this game turned out. Most importantly, we learned many things that will prove useful for our future game development endeavors.

We hope you enjoy our game!