In the previous article, we described the "default" parameter of each level we are going to create with the level generator.
A level is populated with various pieces we call "Level Element".
Level Element have been defined in the following list, each of the type has its own particularity and purpose in the level creation:
- Entrance: That's where the player will start
- Rooms: The important place of the level, where the main enemies and treasure will be found.
- Corridor: Each art of the level that is supposed to connect room to each other. Generally less important than room.
- Stairs: Similar to corridor, but these element are supposed to change the verticality of the level. We divided this type in two, for reason described below
- Stairs up
- Stairs down
- Exit: The end of the level, allowing player to move to another level or ending the current scenario.
To make things easier, we decided to have a virtual 2D array of various size to manage the placement of our Level Elements.
Each of our Level Element will take a certain size in the 2D grid.
We first wanted to place each Level Elements according to their Bounding Box, but it ends up that using a 3D grid was pretty much exactly the same in the end.We then define what the important parameters our Level Element will have are.
- Name: Always unique
- Type: Entrance, Room, Corridor, ect...
- FilePath: The default associated ground geometry. See below why.
- XSize and YSize: For Level Element placement, described before.
- Level: Each room have a level, according to its importance. Is it a dangerous room full of treasure or a simple one? Also, we may want to spawn important room later, when the player will be more powerful.
- Prefab: Prefabs are an interesting feature of CryEngine, allowing to load at runtime any collection of geometry or entity. Each Element may have one or several different prefabs, and are selected according to their Frequency parameter.
- Frequency: How often is that Element supposed to appear in the level ?
- CountMax: Useful to make sure that a room will not appear too many time in a level, or to make sure it will be a unique room (boss, large treasure...)
- NoSpawnBeforeXElements: This Element is not supposed to spawn before X other element in the level. I will make sure that some important Eement will never be too close to the entrance.
- NoSpawnBeforeXElementOfSameType: Same as before, but only considering the sametype of the current Element.
- IsStairUp/IsStairDown: For non-Stairs Element, we have this parameter telling us if the Element is making the level climb up or down. It will allow us to select or discard the Element if we want our Level to never go up or down.
Placement in the Level
The easiest and most effective way to create our level generator is to use a 2D grid. This grid will ease the placement of each element in the level, but may be problematic since element in a grid are quads - we pretty much want to manage any kind of shape for our Level Elements.
To fix that problem, our Element will not use the size of their actual BBox in the grid, but a virtual value given in their parameter file. Again, we could fix that problem by using oriented bounding boxes, but the result will be the same and managing a 2D grid is much simpler.
Before explaining how our path are generated, we will explain how an Element is placed in the level and how we connect Element to each other.
The base geometry of our Level Element is the ground. On each geometry, we add several dummies (called Helper in CryEngine) in order to mark entrance and exit points. This is done in 3DStudio, because we want the modeler to control the placement of the dummies.
According to the position and the orientation of the helpers, we will connect an Element with another one. The following picture shows various example of Level Element placement (Basic Geometries)
As described before, prefab are an important feature of our Level Generator.
The idea is to create a simple ground first in order to assemble all our Level Elements, and then create all the component entity.
The following picture shows a basic ground on the right, and a Prefab associated to it on the left. For obvious reasons, we first create the shape of the level only with basic geometry, then add prefabs.
Also, since we manage any kind of entity in our Prefab, we can also use random content generator inside the prefab, in order to get even more variety - That's the way we also create furniture in the rooms, but that specific part will be described later.
That's it for today. I wanted to describe the generation process in this article, but it would result in a quite long article, so we will reveal it in our next post!