Latest Blog Post
Procedural Terrain Generation in Bevy
Kieran Cheung
30 Nov 2024
I’ve been learning a bit about procedural generation in games like Dwarf Fortress and Minecraft. It inspired me to make a little world-generation toy using Bevy, a game engine built in Rust. Bevy supports compilation to Webassembly and WebGL graphics. So I made the toy available here to mess around with.
A screenshot from the terrain generator
The generator manipulates Perlin-noise maps, which are ascribed meaningful properties. My generator uses three noise maps:
- Continental Height (representing continental plates)
- Local Pressure (representing local differences in average atmospheric pressure)
- Peaks and valleys (representing smaller scale but higher frequency height changes like mountains and hills)
These three values are passed through several formulae to give each tile other properties, namely:
- Absolute Height
- Temperature
- Humidity
Then these values form a matrix to assign the tile a biome and a ‘tile type.’ For example, tiles which are hot and dry form desert biomes, hot and humid tiles form jungle biomes, cold tiles become glaciers.
The biome and the tile-type are correlated, but not a 1:1 link. For example, beach tiles exist at the coast of many different biomes.
The final feature I implemented was rivers. River generation occurs in a second phase after the first generation of tiles are placed. Several ‘sources’ are placed at random within mountains on the map - and a recursive algorithm is used to simiulate the ‘flow’ of the rivers downhill.
River Generation Algorithm
This algorithm is very basic, but I was surprised how well it interacts with the heightmap to form natural features like lakes and tributaries. It could definitely be improved with some simulation of erosion - implementing realistic erosion is a popular but complex topic in the world of procedural generation. This will do for now!
Notable libraries:
- Bevy - a rust based ECS game engine
- bevy_ecs_tilemap - a crate that makes tilemap rendering play nicely with bevy’s entity-component-system paradigm
- bevy_egui - bevy + egui integration crate, used this to add a simple ui to mess about with the world-gen biases