¿Cuál es la forma adecuada de definir la configuration de los objects de juego para un código apropiado al que se accede a través de C ++?

Definí una gran cantidad de configuraciones y configuraciones de ciertos types de caracteres enemigos dentro del encabezado a través de #define similar al siguiente.

// --- 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 

De todos modos, los expertos en c ++ tienden a no recomendar el uso de estados globales o variables globales en absoluto (si es necesario). Hay algunos pensamientos sobre variables globales aquí y aquí .

Ahora quiero saber cuál es la forma correcta de definir este tipo de valores a los que se accederá a través de sus propias classs específicas más adelante. ¿Es una mala opción de layout si uso como lo hice actualmente?

Debería ser más unidad de datos como @sharethis sugirió. Pero deberías, seriusly, usar Lua para getlo. Por qué:

  • Lua integrado directamente con C y C ++
  • Permite tener lógica en tu file de configuration, no solo define.
  • Lua es un poderoso, rápido y liviano
  • Cuando empiece a usarlo, querrá usar más.

Por ejemplo, cómo cargar el file de configuration desde Lua (código de trabajo):

 #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; } 

Un file de configuration de Lua (config.lua) es simple (observe la lógica de ejemplo que incluí en él):

 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 ) 

Para su caso, la solución final es poner todas las variables en una class Singleton como miembros públicos, y cargar de Lua sus valores en el constructor.

Spoiler:

Yo también puedo, obviamente, cambiar a Lua por LuaJit, Scheme, Guile, Zangief, lo que sea … pero entérate de la idea.

Si usted u otro progtwigdor son los únicos que ajustan los valores, y los times de compilation no son tan largos como para hacer que los valores codificados funcionen (uno de los principales beneficios de los numbers basados ​​en datos), entonces no hay nada de malo en que estas haciendo.

Sin embargo, sugeriría usar const ints / floats en lugar de #defines debido a los motivos establecidos aquí: https://stackoverflow.com/questions/1674032/static-const-vs-define-in-c

Editar: esta pregunta es específica de C ++, pero la mayoría de los mismos datos están allí: https://stackoverflow.com/questions/1637332/static-const-vs-define o este https://stackoverflow.com/questions/112433 / should-i-use-define-enum-or-const

El enfoque común para eso son los files de configuration. Pueden ser de cualquier estructura que elijas, INI o XML, por ejemplo.

Hacer uso de los files de configuration hace que su juego sea un poco más manejado por los datos . De modo que puede realizar cambios en la configuration sin volver a comstackr todo el código fuente. Eso ahorra time y, además, puede dividir el trabajo de los progtwigdores y diseñadores de juegos que equilibran los puntos de golpe de los enemigos.