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

Eventos de clic en botones dinámicos con JS

Resumen

Capturar clics en botones generados dinámicamente es uno de los retos más comunes cuando trabajas con JavaScript y DOM. Aquí aprenderás a recorrer un arreglo de botones, asignarles un event listener y guardar la secuencia de ataques de un jugador en un mini juego tipo RPG.

Este flujo te sirve si estás construyendo lógica de selección múltiple, formularios dinámicos o cualquier interfaz donde los elementos se renderizan después de cargar la página.

Por qué usar querySelectorAll en lugar de getElementById

Cuando varios botones cumplen la misma función, no puedes identificarlos con un id. Repetir ids en HTML es mala práctica porque deben ser únicos. La solución es asignarles una clase compartida y seleccionarlos todos juntos.

En el juego, cada botón de ataque recibe la clase BAtaque dentro del HTML que se inyecta dinámicamente [03:12]. Después, en el archivo JavaScript se declara una variable que captura esos elementos:

javascript let botones = document.querySelectorAll('.BAtaque');

¿Qué hace querySelectorAll? Devuelve un NodeList con todos los elementos del DOM que coinciden con el selector indicado. Funciona como un arreglo iterable que puedes recorrer con forEach.

Si imprimes la variable botones con console.log antes de que los botones se rendericen, verás una lista vacía. Por eso la lógica debe ejecutarse después de seleccionar al enemigo.

Cómo iterar el NodeList y asignar el evento clic

Una vez tienes el arreglo poblado, recorres cada botón con forEach y le agregas un addEventListener con el evento click. Dentro del callback recibes el parámetro e, que representa el evento mismo [07:45].

javascript botones.forEach((boton) => { boton.addEventListener('click', (e) => { console.log(e); }); });

Este patrón asegura que cada botón generado, sin importar cuántos sean, tenga su propia función asociada.

Cómo extraer el valor del botón clickeado con e.target.textContent

El objeto e contiene una propiedad llamada target, que apunta al elemento exacto sobre el que ocurrió el clic. Como los elementos HTML se convierten en objetos con propiedades, puedes acceder a su contenido de texto mediante textContent [10:30].

En el juego, cada botón muestra un emoji (fuego, agua o tierra) como contenido de texto. Para capturarlo:

javascript e.target.textContent

¿Qué representa la e en un event listener? Es el objeto evento que JavaScript pasa automáticamente al callback. Contiene información del clic, incluyendo el elemento de origen en target y todas sus propiedades.

Con ese valor ya puedes validar qué tipo de ataque seleccionó el jugador y guardarlo en un arreglo.

Cómo guardar la secuencia de ataques en un arreglo

La lógica del juego cambia: en lugar de tres vidas, ahora se juega una secuencia fija de cinco ataques. Para almacenarlos se declara una variable global:

javascript let ataqueJugador = [];

Dentro del listener, se compara e.target.textContent con cada emoji y se hace push al arreglo correspondiente:

  • Si es fuego, ataqueJugador.push('🔥').
  • Si es agua, ataqueJugador.push('💧').
  • Si es tierra, ataqueJugador.push('🌱').

Después de cada selección, se imprime el arreglo en consola para ver cómo crece la secuencia ronda tras ronda.

Cómo dar feedback visual al usuario tras seleccionar un botón

Un detalle clave de UX es indicar visualmente qué botones ya fueron usados. Para lograrlo, se modifica el color de fondo del botón clickeado dentro del mismo if [16:20]:

javascript boton.style.background = '#2F58CD';

Así, después de cinco clics, el jugador ve claramente cuáles fueron sus elecciones y en qué orden. Esto evita confusiones y refuerza la sensación de control sobre la secuencia.

Errores comunes al refactorizar funciones de clic

Durante la implementación aparecen dos errores típicos que vale la pena anticipar:

  1. Variable ya declarada. Si declaras ataqueJugador dentro de la función y también fuera, JavaScript lanza un error de redeclaración. La solución es dejarla solo en el scope global del juego.
  2. ataqueJugador.push is not a function. Aparece cuando funciones antiguas reasignan el arreglo a un valor distinto (por ejemplo, un string). Si una función posterior sobrescribe la variable, push deja de existir porque ya no es un arreglo.

La limpieza consiste en eliminar las funciones viejas que asignaban ataqueJugador = 'fuego' y dejar solo la nueva lógica con push.

¿Por qué push no funciona después de reasignar la variable? Porque push es un método del prototipo Array. Si reasignas la variable a un string o número, pierde acceso a los métodos de arreglo y arroja un TypeError.

Qué sigue para completar la lógica del juego

Con la secuencia del jugador resuelta, el siguiente paso es generar la secuencia de ataques del enemigo y comparar ambos arreglos en un loop de cinco rondas. Quien acumule más victorias en esas cinco comparaciones gana la partida.

¿Ya implementaste algo parecido en tus proyectos? Cuéntame en los comentarios qué patrón usas para manejar eventos en elementos generados dinámicamente.