Saturday, October 1, 2022

Procedural Buildings: Extending Basements/Underground Rooms

Months ago, I added basements to 3D World’s procedural buildings, including both houses and office buildings. I quite liked the darker underground rooms. They gave zombie gameplay mode a scarier feel, and the lack of windows made it more difficult for the player to navigate this area. Now I've taken it one step further by adding "extended basements" to houses, which are a series of underground rooms connected by mazes of hallways. I like to call this the dungeon.

The first version consisted of a tree of branching hallways, where each hallway had up to four other hallways connected to it at right angles with doors. Then I assigned the dead end (leaf) rooms as other types such as storage rooms, bathrooms, card rooms, etc. Since it can be pretty disorienting to walk around here, I enabled the placement of rugs and pictures on the walls to make the hallways more recognizable. Each room also has a row of lights spaced out along the ceiling that the player can turn on and off.

Each room is placed with a variety of constraints to keep it from intersecting other objects. One constraint is that the entire ceiling area must be under the surface of the mesh. I was initially worried about tree roots poking into the occasional room, so to handle that I simply don't draw trees (or any vegetation) when the player is in the basement. Next, I had to make sure none of the rooms intersected other rooms or the house's basement. Finally, I had to check for intersections with other buildings, including their extended basements. It's okay for these extended basement mazes of nearby buildings to wrap around each other. They sometimes do just that.

Now this is more tricky than it would seem because building generation is multi-threaded and in theory two threads can be attempting to add basements to adjacent buildings at the same time. Of course the probability of that is likely very small, given that there are 16,000 total buildings to be processed in a random order. My partial fix for this is to block off the area around a building until all of its rooms are placed, which should at least avoid intersections with the main building and basement. However, it may not matter anyway, since only the building the player is currently in is drawn when they're in a basement. In theory there could be two basements on top of each other and the player will never know - though I guess I won't know for sure what happens until I come across that situation.

But how do we determine which building the player is actually in when their location is inside two overlapping rooms from different buildings? My fix for this is to keep track of the building the player is currently in, and only allow it to be updated if the player leaves the building. This way it's not possible to move from one building to another in two consecutive frames without being outside all buildings for a frame in between. While that works well, it may interfere with my future plans of connecting the basements between multiple buildings as a way for the player to move between buildings underground. That's an area for future work.

This looked good, but it was too difficult to get cornered by a zombie at a dead end. I decided to add loops to make it more like a maze and less like a tree. Any placed hallway that happens to fully intersect or cross a previously placed room will now connect to it with a door. This means that some of non-hallway leaf rooms are no longer dead ends, which increases the variety of these floorplans.

But that wasn't enough. What's better than a dungeon-like maze of underground hallways and rooms? How about a multi-level maze! So I went about adding stairs and multiple floors, and after a long time spent debugging failed basements I was able to get it to work. I have the number of floors limited to 3 in the config file to keep the extended basements sane, though there's no hard limit other than that the lowest floor needs to be above sea level. Lower levels are added by inserting stairs at the end of a hallway and ending the stairs at the entrance to a new hallway one level below. Lower levels are allowed to cross under upper levels and reconnect with hallways and stairs that lead back up. Some stairs have railings to add variety.

Here are some screenshots of extended basements shown from above, to give a better idea of their overall layout. I've disabled the terrain and grass so that they're visible. All surfaces have back face culling enabled, which is why the ceilings aren't visible. Keep in mind that rooms weren't intended to be viewed through the terrain like this, so the lighting is all wrong (among other problems).

Building extended basement viewed from above, with terrain, grass, and ceilings hidden. 2 levels.

Another extended basement viewed from above, with terrain, grass, and ceilings hidden. 3 levels.

Huge underground basement complex on multiple levels that runs underneath other buildings.

Generating and drawing these added rooms wasn't too bad, but that's only a fraction of the work. I had to make room lighting, shadows, and indirect lighting work. Ray casting and collision detection were more difficult when there are no exterior walls to bound these rooms. I had to make the AIs for building people understand how to navigate down here, follow the player, and cross between the house and its extended basement. Note that the structure down here is very different from the packed rectangular areas of the above ground parts of the buildings. There's empty space (or I would assume dirt) between these rooms, and that's a great place for the AI to get stuck. Finally, I had to make rats, snakes, and spiders properly handle these areas. This means I actually have to make these rooms work with 4 different AI systems! Overall I was able to share most of the code, but I did have to add quite a few special cases to the code.

Here are some screenshots of extended basements shown in the intended way where the player is inside the rooms rather than looking down with X-ray vision. You can't see too much at any given time due to the narrow hallways and right angle turns.

Extended basement with three levels (two sets of stairs) along the same hallway.

Extended basement hallways and rooms with a person, a rat on the floor, and railings for the stairs.

Even extended basements contain bathrooms, with mirror reflections.

I'm sure there are many future extensions of this system. As mentioned above, I would like to consider connecting the basements of adjacent houses that happen to be at the same elevation. It may also be interesting to add more basement and parking garage areas to office buildings in a similar way. I made some of the basement lights flicker, but I'm sure there are other interesting effects that I can add to increase the spooky atmosphere of basements.

3 comments:

  1. One of the things that constantly strikes me about this project is that your art style doesn't seem to mesh at all with the mechanics. I would expect a zombie infested basement to look something like this:
    https://media.discordapp.net/ephemeral-attachments/989274728155992124/1148032656626429952/dudecon_a_multi-story_basement_labrythne_in_the_style_of_RPG_du_db6a9d4a-90c7-4da2-b038-03371a5f5f5a.png?width=1038&height=582
    Wheras what you have might be best described as "suburban ennui". Which isn't an insult by any means, but seems to lend itself to an entirely different set of mechanics.
    Perhaps something playing into the melancholic and sterile visuals? Time manipulation, weather-based puzzles, leaning in to the light and shadows perhaps with memory based gameplay? Sanity mechanics, with dreamlike content re-generation? Maybe the only inhabitants are wildlife, and you are helping nature to reclaim the abandoned city?

    ReplyDelete
    Replies
    1. Thanks for your feedback. I completely agree. It's difficult to create a large dirty/broken world with procedural generation because the results of generating geometry with code tends to be too clean and perfect. A proper zombie environment like you showed is more organic with dirt on everything and lots of small detail objects. I don't think I could create something that that by hand, let along with code.

      Keep in mind that this isn't a game. It's a tech demo. I added the zombies for fun when I was halfway through generating the buildings and without much thought to how they work together. I probably want some sort of ghost, entity, or water monster in these areas rather than zombies. If I created a real game I would have to redo all of the models/textures/sounds/etc. anyway because the assets I used generally aren't available for commercial use.

      This did give me an idea. Maybe I should add another basement level that's fully underwater, with the stairs down to it looking like a dark hole. Then if the player tries to go down, some sort of procedurally drawn/animated tentacled monster kills them. I've been thinking of trying to created something like that with code.

      Delete
    2. I forgot to add that the original idea was that people were turned into zombies during or just before gameplay. Maybe it's temporary. The player is supposed to steal items from buildings before they turn back, or something like that. I do have a key binding to toggle between normal people and zombie mode. So it's not that the world has been inhabited by zombies for a long time, rather it just happened.

      Delete