En primer lugar, no me refiero a la gestión de la escena; Estoy definiendo el estado del juego libremente como cualquier tipo de estado en un juego que tiene implicaciones sobre si la entrada del usuario debe estar habilitada o no, o si ciertos actores deben deshabilitarse temporalmente, etc.
Como ejemplo concreto, digamos que es un juego del clásico Battlechess. Después de hacer un movimiento para tomar la pieza de otro jugador, se reproduce una breve secuencia de batalla. Durante esta secuencia, el jugador no debe poder mover piezas. Entonces, ¿cómo rastrearías este tipo de transición de estado? ¿Una máquina de estados finitos? ¿Un simple cheque booleano? Parece que este último solo funcionaría bien para un juego con muy pocos cambios de estado de este tipo.
Puedo pensar en muchas formas directas de manejar esto usando máquinas de estados finitos, pero también puedo ver que se salen de control rápidamente. Tengo curiosidad por saber si hay una forma más elegante de realizar un seguimiento de los estados / transiciones del juego.
Respuestas:
Una vez me encontré con un artículo que resuelve su problema con bastante elegancia. Es una implementación básica de FSM, que se llama en su bucle principal. He esbozado el resumen básico del artículo en el resto de esta respuesta.
Su estado de juego básico se ve así:
Cada estado del juego está representado por una implementación de esta interfaz. Para su ejemplo de Battlechess, esto podría significar estos estados:
Los estados se administran en su motor de estado:
Tenga en cuenta que cada estado necesita un puntero al CGameEngine en algún momento, por lo que el estado mismo puede decidir si se debe ingresar un nuevo estado. El artículo sugiere pasar CGameEngine como parámetro para HandleEvents, Update y Draw.
Al final, su ciclo principal solo trata con el motor de estado:
fuente
Comienzo manejando este tipo de cosas de la manera más simple posible.
Luego agregaré los cheques contra esa bandera booleana en los lugares relevantes.
Si luego descubro que necesito más casos especiales que este, y solo eso, vuelvo a factorizar en algo mejor. Generalmente hay 3 enfoques que tomaré:
enum { PRE_MOVE, MOVE, POST_MOVE }
y agregue las transiciones donde sea necesario. Entonces puedo verificar con esta enumeración donde solía verificar con la bandera booleana. Este es un cambio simple pero que reduce la cantidad de cosas con las que tiene que verificar, le permite usar declaraciones de cambio para administrar el comportamiento de manera efectiva, etc.pieceSelectionManager->disable()
o algo similar al comienzo de la secuencia, ypieceSelectionManager->enable()
. Esencialmente, todavía tiene banderas, pero ahora están almacenadas más cerca del objeto que controlan, y no necesita mantener ningún estado adicional en su código de juego.En términos generales, nunca necesito ir más allá de esto cuando se trata de subestados de casos especiales, por lo que no creo que exista el riesgo de que 'se salga de control rápidamente'.
fuente
¡http://www.ai-junkie.com/architecture/state_driven/tut_state1.html es un hermoso tutorial para la gestión del estado del juego! Puede usarlo para entidades de juego o para un sistema de menús como el anterior.
Comienza a enseñar sobre el patrón de diseño estatal , y luego implementa un
State Machine
, y lo extiende sucesivamente más y más. ¡Es una muy buena lectura! ¡Le dará una comprensión sólida de cómo funciona todo el concepto y cómo aplicarlo a nuevos tipos de problemas!fuente
Intento no utilizar máquinas de estado y booleanos para este propósito, porque ambos no son escalables. Ambos se convierten en un desastre cuando crece el número de estados.
Por lo general, diseño el juego como una secuencia de acciones y consecuencias, cualquier estado del juego es algo natural sin necesidad de definirlo por separado.
Por ejemplo, en su caso con la deshabilitación de la entrada del jugador: tiene algún controlador de entrada del usuario y alguna indicación visual en el juego de que la entrada está deshabilitada, debe convertirlos en un solo objeto o componente, por lo que para deshabilitar la entrada simplemente deshabilita todo el objeto, no es necesario sincronícelos en alguna máquina de estados o reaccione a algún indicador booleano.
fuente