Country Terrains - Towns

When it comes to procedural generation, there is one question that creates huge divides as to what kind of methods can be used: Can generation be done post hoc?

Some kinds of methods are much easier if you can first generate a map, and then afterwards, cutting off possibilities of infinite terrain, you run a script which looks at the finite map and generates things. One example is that of rivers, which are easy to generate when you know where there are mountains - but the river itself ends up far from its source, making truly procedural rivers very difficult.

Today, however, we are going to talk about procedural, that is, NOT post hoc, generation of towns, or cities, or whatever you want to call it. This is just a broad-strokes technique I'll describe. Look, these are the kinds of towns we will make:



The houses are far from being highly detailed. Instead, what we shall discuss is how to place houses, specifically, how we let houses form towns without either being gigantic blobs or the American midwest. But first, we should talk about streets.

Houses are, generally speaking, rectangular areas surrounded by areas that are not house. This gives us a simple solution: Using modulus on our x and y coordinates to construct a grid:



Given a simple algorithm where a cell is a house (red) if neither its x or y coordinate is divisible by 4, we get this nice grid structure. Putting this into our map, we get the following:



Welcome to Greece, population ten billion. Not only do we have too many houses, but all the houses have the same size and shape, all roads are straight like some sort of Barcelona, and this just won't do.

You may notice that by the mountains, the houses are distorted by the height of the terrain. This can be fixed if, once we have found out if the pixel is part of a house, using rounded coordinates to find the height so it is all built on the same level. This is not that important because we should not have houses on mountains anyway. Furthermore, perhaps it is exactly distortions that we want - this, for certain, could break up the monotony of the grid at least somewhat.

For more on distortions see: (A post named Fluid-like Perlin noise)


This method is not perfect. Some places, like on the harbour-town area in the left corner, the straight streets become much more realistic looking Also, some houses become bigger than others, enabling interpretation of rich and poor neighbourhoods. But the distortions, too, seem a bit obvious. This might be because we still have way too many houses.

How about just straight up limiting where houses can be via Perlin noise?


Phew, that certainly was a load off our shoulders. This is much nicer to look at, and already the distortions become a bit more subtle. I also used the height of terrain as part of the boundary for the Perlin noise, meaning that cities are most common by the sea.

Anyway, we still have a bit of a problem. The cities are still very tightly packed, then end immediately. The next thought might be to add a normal random chance on top of the Perlin noise, but then we run into a problem that one house consists of several completely independent pixels. We need to make sure that the whole potential house agrees on what this random number would be.

Earlier, we used modules to create streets, but in so doing, we also make it easy now to use division and flooring to give unique IDs to every potential house. This ID can then be used to generate a random number used common for this specific building. This allows us to create the gradient from dense urban centre to sparse rural sprawl:


I guess in this case, there are not that many dense urban centres, only an oddly placed town by the lone mountain towards the east.

Now, this could easily be expanded upon. Personally I chose that everything should be generated on the pixel level, but it would be easy to instead just trigger a script in the bottom corner of the house to generate a more detailed building.

This post, however, was interested in towns rather than houses. We have explored a simple way to create houses from a grid-seeking algorithm, then done our best to make houses sparse enough that the grid is less apparent, apart from where it fits. This is an entry-level way to generate towns, using only five lines of code:

  • Two lines to distort x and y coordinates
  • One line to calculate a common house ID
  • One line to determine if a pixel is a house
  • And one to colour the house differently.
I guess I should mention. Here, I draw both walls and a roof. First, the house is raised off the ground by a couple of pixels. Then, either roof-colour or wall-colour is used to draw, depending on where in the grid the pixel is:



It really can be this simple. I'm not saying that it has to be, but more often than not, simple solutions are effective until much further in a project's course.

For live generation and source code, see: https://www.openprocessing.org/sketch/582973

Comments