Jugable
Apuntarme

Un sprite que camina y se detiene

  • Nivel: empiezo
  • Sprites
  • Input
  • 2 min de lectura

Este ejercicio parece de dos líneas y casi nadie lo entrega bien a la primera. El bug clásico es un personaje que "vibra": la animación de correr se reinicia en cada frame porque la estás pidiendo en cada frame.

Qué tienes que construir

Un personaje visto de lado, sobre un piso plano, con tres animaciones:

  • quieto — 2 a 4 cuadros, lento, en bucle.
  • corriendo — 6 a 8 cuadros, en bucle.
  • frenando — 2 cuadros, una sola vez, cuando pasa de correr a quieto.

Se mueve con las flechas izquierda y derecha. Si no tienes un spritesheet a la mano, genera uno o usa cuadros de colores planos: el ejercicio es la máquina de estados, no el arte.

Criterios de aceptación

  1. Dejando la flecha derecha presionada 5 segundos, la animación de correr se reproduce continua, sin saltar al primer cuadro cada frame.
  2. Al soltar la tecla, se ve la animación de frenado completa y luego pasa a quieto. No se corta a la mitad.
  3. Al cambiar de derecha a izquierda sin soltar, el sprite voltea y sigue corriendo — no reinicia la animación ni pasa por frenado.
  4. Presionar y soltar la tecla muy rápido, veinte veces seguidas, no deja al personaje atorado en frenado ni en un cuadro suelto.
  5. En tu update no hay ningún play() sin una condición que lo proteja.

Pistas

El truco entero está en el segundo parámetro de play:

this.sprite.play('correr', true)   // true = ignorar si ya está corriendo

Con true, Phaser no reinicia la animación si ya es la que está sonando. Es la solución de una palabra, y sirve para quieto y correr.

Para frenando no sirve, porque esa sí es de una sola pasada y necesitas saber cuándo terminó. Escúchala:

this.sprite.once('animationcomplete-frenar', () => { this.estado = 'quieto' })

Sobre el criterio 4: si guardas el estado en una variable y solo cambias de animación cuando el estado cambia, los cuatro primeros criterios salen solos. Si en cambio decides la animación mirando la velocidad en cada frame, vas a pelearte con casos borde toda la tarde. Esa es la lección.

setEstado(nuevo) {
  if (nuevo === this.estado) return
  this.estado = nuevo
  // ... aquí, y solo aquí, se llama play()
}

Cuando ya te salió

Agrega arranque: una animación de dos cuadros que se vea una vez al pasar de quieto a corriendo, igual que frenando pero al revés.

Ahora tienes cuatro estados y las transiciones ya no son obvias — ¿qué pasa si sueltas la tecla mientras se ve el arranque? Decídelo tú, escríbelo como una regla, y haz que tu código la respete. Ese documento de dos renglones que acabas de escribir es una máquina de estados, y es la misma herramienta con la que se controla un jefe final.

Sigue con estos

Ver el catálogo completo

Empiezo

El cronómetro que no miente

Un contador en pantalla que marque exactamente los mismos segundos en un monitor de 60 Hz y en uno de 144 Hz. Suena trivial hasta que lo mides.

  • Game loop
Leer el ejercicio Sin repo todavía
Empiezo

Monedas que no se cuentan dos veces

Veinte monedas, un marcador y un bug que aparece solo cuando el jugador es lento: la moneda que suma tres veces porque tardaste tres frames en salir de ella.

  • Colisiones
  • UI y estado
Leer el ejercicio Sin repo todavía

El próximo grupo

Un día
y un juego tuyo

Presencial en Tijuana

Cupo limitado por grupo

apartar lugar