Este material continúa una serie de publicaciones basadas en los informes que hicimos en la conferencia Games Gathering 2017 en diciembre pasado. En uno de los
informes , se planteó el tema de elegir un lenguaje de script integrado.

¿Qué es y por qué se necesitan lenguajes de script?
Como ya se mencionó en la
publicación anterior de nuestro blog , nuestra compañía ha escrito su propio motor. Hoy hablaremos sobre lo que nos guió al elegir un lenguaje de script para este motor.
¿Por qué hay una necesidad de lenguajes de script? Como dice el refrán,
"en la industria del juego no hay problemas complejos, no hay necesidad de exigir soluciones complejas" . Además de programadores experimentados (¡y caros!) Que resuelven problemas complejos, necesitamos personas (¡muchas personas!) Que se involucrarán, por ejemplo, en misiones. Y, para ser sincero, nos gustaría que estos programadores no sean tan caros, e idealmente no sean programadores en absoluto, sino directamente diseñadores de juegos y guionistas.
Por lo tanto, existe la necesidad de una herramienta para describir la lógica simple, pero lógica, sin involucrar artillería pesada por parte de los programadores. Concluimos: ¿qué es un lenguaje de script para nosotros? Esta es una herramienta que hará que el desarrollo del juego sea más rápido y económico.
La pregunta surge de inmediato, ¿por qué no usamos algo como XML? El hecho es que para nuestros propósitos a menudo necesitamos estructuras de control: ramificación y bucles, mientras que XML es una descripción declarativa.
Otra ventaja de los lenguajes de scripting es que los scripts en un proyecto pueden ser código o un recurso. Y, en consecuencia, la parte del script del juego se puede actualizar no solo con el código, es decir, durante las actualizaciones periódicas a través de los mecanismos de las tiendas de aplicaciones. Pero también con recursos, es decir, junto con gráficos y otros materiales que utilizan CDN.
Requisitos perfectos del lenguaje de programación
Formulamos los requisitos para un lenguaje de script ideal.
- Dinámica A nuestro entender, un lenguaje de script ideal debería ser dinámico.
- Popularidad. Por popularidad de un idioma, nos referimos a la presencia de una comunidad suficientemente grande lista para responder preguntas sobre recursos especializados como StackOverflow.
- La suave curva de aprendizaje. Queremos tomar, en términos relativos, prácticamente a cualquier persona, y entrenarlo rápidamente a un nivel que le permita a esta persona trabajar productivamente en nuestras tareas.
- Amplias oportunidades. El lenguaje debe ser poderoso y tener suficientes características, debe admitir diferentes paradigmas de programación. Un programador profesional al que se le ofrezca escribir en ese idioma podrá hacerlo con comodidad y placer.
- Alto rendimiento El rendimiento es uno de los pilares de la industria del juego.
- Una gran cantidad de bibliotecas. Muy a menudo, en el curso de la resolución de las tareas que enfrentamos, no creamos un código fundamentalmente nuevo, sino que usamos lo que otra persona ya ha escrito. Las bibliotecas más estables y con mejor soporte que podamos usar usando un determinado idioma, mejor.
- Fácil de empotrar. Estamos hablando de lenguajes incrustados, por lo que al elegir un lenguaje de secuencias de comandos, la capacidad de incrustarlo juega un papel importante.
Analicemos algunos lenguajes de programación populares que se utilizan como scripts para cumplir con estos requisitos.
Pitón
Python es un lenguaje dinámico que es muy popular. Se caracteriza por una curva de aprendizaje bastante suave, es bastante simple de aprender. Sin embargo, estudiarlo adecuadamente no debería ser tan fácil. Como resultado, los buenos programadores de Python son raros y caros. Esto contradice nuestro deseo de acelerar y reducir el costo de desarrollar la lógica del juego.
Python tiene excelentes características y buen rendimiento. Su problema es un sistema de biblioteca inconsistente. Otro de sus problemas, que juega un papel importante para nosotros, es que él, de hecho, no es un lenguaje incrustado. Este es un lenguaje desde el cual es conveniente llamar a las bibliotecas escritas en C o C ++.
Con respecto a las capacidades de incrustación de Python, podemos decir que, por ejemplo, existe Maya, donde se usa Python. Pero cualquiera que haya visto los complementos de Python para Maya desde adentro estará de acuerdo con nosotros en que no se ven muy bien.
Como resultado, podemos decir que Python, a pesar de todas sus fortalezas, no nos conviene. Ahora considere JavaScript.
Javascript
JavaScript es, sin exagerar, un gran lenguaje que literalmente se ha apoderado del mundo.
JavaScript es un lenguaje dinámico popular, caracterizado por una curva de aprendizaje suave, con características ricas, buen rendimiento y un amplio conjunto de bibliotecas.
Si necesitamos un intérprete de idiomas para construir un motor de juego, podemos encontrar muchos de estos intérpretes. En realidad, debe elegir entre dos proyectos de este tipo: V8 y WebKit. Tanto eso como otro tienen tamaños bastante grandes. Como resultado, si hablamos de juegos de mesa, podríamos arriesgarnos e incluir a todo el intérprete en el juego, pero en el caso de los juegos móviles, esta opción no nos conviene.
SocialQuantum tiene su propio intérprete de JavaScript, que pasa el 98% de las pruebas, planeamos transferir este proyecto a la categoría de código abierto.
Como resultado, resulta que JavaScript parece un fuerte candidato para el papel de un lenguaje incrustado, pero tampoco nos conviene.
Haxe
Cabe señalar que cuando se trata de hablar sobre JavaScript, los siguientes generalmente recuerdan a Haxe. Pero, de hecho, no tiene sentido hablar de la posibilidad de usar este lenguaje como un lenguaje incrustado, ya que Haxe, de hecho, no es tanto un lenguaje como un compilador trans a otros idiomas. Y esto no es lo que necesitamos.
¿Quizás estamos satisfechos con ActionScript o algún otro lenguaje de script?
ActionScript
Si analizamos formalmente ActionScript para el cumplimiento de los requisitos anteriores, puede parecer que se ha encontrado el lenguaje de script ideal. De su lado están la naturaleza dinámica, popularidad, facilidad de estudio, buenas características, rendimiento, disponibilidad de bibliotecas, facilidad de integración. Este lenguaje es amado y recordado en la industria del juego, está escrito en una gran cantidad de maravillosos juegos Flash. El principal problema con ActionScript es que este lenguaje está casi muerto. Por lo tanto, tampoco nos conviene.
AngelScript, Squirrel y otros
Además de ActionScript, hay muchos lenguajes de script como AngelScript, Squirrel y otros. Entre ellos puede encontrar aquellos que, formalmente, satisfacen casi por completo nuestros requisitos, pero generalmente son lenguajes vinculados a su desarrollador, tienen algunos problemas antiguos que no se han solucionado durante años. Lo más probable es que no sean muy populares, no estén bien documentados, hay pocos materiales de capacitación sobre ellos, no tienen comunidades muy grandes. Una de las consecuencias de este estado de cosas es el hecho de que son difíciles de estudiar, aunque solo sea porque no está completamente claro, qué son y cómo funcionan.
Como puede ver, todavía no hemos encontrado el lenguaje integrado ideal. ¿Qué pasa si creas tu propio idioma?
Crea tu propio idioma
Es posible que el lenguaje desarrollado dentro de la empresa se ajuste idealmente a sus necesidades y sea fácil de aprender. Pero, muy probablemente, ese lenguaje no se hará popular. Tal lenguaje tendrá un número mínimo de bibliotecas o no existirá en absoluto. Además, es difícil creer que en las condiciones modernas es posible crear algo que funcione mejor, que tenga una mayor productividad y sea más fácil de integrar que algo que ya está en el mercado.
Hay empresas que desarrollan y usan sus propios idiomas, entre ellas hay jugadores exitosos en el mercado de juegos, pero lo más probable es que no sea una buena idea.
Habiendo examinado los lenguajes de programación existentes que dicen estar integrados y discutido la idea de desarrollar nuestro propio lenguaje, pasemos a Lua.
Lua es el lenguaje incrustado que hemos elegido
Lua es un lenguaje dinámico. Es bastante popular, una gran comunidad se ha desarrollado a su alrededor, especialmente en el campo del desarrollo de juegos. Tiene una curva de aprendizaje muy suave. Por ejemplo, en nuestra empresa, los scripts para autotests están escritos en Lua. Un curso introductorio estándar para pruebas automáticas dura aproximadamente dos horas, después de lo cual una persona puede usar este idioma. Al mismo tiempo, Lua es un lenguaje multi-paradigmático. Es compatible con un estilo funcional de programación y POO. Como resultado, es adecuado no solo para resolver algunas tareas simples, sino también para asuntos más serios que hacen los programadores profesionales.
Lua tiene un buen rendimiento y tiene bastantes bibliotecas. No tanto como JavaScript, pero, sin embargo, en el
sitio web de
LuaForge puedes encontrar casi cualquier cosa que necesites. Y finalmente, Lua es muy fácil de integrar, además, fue creado para ser utilizado como un lenguaje integrado.
Por ejemplo, así es como se ve
nuestro espacio de trabajo JetBrains IDE
CLion . Aquí puede ver el mecanismo de autocompletado creado por nosotros para Lua, que planeamos hacer de código abierto. Vamos a hacer un depurador de código abierto.
Ambiente de trabajoElegimos Lua, pero cuando se trata de usarlo como un lenguaje de secuencias de comandos incrustable, generalmente te encuentras con las mismas objeciones que ahora consideraremos.
Objeciones al uso de Lua
Lua es para C, no para C ++
Nadie argumenta que Lua es un gran lenguaje incrustable. Lo principal que consideran un inconveniente es que se creó para usar con el lenguaje C, y no con C ++. Debido a esto, cuando intentamos aplicar algo en Lua que está en C ++ y no en C, nos encontramos con problemas. Sin embargo, uno debe entender aquí que estos problemas fueron resueltos por muchas personas bastante inteligentes. Entre las herramientas que resuelven los problemas de incrustar Lua en C ++ se encuentran proyectos, como Luabind, Luabridge, toLua ++, SQLuaHost. Esta no es una lista completa. Tienen diferentes ventajas y desventajas, pero, sin embargo, lo más probable es que todo lo que pueda necesitar ya esté implementado en una de estas soluciones.
Considere, por ejemplo, SQLuaHost. Este es un enlace que se realiza dentro de SocialQuantum y que está previsto que sea de código abierto. Esta decisión representa nuestra visión de cómo Lua debería unirse. Por lo tanto, es muy posible que si no encuentra lo que necesita en las carpetas existentes, lo encontrará en SQLuaHost.
Lua es lenta
A menudo nos encontramos con la opinión de que Lua es un lenguaje muy lento. En primer lugar, esto no es así. Lua es una máquina apilada, y realmente no hay nada para frenar allí. Además, debemos entender que en el lenguaje de programación generalmente regalamos lógica de juego, lógica de negocios y no algunas cosas realmente pesadas. Como resultado, si los scripts de Lua hacen que el juego se ralentice, entonces el problema puede deberse a un enlace subóptimo o al uso inapropiado de algunas características del lenguaje. Por ejemplo, realizamos pruebas sintéticas en las que LuaJIT es más rápido que Mono. Al mismo tiempo, nadie se molesta en escribir sobre ese código no óptimo:
function myGame:onUpdate() local tex = Texture::new(name) self.background:setTexture(tex) end
Aquí, en cada tic del juego, se crea una nueva textura y se establece como fondo. Por supuesto, tal diseño no funcionará especialmente rápido, pero nadie se molesta en escribir tales cosas.
Lua solo es adecuado para pequeños proyectos.
La siguiente objeción es que Lua está hecha para escribir algunas cosas pequeñas y algo grande no se puede escribir en este idioma. Por un lado es verdad. Pero este lenguaje es altamente modular. Y a partir de los muchos bloques pequeños puede hacer sistemas bastante grandes y complejos. Y si recuerda lo que ya se ha dicho sobre multiparadigmness y OOP, resulta que OOP alienta al desarrollador a crear pequeños módulos que se pueden usar para crear estructuras grandes y complejas.
Además, a menudo en Lua, algunos módulos pequeños se escriben rápidamente, y en la industria del juego "más rápido" significa "más barato".
Otros argumentos contra Lua
Al criticar a Lua, dicen que el lenguaje es antiguo, que, como dicen, "listo para usar" no admite OOP, que la numeración de elementos en sus tablas no comienza con 0, como cabría esperar de cualquier lenguaje decente, sino con 1)
Dicen que su menos es que no tiene un operador ternario. De hecho, hay bastantes argumentos en contra de Lua, pero no los discutiremos, ya que creemos que, en su mayor parte, se relacionan con los hábitos y las preferencias personales de los desarrolladores.
Resumen
Para resumir. Si su tarea es obtener un lenguaje incrustado con el mínimo esfuerzo, tome Lua. Al mismo tiempo, si tiene el tiempo y los recursos para desarrollar su propio idioma o sus propios enlaces, nuevamente, preste atención a Lua. ¿Por qué recomendamos Lua tanto en el primer como en el segundo caso?
En el primer caso, al elegir Lua, elegirás un idioma que sea muy fácil de insertar y usar. Hay exactamente un
tutorial sobre este idioma escrito por su autor. No hay otros libros simplemente porque el primero dice absolutamente todo lo que necesitas saber sobre Lua, y no hay nada más que contar al respecto. Lua no es un idioma ideal o el idioma más extendido en el mundo, pero, por la suma de los criterios, definitivamente es uno de los mejores idiomas para incrustar. Él es el mejor que tenemos en este momento. Además, hay muchas herramientas estándar para Lua que simplifican enormemente la vida de quienes lo usan.
En el segundo caso, si tienes los recursos para desarrollar herramientas, elegir Lua realmente puede gastar estos recursos, ya que Lua, a pesar de su popularidad en el entorno de desarrollo de juegos, el lenguaje está muy subestimado. Como resultado, tendrá la oportunidad, tomando a Lua como base, de tener en cuenta sus necesidades y obtener exactamente lo que necesita.