Actualmente estoy construyendo un juego de elegir tu propia aventura. Ahora es bastante fácil tener un resultado para cada elección y crear un flujo lineal, pero ¿existe un buen algoritmo para que todas las selecciones anteriores afecten al siguiente resultado? Obviamente, podría almacenar cada selección anterior y tener grandes declaraciones 'IF' para decidir, pero me preguntaba si había una mejor manera.
Parte de mí se pregunta si cada opción debería tener un 'puntaje' y luego lo uso (tal vez con un umbral) para determinar cuál debería ser la siguiente acción y cada acción se agrega al puntaje.
Principalmente estoy haciendo esto en swift / SpriteKit, pero creo que se trata más del concepto que del código en este momento.
En respuesta al comentario de Josh a continuación:
Supongo que todavía estoy en la fase conceptual en este momento, pero cada 'página' sería un objeto personalizado o un archivo json. Estaba pensando en su respuesta (ahora eliminada) y tal vez tener cada opción ENUM como un poco. Entonces cada página podría tener un 'puntaje'. Luego, utilizando las opciones anteriores seleccionadas, determine qué bits se configuran y eso determina qué página. Supongo que me preguntaba si había una solución existente para este problema antes de comenzar a ayudar a decidir cómo debería formatear la 'historia'
Aproximación aproximada al formato:
{ "text":"You arrive in the dungeon and there are 2 doors",
"options":[
1: "Go left",
2: "Go Right"
],
"score" : 0 // first page
}
{"text" "You went left and meet a dragon",
"options":[
0: "Game over, you were eaten" // something to handle game over
],
"score" : 1
}
{"text" "You meet a mushroom who tells you the princess is in another castle",
"options":[
4: "Give up, game over", // something to handle game over
8: "Jump down the pipe"
],
"score" : 2
}
Gracias
fuente
if
'selse
',switch
'scase
' y 'con la esperanza de que termines antes de perder la cordura.Respuestas:
Muchos juegos de Aventura / RPG manejan esto de dos maneras (puede haber más de los que no estoy al tanto).
Uso de banderas
El primero es establecer una bandera si algo sucedió (generalmente alguna máscara de bits). Esto está bien si no tienes muchas cosas que rastrear. En la sala / encuentro puede haber una verificación contra una bandera que altera algo. En su ejemplo, podría agregar una regla:
Donde la segunda opción solo aparece si
flags & 64
está configurada. También podría implementar lasetflag
opción si aparece la escena, o si se hizo una elección particular.Uso de artículos
La segunda opción es agregar elementos al inventario del jugador. Estos son "este elemento es necesario para completar una misión" que ves a menudo en los juegos. Básicamente funcionan como 'banderas' portátiles. Esto se puede implementar de dos maneras (o una combinación):
El elemento es la 'bandera': haga que la escena o el diálogo comprueben si el jugador tiene un objeto específico en su inventario. Esto es muy parecido a la mecánica de 'comprobar una bandera' como se describió anteriormente. Lo bueno es que puede ser mucho más fácil para ti diseñar encuentros a medida que verificas contra objetos conocidos con nombre.
Los elementos tienen propiedades que funcionan como una bandera. Por ejemplo, en The Witcher 3, el jugador obtiene un objeto que puede disipar paredes ilusorias. Ese elemento en sí podría ser una 'bandera' pero también podría ser que el objeto tiene una propiedad
can_dispel_illusions
. La ventaja aquí es que podría implementar varios objetos que se pueden usar en el mismo escenario. Por lo tanto, una escena / diálogo / puerta podría verificar si el jugador tiene 'algo' en su inventario que tiene la propiedadcan_dispel_illusions
.Esto te da la posibilidad de darle al jugador la ilusión de elegir; Si el jugador no se encontró con la bruja en la escena uno, por lo tanto, al perder la 'varita de disipación', el jugador podría obtener un 'anillo de disipación' más tarde de algún comerciante sombrío, evitando un estado del juego imposible de ganar.
Si no planeas darle al jugador un inventario "real", los artículos de la misión podrían ir a una lista oculta del jugador.
ejemplo:
y:
fuente
Una solución que he visto que detalla su enfoque es tener varios atributos con puntajes asociados. Algunas opciones dan como resultado la modificación de uno o más de estos puntajes. Los puntajes a su vez pueden modificar las opciones disponibles para el jugador.
Por ejemplo, al principio de la historia, puede haber algunas opciones de encuentros de combate. Si el jugador entra en combate, el atributo de valentía aumentaría, mientras que huir haría que disminuyera. Más adelante, una rama de la historia en particular solo podría estar disponible si el puntaje de valentía estaba por encima o por debajo de un umbral determinado. Para agregar más profundidad, algunas decisiones deberían afectar a más de un puntaje. Por ejemplo, recoger bolsillos podría aumentar un puntaje de sigilo y disminuir un puntaje de honestidad.
En general, he visto este enfoque utilizado en la ficción interactiva del tipo de simulación. Puedes escuchar a Dan Fabulich de Choice Of Games discutir esta solución en este episodio de la Mesa Redonda de Diseño de Juegos.
Los beneficios de este enfoque son:
Algunos inconvenientes son:
fuente
Este es el gran problema que enfrentan los juegos basados en la historia: explosión combinatoria. Como tal, si observa, por ejemplo, los juegos Bioware o Telltale, encontrará que el enfoque más común parece ser tratar de restringir la historia para que sea más lineal y mantener las consecuencias de las acciones limitadas a sus capítulos.
El enfoque que Bioware parece estar usando divide cada historia en subprocesos o subarcos separados. Los arcos son bastante independientes entre sí, pero suceden simultáneamente y pueden contribuir al final. De esa manera, no tiene que modelar cada combinación de arcos, solo alterna capítulos entre arcos, y las consecuencias se limitan al subarco particular con el que está lidiando en este momento, o cómo terminar un arco. (o cómo terminar el arco de un personaje. Si ya no necesitas ese NPC, a menudo tienes la opción de matarlos, arrestarlos o liberarlos, por ejemplo, dándote elección, pero limitando las consecuencias al resto de la historia)
El final de toda la historia solo necesita saber cómo terminó cada arco y vincular toda la narración en una pequeña reverencia ordenada.
¿Cómo modelarías eso en un programa?
Esto simplemente empuja el problema hacia abajo un nivel (porque cada subarco necesita rastrear las diferencias como lo haría una historia simple), pero básicamente tendría una serie de banderas (por ejemplo, un campo de bits o una lista de elementos con banderas que representan capacidad de efectuar ciertos resultados) para cada subarco.
Además, cuando está contando su final, generalmente toma el mismo enfoque de alternar cuando le cuenta al jugador las consecuencias: el resultado de cada subarco obtiene su propio nodo de párrafo / conversación, lo que simplifica enormemente sus condicionales.
fuente
Puede tomar un poco de tiempo, pero desarrollar su propio árbol (como un árbol de comportamiento o árbol de diálogo, pero para páginas) puede ser beneficioso. Y podrías usar uno de esos como modelo. Algo como esto:
¿Cómo funcionan los árboles de diálogo?
Esto le permitiría adaptarlo a sus necesidades específicas, pero también permitiría que el código maneje la mayor parte del trabajo.
fuente
¿Qué sucede si utiliza un enfoque de tipo motor de reglas? Cuando un jugador interactúa con un NPC, el juego ejecutaría un motor de reglas simplificado que comenzaría con banderas que habían sido creadas por elecciones / comportamientos pasados y lo compararía con un conjunto de reglas definidas por usted de antemano. Algo así como Drools es probablemente demasiado grande y ambicioso, por no mencionar lento, pero un motor de reglas de alcance limitado teóricamente podría brindarte un mejor rendimiento y mucha flexibilidad.
fuente