October 18, 2020

Project 2: Dev Blog #1

"Project 2 is the next game indirectly following on from my previous release Prophecy. It's shaping up to be a turn-based escape style game, with cel-shaded style visuals."

Project 2: Dev Blog #1

Welcome!

It's a dev blog, and one that I'll be keeping up through the development of Project 2.

Before we dive in to the meat of what I've been doing, you're probably wondering 'What is Project 2?' Well, Project 2 is the next game indirectly following on from my previous release Prophecy. It's shaping up to be a turn-based escape style game, with cel-shaded style visuals.

Procedural World Generation

For the most part since starting this project I'd been designing out the mechanics and laying the ground-work in the design document for where I'd want this game to go.

This is where I'd first hit on what I see as one of the more interesting sides of the game, Procedural World Generation. It's not the first time I've had a look into using it and it certainly won't be my last.

So, how have I done it this time? Well as my current like in programming is Builders, I've made the world generation fairly modular and made it so at its simplest I just need to provide Texture2D and run the build function.

var map = new WorldBuilder()
    .AddTexture(new Texture2D()) // Provide an actual texture here.
    .Build();
I plugged in some perlin-noise generation on to generate the world texture.

At its most complicated you can add biome ranges based on height, have a cutoff on both top or bottom levels and different tile types.

var map = new WorldBuilder()
    .Addtexture(new Texture2D())
    .AddBiomeTypeRange(0f, 0.5f, BiomeType.Grass)
    .AddBiomeTypeRange(0.5f, 1f, BiomeType.Dirt)
    .AddTileTypeRanges(new List<Tuple<TileType, float, float>>{
        new Tuple<TileType, float, float>(TileType.Ruins, 0.3f, 0.7f),
        new Tuple<TileType, float, float>(TileType.Village, 0.5f, 1.0f),
    })
    .AddCutOffRange(0.2f, 0.9f)
    .Build();
An example of what gets generated in the test environment.

The way this is possible is via an implementation of this interface:

Each of the returns help with building up an internal state which would be used in the resulting Build() function.

It's not as flexible as I'd like, but is flexible enough for its current use in taking in a texture and outputting an object with all the world data.

Related to the world generation bits I've also changed up how I write the more management related systems in this project. They're now defined as services, these will be setup in one place, have the details added to them and then passed through out the entire game to be used.

Currently I have the PrefabService, which takes enum keys and GameObjects then spits them out when called. I also have the MaterialService, which works in a similar way to the Prefab variant, just it uses materials instead.

The way I'd done it in previous projects was have a selection of management systems which would handle a specific domain (UI, Gameplay, Levels etc) but I'm finding the more Servicey approach makes the game significantly more testable and easier to build in a modular fashion.

Anyway, this has been the first of hopefully many dev blogs while work on this project progresses.

If you want to support me then you can hop on over to the Support Me page for all the ways you can.