views:

120

answers:

5

I'm working on a small online game where there is a need to store a reasonable amount of information about many (100+) different kinds of game objects.

I'm trying to decide whether to have this data generated by code or stored in some configuration file.

Data generation approach would be something like (in java-ish pseudo code):

(within a set of functions executed once at program startup)
....
// create grass terrain
grass=new GameObject();
grass.inheritProperties(generic_terrain);
grass.set(NAME,grass);
grass.set(MOVEABLE,true);
grass.set(MOVECOST,10);
grass.set(IMAGE_INDEX,1);
....

Whereas the config file approach would probably just use an XML-type format e.g.

(within terrain.xml file)
....
<terrain name="grass">
    <inherit class="generic_terrain"/>
    <property key="NAME" value="grass"/>
    <property key="MOVABLE" value="true"/>
    <property key="MOVECOST" value="10"/>
    <property key="IMAGE_INDEX" value="1"/>
</terrain>
....

Some important points:

  • This information is static each time the game game is run (i.e. does not change during execution)
  • The property names (NAME, MOVECOST etc.) are a relatively small list but additional ones could be added over time
  • It is safe to assume that it will only get changed by the development team (i.e. there is not a need for configuration to be managed outside the build process).
  • It will need to be tweaked quite regularly during development for game balancing reasons (e.g. making units less/more powerful)
  • There is a certain amount of "inheritance" of properties, i.e. in the example above grass needs to have all the standard properties defined by generic_terrain plus a few new additions/changes.

Which approach would be best for this situation? Any more importantly why?

+2  A: 

Separating data from code is just about ALWAYS a good idea. Even if the data is static during execution, it isn't during the design process. A game with hard-coded data is much less flexible than one which gathers its data from an easily-modifiable config file.

Keeping the data in separate files, xml for example, allows for quick and simple altering of the various values, which you say is important.

tlayton
The config file can be a separate file even if it would only be code.
Tom
+5  A: 

Personally I like to push as much to config as possible. The reason for this is that at some point I may want to reuse the code I wrote for the game in a completely different way. If the source code is littered with references to implementation specific details this becomes much harder.

One interesting caveat to the config approach comes up when you want to start describing the behaviors of objects in addition to their values. Consider a simple example where you have a cup object which needs to "catch" ball objects. You might express them like:

<object name="ball">
    <property key="shape" value="circle"/>
    <property key="movable" value="true"/>
    <property key="speed" value="10"/>
</object>

<object name="cup">
    <property key="shape" value="rectangle"/>
    <property key="movable" value="true"/>
    <property key="speed" value="6"/>
    <property key="catches" value="ball"/>
</object>

The problem here is that somewhere you still have to define what "catches" does inside your code. If you are using an interpreted language you could do something like:

<object name="cup">
    <property key="shape" value="rectangle"/>
    <property key="movable" value="true"/>
    <property key="speed" value="6"/>

    <oncollision>
      if (collided.getName() == "ball") {
        collided.destroy();
        points++;
      }
    </oncollision>
</object>

Now you have gained the ability to describe how an object behaves as well as what it is. The only problem here is that if you are not working in a interpreted language you do not have the luxury of defining code at run time. This is one of the reasons Lua has become so popular in game development. It works well as both a declarative and procedural language and it is easy to embed in a compiled application. So you may express this situation like:

object {
  name='ball';
  movable=true;
  speed=10;
}

object {
  name='cup';
  movable=true;
  speed=6;
  oncollision=function(collided)      
     if collided:getName() == "ball" then
        collided:destroy();
        points++;
     end
  end;
}
Nick
+2  A: 

This isn't language-agnostic.

If you're using a compiled language, use a configuration file so that you don't force a recompile every time you tweak something.

If you're using a language where you don't have to perform an explicit compile/link process, do it in code so that you don't have to deal with parsing and loading. (But do it in one place so that it's easy to completely swap out functionality, should you need to do so at some point in the future).

The basic philosophy here is that code is data, but sometimes code-as-data is painfully difficult to modify; in such cases (e.g., the compiled-language case), write it in a kind of code that's easier to modify. (Your interpreted configuration language.)

pkh
Interesting... though personally I've never been impacted by the cost of a recompile in this situation - if compile+run all tests takes three seconds (or even better runs automatically in the background) then it probably isn't costing you any more than navigating to/from separate config files.
mikera
If you have the luxury of using dynamically loaded libraries, I guess this might be the case. Compiling / linking the system I work on, given only a single .cpp file changed, takes ~45s. So YMMV on this one.
pkh
+2  A: 

A lot of game engines use scripting languages for many of the reasons you mentioned. Lua is a really great, fairly fast, lightweight scripting engine that has been used to great success in a lot of games. You can easily use the parser to do simple config setting and leave it at that, or build in more functionality and let actual code be written in the file. Your example in lua might look something like:

grass = {
    NAME = "grass",
    MOVEABLE = true,
    MOVECOST = 10,
    IMAGE_INDEX = 1
}

setmetatable(grass, generic_terrain)
Dolphin
So if I understand correctly Lua falls in the "code" camp but does it in a lightweight domain specific language and runs it dynamically so that it behaves more like a config file?
mikera
It _could_ behave like a simple config file if you wanted to set it up that way. The basic data structure for Lua is a table ( which is a combination hash-table and array) which makes it work fairly well for a a config language.
Dolphin
+2  A: 

If you do choose to use XML, at least try to use a sane schema. There's no reason to embed your own little schema ("object", "property", "key", "value") into XML when it's designed to represent just that stuff directly. How about:

<ball>
    <shape>circle</shape>
    <movable>true</movable>
    <speed>10</speed>
</ball>

<cup>
    <shape>rectangle</shape>
    <movable>true</movable>
    <speed>6</speed>
    <catches>ball</catches/>
</cup>
munificent