¡Buenas!, les quería compartir un resumen de los avances que pude realizar estos últimos 15 días con respecto a pilas-engine.
Me pareció buena idea mostrarlo por aquí para darle visibilidad y que puedan conocer una fase mucho más interna de la evolución de pilas. Además, me parece una oportunidad única para invitarlos a participar en el desarrollo y sumar ideas !!!
Cómo les comentaba en otro post, estamos aventurándonos en implementar la versión 2 de pilas-engine usando tecnologías web, y si bien queda mucho por delante, ya estamos dando pasos muy importantes.
Les dejo un resumen de los avances:
Pasamos de Phaser CE 2 a Phaser 3
Este fue uno los cambios más grandes de estos días. Les diría que fué lo más laborioso de todo: en pilas-engine 2 estábamos usando la versión estable de Phaser 2, ya que nos permite dibujar en pantalla, emitir sonidos, manejar escenas, realizar simulaciones físicas y más.
Resulta que mientras estaba haciendo los primeros bocetos de pilas-engine 2 (a mediados del 2017), la versión más reciente de Phaser era la versión 2, y si bien el equipo de desarrollo de Phaser estaba trabajando en la versión 3, en esos días no había algo realmente “usable” como para invertir tiempo en usar Phaser 3.
Ahora bien, la evolución del desarrollo de Phaser fue impresionante. Phaser avanzó tanto, que hace menos de un mes se publicó la versión 3 de Phaser (Welcome to Phaser 3 - Phaser3 - Phaser), con muchísimas mejoras: hicieron un motor de dibujado completamente desde cero (super rápido), implementaron un motor de física llamado matter-js (Matter.js - a 2D rigid body JavaScript physics engine · code by @liabru), un sistema de escenas múltiple, partículas, animaciones, fuentes tipo bitmaps etc…
Y con eso me surgió un dilema importante: esperar unos meses a que Phaser 3 madure un poco más o aprovechar el boom del lanzamiento y migrar lo que tenemos de pilas-engine 2 a Phaser 3 desde ahora.
Elegí lo segundo
La buena noticia es que puede migrar todo a Phaser 3 en este sprint, me llevó como 20 commits y muchas pruebas y errores. Phaser 3 es super diferente a Phaser 2, pero desde el primer momento se nota que es mucho más rápido y fácil de integrar a pilas. Parece el movimiento correcto de cara al futuro de Pilas.
Lo malo de Phaser 3 es que aún continúa en desarrollo, así que le faltan ejemplos y documentación para comprender mejor su estructura. Sin embargo, leyendo el código y preguntando el foro de Phaser se puede avanzar bien.
Les dejo el link a la versión más reciente por si quieren hacer pruebas:
También generé las versiones binarias de la aplicación, para usar de forma offline:
Creando un sistema de animaciones básico
Para crear animaciones me pareció buena idea simplificar un poco la forma de crear animaciones que teníamos en pilas 1.
Decidí no replicar exactamente lo mismo que teníamos en aquella versión, sino resolverlo con dos funciones. Así que definí dos métodos nuevos llamados “crear_animación” y “reproducir_animación”.
El método “crear_animacion” se puede llamar especificando el nombre de la animación, los cuadros que se deben mostrar y la velocidad.
Por ejemplo, para crear una animación de un actor mientras está esperando usé lo siguiente:
this.crear_animacion("conejo_parado", ["conejo_parado1", "conejo_parado2"], 2);
El valor “2” significa que la animación se debe mostrar a una velocidad de 2 cuadros por segundo.
Luego, una vez creada la animación, se puede reproducir usando esta llamada:
this.reproducir_animacion("conejo_parado");
Posiblemente más adelante la cambiemos por algo mas sencillo cómo this.animacion = "conejo_parado"
, pero aún no estoy muy seguro, es para investigar pros y contras.
Autómatas y estados para actores
Un desafío muy común en el desarrollo de juegos es lograr que los actores puedan mostrar animaciones y reaccionar de acuerdo a modos particulares: saltar, caminar, quedarse parado, pediendo etc…
Así para para este sprint armé un sistema de estados muy simple, pensado para simplificar mucho este tipo de necesidades.
¿Cómo funciona?, imagina que necesitamos crear un actor que pueda caminar, saltar o quedarse parado. Esta es una forma muy gráfica de representar cómo queremos que se comporte en la escena:
Lo ideal es lograr que el código de cada estado quede separado de los demás, sobre todo si queremos agregar estados nuevos más adelante o corregir algún error.
Todos los actores en pilas tienen un método “iniciar” y “actualizar”, como en pilas 1, pero ahora se agrega el atributo “estado” y la posibilidad de crear un método “iniciar” y “actualizar” por cada estado.
Por ejemplo, si asignas un valor al atributo “estado” como “parado”, pilas buscará llamar al método “parado_iniciar” y “parado_actualizar” para que ahí puedas tener el código de ese estado. Algo así:
Y a su vez, si queres crear más estados, como “camina” o “salta”, simplemente tienes que asignar un valor al atributo “estado” y luego crear dos métodos para cada estado “camina_iniciar”, “camina_actualizar” y “salta_iniciar”, “salta_actualizar”.
Con esto podemos simplificar muchísimo el código de los actores, no hay necesidad de crear muchas variables como “debe_caminar” o “esta_saltado” ni tener que incluir muchas sentencias “if” para prevenir que se nos mezcle la lógica de cada estado.
En la siguiente tarea les cuento un ejemplo que armé usando esto.
Versión inicial del motor de física con colisiones
Aprovechando la adaptación a Phaser 3, comencé a investigar cómo funciona “matter-js”, uno de los motores de física que incluye Phaser.
Encontré varias cosas interesantes, por un lado, pude integrar controles para controlar la figura física del actor seleccionado. Una idea que había comentado Jorninur en el foro:
También encontré que “matter-js” tiene un gestor global de colisiones, así que pude simplificar mucho la interacción de los actores con respecto a las colisiones.
Ahora los actores pueden definir 3 métodos para detectar colisiones fácilmente:
- cuando_comienza_una_colision
- cuando_se_mantiene_una_colision
- cuando_termina_una_colision
Estos 3 métodos se van a invocar automáticamente cuando se produzca una colisión.
Por ahora es un sistema muy básico, pero creo que con un poco de esfuerzo podríamos mejorar mucho este mecanismo para permitirle a los usuario hacer cosas como estas:
cuando_colisiona(otro_actor) {
if (otro_actor.etiqueta === "moneda") {
puntaje.aumentar()
otro_actor.eliminar()
this.pilas.emitir_sonido("coin");
}
}
Es decir, eliminaríamos la necesidad de tener una llamada a “pilas.colisiones.agregar” y variables para referirnos a los actores como grupos o etiquetas.
Creando el actor Conejo
Armé un actor nuevo para ilustrar cómo usar el sistema de animaciones, estados y colisiones. El resultado me pareció bastante bueno, pude hacer que el actor se controle con el teclado, puede caminar, saltar y pisar plataformas.
¡Aquí les dejo una animación del actor en movimiento!
Por cierto, ¿notaron el detalle de las cajas?: con alterar el atributo “figura_dinamica” podemos convertirlas en plataformas estáticas.
Lo que viene en el Sprint #2
Esta semana vamos a encarar algunas tareas super importantes:
-
Quiero reunirme con varios chicos del equipo de pilas para coordinar y armar juntos un plan de desarrollo y documentación que nos ayude a mejorar el proyecto. Así que la semana próxima, o la otra, tengamos algunas buenas novedades para contarles al respecto.
-
Me gustaría documentar los primeros pasos para usar el editor y documentar estas nuevas características (animaciones, autómatas y física). Creo que si vamos documentando poco a poco nos va a resultar más sencillo que escribir todo al final.
-
Tengo pendiente seguir investigando matter-js, creo que podríamos lograr que el motor de física dibuje la posición de los objetos incluso en el modo edición. Ahora si o si se tiene que pulsar “ejecutar” para ver qué objeto tiene física y que forma le corresponde.
¡Nos vemos!