For our procedural generation, we had the idea of creating dungeons consisting of seven to ten compartments, where there could be limited chests or shopkeepers in random compartments.
These dungeons are randomly composed by one of the seven existing elements, resulting in unique characteristics in the composition of the scenario, greater chances of spawning monsters from the element of the dungeon, and a final boss also related to the element.
To create the procedural generation, we created an algorithm that allowed us to have control of some elements that we consider crucial for our objective. These elements are the positional limits of the dungeon, number of compartments and corridors, distance from the final compartment to the initial one and the number of compartments that spawned chests or shopkeepers.
There are three elements to generate the structure of the dungeon:
- Contact point (a point that connects with another compartment or corridor);
- Compartment (has one or more contact points);
- Corridor (has a maximum of two contact points);
For the creation and connections of compartments and corridors we use points located in each possible exit of the room. Each compartment has one or more Contact Point, and these contact points have two states, these being the state of opened or closed, depending on if they are connected to another compartment/corridor or not.
The dungeon's structure generation algorithm can be divided into a few steps:
- Spawn an initial room and a corridor;
- Loop Starts (while the room count has not reached its limit):
- Get opened contact points for each compartment and corridor;
- If it’s possible, place a compartment or a corridor on each opened contact point, else it will create a wall;
- Close the contact points that were filled with a compartment, a corridor or a wall;
- Spawn final room at the farthest possible distance from the starting compartment;
- Close all remaining opened contact points;
Later, no longer related to the dungeon structure generation but still part of the process, the algorithm creates enemies, with different formations (positions and enemy combinations) depending on the floor the player is on and the chosen difficulty. These formations are previously set, so we have control of which enemies we want on each compartment.
After that, random rooms are chosen, which contain chests and shopkeepers. The algorithm sets them in previously set positions as well, so we can place them in strategic places so that they are easily visible to the player.
Finally, the algorithm ends with the definition of what type of loot each compartment will have as soon as it is cleared, then placing an icon on each access door, with the type of drop existing in the compartment as seen on the image below.
In the videos bellow we will show the evolution of the procedural generation.
Initial generation, still with some bugs. As seen in the video below, there are contact points that stay opened, without any wall closing them. This is the initial algorithm, and it’s already working with position limits, quantity of rooms and connections of compartments and corridors.
The video below shows the base of the current algorithm. It’s possible to see every contact point, represented by red dots.
The next video shows how tweaking the generation parameters affects the layout of the dungeon. By changing these parameters we can control the position limits of the dungeon and the quantity of rooms.
Finally, the current procedural generation with the current compartments and corridors.
Examples of Layouts
The images below show some examples of layouts generated by the algorithm.
In conclusion, this technical part of the game was a new and difficult challenge due to the inexperience in creating procedural content. It's not even close to being perfect and there's still a lot of room for improvement, but we're very happy and satisfied with the final result.