# What's the appropriate way to define configuration settings of game objects for a proper code accessed via C++?

I defined a lot of configuration and settings of certain types of enemy characters inside header via #define similar to the following.

// --- RULES ---
#define MAX_INC_ATTACK_POINT 50
#define MIN_INC_ATTACK_POINT 0
#define MAX_DEF_PERCENT 0.1f
#define MIN_DEF_PERCENT 0.0f

#define PUNCH_ATTACK_POINT 12
#define PUNCHHARD_ATTACK_POINT 15
#define KICK_ATTACK_POINT 12
#define KICKHARD_ATTACK_POINT 15
#define COMBO06_03_ATTACK_POINT 20
#define COMBO06_04_ATTACK_POINT 5
#define COMBO06_04_01_ATTACK_POINT 15

#define START_MAX_HP 100
#define START_INCATTACK_POINT 0
#define START_DEF_PERCENT 0.0f
#define MAX_ULTIMATE 100


Anyway, c++ experts tend to not recommend to use global states or global variables at all (if necessary). There're some thoughts about global variables here and here.

Now I want to know what's the proper way to define these kind of values to be accessed via its own specific classes later? Is that a bad design choice if I use like I did it currently?

• Everything's fine, just go with what you have. Those so-called experts rarely consider practical matters so do your best to take everything they say with a grain of salt. All they care about is "perfect" use of C++ while I'm sure you care more about getting things done. The goals obviously do not match. – snake5 Mar 7 '13 at 14:54

You should be more data drive as @sharethis suggested. But You should, seriusly, use Lua to get it. Why:

• Lua integrated directly with C and C++
• It allows to have logic in your config file, not only defines.
• Lua is a powerful, fast, lightweight
• When you start to use it, you will want to use more.

E.g, How to load configure file from Lua (working code):

#include <cassert>
#include <iostream>
#include <cstdlib>
#include "lua.hpp"

int main( int argc, char * argv[] ){
// Lua Initialization
lua_State * L = luaL_newstate();
assert( L && "Can't create Lua State" );
lua_gc(L, LUA_GCSTOP, 0);
luaL_openlibs( L );
lua_gc(L, LUA_GCRESTART, 0);

// execute config file
int ret = luaL_dofile( L, "config.lua" );
if( ret != 0 ){
const char * msg = lua_tostring(L, -1);
if( msg ){
std::cerr << "Error: " << msg << std::endl;
}else{
std::cerr << "Error: (error object is not a string)\n";
}
return EXIT_FAILURE;
}

// get variables
lua_getglobal( L, "MAX_ULTIMATE" );
int val = lua_tointeger( L, -1 );
std::cout << "MAX_ULTIMATE = " << val << std::endl;

lua_close( L );

return EXIT_SUCCESS;
}


An the Lua config file (config.lua) is simple as (notice the example logic I included on it):

START_MAX_HP = 100
START_INCATTACK_POINT = 0
START_DEF_PERCENT = math.abs( START_INCATTACK_POINT * START_MAX_HP )
MAX_ULTIMATE = START_MAX_HP

WIDTH = 800
HEIGHT = math.floor( WIDTH / 1.333 )


For your case, the final solution is put all the variables in a Singleton Class as public members, and load from Lua their values in the constructor.

Spoiler:

Yo also can, obviously, change Lua for LuaJit, Scheme, Guile, Zangief, whatever.. but get the idea.

• +1 for ready to use/test example. I'm looking into what I can do more with Lua. – haxpor Mar 8 '13 at 14:43

If you or another programmer are the only ones tweaking values, and compile times aren't so long as to make hard-coded values a pain to work with (one of the major benefits of data-driven numbers), then there's nothing wrong with what you're doing.

However I would suggest using const ints/floats instead of #defines due to the reasons set out here: https://stackoverflow.com/questions/1674032/static-const-vs-define-in-c

Edit: this question is C++ specific, but most of the same data is there: https://stackoverflow.com/questions/1637332/static-const-vs-define or this one https://stackoverflow.com/questions/112433/should-i-use-define-enum-or-const

• Also, with C++11 standard, you should use constexpr instead of const. – Zhen Mar 8 '13 at 9:21

The common approach for that are configuration files. They can be of whatever structure you choose, INI or XML for example.

Making use of configuration files makes your game a bit more data driven. So you can make changes to the configuration without recompiling the whole source code. That saves time and moreover, you can divide the work of programmers and game designers who balance the hit points of enemies.

• Consider for the case that I want it to live in code environment, not external config-file, or xml file existing along the game binary when release. I don't plan to make changes later in convenient way. Is my design above not usual to follow or there's something that could be a timed-bomb later on? – haxpor Mar 7 '13 at 14:49
• Since want to deliver your game as a self-including executable, I believe that you are working on a very small project. Otherwise exactly this attitude would be your time bomb later on. But if you haven't more settings than you showed us in your question, defining constants is adequate. – danijar Mar 7 '13 at 14:53
• @sharethis Have you seen any Linux-oriented C project? They have way more #defines and they "somehow" seem to be working just fine. – snake5 Mar 7 '13 at 14:56
• I appreciate your thought. I explain it more below. Actually it's not that small. I will have around 30+ game objects to access this kind of settings with some of values will be specific to them. I just think that if I have xml, json or external file, I will need to read the files and store the values some where maybe in a class that exposed functions allowing other classes to access (getter). I don't say it's too much effort, but it's too many hops and the code won't be clean enough for the situation that I only need to access those values directly. So this solution is not my goal currently. – haxpor Mar 7 '13 at 15:00
• @sharethis I'm starting to realize about the benefit of data driven after I see the example from Zhen's answer. Now I go back, and give you +1 for the root of topic. I'm digging it more and see what I can do with it in the way of balancing external and internal data. – haxpor Mar 8 '13 at 14:54