Building the island's elevation uses a blend of a few different techniques:
First, create a heightmap by throwing down a bunch of sorta-centered blobs with a random height and radius. A percentage of the blobs will have negative height and reduce the elevation. Keep throwing blobs until you have enough land. I think this has interesting and island-like coastlines with and good variation of height. It can be weirdly mesmerizing too.
Using the first heightmap, create a second heightmap based on the distance from the water. I think this looks neat on it's own and when there's jagged coastlines it reminds me of what real mountain ranges look like from above.
Using the first heightmap again, create a third heightmap based on simplex noise. Water has zero height and everything else is a noise lookup.
Once you have all three heightmaps, multiply each by a different weight and add them together form a final height map. By changing the multipliers for each, you can adjust the overall look to get the best of each map with few downsides.
Finally, I want the highest parts to really stand out above everything else so I do one last thing: cube each height (that is, set each height to height * height * height). This effectively pushes the lowest parts down and increases the contrast for the higher elevations.
That looks okay. I'm sure it will change more.
|An in-game map.|
|Much higher elevation to the west, much lower elevation to the east. One level higher to the south and one level lower to the south east.|
I think I can do something like a midpoint displacement algorithm to make it less blocky. Adding up-slopes and down-slopes at elevation boundaries and hiding the interior of the higher elevation should help make it look better too. That should keep me busy for a week.
Edit: It took about three hours. The midpoint displacement wasn't working how I thought it would so I lerp the midpoints and add a bit of noise instead.
Doing all that was almost 350 lines of Clojure so I moved some functionality into separate open source libraries.
super-simple-window: Java Swing windows can have a ton of callbacks and settings that need to be done in a specific order and I always forget how to do it right. This is one function that creates a JFrame with a Canvas that uses all the settings and callbacks you supply: title, width, height, on-render, on-key-press, etc. Even makes a timer if you supply an on-timer callback.
render-terminal: Render terminal-like data to a Java Swing Graphics object. Call render with a map of points to character data. Does a bunch of caching to keep things fast. Supports 9x16, 10x10, and a 12x12 font so far but it's easy to extend.