Designing Dice Climber


Recently, I created the game Dice Climber as a submission for GMTK Game Jam 2022. It was completed within the jam period of 48 hours. Or at least, the first form of it was, as I have now been adding to it and making improvements since the initial release. This was my first ever game jam project, and with that considered, I think it went pretty well. I wanted to make this post to go over the whole process -- what my initial approach was, my thought process leading me to various ideas, and a few implementation details that I found interesting.

Preparation

Before the jam even started, there were some things I tried to plan for. First off, I built some basic platforming mechanics in GameMaker, as platformers are a go-to gameplay style for me that I have some experience building, so that seemed like a good place to start. The theme of the jam was announced at the start of the 48 hour period, meaning there was no way I was able to know what the actual game I was going to make would be until it started. With that in mind, I established the following guidelines for myself to try to stick to:

  1. Whatever the theme is, it should be a core part of the game rather than something tacked onto a game that might as well not have it.
  2. The type of game should fit the scope of a short game jam project.

Entering my first game jam at age 32, this feels like something I should have been doing a long time ago, but there's at least one way in which I think doing this later in my life benefitted me, and that relates to the second point above. As a software developer already and having a lot of experience in other little game developey stuff like my StepMania theme, I'm acutely aware of just how much longer you might spend on any given problem than you initially estimate. Basically, I knew that in order to finish something substantial in 48 hours, it had to be something really small. Any game with a start and an end to it has a crucial problem of level design -- if you're going to spend most of the time allotted building your base game, you then have to build a good set of levels, which might take a whole lot of iteration all on its own. If not enough time is given to that, you'll probably only finish a couple levels, and then the end product won't have enough of an actual game to go with its idea.

With all of that in mind, I was already thinking about arcade games as a good fit. I was thinking about games like PAC-MAN and Tetris, though I'm not under any illusion that I could make a game as great as either of those. The ideal type of game I wanted to make would be a simple game that could provide a lot of variety in gameplay through many plays, rather than a quick go through a few levels or something.

The Idea

The theme of GMTK Game Jam 2022 was Roll of the Dice. After this was announced, I spent the first few hours just thinking about different possibilities for games I could make with this theme. Pretty early on I came up with a few design considerations I wanted to stick to:

  1. The theme of dice would not be just used aesthetically.
  2. Actual "dice" should be used in some way, rather than just using the theme as a loose excuse for random numbers.
  3. The randomness of a die roll should be a core part of the game.
  4. The numerical value of the dice should be significant in an obvious way.

As I tossed around various ideas in my head, I would try to evaluate how good they were. Whenever I decided against an idea, it was usually because it went against one of those points above. A game that just uses the theme aesthetically is literally just any game you could have made outside the jam, which feels like a cop out. A game where you play as a die and roll as your way to move around might be funny, but in that idea the shape of a cube is more significant than it being a die. For a more specific example, one of the ideas I started thinking about was a platformer where you have several different possible actions, but can only use one of them which is determined by a die roll. This idea might have some potential if fleshed out, but for this particular application it breaks rule 4 -- there would have to be some translation between the number on the die and some action. You would never know what "2" means until you've seen 2 happen already, and even then, you'd have to memorize all 6 associations which seems like a bad idea. To that end, a better solution would be to not use a die at all, cut out the middleman and just say your current ability is randomly selected. But taking it to that logical conclusion the idea now breaks rule 2. There is no longer a die at all, and the only way you could say it fits the theme is by some loose connection to random numbers. A modification of this idea that I thought about for a bit in an attempt to course correct it, was that the die would influence some property like your jump height instead of just determining which ability you have. This still didn't seem good to me, as it breaks rule 4 in a more subtle way. It's true that I could use the number on the die as a direct factor in something like jump height or movement speed, but it's still not exactly obvious what the result of each one is. It's easy to conceptualize the idea that "4" might mean you jump a medium height compared to the min and max possible, but it still wouldn't be obvious exactly how high 4 means the first time you see it. I think in a way this could end up even worse than the idea with varying abilities, because at least in that one it's easier to separate different abilities as discreet outcomes, whereas jump height is more fluid which would make it harder to internalize each association. Anyway, this is all to show how those four points above were what I used to try to steer my thoughts in the right direction.

I keep referring to my thoughts here, and I'd like to point out that all I was doing for the first several hours was that: thinking. I wasn't writing any code or doing any work at the computer during this time, but it's important to highlight that the thought process is a crucial part of the project. It might feel like you're not getting anything done, but that isn't exactly true. Your brain can only focus on so much at a time; if you're preoccupied thinking you need to be writing code or making graphics or whatever else in your development environment at all times, you'll spend all your mental energy doing those things, and may not even end up with a good idea since not enough time was put into coming up with one. I made it a point not to stress out about "losing time" due to the time taken to think my ideas through. Even if it took me the whole first day to come up with a good idea, I would be able to spend the whole next day focused on that idea and whatever I finished would at least have been with a good idea in mind. Whereas if I stressed out about it thinking I needed to be "making" something right away, I would never have gotten to that idea and likely wouldn't have even finished anything in the end. I like to go for walks while I think about things to myself, and indeed, the idea for Dice Climber solidified while I was out on a walk.

It took me a few hours to solidify the idea, but with all of the above points in mind, you can already start to see things starting to fall into place. Given the small scope of the game, the best possibilities for a platformer are basically either some kind of endless scroller, or something with a single level layout like the original Mario Bros. arcade game. My requirement for numerical significance of dice led to the idea for the die block with a decreasing number for every time you touch it. But that mechanic on its own is nothing new, and also is only really a counter, not a die roll. So the starting value of a block would need to be based on some random roll. Thinking about the idea of a vertical scroller divided into floors, it's easy to come to the idea that a floor can have its own roll of a die, which determines its blocks' starting value. From there, it was all about thinking about what kinds of decisions the random element would influence. The first thing I thought of in that regard is that with a higher number, you have more time and room to move around in a floor, so it would make sense to have more required of you to get through a floor with a high roll than with a low roll. If there's one final piece that brings it all together, it would be influence from Super Meat Boy. The behavior of blocks when they're at 1 made me think about that game's own breakable blocks, and how they're often used to great effect with levels requiring you to strategically plan where you touch ground and wall tiles in order to proceed. The thought about higher numbers requiring more to do led naturally to the idea of having some number of things to collect, and that number being equivalent to the die value was a pretty obvious next step. Having lock blocks that open by collecting keys might also be attributed to Super Meat Boy, which has a more or less identical mechanic, the main differences being that that game only requires 1 key for a set of locks, and any locks connected to the same key are unlocked in a chain rather than all at once. Obviously significant differences to suit the respective games, but I was definitely thinking about Super Meat Boy when designing this game; the wall jump behavior also reflects that to some degree, though of course with its own nuances to suit this game as well. Consider this paragraph a recommendation for that game -- it remains to be one of my favorite platformers I've ever played. I recommend playing it on PC since that version has an option to use the original soundtrack by Danny Baranowsky, which if you ask me is far better than the replacement soundtrack that was used for later releases of the game.

Thinking about this idea I could already see some potential for tight decision making. I knew that the ground for the next floor would be able to be broken which would allow you to skip keys in order to climb a floor faster, but with the tradeoff that you would then have less ground to work with on the next floor. Thinking about these kinds of situations convinced me that this idea had potential if fleshed out with varying floor layouts, obstacles and hazards, so at this point I settled on this as the idea I would spend the next couple days building.

Evolution

In order to present some variety in floor layouts, I knew that I wanted to have at least a few different obstacles that could be randomly placed in a floor. I initially had three categories of obstacles in mind:

  1. Normal blocks
  2. Obstacles that influence your movement in some way
  3. Hazards, that if you touch, you lose

That third category should be unfamiliar to anyone reading this, because it was entirely cut from the game. I had several ideas for hazards you'd have to avoid, including spikes that could replace a floor or wall tile, beams that would take up a vertical column of the floor and appear for a short time on some timing cycle, and lasers that would shoot from somewhere and bounce around for some time. I had all these ideas, but never ended up implementing them as it became clear upon implementing the movement obstacles and seeing how dramatically those could already shake things up. I could see that the game was already very hard, and more hazards just weren't necessary and probably would have even been detrimental to the game overall given the confined nature of the floors in practice. Ideas are cut from games all the time; it's easy to lament about things that could have been, but if you ask me, a better way to look at it is that it's a good thing to have more ideas than you end up using. It's just a natural process of having a bunch of possibilities, trying them all out, and selecting the ones that work the best. Maybe there's some better version of this game that could be made that would be better suited to these more elaborate hazards, but that would have required a lot more work in the systems that randomly generate floors, in order to determine that floors would always be fair. Definitely more work than would be reasonable in a 48 hour time period, which is especially apparent given the fact that there are already some questionable scenarios that can pop up within the rules I did land on and implement. All this is to say that despite cutting ideas that seemed cool at first, I'm pretty happy with the elements that did make it into the game.

More interesting to me than what got cut, however, is the way certain aspects changed over time as I tested and played with them. One really interesting occurrence was that the lock and key system presented a sort of emergent strategy that I wasn't even considering while building it. The fact that when skipping keys, the lock blocks become a safe platform for the floor above wasn't even something I was initially thinking about, and I was even thinking it might be a problem at first. But the more I played around with it the more I realized this was actually really beneficial to the game. It made situations that might have initially seemed unfair end up rewarding a player that plans their moves carefully. It also presents more choices in situations like when a high numbered floor comes right after a low numbered floor. You can either carefully plan your route to the key on the low floor, or you can preemptively skip the keys, stand on the lock blocks for the low floor, and just break through the blocks above to the next floor (something you otherwise would not have enough jumps to do on a low numbered floor). These are exactly the type of nuances and opportunities for decision making I was looking for, and in testing, these turned out to be the most fun encounters for me.

One other interesting evolution was the way teleporters were implemented. My initial idea for these was that both holes would appear on the same floor, with some restrictions on where they could be, and would just be another obstacle within a floor. With this original implementation they also didn't go away when you entered one, so you could travel back and forth through them. In practice, this turned out to be far too disorienting when combined with the automatic scrolling and varying floor layouts, and it felt like it would be way too hard to meaningfully allow them to spawn while avoiding situations where parts of a floor are inaccessible. With those considerations in mind, I almost scrapped them from the game, when seemingly out of nowhere I got the idea to make one of the holes on the next floor up, giving an opportunity to "skip" a floor. I liked this idea so much that I actually made a change to how floors are generated in order to accommodate it, as now the function to generate a teleporter had to look at the map for the previously built floor in order to find a valid location to put one. I'm really happy with how this turned out in the end.

An Endless Climb

I'm not going to go into the implementation details of everything in this game, but I did want to highlight what was the most interesting problem for me: randomly generating floors endlessly. I had the following considerations in mind for an endless arcade style game:

  1. Floors should have a wide variety of possible layouts.
  2. The game should ramp up in difficulty as you climb higher.
  3. It should never become impossible to keep going.

The latter two points together can be a huge challenge to reconcile with each other. If the game becomes impossible after a certain point due to difficulty increasing in some programmatic way, then the logical conclusion of gameplay at the highest level is getting to that point and hoping your score happens to be higher than it was before. When two completely optimal plays of the game are pitted against each other in that scenario, the difference in score comes down to the random elements, like how many keys there were on each floor. I don't think I was able to strike the ideal balance with this within the time given for the jam. One area that didn't get nearly enough testing and consideration was with how the scroll speed changes; it changes too much at a time and the max speed starting at floor 50 is unreasonably fast in many situations. I've already made some tweaks to that for a newer version of the game that will be released sometime soon. With that issue aside, I'm mostly happy with how the rules for generating floors turned out in practice. Almost every time I lose, it feels like there was something I could have done differently or executed better that would have worked out, which is what I want.

This section will be breaking down exactly how a floor is built with the implementation in the version of the game released in the jam. A floor actually has two stages of being "built" -- the first is when all of the blocks and obstacles (and the coin) are placed, the second is when it is "activated" or when its die is rolled. When the floor is activated, key locations are determined based on available space and the number chosen by the die roll.

The initial build of a floor has the following steps in this order:

  1. The height of the floor is determined (3, 4 or 5 tiles high).
  2. Lock block position for the next floor (which doubles as the ceiling for this floor) is randomly chosen.
  3. Die blocks are placed in "wall" and "ground" positions, along with lock blocks in the position already chosen for the current floor.
  4. Random die blocks are placed.
  5. Random springs are placed.
  6. Random bumpers are placed.
  7. A teleporter might be placed randomly.
  8. A coin is placed in a random free tile.

For the height of the floor, there is a 50% chance it will choose the standard floor height of 4 tiles. There is a 40% chance of choosing 3 tiles, and a 10% chance for the highest height of 5 tiles. The lock block position for the next floor needs to be known now in order for the rules for placing obstacles to work. Those rules will be outlined below.

The first layer of rules for placing obstacles is how many of any particular object is allowed to be placed on a given floor. Each type of obstacle has different values and floor ranges for this. To determine how many should be placed, the game simply picks a random number from 0 to the max amount allowed for the floor. It then randomly chooses locations until it finds a valid location based on the rules for the given object, and repeats the number of times chosen. The teleporter has its own separate condition.

Die Blocks

Floor Range                 Number Allowed Normally  Number Allowed if Height is 3
1-920
10-1942
20 ...52

Rules:

  • A die block cannot be placed directly above one of this floor's lock blocks, or directly below one of the next floor's lock blocks.
  • A die block cannot have another die block directly above, below, or diagonally to it, unless the one found is in the ground or "ceiling" row.

The second rule there is to prevent creating walls. While walls could be broken, it would often be too hard to break them without also breaking the ground, which seems like an unreasonable situation given the limited time you're able to spend in a floor. Also, the "ceiling" row again actually refers to the ground row of the next floor.

Springs

Floor Range                  Number Allowed Normally   Number Allowed if Height is 3
1-1400
15-2411
25-3422
35 ...32

Rules:

  • Springs cannot be placed directly above one of this floor's lock blocks, or directly below one of the next floor's lock blocks.*
  • Springs must be "attached" to a die block, which has two implications:
    • A spring has to have a die block adjacent to it.
    • The adjacent die blocks determine which directions the spring can face (away from any adjacent die block)
  • Springs must be at least 3 tiles away from each other on either the x or y axis.
  • A spring cannot face directly toward an adjacent die block.

When a randomly selected location is determined to be valid based on the rules, it builds a list of valid directions it can point, and then chooses one at random and places the spring. Also, the asterisk on the first rule is because a bug in the logic actually allowed springs to be placed above the floor's lock blocks, whoops.

Bumpers

Floor Range                  Number Allowed Normally   Number Allowed if Height is 3
1-19 00
20-29 1 1
30-492 2
50 ...32

Rules:

  • A bumper cannot be placed directly above one of this floor's lock blocks, or directly below one of the next floor's lock blocks.
  • A bumper must have free tiles on all three neighboring tiles either above or below (not necessarily both).
  • Bumpers must be at least 3 tiles away from each other on either the x or y axis.

Teleporters

Teleporters have their own conditions which are much simpler. There is a variable that keeps track of the next floor where a teleporter is allowed to be created, which starts at 10. If the floor being built is at least this value, a teleporter has a 10% chance of spawning in a random free tile. If one does spawn, the next allowed floor value is set to 5 above the floor being built (so 5 more always have to go by before another one can be created). As a sidenote, from the player's point of view this is always happening at 1 lower than where it is internally, since when a teleporter is created, it creates the entrance on the floor below the one being built at a random free tile.

After all this happens, the coin is placed on a random free tile. When the floor is activated, keys are placed in random tiles among the ones that are still free after everything else has been created.

I'm sure there are ways this system can be improved; at the very least, I've already fixed the bug mentioned with springs and made one other tweak since this version was released. That said, it's surprising to me how well it has played out so far. The system in place allows for a lot of variety, but still feels mostly reasonable when you're good at the game; I've consistently been able to get above floor 30 and have gotten above 50 a few times as well.

What's Next

That's about it for this post I think. This was a pretty fun experience as my first time entering a game jam, and I'll probably be entering more in the future. I've currently been working on an updated version of Dice Climber with additions and improvements that I'll be releasing at some point soon. It's still not going to be anything huge; I don't want to spend a ton more time on this game honestly. I'd prefer to move onto other projects, but there are still a handful of things I'd like to do with this game before I'm done with it.

Get Dice Climber

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.