An article covering the design and implementation of a data-driven game engine to allow anything and everything to be open to modifications.

Posted by RocketJumpTechnology on Aug 10th, 2016

In this article I'm going to talk a bit about the design decisions and goals when it comes to modding in King under the Mountain. Please excuse the poor programmer art!

A bit too long ago when I was studying at university, dreaming of being a game developer, I read the first few entries in the Game Programming Gems series. The very first chapter in the first volume stuck in my mind and stayed there, it was titled "The Magic of Data-Driven Design" by Steve Rabin. Here's a decent article (from the same time period) by Kyle Wilson on the subject (and here's a good stack overflow post), but it can be summed up as not having any game-specific data hard-coded into the game engine, instead it is all pulled in from external data files. All the weapons, enemies, levels, AI and anything else is driven by easily modifiable data files so that additions and changes can be made easily without needing a single line of code to be changed. Internally for a team of game developers, this lets artists and designers plug their assets or variables/scripts into the game they're working on without needing a programmer to make any code changes, speeding up the development process considerably. There's a potentially even bigger win for game devs however, in that this also opens up your game to the modding community, who often come up with weird and wonderful additions that the original devs wouldn't (or couldn't) have managed on their own.

Having as much as possible in the game open to modding is one of the architectural design goals of King under the Mountain. Not only does this make new content easier to add as the game developer, modding communities tend to extend the life and enjoyment factor of a game massively. Despite some complicated algorithms going on under the hood (such as the lighting algorithms and figuring out which wall tiles to draw), I wanted the data-driven side of the game to be as easy and accessible as possible. I decided to use JSON as the data format of choice (here's an intro for non-programmers by Scott Lowe) because it's a fairly compact text format, easy for humans to read and edit, and has good support in terms of coding tools and libraries. Next I'll show you some examples of how this is being used under the hood.

The image at the top of this post shows a variety of different types or rock and gems (as I said, please excuse the placeholder artwork, I'm on the lookout for a real artist to do a better job). As you can see from the "diagram" this is actually just two simple sprites with colour added to them and drawn on top of each other. Each of these types of rock and gems can have different names, economical values, rarity in terms of map generation, and (as you can see) different colours. Here's what a definition for limestone as a type of rock currently looks like:

{ "materialName": "Limestone", "materialType": "ROCK", "rockGroup": "Sedimentary", "prevalence": 2, "colorCode": "#FFFFE6", "isFluxMaterial": true, "oreNames": ["Hematite", "Bituminous Coal", "Cassiterite"] }

There's a bunch of properties here and I expect it's going to change drastically before release. For now though, the JSON object specifies that the material is rock (rather than wood, metal, or a bunch of other pre-defined types. This list of types will itself be driven from a data file though today it is hard-coded), specifically sedimentary rock (this info is used by the map generator when deciding where to place it), a prevalence of 2 (meaning it's more or less common than other types or rock with a different value), it's colour as a HTML-style hex code, "isFluxMaterial" set to true as a special property indicating it can be used as a flux in the creation of steel from iron (more on that another time!) and a list of ores that may be found in limestone, which are themselves driven from a similar list of materials of the "ORE" type. It's currently trivial to add your own types to the list of rocks, give them a colour of your choice, and they'll automatically be used in map generation which will then be imported to the main game. The types of rocks, ores and gems in the game currently can be considered a placeholder, and I'll be adding more variety (as it is now so easy to do so) before the main release.

As another example, consider the day to night cycle:

This is configured by another JSON file that (currently) looks like this:

{ "_info": "To mod this file, replace it entirely. This file defines the color of sunlight outdoors at different times of the day, times are in hours, rgb values are out of 255", "colors": { "Darkness": "#1E2638", "Moonlight": "#323C64", "Dawn": "#5A6E8C", "Sunrise": "#E6DCAA", "Sunlight": "#FFFFFF", "Sunset": "#F0D2AA" }, "phases": [ { "time": 0.0, "color": "Moonlight" }, { "time": 3.0, "color": "Moonlight" }, { "time": 4.5, "color": "Dawn" }, { "time": 5.5, "color": "Sunrise" }, { "time": 8.0, "color": "Sunlight" }, { "time": 17, "color": "Sunlight" }, { "time": 20, "color": "Sunset" }, { "time": 21, "color": "Dawn" }, { "time": 23, "color": "Moonlight" }, { "time": 24, "color": "Moonlight" } ] }

You'll notice this includes a "_info" property to help modders understand how to change it. "colors" is there as a convenience to give names to more hex code colour values which are then described in an array for different times of the day (against a 24 hour clock). The game engine then blends the two colours for a specified time together (e.g. at 22:00 will mostly be the "Dawn" colour with some of the "Moonlight" colour) which you can see in action in the video. Whereas the rock materials described earlier can be added to by mods (i.e. more materials can be added while including those in the base game), I expect the sunlight colour data to be entirely replaced by a single mod, as described by the "_info" property. When the game is ready for a wider audience I plan to write more documentation on how to create mods for the game.

Similarly, the characters in the game and their constituent parts (such as the dwarves' beards, hair, clothes and so on) are each individual sprites which are layered on top of each other, and in some cases coloured in (such as hair and skin tones) like the rocks at the top of this post. Each part of a character has its own JSON data file describing what it is, which kind of characters it can be added to, any colours to apply (as a generalised "skin tone colour" that could be different for each one), and any layout adjustments such as scaling the sprite to be bigger or smaller, or adjusting its position relative to its parent (as an example, a head is placed a certain amount above the character's body). These assets are stored and described individually, then combined into a single spritesheet and dataset by the game engine automatically.

Here you can see a small part of the spritesheet automatically generated by the game engine, showing some of the current dwarf clothing plus a fat dwarf's naked body (sorry about that) which is stored as a greyscale image to be combined with a specific skin colour as it is rendered to the screen.

In summary, using this approach makes it a lot easier for myself to add more content to the game easily, including a lot more variation in terms of colours as you've seen. Better yet, it's designed from the ground up to be open to modders to make their own additions or changes to the original assets, which I have no doubt will result in more and much better content than I'd be able to add by myself.