Hello! Today I will talk about procedural generation in Deusira - the game we are currently working on with our small team consisting of a programmer (me) and an artist (my friend Ali). Game genre - First person roguelike with melee combat mechanics. Since I play the role of a programmer in the team, I was charged with the task of implementing the procedural generation of the dungeon and the rooms in particular, which I want to talk about. I’m using very simple algorithms and rules that give a good result at the end.
Basic room generation rules
We decided to use the following rule as the basis for generation: there are n pre-modeled rooms that can be turned into procedural with a simple algorithm and certain settings.
How it works: we have a set of models of the floor, walls, columns, roofs and other elements of architecture. The room itself is represented by a set of tiles (I will call them TileActor), each of which contains one element of the architecture - column (possibly with its destroyed pieces), floor, walls, etc. Also TileActor contains a number of settings and seeds.
These seeds allow me to configure what meshes will be selected on groups of tiles, set dependencies between different groups, set a group of architecture pieces that are incompatible with each other, configure removing probability for some pieces, enable/disable random rotation etc.
Here is an example showing how such a type of procedural architecture works (no light, only architecture):
What about light?
The next step is the torches installation. After uniting the columns inside the room into several groups (thanks to Torch Seed), we have quite a good variation for the light: torches can be spawned on one group of columns or on several, on one or two sides, either lit or not. I’m also making a simple check of the area where a torch will appear for collision with other elements of the architecture, before it is spawned.
Well, the most important stage is to unite the rooms into a finished dungeon. To do this, I need to mark TileActor’s walls that can be replaced by doors in future (room’s entrance/ exit). Also I need to create a blueprint prototype of the room, which indicates its size (through volume) and possible coordinates of the doors (via billboards).
This prototype will be used for the dungeon generator at the initial stage. Generator selects a random prototype from the list and tries to place it in such a way that the position of the future door coincides with the position of the door of one of the allocated rooms. Also I need to check that no conflicts between new rooms and existing ones exist. In fact, I have an array of points in which you can put the transition to another room, which means my task is to walk through these points, constantly rotating and changing the position of the future room until it takes its correct place.
The most pleasant thing for me in this simple algorithm is that the rooms can be placed not only on the plane next to each other, but also one above the other, as in this screenshot.
To do this, it is enough to make several exit points in room and place them at different heights.
That’s how our future dungeon will look like. For now all rooms are appearing close to each other, but in the future corridor rooms will be added.
Now there’s almost nothing left to do - it remains to load our rooms into the volumes allocated for them, randomize the elements of architecture and place the torches.
Blueprint doors are appearing at the points that were chosen as passages between the rooms. It is necessary not to forget to set the same material for the wall-arch above the door as the one at the remote wall. Also, I did not forget to replace the plinth with a suitable one.
The same actions need to be done from another side of the door
Now I want to add few details - the grass, for example, which will grow through cracks in the floor, between the bricks and also in those places of the dungeon, where the dirt floor is located. Such floor tiles can be quickly labeled with splines on which future grass will grow:
The grass generation system is extremely simple: spheres with a random scale and location are scattered around the finished dungeon. If any of the sections of the spline falls inside the sphere, then we can place a foliage instance on it, and the closer the grass is to the center of the sphere, the larger will be its size.
Only few details left – I can spawn fog and fireflies particles in different places of the dungeon.
In the end we have a dungeon generator that consist of rooms with procedural architecture and light changing. Also we have opportunity to create multi-floor dungeon with rooms on top of each other. Finally – thanks to the simple algorithms most time spent on loading screen goes only on actors spawning.
The next thing we will work on in is one of the main gameplay mechanics (fights with enemies in the dungeon) and the filling of rooms with interior elements (props generator).
If this small article turns out to be useful or interesting to someone, I will be happy to write about new procedural features that we will add to the project during development.