Un sprite que camina y se detiene
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
- Dejando la flecha derecha presionada 5 segundos, la animación de correr se reproduce continua, sin saltar al primer cuadro cada frame.
- Al soltar la tecla, se ve la animación de frenado completa y luego pasa a quieto. No se corta a la mitad.
- Al cambiar de derecha a izquierda sin soltar, el sprite voltea y sigue corriendo — no reinicia la animación ni pasa por frenado.
- Presionar y soltar la tecla muy rápido, veinte veces seguidas, no deja al personaje atorado en frenado ni en un cuadro suelto.
- En tu
updateno hay ningúnplay()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
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
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
Una cámara que sigue sin marear
Pegar la cámara al personaje es una línea. Que no se sienta como ir en el asiento de atrás de un taxi es el ejercicio.
- Cámara