I got some basic worldgen done this week. Just creating a bare island and walking around on it but that's not bad for one week starting from scratch with a language I'm still learning.
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. |
Each tile on the map represents "chunk" of 30x30 tiles for now. As you walk around, nearby chunks are instantiated as needed based on the overall map. It's blocky and not very exciting though.
|
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.