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_DEF_PERCENT 0.1f
#define MIN_DEF_PERCENT 0.0f

#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_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?

  • \$\begingroup\$ 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. \$\endgroup\$
    – snake5
    Commented Mar 7, 2013 at 14:54

3 Answers 3


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;
            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):


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.


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

  • \$\begingroup\$ +1 for ready to use/test example. I'm looking into what I can do more with Lua. \$\endgroup\$
    – haxpor
    Commented Mar 8, 2013 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

  • 2
    \$\begingroup\$ Also, with C++11 standard, you should use constexpr instead of const. \$\endgroup\$
    – Zhen
    Commented Mar 8, 2013 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.

  • \$\begingroup\$ 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? \$\endgroup\$
    – haxpor
    Commented Mar 7, 2013 at 14:49
  • \$\begingroup\$ 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. \$\endgroup\$
    – danijar
    Commented Mar 7, 2013 at 14:53
  • \$\begingroup\$ @sharethis Have you seen any Linux-oriented C project? They have way more #defines and they "somehow" seem to be working just fine. \$\endgroup\$
    – snake5
    Commented Mar 7, 2013 at 14:56
  • \$\begingroup\$ 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. \$\endgroup\$
    – haxpor
    Commented Mar 7, 2013 at 15:00
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – haxpor
    Commented Mar 8, 2013 at 14:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .