Tengo una pantalla de opciones para cosas como dificultad, resolución, pantalla completa, etc., pero estoy luchando por encontrar la "mejor" forma de almacenar / obtener estas variables en tiempo de ejecución.
Actualmente, he implementado una Constants
clase que contiene todas las GameOption
enumeraciones, pero ¿cómo elijo un valor predeterminado para todas estas opciones? Además, ¿cómo obtengo la enumeración seleccionada actualmente?
En cuanto a la resolución, específicamente, he decidido almacenar los valores, pero no estoy seguro de cómo obtener los valores predeterminados o almacenados actualmente. Cualquier dirección sería genial; ¡Gracias! :)
namespace V1.test.RPG
{
public class GameOptions
{
public enum Difficulty { EASY, MEDIUM, HARD }
public enum Sound { ON, QUIET, OFF }
public enum Music { ON, QUIET, OFF }
public enum ResolutionWidth
{
SMALL = 1280,
MEDIUM = 1366,
LARGE = 1920,
WIDESCREEN = 2560
}
public enum ResolutionHeight
{
SMALL = 800,
MEDIUM = 768,
LARGE = 1080,
WIDESCREEN = 1080
}
public Boolean fullScreen = false;
}
}
NB: pregunté a SO y me señalaron este lugar. Hay un comentario allí, pero me gustaría escuchar diferentes formas de hacerlo / las formas más utilizadas.
Respuestas:
Planificación para crecer:
las constantes codificadas están bien para proyectos pequeños pero, eventualmente, a medida que su software crezca en tamaño, deseará poder cambiar esas configuraciones sin tener que volver a compilar todo. Hay muchas veces que querrás cambiar la configuración mientras el juego se está ejecutando y no puedes hacerlo con constantes codificadas.
CVars: una
vez que su proyecto crezca, es posible que desee echar un vistazo a CVAR . Un CVAR es una "variable inteligente", por así decirlo, que puede modificar durante el tiempo de ejecución a través de una consola, terminal o interfaz de usuario. Los CVAR generalmente se implementan en términos de un objeto que envuelve un valor subyacente. El objeto puede, entonces, realizar un seguimiento del valor, así como guardarlo / cargarlo en / desde el archivo. Puede almacenar los objetos CVAR en un mapa para acceder a ellos con un nombre u otro identificador único.
Para ilustrar un poco más el concepto, el siguiente pseudocódigo es un ejemplo simple de un tipo CVAR que envuelve un
int
valor:Acceso global:
en el ejemplo anterior, supuse que el constructor de
CVar
siempre registra la variable con elcvars
mapa global ; Esto es bastante útil, ya que le permite declarar una variable así:Esa variable se pone automáticamente a disposición en el mapa global y puede acceder a ella desde cualquier otro lugar indexando el mapa con el nombre de la variable:
Persistencia:
cuando el juego se está cerrando, itera el mapa y guarda todas las variables marcadas como
CVAR_PERSISTENT
, en un archivo. La próxima vez que comience el juego, vuelve a cargarlos.Jurisprudencia: para
obtener un ejemplo más específico de un sistema CVAR robusto, consulte la implementación presentada en Doom 3 .
fuente
En primer lugar, una enumeración define cuáles pueden ser los valores , no cuáles son los valores . Por lo tanto, aún debe declarar otra variable después de haber declarado la enumeración. Por ejemplo:
En este ejemplo, ahora puede establecerlo
soundValue
en ON, QUIET u OFF.Entonces aún necesita estructurar su código para que otras partes de su código puedan acceder a este objeto de "configuración". No sé si necesita ayuda con esa parte también, pero los patrones comunes para abordar este problema incluyen singletons (que están mal vistos en estos días) o localizadores de servicios o inyección de dependencia.
fuente
La solución glampert es muy completa, pero agregaré mi experiencia personal.
Me encontré con este mismo problema, y mi solución fue usar una clase de variables estáticas.
La clase Variables mantiene internamente un mapa de cadena a cadena (hasta ahora todas mis variables son solo cadenas) y se accede a través de getters y setters.
El punto es que obtener acceso a variables globales puede introducir todo tipo de errores sutiles, ya que partes del código totalmente no relacionadas interfieren repentinamente entre sí.
Para evitar esto, impuse la siguiente semántica: el uso del
set
método arroja una excepción si ya existe una variable con ese nombre en el diccionario, yget
elimina la variable del diccionario antes de devolverlo.Dos métodos adicionales proporcionan lo que esperaría,
setAndOverwrite
ygetAndKeep
. El punto de la semántica de los otros métodos es que puede detectar fácilmente errores del tipo "se supone que este método inicializa esta variable, pero otro método lo hizo antes".Para inicializar el diccionario, las variables iniciales se almacenan en un archivo json y luego se leen cuando comienza el juego.
Lamentablemente, todavía no me he alejado demasiado con mi juego, por lo que no puedo testificar la solidez de este enfoque. Aún así, tal vez pueda proporcionar algo interesante además de los CVAR.
fuente