Kabosu - Creando cosas
Publicado: 2025-01-05
Etiquetas: Godot, Inkscape, Juegos, Proyectos
En el artículo sobre juegos pequeños dije que había empezado a desarrollar un minijuego llamado Montonet. Durante las últimas 2 semanas le he dedicado algunos ratos más y finalmente ayer lo publiqué en mi página de itch.io. Fui dando pequeñas actualizaciones en Mastodon pero aquí no había mencionado así que aquí pongo un pequeño resumen de cómo fue el proceso.
Antes que nada definir lo que es un "montonet". El montonet es una broma que se hacía cuando yo era joven por la zona de Valencia donde me crié que consistía en, cuando había una persona tumbada en el suelo, el resto de personas se lanzaban encima al grito de "montonet! montonet!". La pobre víctima a lo mejor estaba durmiendo la siesta en la playa y de repente tenía 5 personas encima. He probado en varios buscadores no aparece prácticamente nada sobre montonets valencianos. En Google he visto un enlace a un tuit del Valencia Club de Fútbol que no he podido ver porque no tengo cuenta.
La idea del juego era plasmar un poco la esencia del montonet que son los cuerpos amontonados unos encima de otros.
Para sustituir a las naves que usé en el prototipo y que se pueden ver en el artículo enlazado arriba, dibujé 2 personajes con Inkscape. Les puse colisiones y sustituí a las naves. Con esto el juego ya era un poco más entretenido porque la forma de los dos personajes se podía combinar bien para hacer diferentes montonets. No como las naves que eran triángulos.
Para hacerlo un poco más interesante quería calcular cuál era la altura del montonet para guardar el récord y motivar un poco para intentar superarlo. Como la posición vertical 0 está arriba, había que buscar la menor posición ocupada por un cuerpo.
Me costó un rato descubrir cómo hacerlo en Godot. Lo más sencillo era buscar entre todas los nodos de personas cuál era el que tenía una coordenada Y menor pero, como los cuerpos pueden rotar por las físicas, no daba un resultado exacto. Estuve investigando un rato pero no encontré nada interesante. Para físicas 3D parece que hay algo llamado AABB que da me darías las coordenadas "bounding box" pero yo estaba usando 2D y no vi nada similar.
Al final se me ocurrió una idea bastante buena en mi inexperta opinión: crearía un objeto con volumen (llamado Limit) que pondría arriba del todo de la pantalla y lo iría bajando hacia abajo hasta encontrar el punto en el que colisionaba con algo. La posición Y de Limit al colisionar sería la altura del montonet. El segundo parámetro de la función move_and_collide
se puede poner a true
para que simule el movimiento del objeto y diga si colisionaría o no.
Para saber hasta dónde tenía que mover a Limit implementé una búsqueda binaria. Empezando con el intervalo entre la posición -1000 y la posición Y de la plataforma, iba dividiendo el intervalo entre 2 mirando si move_and_collide
devolvía null (no colisión) o devolvía un objeto (colisión). Esto me daba la posición exacta en la que poner la línea de Limit y por tanto la altura.
Usé este algoritmo durante unos días y funcionaba muy bien pero me parecía poco elegante. Seguramente había alguna forma de calcular el objeto que estaba más arriba con alguna función de Godot pero yo no la encontraba. Me puse a escribir un mensaje para pedir ayuda en el foro de Godot. Estuve una hora haciendo capturas de pantalla, explicando mi solución, revisando el texto una y otra vez... Quería estar seguro de que no me estaba dejando ningún detalle para que no me dijeran que soy tonto. No llegué ni a publicar la pregunta porque efectivamente soy tonto y había pasado por alto que move_and_collide
devuelve un montón de información. En concreto, esa función intenta mover el objeto y si colisiona devuelve la posición en la que se ha quedado bloqueado. Era justo lo que necesitaba. En vez de hacer estar probando diferentes posiciones simplemente tenía que llamar a move_and_collide
intentando avanzar hacia la plataforma de abajo. Si devolvía null es que no había ninguna persona por el camino. Si devolvía otra cosa podía inspeccionar el resultado y sacar de ahí la posición Y que sería la altura del montonet. No había falta búsqueda binaria ni nada.
En un principio bastaba con pulsar el botón izquierdo del ratón para dejar caer una persona pero luego añadí el botón derecho que servía para girar el cuerpo antes de lanzarlo. Esto permitía optimizar más lo montonets y hacía ligeramente más fácil alcanzar altura. Esto hizo que muchas veces terminara haciendo montonets que se salían por arriba de la pantalla.
Para poder seguir jugando cuando el montonet alcanzaba la parte de arriba de la pantalla quería que la cámara se alejara poco a poco a medida que se alcanzaba altura para mostrar siempre todos los cuerpos. Necesité varias horas de prueba y error hasta encontrar unas fórmulas que funcionaran decentemente.
No me termina de gustar cómo funciona el zoom ahora porque se va haciendo todo más pequeño cada vez y se ve mucho espacio debajo de la plataforma azul que no aporta nada como se puede ver en la captura siguiente. Intenté que al hacer zoom también se moviera la cámara ligeramente hacia arriba para compensar pero no conseguí que funcionara bien del todo así que lo quité.
Dediqué una tarde a hacer una pantalla de título con el logo del juego y a guardar la mayor altura conseguida. Con esto ya di por finalizado el juego. No quería gastar mucho más tiempo.
Subí el juego a itch.io y publiqué un mensaje bastante seco en Mastodon anunciándolo.
Puedes jugar a Montonet con tu navegador aquí.
Me sorprendió que inmediatamente la gente empezó a dar al "me gusta" y a compartir el anuncio. En unas horas casi 100 interacciones en Mastodon y la gente estaba comentando sus mejores puntuaciones. No esperaba que le fuera a interesar a nadie. Las métricas de itch.io también indican que fue bastante exitoso. Más de 150 visitas a la web del juego y más de 60 personas que lo han jugado en 24 horas. No me puedo quejar para haber sido una pequeña prueba con la que aprender a usar las físicas de Godot.
Si llego a saber que iba a despertar tanto interés lo hubiera pulido un poco más antes de lanzarlo.
Es jugable pero hay un montón de cosas que están sin hacer: el juego no tiene fondo, los muñecos eran un dibujo provisional que luego pensaba cambiar pero nunca hice, la cámara no me gusta nada, los récords no se guardan si reinicias el juego... y lo peor es el juego con pantalla táctil. Se puede jugar en un teléfono pero al no haber botón derecho no se puede rotar al personaje. Tampoco puedes ver cuál es el siguiente muñeco que va a salir porque se muestra en el cursor del ratón y no hay cursor en pantallas táctiles.
En principio este era una juego de aprendizaje y, siguiendo las "normas" de los juegos pequeños solo iba a trabajar en él durante un par de semanas para luego abandonarlo completamente así que no pensaba tocarlo más pero el administrador de la instancia TKZ.one de Mastodon me preguntó si podía incluir el juego en los extras de la web. Preguntaré a ver si de verdad está interesado y, si es así, le haré una nueva versión puliendo alguna cosa pero tampoco quiero dedicar mucho más tiempo al juego.
Como comenté en el artículo de juegos pequeños, quería experimentar y aprender sobre 4 partes de Godot que nunca había probado: físicas 2D, internacionalización, navegación y juegos 3D. Con Montonet creo que ya me he familiarizado un poco sobre el primer ítem de la lista. Ahora tengo que pensar proyectos sencillos con el resto.