World Generation Teaser
Happy 2013 everyone! Rather than risking going three months without an update, I figured I’d post some teaser screenshots of the world generation progress on my latest project:
Elevation and water line
Here’s the first pass, mostly focused on getting the land formation looking good with Perlin noise, and sampling the water to ensure a landmass percentage. I’ve also ensured the edges of the map taper off by multiplying the elevation values times a box gradient.
A plain Perlin noise elevation is pretty tame, so I figured I’d throw a twist in it this time around and applied a Perlin noise distortion. My distortion implementation involves generating two additional 2D Perlin noise maps, using one to determine the x-offset and another the y. I then sample the original map with these offsets multiplied by a maximum amplitude. It’s worth noting that Ken Perlin’s original C implementation outputs values between -1 and 1, so sampling offsets for a distortion is straightforward. It’s also worth noting that because Objective-C is a superset of C, said original implementation can be used straight out, no porting necessary (although you’ll need to do some work to output the fBm you’re likely expecting).
Floodfilling to identify landmasses
Landmasses have been floodfilled to identify continents and islands (differences not pictured). I’ve picked a somewhat arbitrary minimum area to qualify as a continent (I believe around 4000 tiles), which will determine starting areas for players.
Inspired by the [now defunct?] Dungeon League article on Wind Direction, I’ve generated an interpolated wind map, then distorted the result with a Perlin noise distortion. Pictured are the degrees of the wind mapped to 0-255.
Wind vectors over land
Arbitrary wind directions are a good starting point, but the purpose of the wind is to determine humidity distribution by simulating how far moisture would have to travel from water to a given tile, with the added obstructions of mountains that are higher than cloud elevation. To this end, the wind direction on one tile must point towards another tile, so it is necessary to clamp the wind directions to the four cardinal and diagonal directions, resulting in 45° zones. The first pass at clamping had hard boundaries between the zones, which meant the resulting rain shadow had too many straight edges, which then resulted in rather unorganically-bound biomes. To solve this, I set up a random dithering rather than clamping. Pictured are wind directions N, NE, E, SE, S, etc. with a corresponding solid color assigned.
Also taking a cue from the Dungeon League article on this topic, I then step backwards through the wind vectors, starting at each land tile, and count how many tiles it takes to get to water or to another tile whose humidity has already been set. I set an upper clamp for how long this can go on, in the odd but remotely possible case that you catch a wind loop that never touches water. This max value is also assigned to areas above cloud elevation, which results in mountains creating a rain shadow.
I’ve stopped just short of identifying biomes, which is the next step, precluded by a quick temperature gradient generation.
For this particular game, biomes add flavor rather than being a key part of the gameplay, so I’ve shifted gears to building a simple tiling system to represent the terrain. After all, each world tile will be larger than two pixels in the actual game!