Jugable
Apuntarme

Monedas que no se cuentan dos veces

  • Nivel: empiezo
  • Colisiones
  • UI y estado
  • 2 min de lectura

Hay un bug que casi todos los juegos de principiante tienen y casi nadie nota, porque solo se dispara cuando el jugador pasa despacio por encima del objeto: la moneda suma dos, tres, cinco veces antes de desaparecer.

La causa es que un overlap no es un evento, es un estado. Se cumple en cada frame en el que los dos cuerpos se tocan, no una sola vez cuando empiezan a tocarse.

Qué tienes que construir

Una escena con:

  • Un personaje que se mueve en las cuatro direcciones.
  • 20 monedas repartidas, algunas encimadas entre sí a propósito.
  • Un marcador arriba que diga Monedas: 0 / 20.
  • Un mensaje de "¡completo!" cuando llegue a 20.

Criterios de aceptación

  1. Pasar por encima de una moneda suma exactamente 1, ni con el personaje parado encima de ella, ni entrando muy despacio.
  2. Quedarse quieto sobre el lugar donde había una moneda no suma nada más.
  3. Pasar por dos monedas encimadas suma exactamente 2.
  4. Recorrer las 20 muestra el mensaje de completo una sola vez.
  5. El marcador nunca pasa de 20, hagas lo que hagas.
  6. Recargar la página reinicia todo limpio, sin monedas fantasma.

Pistas

Tienes dos caminos y conviene que pruebes los dos, porque no son intercambiables:

El fácil: desactiva el cuerpo físico en el momento de recogerla.

this.physics.add.overlap(jugador, monedas, (jugador, moneda) => {
  moneda.disableBody(true, true)   // apaga el cuerpo y esconde el sprite
  this.puntos++
})

Con el cuerpo apagado, el overlap deja de cumplirse en el siguiente frame y el problema desaparece. Es lo correcto para una moneda, que no vuelve.

El que sí vas a necesitar después: una bandera propia.

if (moneda.recogida) return
moneda.recogida = true

Este te hace falta cuando el objeto no desaparece: una placa de presión, una zona de daño, un checkpoint. Ahí no puedes apagar el cuerpo porque el objeto sigue existiendo, y la bandera es la única salida.

Dos detalles que muerden:

  • destroy() en medio del callback de colisión puede dejarte un objeto a medio borrar dentro del recorrido del grupo. disableBody(true, true) es más seguro.
  • El mensaje de completo dentro del mismo callback se va a disparar una vez por moneda si tu condición es >= 20 sin protección. Necesita su propia bandera, por la misma razón exacta que la moneda.

Cuando ya te salió

Cambia una de las monedas por una placa de presión: mientras el personaje está encima, una puerta se abre; cuando se baja, se cierra.

Ahora necesitas detectar los dos flancos — cuándo empieza y cuándo termina el contacto — y Phaser solo te avisa del estado, no de los flancos. Vas a tener que compararlo contra el frame anterior tú mismo. Es cinco líneas, y entenderlas es la diferencia entre pelearte con las colisiones y mandarlas.

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

Un sprite que camina y se detiene

Un personaje que corre cuando lo mueves y se queda quieto cuando lo sueltas, sin que la animación se reinicie sola ni se quede pegada en medio del paso.

  • Sprites
  • Input
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