Data-driven design?

Started by
7 comments, last by lvenonl 9 years, 7 months ago

Hello,

I've been studying game programming with SDL and I came across a very interesting subject which is the Data-driven design. I searched around the web and I found lots of definitions and approaches about it and I didn't understand it very well. What is it exactly? How can it be used in game programming?

Thanks in advance

lvenonl

Advertisement

I've been studying game programming with SDL and I came across a very interesting subject which is the Data-driven design. I searched around the web and I found lots of definitions and approaches about it and I didn't understand it very well. What is it exactly? How can it be used in game programming?


There's two similar terms floating around, so just to be clear I'll explain 'em both.

data-driven design: behavior should be specified by data, not code.

A data-driven approach might have a file like:

// orc.json
{
  "name": "orc",
  "hp": 150,
  "armor": 10
}
While a non-data driven approach might do something terrible like:

// orc.cpp
class Orc : public Monster {
public:
  string_view getName() const { return "orc"; }
  int getHp() const { return 150; }
  int getArmor() const { return 10; }
};
The latter approach is bad. It hard-codes the orc into the game. A designer must be an engineer and have the ability to recompile the game to make a simple change. After making the change, the game must be completely restarted to see the change; it cannot be edited while the game is running.

The former approach uses a data file. A designer can edit this file. A nice GUI for editing these files can be produced, or tools that import it into a database or CSV for each comparison with other monsters and to making tuning and balancing easier. The file could be reloaded while the game is running. etc.

There'd still be code, of course, but it should be general and non-specific. The code specifies _how_ something is done, but the data specified _what_ is done. e.g., in a data-driven approach, you might have:

// monsterdata.cpp
struct MonsterData {
  string name;
  int hp;
  int armor;
};

// load from a JSON file
bool LoadMonsterData(string path, MonsterData& data);

// save to a JSON file
bool SaveMonsterData(string path, MonsterData const& data);
and there the data is a simple struct you can edit with AntTweakBar or a custom editor GUI. It can be loaded, saved, etc. Much more flexible. You can take this even further and not have a specific Monster class but rather a general purpose set of components or attributes (so anything can have HP, not just monsters, for example) which now lets designers create whole new types of objects out of small pieces rather than needing an engineer to write code for new types of objects.

Again, let the code decide _how_ things are done (HP/kill tracking, etc.) and let data decide _what_ is done (who has HP, how much, what causes damage, how much damage is done, etc.).

data-oriented design: think about the data being operated on while writing code.

Since this isn't what you asked about (I just know a lot of people confuse the terms) I'll give the short version.

Basically, data-oriented design says that you should "code to your data" while contemporary OO-ish teachings tell you to "code to the abstraction". Abstractions typically force you to operate on data in overly-complicated and inefficient ways while directly manipulating data is less reusable or flexible.

Sean Middleditch – Game Systems Engineer – Join my team!


A data-driven approach might have a file like:


// orc.json
{
  "name": "orc",
  "hp": 150,
  "armor": 10
}
While a non-data driven approach might do something terrible like:


// orc.cpp
class Orc : public Monster {
public:
  string_view getName() const { return "orc"; }
  int getHp() const { return 150; }
  int getArmor() const { return 10; }
};
The latter approach is bad. It hard-codes the orc into the game. A designer must be an engineer and have the ability to recompile the game to make a simple change. After making the change, the game must be completely restarted to see the change; it cannot be edited while the game is running.

The former approach uses a data file. A designer can edit this file. A nice GUI for editing these files can be produced, or tools that import it into a database or CSV for each comparison with other monsters and to making tuning and balancing easier. The file could be reloaded while the game is running. etc.

There'd still be code, of course, but it should be general and non-specific. The code specifies _how_ something is done, but the data specified _what_ is done. e.g., in a data-driven approach, you might have:


// monsterdata.cpp
struct MonsterData {
  string name;
  int hp;
  int armor;
};

// load from a JSON file
bool LoadMonsterData(string path, MonsterData& data);

// save to a JSON file
bool SaveMonsterData(string path, MonsterData const& data);
and there the data is a simple struct you can edit with AntTweakBar or a custom editor GUI. It can be loaded, saved, etc. Much more flexible. You can take this even further and not have a specific Monster class but rather a general purpose set of components or attributes (so anything can have HP, not just monsters, for example) which now lets designers create whole new types of objects out of small pieces rather than needing an engineer to write code for new types of objects.

Again, let the code decide _how_ things are done (HP/kill tracking, etc.) and let data decide _what_ is done (who has HP, how much, what causes damage, how much damage is done, etc.).

I see! It looks more efficient!

Just one more question: Is XML a good option for data files? Do you recommend any other data file instead of XML to use for a 2D game?

XML isn't bad, just really, really verbose. I think these days most people prefer JSON, but you'd be fine with XML as well. You can get libraries to parse either for basically any programming language nowadays.

Since C# had XML serialization built in early on, I use XML. In last week's "Week of Awesome II" contest, I used data driving to control lots of my game which allowed me to do several things.

I put my unit stats like Movement speed, damage, range, turn rate, etc. in the files. It saved me some time during unit balancing.

At first we didn't have many sound effects. I wired up the Bear-hit to everything in datafiles. When it came time to plug in sounds, my graphics artist was able to plug those in for me so I could stay focused on the code. Same thing for the graphics, when she changed them, she could wire them up without bugging me.

I used it to detail out the different states of the game, and again I was able to hand this off to my wife to plug in her story slides.

When my game crashed on the judge's computer for playing a song, we turned the songs off on each of the levels and then he was able to run my game. :D Turns out XNA requires Media Player be installed for song playing, and I hadn't stumbled across that during all the testing I did. After he installed that, my game worked like a champ.

My game is actually modable, which I think is pretty cool for a 7-day game jam. :D You can create new units, wire up different graphics and sounds, put in new cut scenes, play as the monsters instead of the toys, or even play hot-seat with a friend. :)

Feel free to checkout the data files in the game. There's a link in my day-7 journal:

http://www.gamedev.net/blog/1922/entry-2260272-the-week-of-awesome-ii-day-7-crossing-the-finish-line/

The xml files are in the "Data" folder.

- Eck

EckTech Games - Games and Unity Assets I'm working on
Still Flying - My GameDev journal
The Shilwulf Dynasty - Campaign notes for my Rogue Trader RPG


Just one more question: Is XML a good option for data files? Do you recommend any other data file instead of XML to use for a 2D game?

XML is just one of many options. It is a format that lots of tools can easily support. JSON and YAML are also formats that lots of tools can easily support. You can even make your own data formats if you want, just recognize that less tools will easily support them.

What matters is that the programmers are not hard coding everything.

Data driven means values can be adjusted by modifying data. Examples.... When you want to print a new document, you don't modify the source code of your word processor to the contents you need, instead you have a document that you modify and print. When you want to manipulate a table of data, you don't build a specialized spreadsheet program with those specific values hard coded, you use a general purpose program that manipulates a chunk of data stored in a separate file. You don't distribute a specialized executable to display a web page, then another specialized executable for another web page, instead you have a program that loads data and takes actions based on the contents of the file.

The map is something that can be modified with data, it doesn't require the programmer to adjust arrays in the code. The attributes of objects can be modified with data, they don't require someone editing a .cpp file and changing a value. Adjusting the AI's interest level in doing something can be adjusted by a designer directly, and doesn't require a programmer to make the change, start a build, and deliver a new updated executable.

The point is not to worry about a specific data format, instead, data driven means to separate the data from the executable.

For some code, including prototype code designed to prove or disprove an experiment in a few hour's work, the values might be coded directly in. In certain contexts, like in code designed to be used once then thrown away, a non-data-driven system is acceptable. Also in certain old systems, like the very old games in consoles where memory was measured in bytes, it made sense to store values directly and in their minimal forms. In special cases like these having hard-coded values is a known exception that makes sense.

Thanks for all the information guys!

I'm making some tests with both XML and JSON to see which of them I like the most. I managed to implement XML in my game using TinyXML.

However, I'm having issues with JSON, I'm using RapidJson and I got some errors with their headers when parsing the file and reading it:


d:\sdl\include\rapidjson\reader.h(392): error C2228: left of '.Peek' must have class/struct/union

Does anyone know how to solve it? Maybe there's a better library for json?


d:\sdl\include\rapidjson\reader.h(392): error C2228: left of '.Peek' must have class/struct/union

Does anyone know how to solve it? Maybe there's a better library for json?

Sorry, not too familiar with RapidJSON, but as far as alternatives... perhaps you may like JsonCPP ?


d:\sdl\include\rapidjson\reader.h(392): error C2228: left of '.Peek' must have class/struct/union

Does anyone know how to solve it? Maybe there's a better library for json?

Sorry, not too familiar with RapidJSON, but as far as alternatives... perhaps you may like JsonCPP ?

JsonCPP is better! Could use it without a problem! I think I'll use JSON...it's easier to write than XML!

Thanks for the help guys! I really appreciate it! biggrin.pngbiggrin.pngbiggrin.png

This topic is closed to new replies.

Advertisement