Generating a Fantasy Map

This post presents the various stages of design and coding that I used for my 2021 Procjam entry https://tomnullpointer.itch.io/procjam21

I have always loved the look of D&D/Tolkien style fantasy maps. I have always wanted to try generating this sort of pen and paper cartography. And as usual Procjam was a good excuse to spend a bit of time investigating the idea..

Starting with a Voronoi graph

As with many of my terrain generation projects I decided to use a Voronoi dual graph as the basis of the map.

I generate the graph from a fairly even distribution of initial cells and then mark border cells (red), ocean cells (blue), and terrain cells (green) - based on distance from the edges of the world. Later on i refined this process to result in more organic coast lines.

The code then positions several mountain peaks in the graph (set safely away from the coasts) and uses a simple diffusion loop to spread out the height, resulting in a range of altitude across the terrain.

The process then flags each cell with a biome tag biome based on a number of factors such as; distance from the ocean, altitude and underlying noise sampling.

Pathfinding

After setting up a the assignment of biomes across the map I pick some key cells to serve as destinations for a simulated road system. These are chosen by selecting points on a coarse superimposed grid that guarantees that each destination is always a certain distance from its nearest neighbour Any points that are too close or unreachable are discarded.

A simple A* pathfinding system is used to connect the key cells. To ensure a natural flow to the connecting paths, the map is first seeded with traversal penalties. Higher altitude cells have higher penalties and certain biomes (swamps for example) are made harder to cross. In addition to feature specific obstacles, all terrain  cells are treated with a light modifier based on a simple 2d noise array in order to add some randomness to the paths returned. 

Once a road network has been found the system deletes a few random points and connections (while ensuring that all destinations still have at least one path connecting them) to make the road network less grid like and encourage the occasional appearance of remote outposts etc.

After the roads are built, a similar system is used to create rivers. In this case the initial points are set to be at the top of the mountain areas close to the peaks used to drive the initial altitude diffusion. The rivers then proceed along cell edges, always trying to path to neighbouring cells with lower altitudes. This creates natural looking streams that end up in the ocean or a landlocked lake.

I use cell edges rather than  centres so that the rivers wont occupy the same space as any roads that might exist in the same locations.

I could have continued to refine the data creation for the cells to give the map more expressive range, but as the project was part of a jam I decided to stop with my data structure work and start the visual 'cladding' of the map.

Each cell has a biome type which drives it to pull a sprite from a set defined by that biome. For instance, a cell above a specific height is a mountain and can use any of the 5 possible mountain sprites I had prepared. Again the number of cell types is fairly limited with locations such as hills,  forest, marshes, villages, towns, towers etc.

Finally I added a few parameters for the players to adjust, so that they could explore the range of maps the tool can generate.

This article was updated on

Related post