Un nuevo juego con un ambiente antiguo en Three.js

Hay muchos fanáticos de los viejos juegos. Y no son reacios a dejar escapar una lágrima nostálgica y no, no, sino jugar "Arkanoid", "Pakman" o "Prince of Persia" como veinte, treinta, cuarenta o - sustituir el número deseado - hace años. DOS-box y emuladores, para ayudarlos. Sí, qué hay allí, recientemente vi la transmisión del primer "Prince of Persia" en 2D en YouTube, donde un streamer bastante joven, después de pasar otro obstáculo mortal, agitando el sudor de su frente con la mano, dijo: "Nunca me había asustado tanto en un juego de computadora ". Es decir, incluso los jóvenes pueden apreciar el hardcore y la frescura de los juegos antiguos.


Pensé, ¿por qué no crear un nuevo juego con un estilo similar? Sí, hay varios remakes y clones. Además, los juegos modernos en el estilo de pixel art deleitan. Sin embargo, todos ellos, por regla general, repiten misiones, mecánicas y, a veces, incluso diseñan por completo los juegos antiguos, en función de los cuales se hicieron. Bueno, o, por el contrario, ofrecen una trama y ubicaciones completamente nuevas, que es simplemente una estilización visual de "antigüedades". Pero, ¿qué pasa si te imaginas cuál sería la nueva parte del viejo juego si siguiera al último de la serie? Decidí crear uno.

Tomé un juego de plataformas en 2D y agregué gráficos en 3D allí, conservando la vista lateral clásica. Construyó nuevos laberintos, ideó nuevas misiones, introdujo tareas e implementó ranuras de inventario. Ligeramente diversificado la sensación de espacio, agregando giros de 90 grados. Quizás, en aquellos tiempos antiguos, antes de la transición total de los juegos en 3D con tres grados de libertad, algo así podría salir bien.

Como soy aficionado a escribir juegos para navegadores, decidí hacer un juego para el navegador. Debido a su especificidad, no tiene ningún número loco de polígonos, al menos se muestra en la pantalla al mismo tiempo, no hay un mundo abierto. Por lo tanto, todo esto no cargará mucho el navegador. Para mostrar gráficos en 3D, elegí mi biblioteca Three.js favorita (WebGL) con mi propio contenedor. No se utilizan otras bibliotecas, y el código está escrito en javascript puro.

Three.js y los problemas que encontré


Los desarrolladores de motores gráficos 3D periódicamente, aproximadamente una vez cada dos años, lanzan nuevas versiones de sus creaciones. En el caso de la biblioteca de scripts Three.js, los desarrolladores nos deleitan con actualizaciones con una frecuencia frenética, aproximadamente una vez al mes. Al momento de escribir, la última versión tenía el número 106. Parece que está bien. (No)

¿Por qué nadie piensa siquiera en la compatibilidad con versiones anteriores? Cuando los desarrolladores de Three.js cambiaron el nombre del entorno de propiedad de material, me di cuenta de que "Houston, tenemos problemas" . Bien, digamos que no fue difícil para mí en todo mi código cambiar la palabra "ambiente" a "color" con un reemplazo de búsqueda. Pero cuando descartaron la posibilidad de que una fuente de luz creara una sombra sin iluminación como tal, me di cuenta de que ahora el aterrizaje del Águila está en peligro real, y la base de Calm lentamente comienza a convertirse en la base de Rabia . Sin embargo, como resultó más tarde, no fue tan malo ...

El hecho es que en mi juego, además de la luz al horno, también se usa iluminación dinámica. El número de fuentes dinámicas en una escena 3D afecta en gran medida el rendimiento.


Elegí la cantidad de fuentes en la configuración del juego, de 1 a 7. Y dependiendo de la potencia de la tarjeta de video, puedes probar diferentes valores.

También hay una matriz que contiene las coordenadas y características de cada fuente: intensidad, color, etc. Funciona asi. Cuando se mueve por el mundo del juego en una determinada casilla alrededor del jugador, se enciende la cantidad de fuentes de luz especificadas en la configuración con las características especificadas. Es decir, las fuentes de luz parecen seguir al jugador (a su alrededor) por la nube.

Entonces, Houston, ¿cuáles son nuestros problemas? Yo informo.

Problema número 1: sombras


Las fuentes de luz crean sombras. Noté que las sombras de las fuentes de luz puntuales consumen muchos más recursos que las sombras dirigidas (luz puntual). Y esto es comprensible: en el caso de una fuente puntual, las sombras se proyectan en todas las direcciones y son direccionales, solo en un cono dado. Sin embargo, sugerí que cuando no se necesitan sombras en todas las direcciones, se pueden utilizar dos fuentes a la vez: un punto creará solo iluminación y uno direccional solo creará sombras en una dirección determinada. Esto es perfecto para mi juego y, como resultó, realmente, ahorra significativamente la potencia informática.


La pirámide limita el área en la que pueden aparecer sombras.

Pero aquí está el problema, comenzando con la versión three.js r73, una fuente de luz direccional ya no solo puede proyectar una sombra, ahora también proporciona iluminación. Y la luz de ella se extiende dentro del área, así como la sombra. Es imposible eliminar una fuente puntual y dejar solo una direccional: necesito iluminación en todas las direcciones. Y usar ambas fuentes, ajustándolas al brillo deseado, tampoco funciona: entonces los objetos dentro del cono se iluminarán mucho más. El uso de iluminación "honesta" con sombras en todas las direcciones afecta fatalmente el rendimiento del juego.

Y eliminaron la propiedad necesaria de una fuente de luz direccional .soloSombra, solo porque el autor del motor lo quería así.

Problema número 2: nombres de propiedad


Decidí que preferiría quedarme en la versión r71, donde la propiedad de iluminación que necesito todavía está presente. ¿Por qué no entonces r72? Después de todo, la propiedad desapareció solo en la versión r73. Porque ya escribí bastante código para cargar modelos 3D, animaciones y física para la versión r71. Y en la versión r72, ha cambiado una gran cantidad de nombres de propiedades: tipo - shadowMap se ha convertido en shadow.map, etc. En general, tampoco quería renombrar todo esto. Y la diferencia entre una versión es pequeña. Entonces, seguimos en la versión r71.

Problema número 3: asar sombras



La luz al horno en diferentes versiones del motor también se ve diferente. No sé qué están haciendo con él allí, pero al aplicar un mapa de sombras a la textura, el brillo e incluso el color cambian drásticamente. En general, de alguna manera resolví este problema sub burlándome del motor en código GLSL y configurando la corrección automática de color en el cargador de modelos 3D en aquellos lugares donde se usan mapas de sombras. Esto funciona, por supuesto, solo para la versión r71. Para otras versiones, tendrá que usar algunos otros parámetros. Esta es otra razón para permanecer en la versión r71.


En realidad, no tiene sentido cambiar a las últimas versiones, ya que el resultado del trabajo, en comparación con el anterior, no difiere fundamentalmente en términos de rendimiento.

Bueno Una fuente de luz direccional crea solo una sombra. Puedo hornear y cargar sombras en el ensamblaje en la versión r71. Y ahora, la emboscada más importante. Personajes

Problema 4: animación esquelética


Por eso luché durante mucho tiempo. En total, pasé un par de semanas tratando de encontrar algún tipo de algoritmo de trabajo para transferir un personaje con un conjunto de animaciones al juego.


Las versiones recientes de Three.js no tienen este problema. Allí creé con éxito un modelo de personaje animado en un conocido servicio en línea, lo convertí al popular formato gltf y lo subí a la escena de prueba. Sin embargo, si las nuevas versiones de Three.js usan el formato gltf 2.0, el mío solo es compatible con 1.0. Parece que cuál es el problema, bueno, convertir a 1.0 y descargar. Resultó no tan simple. Aparentemente, hay varias variaciones del formato gltf 1.0. Necesitaba uno donde, además del archivo del modelo principal, dos archivos más con la extensión * .glsl deberían estar presentes. Pero en este caso, el formato del archivo principal puede variar ... En general, no pude encontrar un convertidor que satisfaga todos los parámetros, especialmente porque también se convirtió del formato nuevo al antiguo. Tampoco pude terminar la versión anterior de three.js para el soporte de gltf 2.0: este soporte es demasiado profundo en el código, arraigado en matemáticas implementadas de manera diferente en diferentes versiones del motor ... En general, gltf de alguna manera no funcionó.

Intenté usar el formato .dae para modelos 3D. Como resultado, el modelo en sí se estaba cargando, pero no pude hacer que las animaciones de los personajes funcionaran correctamente. También hubo problemas con las texturas.

Resultó bien con el formato .md2. El personaje se mostró inmediatamente y todas las animaciones funcionaron correctamente. Pero, según tengo entendido, md2 es un formato modelo para Quake 2 y alguien implementó su soporte en Three.js solo por diversión. Y dónde encontrar modelos en este formato, y aún más, para diseñar y guardar mi propio personaje, no lo encontré.

Intenté algunos formatos más. Pero debajo de ellos, no había un gestor de arranque para three.js, no había programas para crear la preservación de su personaje en ellos, entonces no admitían la animación esquelética en absoluto.

La base "Rabia" fue la correcta para cambiar el nombre de la base "Desesperación".

Ya casi desesperado y pensando en cambiar a una nueva versión del motor a expensas del rendimiento (la historia de una fuente de luz direccional), decidí por última vez atormentar el formato json, con el que realmente comencé. Pero por primera vez, no pude repetir el proceso de convertir un personaje del archivo de ejemplo que vino en el paquete Three.js del formato original .blend a .json en el editor Blender 3D. Las animaciones se estropearon y se comportaron de alguna manera al azar, y con una docena de variaciones del exportador de Blender a json, todas funcionaron incorrectamente. Además, también los probé en varias versiones de Blender. El mismo JSONLoader, es decir, un cargador de modelos en formato json, ahora se ha eliminado de three.js. Decidí ver qué versión había dejado de apoyar, para llevarlo a él y a una muestra del modelo 3D no de mi versión, sino de la que todavía estaba. Ella resultó ser r88. Y he aquí! ¡Logré reproducir la exportación del modelo de prueba en r71 y todo, incluidas las animaciones de los personajes, funcionó bien en el juego!

"Eagle" aterrizó con seguridad.

Luego decidí editar una de las animaciones del personaje de prueba en Blender para ver si podía hacer la mía. Un fastidio me estaba esperando aquí. La animación que edité no quería funcionar en absoluto en el juego. El personaje se congeló en la posición inicial. Aunque otras animaciones funcionaron sin problemas. Pero esto es algo. Es decir, ahora el problema es mi ignorancia de algunos matices de edición de la animación.

Entonces pensé: ¿y si le pregunto al autor de este ejemplo cómo lo hizo? Pero llegar al autor no fue fácil. No tiene contactos personales en Github. Una búsqueda de un apodo y un par de parámetros más traídos a su Twitter, sin embargo, los mensajes privados se cerraron. Pero a partir de ahí supe que era profesor en alguna universidad estadounidense, y fui al sitio web de esta institución educativa. Resultó que el profesor estaba involucrado en gráficos 3D con sus alumnos, utilizando su ejemplo como material metodológico. Luego volví a Github y miré a través de todos sus repositorios. Aquí estaba esperando el éxito. Como esperaba, su ejemplo fue almacenado en un repositorio separado. Y no solo una copia de lo que ya he visto en los ejemplos de three.js, sino un ejemplo cuidadosamente provisto de instrucciones (aparentemente, para estudiantes). Descargué el archivo y, siguiendo las instrucciones, repetí todo. ¡Hurra!

¡Este es un pequeño paso para la humanidad, pero un gran salto para una persona y su juego!

¡No hay problema, Houston!



Ahora entiendo que si sigo este formato, estas instrucciones y estas versiones de Three.js, JSONLoader y Blender y hago todo de la misma manera, puedo crear y cargar cualquiera de mis personajes en el juego del navegador. La buena noticia es que, a pesar de usar la versión anterior del motor, puede usar la última versión del editor 3D Blender y crear cualquier personaje con animación. En ese momento, debe exportarlos de acuerdo con un esquema estrictamente definido utilizando este kit de herramientas específico.

Sí, noté un problema más con la nueva versión de Three.js: durante el juego, al desplazarse por la pantalla, por alguna razón, se observan frisos constantes. Y esto no se debe al aumento del consumo de recursos: el procesador y la tarjeta de video no se cargan al 100%. Y en el viejo r71 no hay tal desgracia.

Ahora solo queda hacer el juego en el editor de personajes 3D con animación. Y, por supuesto, la geometría de los niveles. No sé cuánto tiempo me llevará. Pero hasta ahora acabo de recopilar una versión demo gratuita en Webkit y la he subido a tiendas de aplicaciones populares.

Un poco sobre el juego.


Nombre Llamé al juego Percy Lancaster. Aquí todo es obvio: "Soy un artista y lo veo".

Cómo se crearon los gráficos . Creé dos planos en el editor 3D, los arreglé a una distancia el uno del otro para que el más alejado quedara oculto detrás del más cercano, les puse una textura de piedra, corté agujeros en el más cercano y luego eliminé las partes innecesarias, es decir, invisibles. Luego modeló los planos para pisos y techos. Entonces resultó ser un corredor para que el jugador caminara. Diversifiqué ubicaciones con varias texturas.


En el juego en sí no existe tal tipo, solo hay una vista lateral y no se notan espacios negros. Esta es solo una vista general del corredor.

Decidí crear corredores de intersección. Durante el giro, se completa una pared del otro corredor, gira toda la estructura y luego se retira la pared del primer corredor. Basado en esta mecánica, también planeo crear torres dentro de las cuales puedas subir la escalera de caracol.


Con gráficos estáticos, de hecho, no hay problemas, se exporta fácilmente a json desde cualquier editor 3D. Las dificultades, como ya mencioné, surgieron solo con sombras horneadas y animación de personajes.

Rendimiento En la resolución de pantalla HD, es decir, 1280x720, mi tarjeta gráfica GT-730 no tan potente se carga en aproximadamente un 35-40%, y el procesador Xeon E5440 se carga en aproximadamente un 30%. Creo que esto es más que un resultado aceptable.

OS Hasta ahora, la demostración solo está disponible en Windows como un ensamblado en Webkit. En el futuro planeo lanzar una versión de navegador. Me encontré con el hecho de que no todos los navegadores desplazan la pantalla sin problemas. Todavía necesito trabajar para administrar y llamar a la función de salida de gráficos. Mientras tanto, me decidí por Webkit versión 26.0. Ella pesa poco y todo funciona bien en ella.

El sonido Los sonidos se toman en parte de bibliotecas gratuitas, en parte se generan. En general, se han hecho hasta ahora, "ser". Si bien no me molesté mucho en ellos.

Video Nivel de demostración de pasaje completo.


Planes


Planeo ir a crowdfunding y contratar a un modelador 3D con el dinero recaudado, lo que creará un personaje normal y animaciones para él. Aún así, los gráficos no son míos. Pero ahora sé cómo presentar un personaje a mi juego.

Además, planeo lanzar una versión de navegador para las últimas versiones de Chrome y Firefox. Déjame contarte un secreto, incluso logré ejecutar el juego en MS Edge, pero por alguna razón no había objetos sobre los que se superpusieran las texturas de las sombras horneadas, aún no lo descubrí. A continuación, depuraré los navegadores para Linux y Android, y si obtengo dispositivos Apple para que alguien los pruebe, también para los navegadores en iOS y MacOS.

A la larga, escribir su propia biblioteca para trabajar con WebGL, como Three.js: no me gusta que renuncien bruscamente las propiedades y eliminen la funcionalidad que necesito. Por el contrario, la mayoría de las enormes oportunidades que ofrece Three.js no son necesarias.

Creo que más adelante, cuando descubra el funcionamiento correcto del juego para todos los navegadores en diferentes sistemas operativos, escribiré un artículo sobre esto con algunos detalles técnicos.

Source: https://habr.com/ru/post/468261/


All Articles