Non-visual progress, and a 'Mosaic' area designation system

Work has been mostly in dry foundational non-visual type stuff, which may sound like gobbledegook:

  • A new global Context, provided by a new GameHost class built from well-worn dotnet patterns and technologies instead of my quick hacks:
    • IServiceProvider, allowing dependency injection.
    • IConfiguration, for config management combining many flexible sources.
    • ILogger, backed by Serilog and with a Godot sink, to abstract all logging calls, and provide more features than I should need (I lean pretty heavily on logging during development, so it’s good to be able to filter).
    • HostApplicationBuilder
  • I have GdUnit4 working and converted existing unit-tests over to it. GdUnit4 allows me to run unit-tests with code that requires Godot to be loaded (xUnit/nUnit/Microsoft testrunners don’t know about Godot or how to load it), which will be quite important as I don’t just use it for testing but also to be able to execute specific bits of code as I’m writing it.
    Eventually I’ll need way a way to run tests without their setups fighting over which services should be loaded vs. mocked in the global Context (a reason conventional software would shy away from having a global static Context), but I can just run tests single-threaded for now.
  • Upgrade dotnet from 6.0 to 8.0, and Godot from 4.0 to 4.4.1
  • Register the hobbygame.dev domain, and rehome this devlog system there, since gamedevhobby.com is no longer being shared.

All this stuff may be boring but I think significant enough to record here as a reminder of progress and how far it’s come.

Next up, streaming continents and continent tiles to/from a database, so… retrofitting binary serialization.

There have been visual changes too though…

  1. I made a “dev” visualizer for the continent tiles, which is what was used to generate the images you see below.

    “Continent tiles” being the humongous tiles which contain ocean and many continents (the coloured‐in shapes). Currently they are 80km × 80km, which in spatially‐compressed game‐world terms is huge. The dotted white lines in the image below are continent tile boundaries.

  2. I also made the image comparison slider feature for this Hugo website which you see below. I think this feature will be handy in the blog going forward, and I may put the code on github, though I doubt many other sites would need such a thing.

  3. I replaced the code that generates the continents with an “area designators” abstraction and “mosaic” implementation.

‘Area designation mosaic’ on the left, and the voronoi continents spawned from it on the right. Dotted lines indicate the tile boundary

The pixelated warped images on the left are output from the ‘mosaic’ Area designator:

  • greens are land
  • purple is ocean
  • orange is archipelago
  • cyan is island volcano

The image on the right shows the resulting continents, after each voronoi cell in the tile is assigned its role from the Area designator.

The algorithm it replaces would meander through the tile, creating and growing continents to a desired size.

This new way provides two big advantages:

  1. Cells can know the designations of their neighbors. I was avoiding this before because it needed the whole tile to be generated, then cells along the border would need the entire neighboring tile to be generated, and that would require its neighbors to be generated, etc. Knowing the relationship of a cell to its neighbors allows shapes and noise to be more intelligently introduced to the coastlines and straits - you’ll notice the voronoi continent shapes don’t exactly feel like natural landforms.

  2. The shapes of landforms and how they relate to each other and the oceans to be cleanly adjustable, e.g. instead of homogenous everywhere it could switch style a certain distance from the center of the world, or could be determined by a tileable bitmap, or wavefunction collapse, etc. It’s a simpler system that keeps a lot of doors open.

You may have noticed the current results still have much room for improvement… continents aren’t crossing the tile boundaries, and in the example below you can see that land which is contiguous from the Area Designator can end up quite disjointed when mapped to the voronoi cells. It’s even possible for contiguous land from the Area Designator to end up as literally disconnected voronoi cells.

Continents currently can’t span voronoi cells across the tile border

To that I say two things. Firstly, I’ll worry about it later, I’ve realized I can spend unlimited years tweaking a landscape generator, so better to get a playable game working and then come back to stuff like this.

and secondly:

Principle 1: Let it happen
This is one of the guiding principles I adopted for the game, it says: Don’t spent time making sure generations will always match your desired outcome, since allowing unexpected “wrong” variation adds happy accidents, perfect is the enemy of good, and less code is better code.

If much of the page was incomprehensible, sorry. It’s been partly written as note for future-me, to remember where I got to with Area Designators and where I wanted to go with it.