A few years back I wrote a handful of posts about faking water on top-down maps: generating 2d rivers, cliffs, and an exhumed river channel. Those one-off experiments eventually grew into a proper map library I’ve been maintaining called compass. Revisiting them now is fun because real-world geology already solved the “make it look natural” problem ages ago. I just borrow the names and loosely approximate the process. Here are three of the fluvial generators and how they actually work.

Arroyo

An arroyo is a dry creek bed that only runs when it rains, so it should read as a winding channel cut through rougher ground.

  1. Seed the map with simplex noise, biased horizontally or vertically so the roughness has a grain to it.
  2. Run two drunkenPath walks: one from a terminal edge into the center, then a second from the center out to the opposite terminal. Both walk wide so the bed has some thickness.
  3. If a walk fails to connect (it happens), fall back to a bresenhamsLine between the points so the channel never breaks.
  4. Surround the channel with a buffer, then invert floor and wall so the carved path becomes the walkable area, and clipOrphaned removes anything stranded.

An arroyo carved through noisy terrain

Alluvial Fan

When a stream leaves a canyon and hits flat land it drops its sediment in a fan. That fan shape is the whole effect here.

  1. Build a continent with simplex noise, land below one threshold and water above another.
  2. Drunken-walk a river from an edge until it reaches the water body, recording where it entered.
  3. Draw the fan as an ellipse anchored at that entry point. The interesting bit is computing the foci from the semi-axes so the spread looks like deposition rather than a perfect oval, with the interior almost always water and the outer edge only sometimes.
  4. Surround the whole thing with a sand probability and lay one more pass of noise over the top for texture.

A river fanning out into sediment

Braided Channel

Braided rivers split and rejoin around sandbars, so instead of one path I run several.

  1. Pick a random direction (cardinal or diagonal) and spin up two to four parallel drunken rivers.
  2. If any single river fails to connect, fall back to the meander algorithm to wind it through instead.
  3. Fill the rest of the map with two scales of simplex noise stacked together, a coarse pass for landmasses and a fine pass for grit, cascading through thresholds into wall, rough wall, and floor.

Several rivers braiding around sandbars

There’s also an erosion facet that runs after the fact: it finds the exterior walls touching both floor and empty space, then nibbles them away over a few probabilistic passes, with a bonus chance when a wall already has eroded neighbors so the wear clusters naturally instead of speckling everywhere.

The thing I like looking back is that in 2018 I was hand-rolling each of these from scratch. Now they all lean on the same few primitives: a drunken walker for organic routing, noise for texture, and a couple of cleanup passes. Geology does the art direction for free.