Contenido del curso

Fundamentos de Programación

Desarrollando un juego con HTML y JavaScript

Estilos con CSS

Optimización de código

Mapa con canvas

Backend: videojuego multijugador

Conectar colisiones con ataques en JS

Resumen

Cuando programas un juego en JavaScript y necesitas que dos personajes se encuentren en el mapa para iniciar una batalla, el reto está en conectar el evento de colisión con la lógica de ataques. Aquí aprendes a sincronizar ambos sistemas, evitar listeners duplicados y limpiar intervalos para que tu juego responda como esperas.

¿Cómo mostrar la sección de ataques al detectar una colisión?

El primer paso es ocultar el mapa y mostrar la pantalla de ataques en el momento exacto en que dos moquepones chocan.

Dentro del método que revisa la colisión, en lugar de lanzar un alert, el código cambia el style.display del mapa a none y vuelve visible la sección de selección de ataques. Esto se logra reutilizando las líneas que antes mostraban los ataques al iniciar el juego, ahora movidas al punto donde se detecta el choque [02:00].

¿Qué hace el método revisarColision? Detecta cuándo dos personajes ocupan el mismo espacio en el mapa y dispara las acciones siguientes: detener movimiento, ocultar mapa y mostrar la pantalla de ataques.

¿Cómo seleccionar al enemigo correcto en lugar de uno aleatorio?

Al inicio, el método seleccionarMascotaEnemigo se llamaba justo después de inicializar el mapa y elegía un rival al azar. Eso provocaba que tu Capi Pepo terminara peleando contra otro Capi Pepo aunque hubieras chocado con Ratigueya.

La solución es mover esa llamada al método de colisión y pasarle como argumento el enemigo con el que realmente colisionaste. Así, el rival deja de ser aleatorio y corresponde al personaje del mapa [03:30].

¿Por qué los ataques del enemigo aparecen vacíos?

Después del cambio anterior, el enemigo correcto aparece en pantalla, pero todos sus ataques siguen siendo de fuego por defecto. Un console.log sobre el array de ataques del enemigo revela el problema: el array llega vacío.

La razón es simple. Cuando se construyeron los personajes enemigos, nunca se les hizo push de sus ataques, a diferencia de los personajes del jugador.

La corrección consiste en duplicar el bloque de ataques que ya existía para los personajes jugables y aplicarlo a sus versiones enemigas:

  • Ataques de Hipodoge enemigo.
  • Ataques de Capi Pepo enemigo.
  • Ataques de Ratigueya enemigo.

Como son el mismo personaje, comparten los mismos ataques. Solo cambia el nombre del objeto al que se le hace push.

¿Cómo evitar que los listeners se dupliquen en cada partida?

Al probar de nuevo, aparece un comportamiento extraño: cada clic en un botón de ataque agrega dos ataques al array. Inspeccionando los botones desde la pestaña event listeners del navegador, se confirma que cada botón tiene dos eventos de clic asignados.

Esto pasa porque la función secuenciaDeAtaque se llama varias veces. Un console.log con el mensaje "se detectó una colisión" dentro de revisarColision confirma que el método se ejecuta tres veces seguidas [07:45].

¿Por qué se ejecuta varias veces revisarColision? Porque está dentro de un setInterval que corre cada 50 milisegundos. Mientras los personajes sigan superpuestos, la colisión se detecta una y otra vez.

¿Cómo detener un setInterval con clearInterval?

La pieza que faltaba es detener el intervalo que refresca el mapa una vez detectada la colisión. Para eso se usa clearInterval, pasándole la variable donde se guardó originalmente el setInterval.

En el método de colisión, además de detener el movimiento del personaje, ahora se ejecuta:

javascript clearInterval(this.intervalo);

Esto rompe el ciclo que repetía la detección y, con ello, los listeners dejan de duplicarse. Al volver a probar, la colisión se detecta una sola vez, los botones tienen un único evento de clic y cada ataque se agrega una sola vez al array.

¿Qué habilidades de JavaScript estás aplicando aquí?

Más allá del juego, esta clase entrena varias destrezas concretas que vas a reutilizar en cualquier proyecto interactivo:

  • Manipulación del DOM con style.display para alternar entre vistas [01:30].
  • Paso de parámetros entre métodos para evitar selecciones aleatorias y trabajar con datos reales [04:00].
  • Depuración con console.log para inspeccionar arrays vacíos o flujos que se ejecutan más veces de lo esperado [05:30].
  • Inspección de event listeners desde las DevTools del navegador para detectar duplicados [07:00].
  • Control de ciclos con setInterval y clearInterval para iniciar y detener procesos repetitivos [09:00].

El patrón que se repite es claro: cuando algo se ejecuta más veces de las que esperas, revisa si hay un intervalo activo o un listener que se está reenganchando.

Con estos ajustes, el mapa, la colisión y la secuencia de ataques quedan conectados. Tu mascota se mueve, choca con un enemigo específico y entra a la pelea con sus ataques bien cargados. ¿Qué otro bug te ha tocado resolver con clearInterval? Cuéntalo en los comentarios.