La Regla de los 3 Segundos en Plataformas: Coyote Time y Jump Buffering

Hace unos años, mientras desarrollaba mi tercer minijuego de plataformas en HTML5, me encontré con un problema frustrante: los jugadores saltaban en el momento exacto en que sus pies dejaban la plataforma y, aun así, el salto no se registraba. El personaje caía. La maldición de todo desarrollador indie de plataformas. Fue entonces cuando descubrí que no estaba solo en este problema, y que existía una solución elegante: Coyote Time y Jump Buffering.

Estos dos conceptos, aparentemente simples, son la diferencia entre un juego que se siente "injusto" y uno que se siente "pulido". No es magia, es matemática. Es física de juego. Y después de implementarlos en varios proyectos propios, puedo decir que son de las herramientas más subestimadas del diseño de plataformas modernos.

¿Qué es Coyote Time? El Perdón de 3 Fotogramas

Imagina esto: estás en una plataforma. Te acercas al borde. Presionas salto exactamente cuando tus pies dejan de tocar el suelo. En la mayoría de motores sin pulir, el salto no ocurre porque técnicamente ya no estás en el suelo.

Coyote Time es la solución. Es una ventana de tiempo, generalmente de entre 100 y 150 milisegundos (aproximadamente 6 fotogramas a 60 FPS), durante la cual el jugador puede saltar incluso después de haber dejado la plataforma. El nombre proviene del Correcaminos de la caricatura: como el coyote que corre fuera del acantilado sin caer inmediatamente, el jugador tiene un pequeño margen antes de que la gravedad lo reclame.

video game developer coding screen

Técnicamente, lo que ocurre es esto:

  • Frame 0: El jugador está en el suelo. isGrounded = true
  • Frame 1: El jugador se mueve hacia el borde. Aún en el suelo.
  • Frame 2: El jugador deja la plataforma. isGrounded = false
  • Frames 3-8: Coyote Time activo. El jugador puede saltar como si estuviera en el suelo.
  • Frame 9: Coyote Time expira. Adiós al salto.
  • ¿Por qué funciona esto? Porque los humanos no somos máquinas de precisión. Nuestro tiempo de reacción ronda los 200-300 milisegundos, según distintas estimaciones. Si el juego requiere que presiones salto en el mismo frame exacto en que abandonas la plataforma, estás pidiendo perfección sobrehumana. Coyote Time reconoce esto y añade clemencia.

    Jump Buffering: Anticipar la Intención del Jugador

    Ahora, imagina otro escenario: estás saltando sobre una serie de plataformas pequeñas. Presionas salto mientras aún estás en el aire, anticipando que aterrizarás en la siguiente plataforma. En un juego sin pulir, ese input de salto se pierde. En uno pulido, en cambio, se "recuerda".

    Jump Buffering es exactamente eso: un buffer que almacena el comando de salto durante los últimos 50-100 milisegundos antes de que el jugador toque el suelo. Si presionas salto mientras estás en el aire, pero aterrizas antes de que expire el buffer, el salto se ejecuta automáticamente.

    Esto elimina la sensación de que el juego no "entiende" lo que quieres hacer. Es una forma de decirle al jugador: "He visto tu intención. Espera un momento y la ejecutaré."

    La Implementación Técnica

    En JavaScript/HTML5, esto se vería algo como esto conceptualmente:

    Variables necesarias:

    • coyoteTimer: contador que se decrementa cada frame
    • coyoteTime: valor máximo (típicamente 6 frames a 60 FPS)
    • jumpBufferTimer: contador para el buffer de salto
    • jumpBufferTime: valor máximo (típicamente 6 frames)
    • Lógica principal:

      Si el jugador está en el suelo, resetea coyoteTimer a su valor máximo. Cada frame, decrementa coyoteTimer. Si el jugador presiona salto y (coyoteTimer > 0 O jumpBufferTimer > 0), ejecuta el salto y resetea ambos timers a cero.

      Lo bueno de este enfoque es que es agnóstico del motor. Funciona en Unity, Godot, Phaser, o tu propio motor casero en JavaScript puro.

      pixel art platformer character jump animation

      Datos Verídicos: ¿Cuánto Tiempo es Suficiente?

      Aquí es donde los datos importan, aunque conviene tomarlos como orientación y no como leyes fijas. A través de análisis de juegos conocidos y de mi propia experimentación, los rangos que suelen funcionar bien son los siguientes.

      Para el Coyote Time, lo habitual se mueve entre 100 y 150 milisegundos (unos 6-9 frames a 60 FPS), lo que produce una sensación justa y permisiva; es el enfoque que se percibe en juegos como Celeste o Hollow Knight. El Jump Buffering, por su parte, suele quedarse en un rango más corto, de 50 a 100 milisegundos (3-6 frames), aportando esa sensación receptiva y anticipatoria que se nota en títulos como Super Meat Boy o Cuphead. Cuando ambas mecánicas se combinan, el total ronda los 150-250 milisegundos, y es habitual encontrarlo en juegos especialmente accesibles como Ori o Gris.

      La investigación de Adam Robinson-Yu (desarrollador de Celeste) fue crucial aquí. Según ha comentado públicamente, Celeste usa 6 fotogramas de Coyote Time a 60 FPS, lo que equivale a unos 100 milisegundos. ¿Por qué ese número? Porque es lo suficientemente largo para perdonar la imprecisión humana, pero lo bastante corto como para mantener la sensación de control y consecuencia.

      El Equilibrio Delicado: No Demasiado, No Muy Poco

      Aquí está el truco que aprendí a través de iteración dolorosa:

      Coyote Time demasiado largo (más de 200 ms aproximadamente) hace que el juego se sienta "flotante" o "sin peso". El jugador puede saltar desde el aire de una manera que desafía la física percibida. Pierde la tensión.

      Coyote Time demasiado corto (menos de 50 ms) vuelve al problema original: el juego se siente injusto. Los jugadores casuales se frustran.

      Lo mismo aplica a Jump Buffering. Un buffer muy largo hace que los saltos se ejecuten cuando el jugador ya no quería saltar; uno muy corto, en cambio, lo vuelve inútil.

      La solución pasa por la experimentación sistemática. Toma tu juego, implementa ambas mecánicas con valores conservadores (100 ms + 60 ms) y ajusta después mientras juegas. Pídele a otros que lo prueben. Con el tiempo, los números correctos acaban emergiendo por sí solos.

      Más Allá de los 3 Segundos: Variaciones Avanzadas

      Coyote Time variable: Algunos juegos modernos ajustan Coyote Time basándose en la velocidad vertical del jugador. Si caes rápido, el margen es más pequeño. Si caes lentamente, es más grande. Esto añade una capa de realismo físico.

      Jump Buffering con cancelación: En juegos como Celeste, puedes cancelar un salto en buffer si presionas otra dirección. Esto da al jugador más control y permite movimientos más complejos.

      Wall Coyote: Extensión lógica: si puedes saltar después de dejar una plataforma, ¿por qué no después de dejar una pared? Muchos juegos modernos implementan esto, dándote un pequeño margen para saltar después de deslizarte por una pared.

      ¿Por Qué Importa Esto?

      A lo largo de estos años como desarrollador indie he visto cómo estas dos mecánicas transforman la experiencia de un juego. No son visuales. No son narrativas. Son sensoriales. Marcan la diferencia entre un jugador que dice "este juego es injusto" y otro que dice "este juego es justo, pero difícil".

      La accesibilidad es un beneficio secundario, pero nada menor. Un jugador con discapacidad motora que tiene dificultades con la precisión temporal se beneficia enormemente de Coyote Time. No es una concesión. Es buen diseño, sin más.

      Si estás desarrollando un plataforma, especialmente en HTML5 o JavaScript, vale la pena implementar esto desde el principio. No es opcional, es prácticamente el estándar actual del género. Y una vez que lo pruebas, cuesta volver atrás.

      Mi consejo final: comienza con 100 ms de Coyote Time y 60 ms de Jump Buffering. Juega. Itera. Escucha a tus testers. Los números correctos para tu juego específico acabarán por revelarse solos.