¿Vale la pena implementar las reglas / mecánica del juego por separado del código principal?


25

No estoy seguro de si se ajusta al alcance de esta comunidad, o debería ir a Stackoverflow en su lugar.

Supongamos que quiero que mi juego sea fácilmente extensible en su núcleo, es decir, quiero que mucha gente, incluso sin un conocimiento de programación decente, pueda no solo modificar las reglas existentes, sino incluso agregarle mecánicas de juego totalmente nuevas. No soy un buen programador, pero estoy listo para aprender, solo necesito algunas instrucciones y garantías de que se puede hacer.

Lo que he pensado es si es posible / factible implementar de alguna manera la mecánica del juego por separado del código de utilidad principal. Quiero decir, para los juegos de mesa tenemos esos libros de reglas que no contienen algoritmos reales de todas las acciones, sino que describen algunos protocolos y límites, haciendo referencia en gran medida al contexto de cada elemento. ¿Es posible hacer algo similar para un juego de PC, como describir todas las reglas en un nivel muy alto, fácilmente legible (y modificable) por un lenguaje de programación humano, que luego es "consumido" y analizado por el código de utilidad en un instancia de trabajo de la mecánica del juego?

Eso realmente parece que necesito escribir mi propio idioma y un compilador para él)) Lo cual, por supuesto, no podré hacer. Pero, ¿puede haber un enfoque más fácil para el problema?

FYI: mi idioma de elección para el código de utilidad será Python 3.x


Como no tiene experiencia y trabaja como desarrollador único, le sugiero que no intente implementar todo usted mismo. El uso de las bibliotecas SDL2 puede ser muy útil para usted en muchas áreas y tienen enlaces de Python para que pueda trabajar en el idioma con el que se sienta cómodo. Para lograr lo que está buscando, el diseño de su arquitectura debe hacerse con mucho, mucho cuidado y anticiparía al menos una reescritura completa incluso para un equipo experimentado. Además, Python no es realmente mucho más fácil de aprender que cualquier otro idioma y, en mi opinión, tiene problemas importantes en el nivel intermedio.
ttbek

El concepto que estás buscando es común fuera del desarrollo del juego. Hay una colección de herramientas de software llamadas motores de reglas de negocios que deben hacer exactamente esto. En el desarrollo del juego, también puedes aprovechar estas herramientas. GameplayKit de Apple, por ejemplo, incluía las clases GKRuleSystem y GKRule para un propósito similar. Se necesitaría un poco de esfuerzo para permitir la edición externa de esto, pero podría estructurarse de una manera que cambie el comportamiento sin recompilar su código.
Sandy Chapman

Respuestas:


34

En términos generales, la facilidad con que se puede extender cualquier sistema depende del grado en que sus subsistemas estén estrechamente o poco acoplados . Por lo general, cuanto más sueltos estén los subsistemas, más fácil será modificarlos ya que están aislados y no necesariamente requieren una comprensión completa del sistema en su conjunto.

Sin embargo, nada es gratis: dicho sistema generalmente requiere más recursos (varias combinaciones de tiempo, dinero y habilidad) para construir. El grado de extensibilidad que ha descrito me parece que está directamente en desacuerdo con el nivel de habilidad que se ha atribuido a usted mismo. Podría hacerse, pero crear software como lo ha descrito es una tarea muy difícil.

Lo más cercano que conozco es Vassal (que es mucho más programático de lo que has descrito), o hacer un mod para Tabletop Simulator (que depende principalmente de la interacción humana para interpretar y hacer cumplir las reglas del juego).


Consejo sólido Intento mantener mi código lo más acoplado posible para facilitar la extensibilidad, pero siempre tendrá casos en los que es mucho más fácil codificar / acoplar algo. Incluso como desarrollador profesional no es una tarea fácil, y definitivamente no es amigable para principiantes.
angarg12

TTS ahora es compatible con Lua y las reglas de cumplimiento no están completamente a la altura de las interacciones humanas ahora.
Ave

17

Lo que he pensado es si es posible / factible implementar de alguna manera la mecánica del juego por separado del código de utilidad principal.

Es absolutamente posible Una forma de uso frecuente en los juegos es el script Lua .

Del artículo vinculado:

Lua fue diseñado originalmente en 1993 como un lenguaje para extender las aplicaciones de software para satisfacer la creciente demanda de personalización en ese momento.

Muchos juegos usan Lua. (Me vincularía, pero la reputación del nuevo usuario está limitando mi recuento de enlaces).

Los scripts de Lua se pueden compilar en tiempo de ejecución. Esto significa que pueden (por ejemplo) ser archivos de texto ubicados en el directorio "scripts" de su juego, fácilmente editables por un modder. Tu juego los carga y los ejecuta.

He visto guiones de Lua que definen las propiedades de las unidades en el juego. Aquí hay un ejemplo aleatorio de TA Spring.

Pero quieres "describir todas las reglas". Eso es posible en teoría, ya que Lua es un lenguaje completo, pero el problema es que tienes que ser lo suficientemente premonitorio para que el código del juego central sepa cómo buscar scripts para extender su comportamiento.

Por ejemplo, puede desarrollar un juego de cartas que sepa buscar cartas en un directorio "scripts / cards". Eso es genial para agregar nuevas tarjetas o editar las existentes. Pero si luego desea expandir su juego para incluir miniaturas en una cuadrícula, tendrá que editar el código central; ninguna cantidad de violín Lua lo llevará allí solo.

Tenga en cuenta: menciono Lua porque sé que se usa comúnmente tanto en juegos como en software para personalización. No estoy sugiriendo que sea la única solución, ni la mejor para las necesidades del interlocutor.


77
Esta respuesta implica que Lua es el único lenguaje de script utilizado de esa manera. Hay muchos otros lenguajes de secuencias de comandos que pueden integrarse en los motores de juego. Algunos motores también siguen su propio camino e implementan su propio lenguaje de scripting específico de dominio. Por lo general, no lo recomendaría (porque construir un idioma es mucho trabajo), pero debería mencionarse.
Philipp

3

Hay un continuo de enfoques y si alguno de ellos vale la pena dependerá exactamente de lo que intente hacer. Específicamente, ¿cuánto control quieres ofrecer al tweaker?

En el extremo del control, simplemente puedes dejar que el tweaker modifique el código de todo el juego. En ese momento, esencialmente estaría publicando el código de utilidad y al menos un ejemplo de cómo usarlo. Un tweaker podría usar tanto o tan poco código como quiera.

Un enfoque que ofrece un poco menos de control sería de alguna manera "congelar" su código de utilidad (por ejemplo, compilándolo de antemano) y solo dejar que los modificadores completen funciones específicas (devoluciones de llamada), restringiendo lo que pueden hacer. Dependiendo de lo que quiera hacer, este enfoque puede tomar muchas formas. Un método común sería colocar toda la parte de la pantalla en el código de utilidad / principal y toda la mecánica en la parte modificable. O bien, es posible que desee mantener algunas mecánicas en la parte "congelada" porque es poco probable que los jugadores quieran cambiarlas, o hacerlas modificables es demasiado complicado.

En el extremo de bajo control del continuo solo está permitiendo que los tweakers cambien los valores dentro de un rango fijo. Un archivo de datos que te permite seleccionar los colores de las cosas dentro del juego sería un ejemplo. Sin embargo, podría utilizar este enfoque y seguir ofreciendo mucha personalización. Sería posible definir una selección de funciones y permitir que los modificadores las compongan para crear las devoluciones de llamada a partir del enfoque anterior, pero no permitirles definir otras nuevas. O tal vez omita la parte de composición y solo ofrezca una selección finita.

Los detalles de todos estos enfoques y cuál se adapta a su caso de uso dependen del tipo de juego base que desee realizar y de cuánto control desee renunciar. Tenga en cuenta que los juegos comerciales generalmente usan solo el segundo y el tercer método porque el primero permite a los jugadores crear juegos completamente separados, lo que introduce problemas de licencia complicados. Tenga en cuenta que a medida que estos enfoques forman un continuo, el segundo enfoque también puede introducir estos problemas.


Hacerlo de código abierto es mi objetivo, en realidad. Lo que veo como un problema es cómo implementar esta extensibilidad de la manera más fácil, para que otros jugadores del juego (que es el juego MP, por cierto) puedan crear sus propias extensiones del conjunto básico de reglas y compartirlas con cada uno otro, de alguna manera evitando conflictos al mismo tiempo. Entonces, si un usuario desarrolla alguna extensión que anula ciertas reglas y otro desarrolla una extensión diferente, ¿cómo asegurarse de que el tercer usuario que quiera usar ambos en sus juegos no tenga problemas de compatibilidad? Además de obligarlos a colaborar estrechamente.
es el

..y para implementarlo de tal manera que no requiera la modificación de ningún código de utilidad y, por lo tanto, demasiado conocimiento sobre programación.
es el

1
No creo que haya una forma de evitar problemas de compatibilidad (¡incluso establecer el color de algo puede causar eso!) Creo que lo mejor es tener una forma de detectar posibles problemas de compatibilidad y tener una buena manera para los usuarios responder. Dependiendo del diseño de la interfaz del código de utilidad y las extensiones en cuestión, puede haber una forma de ordenar devoluciones de llamada, etc. que produzca el resultado deseado. Por otra parte, puede que no haya. Alertar al usuario de que podría haber problemas y por qué parece una mejor experiencia de usuario que las cosas que se rompen sin explicación.
Ryan1729

2

Es absolutamente posible separar las reglas del sistema del código que aplica esas reglas. Prefiero estructurar mi código de esa manera para proyectos complejos, ya que hace que sea más fácil agregar nuevas reglas o cambiar las reglas más adelante sin introducir errores en el sistema subyacente. Y los errores en un motor de reglas se encuentran más rápido que los errores en un sistema donde las reglas y el otro código se mezclan entre sí, porque el mismo motor de reglas se usa una y otra vez.

Si vale la pena, depende de la complejidad del sistema. Como si no me molestara por Pac-Man, pero no me podía imaginar escribir Dwarf Fortress de otra manera.


Gracias, @Robyn. ¿Algún consejo de lectura para alguien que no sabe cómo abordar este diseño correctamente? ¿Existen algunos patrones de diseño bien establecidos para tales aplicaciones? ¿Algún libro que cubra el tema?
es

No hay libros, lo siento. Pero la idea básica de un motor de reglas simple: crea una clase de regla que tenga una propiedad para cada información que necesites para describir una regla. Si algunas de estas propiedades tienen funciones lambda, puede asignarles comportamientos complejos. Haga una clase que cree una instancia de una lista de Reglas, para que todas sus reglas estén en un solo lugar. Cree otra clase que tenga un método que tome una lista de Reglas como entrada y las aplique al sistema.
Robyn

2

Definitivamente es factible. Si vale la pena, depende de tus objetivos.

No tiene que inventar su propio idioma o escribir un compilador para que esto funcione.

Si quieres que tu juego sea fácilmente extensible, probablemente sea una buena idea hacerlo.

Probablemente sea más trabajo para usted, al menos a corto plazo, crear sistemas comprensibles y facilitar las modificaciones.

Un juego que hace esto es Rimworld (no tengo afiliación) y es posible que puedas ver y aprender de cómo lo hicieron, básicamente poniendo muchos datos y mecánicas del juego en archivos XML que están en las carpetas del juego para que cualquiera pueda ver y aprender modificar. El núcleo / motor del juego se hizo con Unity.

También existe la posibilidad de extender el juego más / más profundo mediante la codificación real, sé menos sobre eso, pero puedes aprender mirando el foro de modificaciones.

La posibilidad de modificación hace que el juego sea más interesante para muchas personas y creo que ha contribuido mucho a su éxito. También permite a los desarrolladores incorporar cualquier contenido de modulación que deseen en el juego principal y, de alguna manera, acelerar el desarrollo y mejorar el juego, ya que reciben asistencia de mucha gente y pueden decidir aceptar cosas basadas en lo que es popular, lo que parece funcionar, etc.

Y, por supuesto, especialmente para un pequeño estudio independiente, tienen cientos de personas que se les ocurren ideas y las prueban, lo cual es una gran cantidad de trabajo que no podrían hacer ellos mismos, ni probablemente contraten personas para hacer.


Aunque puedo ver cómo se pueden definir los datos del juego con xml, no puedo imaginar cómo puedes usarlo para definir la mecánica / reglas del juego. ¿Podría proporcionar algún ejemplo / artículo sobre el tema, tal vez?
es el

Las Reglas de @tis son solo otro tipo de datos. Si mi motor tiene "Si A hace B", puedo cargar A y B desde un archivo XML, ahora los usuarios pueden poner reglas bastante arbitrarias, un bit adicional que puede ayudar es proporcionar una lista con todos los As y B posibles que admite per se , por ejemplo, "Si el tipo de estado de estado es entonces velocidad de movimiento 100", "Si el tipo de estado de estado y tiempo> x entonces el tipo de estado de estado" Entonces, en su diseño, piense en qué tipo de reglas desea permitir sobre qué tipo de objetos (estado, tiempo, velocidad de movimiento) y con qué tipos de composición permitir (y / o, etc.). Si el estado bajo el agua y el tiempo> 5 de salud -10.
ttbek

1

Es posible que desee examinar el diseño orientado a objetos . Python tiene un buen soporte para eso.

Se escriben libros gruesos sobre esto que pueden dar miedo cuando eres nuevo, pero los principios principales son bastante fáciles.

El punto principal es que identifique con qué tipo de objetos está trabajando. No dices en qué tipo de juego estás pensando, pero cosas como Jugador, Monstruo, Objeto, Equipo, Arma, Armadura, etc. son objetos típicos.

Si quieres diferentes tipos de juego, probablemente quieras un objeto de juego que se encargue de la condición de victoria y demás. ¿Quizás un objeto Map también?

A veces no está claro si algo merece ser un objeto o no, por ejemplo, daño. Si no hace daño a un objeto, el código será más simple, pero convertirlo en un objeto facilita la personalización.

Subclases: tanto las armas como las armaduras son equipos. Los equipos son artículos. Probablemente hay otros tipos de artículos. Probablemente le resulte útil definir una clase Combatiente de la que tanto los Jugadores como los Monstruos sean subclases.

La idea es que, por ejemplo, las armas tendrán muchas cosas en común con todos los demás tipos de artículos, tienen un peso, tamaño y otras propiedades como esa.

Entonces, la subclasificación le da una forma de decir que "las armas son como otros artículos, pero además puede manejarlas, afectan el daño que usted hace, etc."

La subclasificación también permite a tus constructores de mods decir "Mi nuevo tipo de arma es como las armas estándar, excepto que ..."

Luego tienes que decidir qué objeto es responsable de qué. Esto no es tan fácil como parece y debes pensarlo un poco. Tomar las decisiones equivocadas no afectará mucho el juego básico, pero hará que sea más difícil personalizarlo.

Mientras solo juegues por tu cuenta, puedes cambiar las cosas, pero en el momento en que lanzas algo al público, ¡hacer cambios se vuelve mucho más difícil! La gente hará modificaciones que dependan de que las cosas sean como son ahora. Incluso bichos. La gente escribirá modificaciones que dependen de los errores que permanecen en el código. Si cambias las cosas, esas modificaciones se romperán y aparecerán monstruos linchadores en tu casa.

Por ejemplo:

Un jugador que empuña un arma ataca a un monstruo con varias armaduras. Esto tiene lugar en un modo de juego particular y en un mapa determinado.

Ambos combatientes pueden tener habilidades como golpe crítico y esquivar.

Ahora, ¿qué objeto es responsable de qué?

No hay una respuesta correcta para esto. Mucho depende de qué tipo de personalización desea permitir.

Si nunca llama a un objeto (por ejemplo, el Mapa), ese objeto no puede cambiar el ataque de ninguna manera.

Después de tomar todas estas decisiones, documentarlas . Escriba un "Manual de Modders" que enumere exactamente qué métodos modificables tiene cada objeto, qué parámetros toman, qué deben devolver, y así sucesivamente ...

¡Buena suerte!


Su aporte es realmente apreciado, y usted pone mucho esfuerzo en ello, por lo que definitivamente vale la pena un +1, pero estoy enterado de OOP, en general (aunque carece de experiencia en ello). Mis problemas actuales son con el enfoque de diseño más general que debería adoptar. Mi juego no es algo tan grande como D&D por escala, sin embargo, es MUY profundo en su mecánica. Eso significa muchas reglas complejas, entremezcladas en diferentes niveles. Lo que me gustaría permitir a los usuarios ampliar significativamente, no solo modificar algunos valores. Puede ser que no hay solución fácil, de hecho ..
tis

@tis La clave para esto es tomar la decisión correcta sobre cuáles son realmente los objetos en tu modelo OO del juego. El lugar "obvio" para comenzar es con los "sustantivos" como arma, armadura, etc., no es la única forma, y ​​puede conducir a un enredo de código inutilizable. Si una regla dice "solo disparas a algunos monstruos con balas de plata en un cementerio a la medianoche", ¿dónde haces cumplir esa regla en el código? ¿En la clase Gun (o Bullet), en la clase Monster, en la clase Fighter del usuario de armas, en la clase Churchyard o en la clase Time? La mejor respuesta podría ser "ninguna de las anteriores" ...
alephzero

... y repensar todo el diseño en términos de una clase de reglas (que probablemente sea realmente una base de datos) y una clase de resolución de conflictos. Ahora, otras reglas como "si no tienes balas, aún puedes usar tu arma como un garrote" y "si Alice lanza un hechizo que protege parcialmente (pero no completamente) a Bob contra las heridas de bala, mientras Charlie intenta dispararle a Bob, entonces ... "tiene un lugar único y" obvio "para ser implementado en el código. Es posible que su clase de armas original ahora haga muy poco, excepto producir algunos efectos audiovisuales, ¡y ni siquiera eso, si es un juego basado en texto!
alephzero

1

Una forma simple de obtener un soporte básico para esto sería separar la mayoría de los valores numéricos en uno o más archivos de texto separados para permitir que las personas interesadas los modifiquen en el olvido.

Por ejemplo, mencionaste juegos de mesa; si tuviera un juego basado en D&D, podría tener un weapon_damagearchivo que contiene líneas como Battleaxe: 1d12. Su código de utilidad leería ese archivo y cada vez que un daño fuera causado por Battleaxesu código lo leería generate a number from 1-12, 1 time(s)y los agregaría. Ajustar la línea para leer en Battleaxe: 4d6su lugar generate a number from 1-6, 4 time(s)y agregarlos. Del mismo modo, podrías tener una carpeta Creaturesy dentro de ti tienes un archivo para cada criatura, incluyendo líneas como AC: 12; luego agregar nuevos archivos a esa carpeta crearía nuevas criaturas. Incluso podría hacerse para clases de personajes, tipos de terreno, un montón de cosas.

Este estilo de personalización sin código puede ser muy poderoso y cubrir muchas piezas de tu juego. Sin embargo, esto realmente no permite que un usuario realice cambios que no especificó explícitamente. Por ejemplo, puedes permitir Sneak Attack: [damage]que se te dé a cualquier Criatura o Clase para agregar [damage]a cualquier ataque que cumpla las condiciones para un Ataque furtivo. Incluso podría proporcionar formas de cambiar cuáles son las condiciones, como "cuando ataca con sigilo" o "cuando está flanqueando" o "cuando tiene ventaja". Sin embargo, si un usuario decide que quiere que los ataques furtivos sean "Cuando haces una tirada de ataque, también puedes lanzar sigilo contra la percepción del objetivo. Si ambas tiradas tienen éxito, entonces agrega el daño de Ataque furtivo"

Si deseaba que un usuario pudiera agregar un comportamiento completamente nuevo al juego sin necesidad de habilidades de codificación al mismo nivel que el desarrollador, entonces, como la gente mencionó, está buscando esencialmente crear un motor de juego o un lenguaje de programación separado. Para las modificaciones que no requieren conocimientos de codificación, los archivos de datos basados ​​en texto y las estructuras de carpetas pueden proporcionar muchas opciones. Si desea que los usuarios modifiquen más que eso, deberá pedirles que aprendan o conozcan un lenguaje de programación.


Sí, también necesito permitirles agregar nuevas mecánicas, solo ajustar algunos valores no funcionará. También pensé que esto podría necesitar un idioma separado, solo pensé que ya hay uno que puedo emplear en mi código de utilidad Python.
es el

@tis ¿Ya has considerado lo que Wikipedia tiene sobre el tema? en.wikipedia.org/wiki/Logic_programming
ttbek

0

[Soy un desarrollador de software de décadas, pero sin experiencia en desarrollo de juegos, por lo que tal vez la industria de los juegos adopta enfoques diferentes, tal vez por buenas razones ...]

Tu enfoque tiene absolutamente sentido para mí. El núcleo proporciona las funcionalidades básicas sobre las que se basan la mecánica y las reglas, por lo que es una API que deben utilizar los componentes de nivel superior.

Y al diseñar una API, mi guía favorita es crear el lenguaje en el que desea expresar su código de nivel superior (por supuesto, teniendo en cuenta las limitaciones de sintaxis de su lenguaje de programación).

Por lo tanto, un buen enfoque sería escribir algunas reglas y mecanismos hipotéticos de la forma en que le gustaría que se expresen (con la sintaxis de Python, por supuesto), descubriendo así lo que desea que la API principal proporcione a las reglas y los mecanismos. capas.

Y, por supuesto, recomendaría echar un vistazo a las instalaciones de secuencias de comandos de los juegos existentes para tener una idea de lo que hacen.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.