Written by: Mark Bouwman
Implementing difficulty in levels isn’t all that hard! Use random levels and change cut-off values!
Yeah, right. Be like that. “I don’t care about difficulty; I just change cut-off values for spawning things when using math.random!” Even though it does suffice for some situations, you can often find you want just a tad more control over how tough your game really is. Sometimes, you just need that extra bit of control over the situation and need stuff to be a bit more exact. Other times, you just want to manually make a level to keep the best control over the difficulty.
But Mark, how do you decide when to use what?!
Each situation requires a different approach. It really all depends on what you need. During the past few projects I worked on, I have had to implement several different ways of difficulty management: randomly generated levels and manually designed levels. Most of the time you’ll find that if you need infinite gameplay, you need either a randomly spawned level, or a level that confines the player to a small place. When you want short burst of gameplay, it might be better to manually design levels in order to pace the game to your own liking. It’s a pretty important decision to make at the start of development: going for either random levels or pre-set levels makes a huge impact on how you develop the game.
Randomly generated (“procedural”) levels
I’ll start with the randomly generated levels. These are used in a lot of games, most often the ‘infinite’ gameplay types. The pros about using random generated levels is that you don’t have to put hours and hours in manually placing assets in order to create a level and it can lead to quick prototyping. The cons about using randomly generated levels are that you have less control over the game’s flow. It’s tougher to manage the difficulty in a level. Small tweaks are harder to make, and you have to test over and over with every adjustment to see if you didn’t just get that ‘lucky round that played perfectly’.
I’ll explain how we used randomly generated levels.
The customer wanted a doodle jump sort of game to show children they have to eat healthier and exercise more. The game had to appeal to kids and had to get increasingly harder as the player progressed. In theory, the game should offer infinite time of gameplay in a single session. Because of this ‘infinite jumping gameplay’ restriction, we knew had to create a randomly generated level.
There were two challenges in creating this type of level. Challenge number one: The level had to get progressively harder, but should be random enough not to really notice. Challenge number two: the system had to be easily tweakable, so that we could playtest often and adjust to the results from these tests quickly. Our target group were children after all, so we didn’t know how hard the game should be. Our own perception of difficulty is completely unlike theirs.
The system we used was based on percentages. For every object that could spawn in the world, we had a minimal and maximal spawn chance and minimal and maximal distance between two spawned objects of the same type. Every action the player did (jumping, picking up items, completing challenges) rewarded him with points. These points were then used to measure progress.
The amount of ‘progress-points’ the player had gotten over his session decided the difficulty of the game. We compared the current amount of points with the amount of points needed for the maximum difficulty. The percentage we got from that was then used to spawn all of the objects. If the player was halfway through the ‘progress-points’, the level would be halfway through becomes the maximum difficulty.
Because of this system, we could easily adjust the difficulty of the level. Changing the duration of a single session took just a single variable, changing how difficult the game is at the end only took a few more variables. It saved us so much time in tweaking the game, which allowed us to tweak often, resulting in the best gameplay possible. We eventually tweaked the game to last around 10 minutes for the average player; however it could last up to 20 minutes until the maximum difficulty was reached. The best part: difficulty increased along with the player’s progress, not the time spend in a session. Because of this every child could play at his or her own pace.
Manually created levels
I know: it’s something you’d prefer to avoid if possible. It can take really long; you have to really think about positioning stuff, there’s a lot to keep in mind when creating your level. The truth is though, manually creating levels offers a great way of controlling the difficulty and learning curve for a player. Having pre-set levels allow for the best tutorials and are great for oozing in new parts of gameplay. The downside is that all the manual labour you put into creating (each of the) levels can feel repetitive and can take a lot of time to do well.
However, creating levels does not HAVE to be a tedious task. Creating and using tools is the key to surviving here. Of course, it all depends on what kind of game you have, but in most cases you can create a tool to massively improve your workflow. Even though creating tools takes time, almost all of the time it’s a great thing to do.
People often don’t create tools for themselves, thinking it takes up more time than it really gives back. However, the opposite is often true. When you’re able to click a level together way more easily, when adjusting already set level designs gets easier, when using tools to chunk parts together to decrease the time of creating a level all-together. All of these situations allow for the game designer to focus on what really matters: on the actual gameplay, rather than implementation.
Every situation requires different tools. The only thing the programmer can do is listening to what the designer would need and create the tools based on that.
A bit of both levels?
Another thing you can do, is mix. You can manually create set chunks and then use these randomly throughout a world. Or use a pre-set level with random assets in it. You’re not set to either of both. Like I said before: it’s an important decision for your development process. Think about what you need before implementing any code.
Don’t rush it.
3,811 total views, 2 views today