Update:This week we worked on two big things. Firstly, I refactored many parts of the world generators, and secondly, GP and I created a MEGA MOON WORKSHEET that contains every single sprite and block in the game.
World Gen Framework
Continuing on from last week, I created a bunch of separate modules for world generation. The underlying motivation is that each region in Moonman has a distinctive world structure and so having a general shared toolkit will make my life a lot easier. The current world generation (wg) modules are:
wgcommon: 2d arrays of blocks, polygons, and functions for converting between them
wgfunctional: high-level functions (like domain warp)
wgstamp: routines for stamping templates like houses and trees into 2d block arrays
wgdistribute: distribution functions for scattering plants and world objects
wgdungeon: dungeon generation routines and helpers like A* and subdivision
wgcave: functions for carving out caves. you can supply an arbirtrary block function (see below)
wgflood: takes fluid 'seeds' planted in the environment and spreads them out
wgseed: seed specific routines, like glooper
wgmountain: mesa specific, e.g., mountain generation
Planned modules include:
wgarchitect: will contain functionality for designing and building houses
wgarborist: better planting and distribution of flora
Many areas will contain cave-like structures, and so the wgcave module has a flexible function GenerateCaves which creates caves from a user-defined function. A simple example is below.
void generateCaves(){
..
auto cbf = std::bind(&TestGeneratorImpl::caveBlockFunction, this, _1, _2, _3, _4, _5);
auto caves = GenerateCaves<TestBlock>(vec2i{ ww, wh }, caveRegions, cbf, mRandom);
..
}
void caveBlockFunction(const vec2d& p, double depth, const CaveData& cd, CaveBlockCorner& cbc, TestBlock& tb){
// Basic noise function
double x = p.x * 0.15;
double y = p.y * 0.2;
double surface = 1 - clamp(depth / 6, 0., 1.);
double cave = mRandom.noise(x, y, 0);
cave += surface;
if (cave > 0){
cbc.fg = 1;
tb.type = TBT_SOLID;
}
else {
cbc.fg = -1;
tb.type = TBT_EMPTY;
}
};
Running this simple example gives the following output (when printed to console), where the @ symbol represents solid terrain and the period (.) is blank space. wgcave also handles the generation of the smooth slopes.
This is an important part of world generation, but it's only one step of many. More complex functions can be composed together to start building the natural aspect of the world. Here's an example of the Seed level currently under design:
Players won't ever see the world laid bare -- they'll only ever have a local view:
Worksheet
The second thing we've been working on is a big worksheet. We now have a central place we're every design and block will live. It contains all the current stuff and new concepts and sprites. We'll continue to work from this sheet as we create the palettes, update all the old sprites in the game, and adapt and implement the new sprites. It took about 3 full days and I'd like to show you the whole thing, but ** spoilers **, and so here's just a sneak peek of a few parts.