Procedural maps in Spy DNA

Procedural map generation isn’t just terrain, it’s also placing all the things that go on top of the terrain. This includes vegetation (got that one covered) but also roads, buildings, and locations for NPCs and objectives (more about them in a second).

At this point, our game can generate a terrain up to 2x2k meters, and more or less cover it with trees,bushes, and grasses. We’re talking literal thousands of them per square kilometer, with wind animation, and for trees also collision, so they can be used for cover.

But we thought our players would like to do a bit more than just run around in the woods each mission, so we added buildings.

That in turn means, taking another pass at the terrain and smoothing it under buildings, and removing vegetation on each plot designated for a building, because having a Douglas fir in the middle of your living room isn’t everyone’s taste. Also, having to go through literal bushes on the way to the bathroom may be a bit much to ask, even of an NPC.

Additionally, we have to make sure that the locations defined in the mission are all placed on the map in a way that makes the mission flow better for the player. The “location” in this context means anything from a building where the objectives are (item to be retrieved, hostage to be saved, etc.), to a place on the map where the player starts, or an item for the player to pick up.

Over the past weeks, Jason’s been working on improving the code that interprets the mission description from our Editor tool, and generates a level from that. Now we have the ability to place locations within a certain distance from another location, to make sure that things that need to be close together stay that way, such as office buildings on a campus for example.

Another thing we can do now is group buildings by type, so that if we’ve got some residential houses and some industrial buildings, they will be placed on different blocks of the map, like one would expect. Jason implemented a sort of “zoning code” for the map generation, so that a block can be zoned residential, commercial, etc. and only the buildings suited for that zone can be placed there.

Locations that are most important for the mission must be placed on the map, while filler buildings can be optional. This is why we spawn our locations in order, according to what Alex has set in the Editor. This way we can be sure that locations such as the building where the objective is hidden, or the extraction vehicle you need to reach to escape the enemies, are placed on the map before a filler building that’s only there to make the map look good.

Here’s an example sequence of a map being generated. The code creates a bitmap after each location is created, to help us debug it if something doesn’t look right. So we thought we’d share these images with you to illustrate the process.

Here the most important location is placed on the map right at the start. This is the parking garage where an illegal deal is happening. The area around it is zoned commercial, shown in blue.

Now we’re placing a restaurant on the same block with the parking garage, where some NPCs will be spawned after the map is all done.

Next, a residential block across the street is created, and the first house placed there. It’s a small house, so it gets a small lot.

Skipping a few steps ahead, you’ll see another couple commercial buildings placed in the commercial block, and another house in the residential. And so it goes, you get the idea.

As Jason continues working on this code, we’ll be adding more decoration to the maps, things such as road signs and street lights and so on, to add visual interest to our levels, so stay tuned!