Lichbound - New Procedural Level Generation!
A small recap
Hello! It has been a while since my last post about Lichbound. Since then, a lot has happened, so many exciting things!
For example, we were selected for the Indigo 2023 showcase. We didn't think we'd get our game on display at such a big national event, but we did! Many people were able to playtest our demo, and we received lots of feedback.
Our game was played for the first time on Twitch by: KlitchKraft
Which, in turn, yielded a lot of insightful feedback. We all felt a sense of accomplishment after it. We're really looking forward to promoting our game towards content creators in the near future, so having our game livestreamed felt like the whole plan was finally coming together.
We submitted our game to the Dutch Game Awards! Unfortunately, we were not nominated, however, again, we did not think we would get so far as to submit our game for a national awards ceremony to begin with. The game was incomplete and, in comparison to other games that were submitted, we were already aware that we wouldn't be able to proceed beyond submission.
And finally, we went to Gamescom this year! This was our first outing as a company, we all wanted to see what Gamescom was all about. It was huge, and there were a lot of indie-games on display. We sometimes got lost between the stands. We saw some games made by Dutch game companies, and they had excellent demos on display. This made us want to make an exceptional demo, so we can show it at Gamescom in the future as well!
Alright, now that we are all caught up again, let's talk about the juice!
What was wrong with the old generation?
The previous version of the level generation system that I wrote worked… But that's about where the story ends. It was incomplete, inefficient, annoying to set up and work with, but again, it worked. I really stuck to the “If it ain't broke, don't fix it” mentality. Which was not necessarily a bad decision, we needed a game that worked and was a proof of our concept. So we stuck with the old level generation.
The design of the system was simple on paper. The level was made up of rooms. These rooms we're all handmade by me, mostly, and they all had a very annoying limitation that I stupidly set at the beginning of the project. All the rooms needed to be the same size. Which wasn't even that big of a size. This led to a lot of repetition, which in return made all the levels tedious to move through.
And to worsen it. All the points where the rooms connect to each other HAD to be perfectly placed in the cardinal directions. And the rooms could only have 1 connection point per cardinal direction, as illustrated by the picture below.
Now, to be fair, I only ever made 5 different rooms, so that might not have helped either. But regardless of the number of rooms we had, they were still all the same size, had the connection points at the same spots, they could only have 4 connection points maximum, ugh. Yeah, this level generator was the bane of my existence for a long while. And I dare to call myself a beginning professional when it comes to PLG!
So about that new level generation
Anyway, some time has passed, some people from our team have since graduated and some (like me) are still studying for now. So since I have another 5 months to work on my graduation project, I decided to rewrite the entire level generation in Lichbound!
Now I already laid out why I didn't like the previous level generation, so what DO I want to like about the new level generation?
Please note that all the images shown below were created within the game engine without any actual design work being put into them. The rooms, levels, layouts, and gizmos should be seen as previews only, and not as the final product.
The new level generation needs to check the following:
The levels should consist of “puzzle pieces” also known as rooms/rooms/chambers. Everyone on the team should be able to create these rooms.
The size of the rooms, what shape they are and where the connection points are, should not be fixed.
All rooms should not be left with open connection points and are always closed off by other rooms or “End caps”.
The level generation should not be too heavy. Preferably less than 3 seconds at most for a clean transition between levels.
It should be clear to the player which way they should go to reach the end of the level. How this is achieved has yet to be explored.
The levels should not start to look like they are generated on a grid, but more of an “organic” feel. How the levels feel should come from the rooms themselves and not from the algorithm.
It should be configurable per floor which rooms can be used, which enemies, treasures, traps, puzzles, etc. this is important since we want to clearly indicate that the player is going deeper and deeper into the levels, allowing the player to see more and more as they progress.
Some of these cannot be verified as complete via code alone. For example, the "organic" feeling should come from the level design, not the level generation. However, the level should not be made on a grid. This allows for more interesting levels to be made, so it's about 50/50. The generation of levels provides the option for "organic" levels, while the level designer actually utilizes it.
Here is a quick preview of the flowchart of the level generator:
I have excluded certain smaller tasks. Otherwise, the diagram would be hard to read (or maybe I'm not good at drawing diagrams). This should provide you with a brief overview of how the level generator works behind the scenes.
However, I understand that not everyone likes flowcharts and requires additional visual stimuli, so I have included the same steps from the flowchart within the game engine.
To clarify any potential ambiguity, it should be noted that pathways also count as rooms. Since pathways are not required, I handle them the same way as the actual rooms.
Step 1: Create the first room (Spawn Room)
Step 2: loop through all the disconnected connection points and create a new room. Place the new room next to the connection point that was disconnected, and connect them together.
Step 3: Repeat until the number of rooms is reached.
Step 4: Repeat the loop through all disconnected connection points, but now place end caps.
Step 5,6,7… do all the other stuff, like spawning enemies, and the portal to the next floor:
At present, there has been no investment of time into enhancing the appearance of the rooms. Only the layout and a few interior obstructions have been positioned.
Fun fact! Currently, there are only five rooms available. However, due to their considerable variation in size and shape, the levels that can be generated are significantly more intriguing than the previous level generator, I believe.
You might be wondering, how do these rooms function? How do they know where to connect and where to put the enemies?
Let's break it down into smaller pieces, shall we?
Take this room for example:
It is a very straightforward looking room; however, you might have noticed that there are six spots where the room opens up to the void, which is where the rooms connect to other rooms.
Here's what these connections look like:
The red lines indicate where there should be a floor tile underneath, and also indicate the width of the connecting point. This can be changed for each connection point, but for now, all connections use the same width to make things easier.
The blue (actually Cyan) areas indicate the location of wall tiles. The arrows that indicate which direction the connection point is facing help the designer determine which wall tiles to place.
They are more like connection rectangles than connection points, now that I think about it. Oh well.
We can see here the spawn points for the next level portal.
The idea is to put them in front of the connection points, so that if they get closed off with an end cap, it makes a perfect spot for the next level portal.
When all the rooms and end caps have been placed, the level generator will look at spawning the next level portal. This is done by finding the connection point that is the furthest away from the spawn. To ensure that the portal will always be spawned in the furthest room from the spawn.
As you can see in the game:
Now you will notice that there are enemies in every room. In each room, there is a list of shapes in which enemies can spawn. As of the time of writing, the enemies will be generated in a rather inefficient manner. No grouping is done intentionally, but it can happen by accident.
The area in which the enemies can spawn is defined by yellow rectangles.
The only restriction for the enemies is that they can't appear on top of or within a certain distance from each other. Eventually, I would like to add actual grouping. The picture doesn't show a special enemy that acts like a small boss in a room. Frequently, in games that generate a substantial number of trash/fodder enemies, additional elite enemies may be introduced, which may include a group of weaker enemies as guards to increase the difficulty of the encounter.
If you combine this all into one single GIF, you will get this:
The old level generator had many things that were lacking, and numerous things that would actively hinder the process of creating fun and engaging levels. This was okay for a long time, or rather, we accepted it for a long time.
The idea behind the new level generation is to resolve those problems and make fun levels for the players to play through. It's not just a technical upgrade over the previous one, but it's also more user-friendly and sleeker. It would be a good portfolio piece once it's finished, but that's something for later.
Anyway, thank you for taking the time to read my ramblings about the level generation in Lichbound. I hope you found it informative or fun to read. :)
Wishlist Lichbound on Steam! It would mean the world to me (and my team)
This is an image, Wix does not like steam embeds ;(