Devlog

Cómo hicimos Paper Drift: un juego para móvil con Godot

Devlog de Snowcode: cómo se hizo Paper Drift en Godot, con arte dibujado por código, una simulación determinista a 120 Hz y un validador que vuela cada nivel.

Por el equipo de Paper Drift en Snowcode Publicado 7 min de lectura Read in English

Un avión de papel rodeado de seis postales pegadas con cinta de los mundos de Paper Drift: Glaciar, Fundición, Selva, Alienígenas, Desierto y Almacén

Paper Drift lo hemos hecho en Snowcode con el motor Godot, y cada línea del juego está escrita en GDScript. No hay arte dibujado a mano: cada pliegue, cada sombra y cada borde de tinta lo dibuja el código. Debajo del papel hay una simulación determinista a 120 Hz que se juega exactamente igual en cualquier móvil, y un validador que vuela cada tramo del pozo antes de publicarlo para demostrar que se puede superar.

Este devlog cuenta cómo se hizo Paper Drift: cómo encajan esas piezas y lo que le contaríamos a otro equipo indie que quiera hacer un juego para móvil con Godot.

Por qué Godot y GDScript

Queríamos una base de código pequeña que exportara a Android y a iPhone y pasara todos sus tests desde la línea de comandos. Godot 4 cumple. Usamos la versión estándar, no la de .NET, con la versión exacta del motor fijada, porque el editor y las plantillas de exportación tienen que coincidir.

Dos decisiones tempranas lo marcaron todo:

  • Las escenas se construyen en código. Nuestros archivos de escena son esqueletos de tres líneas que cargan un script. Todo se coloca al arrancar según la zona segura de la pantalla, y un comprobador de diseño abre cada pantalla en cuatro proporciones, con Interfaz más grande activada y sin ella, y rompe la compilación si algo se sale.
  • La simulación no contiene tipos del motor. El código que decide dónde está tu avión y con qué choca nunca toca un nodo de escena. Por eso se puede probar sin abrir el juego, y por eso funciona lo que viene después.

Sin arte dibujado a mano: papel hecho con código

Un juego sobre papel tenía que parecer papel, así que convertimos el estilo en un sistema, no en un montón de imágenes.

El avión y todos los obstáculos son geometría vectorial dibujada por código, no sprites. Todos los menús salen de un único kit de papel: las tarjetas son hojas con un grano de papel muy suave, los diálogos llevan los pliegues de un avión de papel, los títulos de sección van impresos en cinta de carrocero, las pestañas están recortadas en cartón kraft y las misiones son tickets con su resguardo troquelado. Si cambias el kit, cambian todas las pantallas a la vez.

Hasta el choque es de papel: cuando acaba la partida, tu avión se arruga en una bola de unas 27 caras, cada una un trocito de su propia pintura girado hacia un lado, así que cada piel nueva tiene su bola arrugada sin código nuevo.

Un avión de papel arrugado en una bola llena de pliegues sobre una bola de cactus con raíces, con el saguaro del Desierto debajo
El choque, dibujado con la pintura del propio avión.

Las paredes también las generan scripts, con una regla muy estricta: nada del fondo puede parecer una viga. Una línea recta larga en una pared se lee como algo mortal, así que los generadores nunca la dibujan, y nunca hay dos ventanas a la misma altura de un lado a otro del pozo. Cada viga de verdad lleva la misma cinta roja de peligro, dibujada la última, sea cual sea el estilo del mundo. Una viga de cartón del Almacén puede cambiar su superficie, pero nunca su contorno ni su cinta.

Paper Drift: hecho con código
Todo en Paper Drift es código que dibuja papel doblado, y el juego vuela cada nivel antes de publicarlo.

Una simulación determinista a 120 Hz

La física de Paper Drift avanza a 120 pasos por segundo fijos, y lo que ves en pantalla se interpola entre los dos últimos pasos. Por eso el juego se ve fluido en una pantalla de 60 Hz, y por eso un fotograma perdido se nota como una pizca de cámara lenta y no como un salto.

La promesa difícil es otra: una partida se juega exactamente igual en cualquier dispositivo. Los fantasmas de Contrarreloj no son vídeos: son tus acciones grabadas, que una segunda copia de la simulación vuelve a volar paso a paso junto a la tuya. El Reto diario da a todos el mismo recorrido, y en Carrera los dos jugadores vuelan el mismo pozo. Todo eso se rompe en cuanto dos móviles no se ponen de acuerdo en un solo bit.

Aquí el enemigo son los números de coma flotante, porque la trigonometría y las potencias pueden redondear distinto según el procesador. Así que dentro de la simulación:

  • No hay senos, cosenos ni potencias. Salen de tablas guardadas en el repositorio, que se leen solo con sumas, restas, multiplicaciones y divisiones, exactas en cualquier chip.
  • No hay vectores de 32 bits. Los vectores estándar de Godot usan 32 bits, que recortarían la simulación sin avisar, así que cada posición es un número de 64 bits.
  • No hay temporizadores que acumulen. Un aturdimiento es un número de pasos, nunca un decimal que va bajando.
# Dentro de la simulación no existe sin(): la trigonometría sale de una tabla
# guardada en el repositorio y solo se opera con + - * /, así que cada móvil
# obtiene exactamente los mismos bits.
var s := Luts.sin_turns(phase)

Un test vuelve a jugar una partida fija y compara un hash del resultado con un valor de referencia. Si un cambio mueve ese hash, es que ha cambiado la jugabilidad, y hay que decirlo.

El validador: cada tramo se vuela antes de publicarse

El pozo es infinito, pero está hecho de tramos cortos de vigas, pistones, ventiladores y persianas, y un juego procedural vive o muere según lo justos que sean. Cada tramo pasa por un validador que lo vuela con la física real del juego, no con una copia. Comprueba cuatro cosas:

  1. Se puede volar desde cualquier sitio. Desde cada punto del hueco de entrada tiene que haber una salida, no solo desde el centro. Un tramo que funciona por el medio y te mata desde la pared izquierda mata a gente que no ha hecho nada mal.
  2. Perdona a un humano. Una segunda pasada lo vuela con un piloto que solo puede cambiar de idea cada 60 ms y con una caja de colisión un 6 % más grande.
  3. Siempre hay aviso. Cada obstáculo está en pantalla al menos 0,9 segundos antes de que el avión pueda alcanzarlo a velocidad máxima. Para cumplirlo, la cámara se aleja un poco a medida que aceleras.
  4. La geometría está limpia. Nada se mete más de unos pocos píxeles en una pared y no hay dos obstáculos solapados.

Todo eso lo hace con las dos simetrías de cada tramo, a tres velocidades desde el principio de una partida hasta la máxima, y con seis ritmos distintos de las piezas móviles, porque un pistón no reinicia su ciclo cuando llegas. Una pasada completa tarda hasta unos 24 minutos, y se puede repartir en trozos que corren en paralelo.

Ningún tramo se supera sin girar

Nuestro fallo favorito: el centro del pozo siempre estaba libre. La comprobación de huecos usaba la anchura del avión inclinado, pero un avión que cae recto es mucho más estrecho, así que los huecos se alineaban por el medio y podías pasarte casi todo el juego sin tocar la pantalla. Ahora el generador rechaza cualquier tramo con un pasillo recto hacia abajo, y dos tests lo vigilan. Tras arreglarlo, una partida sin tocar nada sacaba de media 4 puntos y nunca más de 6: solo los puntos gratis del tutorial y de los respiros.

Nada puede cerrar el pozo

Una persiana que se cierra del todo convierte sobrevivir en una lotería de en qué momento llegas. Así que nada se cierra: el hueco de una persiana nunca baja de 150 px, la guillotina mide 420 px en un pozo de 640 y los pistones se quedan a 500 px. Siempre hay por dónde pasar.

Dos rocas en llamas caen en la Fundición mientras un carril brilla arriba de la pantalla, y un avión de papel rosa las esquiva
El carril de una roca brilla arriba antes de que caiga: cada peligro se ve antes de poder alcanzarte.

Probar a los jefes como lo haría un jugador

Los seis eventos que te persiguen, del dron del Almacén al platillo de Alienígenas, apuntan a tu avión, así que el validador de tramos no puede comprobarlos. Tienen su propio test, que los vuela con la simulación real y exige tres cosas. Un piloto que simplemente esquiva tiene que sobrevivir desde cualquier punto del pozo, al principio de una partida y a velocidad máxima. Quedarse quieto tiene que acabar en golpe, o no es un peligro, es decorado con luces. Y cada peligro tiene que verse antes de poder alcanzarte.

Ese piloto vuela dos veces: una con 60 ms de retraso de reacción y otra viendo la pantalla 200 ms tarde. El segundo existe por culpa de un móvil. El piloto de 60 ms superaba a todos los jefes, y aun así al jugar en un teléfono llegó el aviso de que “algunos son imposibles de esquivar”. Un piloto que ve el mundo una quinta parte de segundo tarde es una persona, y ahora cada jefe tiene que dejarle pasar también a él.

El platillo de Alienígenas sube por debajo de un avión de papel en una sala morada, con su rayo tractor verde brillando al lado del avión
El rayo del platillo te atrae. Los pilotos de prueba también tienen que escapar.

Sonido y música

Los efectos de sonido los sintetiza un script a partir de ruido y tonos, sin ninguna muestra grabada. La música es nuestra: editada y arreglada en el estudio a partir de pistas generadas primero con Suno.

Lo que le diríamos a otro estudio indie

  • Convierte cada regla en un test. “Cada nivel exige girar” parecía evidente hasta que jugamos y encontramos una línea recta por el centro. Ahora un test lo comprueba en cada tramo.
  • Una comprobación que se salta su trabajo sin avisar es peor que no tenerla. Nuestro comprobador de diseño llegó a decir “sin errores” tras saltarse en silencio los paneles que tenía que revisar. Ahora un panel que falta es un error en sí mismo.
  • Diseña para el humano más lento, no para el mejor bot. Un piloto perfecto encuentra salida en cualquier cosa. El de 200 ms es el que te dice si el juego es justo.

El pozo te espera en tu móvil. Conoce a los seis cazadores en los jefes de Paper Drift, recorre los ocho mundos o encuentra material para medios en nuestra página de prensa.

Preguntas

¿Con qué motor está hecho Paper Drift?

Con Godot 4, la versión estándar, y todo el juego está escrito en GDScript.

¿El arte de Paper Drift está dibujado a mano?

No. En el juego no hay nada dibujado a mano. Cada pliegue, cada sombra y cada borde de tinta lo dibuja el propio código, y las texturas de las paredes las generan scripts.

¿Cómo sabéis que cada nivel se puede superar?

Un validador vuela cada tramo del pozo con la simulación real antes de publicarlo: desde cada posición de entrada, en las dos simetrías, a tres velocidades y seis ritmos distintos, más una pasada que simula 60 ms de tiempo de reacción y una caja de colisión un 6 % más grande.

¿Quién ha hecho la música?

La música es nuestra: editada y arreglada en el estudio a partir de pistas generadas primero con Suno.

¿Una partida se juega igual en todos los móviles?

Sí. La simulación es determinista, así que las mismas acciones dan la misma partida en cualquier dispositivo. Los fantasmas, el Reto diario y la Carrera dependen de ello.