¿Es viable implementar su propio lenguaje de script?

21

Estoy codificando un juego beat 'em up en C ++ y ha llegado el momento de implementar secuencias de comandos para eventos, desencadenantes, escenas de corte, etc. He leído en Internet y obtuve bastante información. Mi solución de primera elección sería implementar mi propio lenguaje de script como el de Cave Story . He visto esto sugerido, pero la mayoría de la gente sugiere lua, pero eso no parece ajustarse a mi tipo de programación.

¿Has creado tu propio lenguaje de script? ¿Por qué elegiste rodar el tuyo en lugar de usar uno existente? ¿Qué recursos consultó durante el desarrollo?

skiperic
fuente
43
Mi regla general es: si necesita preguntar a otras personas si es una buena idea lanzar su propio _____, entonces no es una buena idea.
sam hocevar
2
Tenga en cuenta que si implementa su propio idioma, las personas deben aprenderlo y esperar que no haya errores en su intérprete, mientras que los idiomas como el Lua son más populares y mucho menos propensos a tener errores.
Nick Caplinger
2
@NickCaplinger lo golpea en la cabeza. La creación de su propio medio significa que no hay documentación, ni comunidad, ni tutoriales de terceros, ni StackExchange, etc. Cualquier avance menor que obtenga en sintaxis o integración se verá compensado por la falta de soporte a menos que sea un desarrollador realmente conocido con millones de fanáticos
Sean Middleditch
44
También tenga en cuenta las herramientas. Este es mi problema con D, Rust, Dart, etc. Su sintaxis no tiene sentido por sí sola. Necesita un editor adecuado, resaltado, "Intellisense" (finalización de código), buenos diagnósticos, soporte de refactorización, soporte de documentación en línea, etc. para que realmente valga la pena. Sin mencionar todas las características reales del lenguaje, integración, eficiencia, etc.
Sean Middleditch
1
Si eres un programador de C ++ y no te gusta LUA, prueba JavaScript en su lugar.
zeel

Respuestas:

42

No. Al menos, probablemente no.

Este es un caso muy frecuente de reinventar la rueda en el desarrollo del juego, un error que todavía es bastante popular.

Si haces esta pregunta, es muy probable que te influya lo que otros hacen, así que mira lo que Epic Games acaba de hacer con Unreal Engine:

  • UE3 tenía un elemento UnrealScript personalizado, extraño, no optimizado y difícil de depurar,
  • Si el rumor es cierto, su soporte se está eliminando en UE4 , a favor de las DLL de C ++ recargables en caliente.

¿Crees que puedes hacerlo mejor que Epic?

La creación de lenguajes de programación pertenece a los creadores de lenguajes de programación , no a los ingenieros de juegos.

Se necesitan años y años para que un lenguaje se vuelva completamente maduro, y su conjunto de herramientas que lo acompaña (compilador, enlazador, intérprete, depurador ...) se puede usar. Hoy en día tienes muchas soluciones disponibles a mano, así que no hay absolutamente ninguna razón real para comenzar algo nuevo desde cero, al menos no si el objetivo es simplemente hacer un juego. Período.

Para responder a sus preguntas secundarias, no, por estas mismas razones, nunca he implementado mi propio lenguaje de secuencias de comandos. Pero he sufrido mucho con algunos a medio hornear. Debido a que se crearon con una característica muy limitada en mente, siempre tuvieron estas pequeñas peculiaridades que te vuelven loco. A menudo, pasarás muchísimo tiempo intentando evitar las limitaciones del idioma en lugar de solo crear tu juego.

Si la razón por la que desea crear un lenguaje es porque está destinado a ser utilizado por personas que no conocen muy bien la programación, o si cree que lo necesita porque quiere algo muy específico de dominio, déjeme decirle que estos también malas razones Puede escribir una API de muy alto nivel con funciones que do_what_they_say_and_say_what_they_do(), y un código repetitivo muy simple que expone su uso básico. Sus usuarios no tan técnicos estarán encantados de aprender un poco de programación, y usted estará encantado de no estar limitado por algún lenguaje mal implementado.

Entonces, como esto puede sonar un poco brusco o incluso duro, diré que hay un caso en el que podría tener sentido: si quieres aprender cómo se hace un lenguaje de secuencias de comandos. Pero por favor, por favor, si lo haces: no obligues a otros a usarlo.

Editar

Acabo de echar un vistazo a la lista de comandos de Cave Story que has vinculado. Ay:

<ECJx:y      [EC?] Jump           @ Jump to event Y if any npc with ID X is present

No quiero mostrar falta de respeto al desarrollador detrás de Cave Story, pero este es un ejemplo perfecto de una simple lista de comandos que muta en un lenguaje de script personalizado incontrolable. Esto podría seguir siendo útil para un desarrollador único o un equipo muy pequeño, pero en esta etapa le aconsejo que cambie a un lenguaje Turing completo y bien probado (por ejemplo, Lua), donde podría hacer:

if (npc.id == x) then
    jump_to_event(y)
end

Esto facilitará mucho las cosas cuando, por ejemplo, necesite una condición más compleja:

if (npc.id == x) or (npc.type == "enemy") then
    jump_to_event(y)
end
Laurent Couvidou
fuente
21
+1 "La creación de lenguajes de programación pertenece a los creadores de lenguajes de programación, no a los ingenieros de juegos". Esta cita no podría ser más correcta. Después de haber tomado una clase de conceptos de lenguaje de programación enseñada por un tipo que era un genio de los lenguajes de programación, estas personas son de una raza diferente. Una clase me hizo darme cuenta de la cantidad de teoría de CS y matemáticas que se necesitan para crear un lenguaje de programación real. Esto me hizo apreciar a estas personas y sus habilidades aún más. Me dejaron crear los juegos, me mantengo fuera de su camino y les dejo crear los idiomas.
Dean Knight
+1, no sé lua o el lenguaje de scripting personalizado, pero era evidente exactamente lo que estaba sucediendo en lua y ahí es donde la usabilidad es importante
RhysW
1
No hay nada mágico en uno u otro que haga imposible aprender ambos. Tal vez Unreal esté eliminando UnrealScript, pero están mejorando y completando Kismet para que sea un lenguaje de script visual completo y capaz. No eliminaron UnrealScript porque es un error, lo están eliminando porque está anticuado por características significativamente más difíciles (recarga de C ++ en caliente, Kismit actualizado). No tome esto como que estoy en desacuerdo con su punto: escribir su propio idioma es una gran pérdida de tiempo, una fuente de errores y una causa de grandes curvas de aprendizaje, etc.
Sean Middleditch
2
@ ott-- Tampoco tengo miedo, mi punto es que expandir esta notación lo hará cada vez más complicado, mientras que usar un lenguaje apropiado en primer lugar ayudará a largo plazo. La sobrecarga no es relevante en comparación con la facilidad de uso en ese caso, en mi humilde opinión.
Laurent Couvidou
1
Tenga en cuenta que UnrealScript se reemplaza por Blueprints (pero he apostado a mis colegas que volverá). La carga de archivos DLL es una función ortogonal.
sam hocevar
9

¿Has creado tu propio lenguaje de script y por qué elegiste rodar el tuyo en lugar de usar uno existente?

Sí, aunque tomé prestada la sintaxis de otros idiomas. En general, fue una gran experiencia de aprendizaje y en mi caso no fue tan difícil porque el lenguaje era simple.

Lo hice principalmente porque quería usar una sintaxis regular de estilo C para mis scripts, ya que todos en el equipo estaban familiarizados con ella.

También estaba interesado en aprender un poco sobre la implementación de lenguajes de programación, y dado que solo necesitaba un subconjunto muy simple de características (variables, aritmética, condicionales, bucles y llamadas a funciones o rutinas en el juego) decidí probarlo.

¿Qué recursos consultó durante el desarrollo?

Mi principal recurso fue este libro:

ingrese la descripción de la imagen aquí

Logré aprender lo suficiente de este libro para implementar:

  • Un lexer: que era casi trivial usando expresiones regulares, solo usando Regex.Match para identificar y dividir tokens.
  • Un analizador de descenso recursivo: básicamente una función para cada regla en la gramática y algunos métodos auxiliares para mirar hacia adelante y consumir tokens. Miré la especificación gramatical de C # en busca de inspiración. La parte más difícil fue tratar con la aritmética y las precedentes de operadores de relaciones sin entrar en una recursión infinita.
  • Un intérprete de AST: utilizando el patrón de diseño del visitante, atravesé el árbol generado por el analizador y ejecuté cada nodo de instrucción de forma recursiva.

Me habría detenido allí ya que casi todo lo que necesitaba ya estaba funcionando, excepto por una cosa: llamar y ceder en las corutinas de Unity3D desde el intérprete recursivo. Para resolver ese problema, tuve que deshacerme de la recurrencia, y volví una vez más al libro. Esta vez terminé agregando:

  • Un compilador: otro visitante, pero en lugar de ejecutar código, genera una lista de pequeñas instrucciones atómicas de cada nodo del AST (es decir, un simple lenguaje de ensamblaje personalizado basado en pila). Las operaciones como un bucle while o una condición if se convierten en etiquetas e instrucciones tipo goto. En este punto también escribo el script compilado en el disco como un archivo binario.
  • Un intérprete de código de bytes: simplemente itera sobre una lista plana de instrucciones. Sin la recursividad, ahora era fácil de integrar con las rutinas de Unity3D.

Todo el proceso tardó aproximadamente 2 semanas desde cero conocimiento, y fue muy divertido :)

PD: Al final, también quería agregar resaltado de sintaxis e inteligencia para mi lenguaje personalizado en nuestras herramientas. Scintilla fue un salvavidas en este sentido. Usé el siguiente contenedor:

http://scintillanet.codeplex.com/

David Gouveia
fuente
5

He visto esto sugerido, pero la mayoría de la gente sugiere lua, pero eso no parece ajustarse a mi tipo de programación.

Bien, intentemos esto desde un ángulo diferente: ¿qué tiene Lua que no te gusta? ¿Es algo que se puede arreglar fácilmente o es algo fundamental?

Por ejemplo, utilice palabras clave como then/do/enddenotar bloque de código en lugar de buenas llaves de estilo C / C ++. Si ese es tu problema ... eso es algo que puedes solucionar. Todo lo que necesita hacer es definir su propio pequeño dialecto de Lua y escribir una herramienta de transformación simple que convierta su sintaxis de llaves en Lua real.

¿Quieres + = de alguna forma? Eso también es fácilmente algo que puede hacer en un sistema de preprocesamiento. Simplemente convierta las declaraciones del formulario expr1 += expr2en expr1 = expr1 + expr2.

De acuerdo, tendrás que encontrar una manera de detectar si un par de llaves representan una tabla o un do/endpar. Y que tendría que conectar su sistema de pre-procesamiento en Lua reemplazando dofile, loadstringy otras funciones de la biblioteca estándar de Lua. Pero todo es finalmente factible.

Si le preocupan pequeños problemas como ese, y está demasiado casado con un estilo de programación como para cambiar la forma en que codifica (nota: generalmente es una calidad terrible para tener como programador), esta es una alternativa mucho más viable que simplemente escribiendo tu propio idioma. Esto llevaría quizás un par de semanas como máximo . Compare eso con los años que se gastarían en un lenguaje adecuado, con un rico soporte de depuración y similares.

Si sus problemas son mayores que esto (los valores globales son los predeterminados, lo que requiere que lo use en localtodas partes), algunos de estos se pueden administrar (simplemente haga que la declaración de nuevo global sea un error, mediante el uso de entornos alterados y metatablas). Si odias las funciones como objetos de primera clase, corutinas, recolección de basura u otros elementos básicos de Lua ... bueno, entonces estás en tu propia creación;)

Y si realmente quieres ser duro al respecto, puedes escribir tu propio idioma que compilas en Lua. Por lo tanto, al menos podrá aprovechar el muy bien probado tiempo de ejecución de Lua, la excepcional API de Lua y otras instalaciones básicas de Lua, todo desde su idioma! Lua. Esto llevará tiempo, pero aún no serán los años que pasarías en otra cosa.

Nicol Bolas
fuente
Para mí, parece que podría codificar las funciones si tuviera que usar Lua. Parece que solo estoy moviendo código.
skiperic
1
@skiperic: No sé a qué te refieres con eso. ¿Puede dar un ejemplo?
Nicol Bolas
Ver la respuesta de Laurent arriba.
skiperic
2
@skiperic: Eso realmente no explica lo que te preocupa. ¿Puedes codificar en Lua? Sí. ¿Y el problema es ...?
Nicol Bolas
1
@BartekBanachewicz: Incluso aceptando que es una API de C, sigue siendo superior a muchas API de scripting basadas en C ++ que he visto. Es la única API de scripting que realmente consideraría usar raw , sin un tipo de carpeta automática.
Nicol Bolas
3

Para complementar las otras respuestas, esta no es una opción estrictamente binaria. Dentro de un lenguaje de script existente, también puede crear su propio lenguaje específico de dominio . Las ventajas de este enfoque son:

  • En realidad, no tiene que meterse con gramáticas formales, analizadores, implementadores editores personalizados, etc.
  • Obtendrá la mayor parte del beneficio de implementar un lenguaje de script especializado, es decir, una abstracción adicional, específica para su juego.
  • vs homebrew: los usuarios que estén familiarizados con el lenguaje de scripting de su elección podrán usar su DSL de inmediato.
  • vs. lenguaje simple: los usuarios que no estén familiarizados con el lenguaje de secuencias de comandos solo necesitarán conocer el DSL para modificar su juego.

La desventaja principal es que estaría diseñando el DSL con las restricciones de su lenguaje "base".

mikołak
fuente
2

Se podría tener sentido en función de la mecánica de su juego. Algunos juegos con una mecánica lo suficientemente simple podrían usar un lenguaje interpretado para salvarse de una codificación Lua / Python demasiado complicada, pero los ahorros de complejidad podrían no valer demasiado. Por ejemplo, uno de esos juegos de Novela Interactiva podría usar fácilmente un motor de secuencias de comandos escrito a medida.

Si su juego involucra un motor de física, varios componentes del juego y una complejidad variable de personajes y habilidades, definitivamente debería considerar buscar otros lenguajes de secuencias de comandos existentes, por lo que no está luchando para agregar las características necesarias a su personalizado, o corrigiendo errores con eso. Si bien Lua es probablemente el más rápido, hay muchos otros que pueden gustarle más por su sintaxis, y muchos de ellos se jactan de la facilidad con que se integran con C. Python, Ruby y Angelscript son algunos. (Siéntase libre de mencionar a otros en los comentarios)

Si se asegura de que dichos lenguajes solo se usen para el "control lógico" (es decir, manejar un caso de colisión específico para ciertos tipos de objetos, como el lanzallamas tocando un bloque de hielo), el rendimiento casi nunca será un problema. Por supuesto, por otro lado, si los usa para más código de rutina (haciendo un algoritmo de verificación de colisión personalizado que ejecuta cada cuadro), es más probable que lo empañe.

Katana314
fuente
1
Lua también es un lenguaje de script muy popular en el desarrollo de juegos.
Philipp
Sí, Lua se usa por todas partes, pero el OP notó que realmente no le gustaba mucho. Las preferencias de estilo de codificación pueden ser importantes.
Katana314
1
" Por ejemplo, uno de esos juegos interactivos Novel fácilmente podría utilizar un motor de scripting personalizado por escrito. " Es obvio que no ha visto Inform . Realmente, incluso para las aventuras de texto, no tiene sentido inventar su propio idioma.
Nicol Bolas
1
@ Katana314: "Las preferencias del estilo de codificación pueden ser importantes " . Honestamente, el mundo estaría mejor si los programadores dejaran de hablar sobre el "estilo de codificación". Todos seríamos mejores programadores si dejáramos de pensar que <insertar idioma preferido aquí> era fundamentalmente mejor que el de <insertar idioma preferido aquí> de todos los demás. El uso de lenguajes que quizás no le gusten es la sintaxis del carácter de compilación y ayuda a evitar este tipo de error.
Nicol Bolas
1

Yo digo, adelante. En un currículum sería una demostración extra de habilidad. Sin embargo, ten en cuenta que primero necesitas esa habilidad. No va a ser fácil, va a ser bastante difícil. También hay libros sobre el tema y tutoriales en línea, pero en última instancia, dependerá de usted y de su comprensión de cómo funciona un compilador y cómo se analiza y traduce el código.

Asegúrate de que comiences de forma simple, prueba con frecuencia y mantén tu ideal. Pero siempre recuerda, LUA está ahí para ti.

Wolfgang Skyler
fuente
1
Supongo que la pregunta aquí es si el objetivo es hacer un juego o hacer algo que se vea bien en un currículum.
Tridus