• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Design Text Based Level Generation (Downwell, Spelunky) (SOLVED)

KamilSeven

Member
Hi everyone!
In this video I linked, Ojiro Fumoto talking about a text-based random level generation and I was wondering if there are any sources to learn this technique in specific. Any article, tutorial, or contribution to the topic would be really helpful.

33:54 Fumoto starts to talk on the topic.
35:26 shows a little bit of the actual code.


Thank you!
 

Yal

🐧 *penguin noises*
GMC Elder
As far as I know, the text-based approach is mostly a nice blend of easy to work with code-wise and still human-readable (e.g. if you use # for solid ground and spaces for empty cells, and / \ for slopes, you can look at the general shape of a level in a text editor just fine - heck, even DESIGNING a level by just typing in the right string isn't too hard), rather than something that actively makes generation easier. So you don't necessarily need to have text-based generation in order to have easy procgen. One of the limiting factors is the ASCII 256 character set limits (unicode strings can get kinda messy to deal with) so if you know you're going to have more objects and tile types than that, you need to come up with a workaround sooner or later.

My personal preference usually is a list of {x, y, object} tuples - that is, an array filled with smaller arrays - since it's really straightforward to loop through the data when creating the level objects later; having a custom editor helps visualize this data. (Nothing stops you from having a "export" button that creates GML code defining the data and copying it to the Windows clipboard, so you can just paste it into a script to define the data). There's some issues with saving this type of data to a file, though (since resource indices can change on every compilation, you can't just save the "obj_wall" value, you need to save its name and then use asset_get_index on load)

This video goes through the generation process in Spelunky on a conceptual level, could be worth giving a watch to get a better grasp on it with some extra context :
 
Last edited:

KamilSeven

Member
As far as I know, the text-based approach is mostly a nice blend of easy to work with code-wise and still human-readable (e.g. if you use # for solid ground and spaces for empty cells, and / \ for slopes, you can look at the general shape of a level in a text editor just fine - heck, even DESIGNING a level by just typing in the right string isn't too hard), rather than something that actively makes generation easier. So you don't necessarily need to have text-based generation in order to have easy procgen. One of the limiting factors is the ASCII 256 character set limits (unicode strings can get kinda messy to deal with) so if you know you're going to have more objects and tile types than that, you need to come up with a workaround sooner or later.

My personal preference usually is a list of {x, y, object} tuples - that is, an array filled with smaller arrays - since it's really straightforward to loop through the data when creating the level objects later; having a custom editor helps visualize this data. (Nothing stops you from having a "export" button that creates GML code defining the data and copying it to the Windows clipboard, so you can just paste it into a script to define the data). There's some issues with saving this type of data to a file, though (since resource indices can change on every compilation, you can't just save the "obj_wall" value, you need to save its name and then use asset_get_index on load)

This video goes through the generation process in Spelunky on a conceptual level, could be worth giving a watch to get a better grasp on it with some extra context :
I wanted to learn this technique because Ojiro Fumoto was able to have a satisfying result with little programming experience. I will implement Zack Banack's tutorial when I have the time. I've previewed his tutorial and it seems like he only explains how to build levels in txt format but doesn't get into how to spawn rooms in random order with exit path. Overall this technique seems above my skills, but I really want to be able to code random level generation.

I've seen the GMTK video some time ago. I really enjoy the channel and following almost every video from GMTK.

Thank you for your contribution to the topic.
 

YanBG

Member
There's some issues with saving this type of data to a file, though (since resource indices can change on every compilation, you can't just save the "obj_wall" value, you need to save its name and then use asset_get_index on load)
I went with array instead of instances/objects. It takes some time for your brain to get it all organized and planned but it's cleaner in the end. Honestly i don't need most of the built-in object functions. I prefer to have it tailored to my current needs than to start lagging pretty fast.
 
Yeah, I think @Yal's comment hits to the heart of the matter. Sure you can make a text based level editor interact with proc gen, but thinking of the level editor AS the proc gen is kind of wrong. It's like saying "I want to make procedural generation with lizards as enemies, how do I do that?" And the answer is make a procedural generator and then make your enemies lizards. You can have proc gen with or without a text-based level editor having anything to do with it and you can have a text-based level editor with or without proc gen having anything to do with it.

Learning to do procedural generation is really just learning how to constrain randomness. It's like that Michelangelo quote:
The sculpture is already complete within the marble block, before I start my work. It is already there, I just have to chisel away the superfluous material.
The levels that you want the game to be creating already exist within a RNG, you just have to find the specific ways to apply that RNG to carve your levels out from the pure randomness.

Making the level read the text generally isn't very hard (it can seem hard if you're new, but it's a pretty simple process). The hardest part of proc gen is finding the specific ways to constrain the randomness so that what it spits out sits in the sweetest spot in the venn diagram of "all possible levels", "completable levels" and "interesting levels". Finding that generally requires a lot of experimentation, creativity and ability to translate thought into code. If you are building the individual sections by hand, as it seems you want to, it makes the job a little bit easier, but then the "randomness" (which is really the sole reason to use proc gen) can get lost a bit and it will still take creative use of the tools to make generated levels that are different enough from each other that the player won't notice repeated sections and start to get bored.
 
Last edited:

YanBG

Member
Right, even if the text-based level looks simple, that doesn't mean it's easy to code. The #### symbols is just graphics.
 

KamilSeven

Member
Yeah, I think @Yal's comment hits to the heart of the matter. Sure you can make a text based level editor interact with proc gen, but thinking of the level editor AS the proc gen is kind of wrong. It's like saying "I want to make procedural generation with lizards as enemies, how do I do that?" And the answer is make a procedural generator and then make your enemies lizards. You can have proc gen with or without a text-based level editor having anything to do with it and you can have a text-based level editor with or without proc gen having anything to do with it.

Learning to do procedural generation is really just learning how to constrain randomness. It's like that Michelangelo quote:

The levels that you want the game to be creating already exist within a RNG, you just have to find the specific ways to apply that RNG to carve your levels out from the pure randomness.

Making the level read the text generally isn't very hard (it can seem hard if you're new, but it's a pretty simple process). The hardest part of proc gen is finding the specific ways to constrain the randomness so that what it spits out sits in the sweetest spot in the venn diagram of "all possible levels", "completable levels" and "interesting levels". Finding that generally requires a lot of experimentation, creativity and ability to translate thought into code. If you are building the individual sections by hand, as it seems you want to, it makes the job a little bit easier, but then the "randomness" (which is really the sole reason to use proc gen) can get lost a bit and it will still take creative use of the tools to make generated levels that are different enough from each other that the player won't notice repeated sections and start to get bored.
Thank you for the advice. Yes, for now, I want to build sections manually like Spelunky and Downwell. I really need some more time with fundamentals before I can do something proc gen. My only experience with proc gen is pipe spawning for a flappy bird clone which requires just a line of code.
 

Yal

🐧 *penguin noises*
GMC Elder
Procgen is a really big subject so it pays off to study it well before you start.
  • "The Thousand Bowls of Oatmeal" problem comes to mind, tons of high-profile games fail on this (e.g. Watch Dog Legion's characters). Basically, if your randomness technically is random but doesn't provide any palpable difference for the player, you might as well just give them the same result every time (or have a smaller selection of higher-quality handcrafted levels). Make sure your generator makes content that is visibly different and/or feels different to play, the bigger the spread the better.
  • Vaults (pre-made rooms placed randomly) is a good tradeoff between quality and randomness, but players will start recognizing the rooms. You need to have a large selection for it not to become painfully obvious (Starbound fails pretty hard on this). Being able to flip the data horizontally / vertically helps with this, and mutating the data (moving things around a bit as long as they stay out of the critical path, placing enemies independent of the level layout) also does it.
  • Top-down (decide what to make first, then generate that thing - e.g. Spelunky, anything with room templates) and bottom-up generation (spawn a bunch of things, then do some metrics on them to decide what it's supposed to be - e.g. Minecraft, anything using perlin noise) are fundamentally different, and they're good for different things, so make sure you pick the right tool for the job.
Nothing's stopping you from mixing several types of randomness together (e.g. make some random tunnels/corridors, then put down rooms randomly on top; place enemies and loot randomly after the map has been generated, use perlin noise for terrain but then place buildings on top, etc etc) and it's usually way easier to have several small but simple systems glued together than to have a single big one.
 

KamilSeven

Member
Hi everyone! And thanks for all those answers again. It's been a while, I was away from game dev. And @Yal, thank you again! I see you are helping people all over the forum.

Recently, I have followed Blackthornprod's Random Level Generation tutorial (link below) on Unity to have an idea about how room spawn systems like Spelunky's can be done. But the thing is the method Blackthornprod follows, uses prefabs, which Game Maker doesn't have. I think the method on tutorial makes it very easy to implement it and also to have variations. I was wondering how can I convert this method into Game Maker? Any examples or pointing out the topics I should study would be great.

Blackthornprod's Random Level Generation tutorial:
 

Yal

🐧 *penguin noises*
GMC Elder
prefabs, which Game Maker doesn't have
You can use sequences for this (spawning a sequence with a single keyframe is equal to just creating all the instances / sprite-assets it contains). There's some caveats (for some reason with-loops doesn't cross sequence boundaries, coordinates get weird if you rotate a sequence, etc) but for basic cases it should be simple enough.
 

KamilSeven

Member
Hi everyone! Again, it's been a while. Looks like Quench Games's "Spelunky Level Generation" tutorial is back online on youtube. I'll leave the link so the topic can be solved. Many thanks to all.

 
Top