Lógica de juego con el sistema de eventos de Construct

Capítulo 5

Tiempo estimado de lectura: 10 minutos

+ Ejercicio

Cómo funciona el sistema de eventos: condiciones, acciones y subeventos

En Construct, la “lógica” del juego se construye con eventos. Cada evento combina condiciones (cuándo ocurre) y acciones (qué se hace). Puedes anidar subeventos para crear reglas más específicas sin duplicar lógica.

Condiciones

  • Comparaciones: comprobar valores (por ejemplo, Score >= 100, Lives = 0).
  • Estados: comprobar banderas o variables (por ejemplo, Player.Invulnerable = true).
  • Triggers (disparadores): condiciones que se activan en el instante del suceso, como On collision with o On created.

Acciones

Son las consecuencias: cambiar variables, reproducir sonidos, destruir objetos, cargar layouts, crear instancias, etc. Un evento puede tener muchas acciones y se ejecutan en el orden en que aparecen.

Subeventos

Un subevento hereda el “contexto” del evento padre. Por ejemplo, si el padre selecciona un enemigo concreto, el subevento trabaja sobre ese mismo enemigo sin volver a buscarlo. Esto ayuda a mantener la lógica clara y eficiente.

Disparadores esenciales: On collision, On created y su uso correcto

On collision with (trigger)

On collision se dispara una sola vez en el momento del contacto (no cada tick). Es ideal para: recoger ítems, recibir daño, activar un checkpoint, etc. Si necesitas una comprobación continua mientras se solapan, usa condiciones de solapamiento (no trigger) como Is overlapping.

On created (trigger)

On created se dispara cuando una instancia aparece (por ejemplo, al crear una bala o un enemigo). Es perfecto para inicializar variables de instancia, asignar velocidad/dirección, o configurar animaciones.

Continúa en nuestra aplicación.
  • Escuche el audio con la pantalla apagada.
  • Obtenga un certificado al finalizar.
  • ¡Más de 5000 cursos para que explores!
O continúa leyendo más abajo...
Download App

Descargar la aplicación

Ejemplo típico: al crear una bala, establecer su velocidad y un temporizador de autodestrucción.

Bullet: On created -> Set speed 900; Set angle to Player.Angle; Wait 2.0 -> Destroy

Orden de evaluación: por qué importa y cómo evitar errores

Construct evalúa los eventos de arriba hacia abajo en cada tick. Esto implica:

  • Si un evento cambia una variable, los eventos de abajo verán el nuevo valor.
  • Si destruyes un objeto, eventos posteriores ya no podrán actuar sobre esa instancia.
  • Los triggers se disparan cuando ocurre el suceso, pero las acciones se ejecutan en el orden del evento.

Patrones para controlar el orden

  • Coloca primero la lectura de entradas/estados y después las consecuencias (daño, victoria, cambio de escena).
  • Usa grupos de eventos para separar fases: Gameplay, UI, Transiciones.
  • Cuando haya reglas excluyentes, usa Else o variables de estado (por ejemplo, GameState).

Variables globales y de instancia: cuándo usar cada una

Variables globales

Viven a nivel de proyecto/escena (según configuración) y sirven para datos compartidos: puntuación total, vidas, nivel actual, estado de partida.

  • gScore (número)
  • gLives (número)
  • gLevel (número)
  • gHasCheckpoint (booleano)

Variables de instancia

Pertenecen a cada objeto individual. Útiles para salud por enemigo, si un ítem ya fue recogido, invulnerabilidad del jugador, etc.

  • En Player: hp, invuln, respawnX, respawnY
  • En Enemy: hp, worth

Regla práctica

Si el dato describe a una instancia concreta, es variable de instancia. Si describe el estado general de la partida, es global.

Organización: grupos de eventos y comentarios para mantener claridad

Cuando tu lógica crece, la organización es parte del “no programar”. Estructura tu hoja de eventos con grupos y comentarios.

Grupos recomendados

  • 00_Init: inicialización al empezar layout.
  • 10_Player: daño, respawn, animaciones lógicas.
  • 20_Items: monedas, llaves, pickups.
  • 30_Checkpoints: activación y respawn.
  • 40_WinLose: condiciones de victoria/derrota.
  • 90_Debug: atajos y textos de prueba (desactivable).

Comentarios útiles

  • “Este evento usa trigger; no cambiar a Is overlapping”.
  • “Orden importante: primero restar vida, luego invulnerabilidad”.
  • “Si se añade nuevo coleccionable, sumar aquí”.

Patrones esenciales con eventos (plantillas reutilizables)

1) Reinicio de nivel (reset) sin romper el estado

Objetivo: reiniciar el layout cuando el jugador muere, manteniendo o no ciertos valores (por ejemplo, vidas sí, puntuación quizá sí).

Variables sugeridas:

  • gLives (global)
  • gScore (global)
  • Player.respawnX, Player.respawnY (instancia)

Evento base:

System: On start of layout -> (Inicializar respawn al inicio del nivel)
Player: On created -> Set respawnX to X; Set respawnY to Y
System: (Condición de muerte) Player.hp <= 0 -> Subtract 1 from gLives; Go to layout (current)

Si quieres un “reinicio suave” sin recargar layout, puedes reposicionar y resetear objetos clave, pero recargar el layout suele ser más simple para empezar.

2) Checkpoints (puntos de control)

Objetivo: al tocar un checkpoint, guardar la posición de respawn del jugador.

Objetos: Checkpoint (sprite), Player.

Variables:

  • En Checkpoint: activated (booleano)
  • En Player: respawnX, respawnY

Eventos:

Checkpoint: On collision with Player AND Checkpoint.activated = false -> Set activated = true; Player: Set respawnX to Player.X; Set respawnY to Player.Y

Para feedback visual, añade una acción de animación o cambio de frame del checkpoint al activarse.

Respawn usando checkpoint:

System: (Condición de muerte) Player.hp <= 0 -> Subtract 1 from gLives; Player: Set position to (respawnX, respawnY); Set hp to 1

Si el nivel es peligroso al respawnear, combina con invulnerabilidad temporal (ver temporizadores).

3) Conteo de vidas y daño con invulnerabilidad

Objetivo: al chocar con un enemigo, perder vida una vez, no cada frame, y tener una ventana de invulnerabilidad.

Variables:

  • gLives (global)
  • En Player: hp (número), invuln (booleano)

Eventos:

Enemy: On collision with Player AND Player.invuln = false -> Player: Subtract 1 from hp; Set invuln = true; (Opcional) Set opacity 50
System: Wait 1.0 -> Player: Set invuln = false; Set opacity 100

Nota de orden: si en el mismo tick también evalúas muerte (hp <= 0), coloca la comprobación de muerte debajo del evento de daño para que vea el hp actualizado.

4) Puntuación (score) con coleccionables

Objetivo: sumar puntos al recoger ítems y evitar dobles sumas.

Objetos: Coin.

Variables:

  • gScore (global)
  • En Coin: value (número) o usar un valor fijo

Eventos:

Coin: On collision with Player -> Add Coin.value to gScore; Destroy Coin

Si todas valen lo mismo, reemplaza Coin.value por un número (por ejemplo, 10).

5) Temporizadores: Wait, Timer y contadores

Construct permite temporizar acciones con eventos. Dos enfoques comunes:

  • Wait: simple para secuencias (invulnerabilidad, retraso antes de reiniciar).
  • Contador: variable que disminuye con dt para UI o lógica continua.

Ejemplo con contador (tiempo restante):

  • Global: gTimeLeft (número)
System: Every tick -> Subtract dt from gTimeLeft
System: gTimeLeft <= 0 -> (Disparar derrota por tiempo)

Para mostrarlo en UI, enlaza un texto a floor(gTimeLeft) (si ya tienes UI creada en otro capítulo, aquí solo conectas el valor).

Práctica estructurada: lógica completa de ganar/perder, reiniciar y avanzar de escena

Vas a construir una lógica completa típica: el jugador puede ganar al llegar a una meta o recoger todos los ítems; puede perder por vidas o por tiempo; y el juego puede reiniciar o avanzar al siguiente layout. La clave es separar en grupos y controlar estados para evitar que se disparen varias transiciones.

Preparación: variables y objetos mínimos

Objetos (nombres sugeridos):

  • Player
  • Goal (meta)
  • Coin (coleccionable)
  • Enemy (peligro)
  • Checkpoint (opcional)
  • TextStatus (opcional para depurar: mostrar estado)

Variables globales:

  • gScore (número, inicial 0)
  • gLives (número, inicial 3)
  • gTimeLeft (número, inicial 60)
  • gCoinsTotal (número, inicial 0)
  • gCoinsCollected (número, inicial 0)
  • gGameState (texto, inicial "PLAY")

Variables de instancia (Player):

  • hp (número, inicial 1)
  • invuln (booleano, inicial false)
  • respawnX, respawnY (número)

Paso 1: Grupo 00_Init (contar monedas y fijar respawn inicial)

System: On start of layout -> Set gGameState to "PLAY"; Set gTimeLeft to 60; Set gCoinsCollected to 0
System: On start of layout -> Set gCoinsTotal to Coin.Count
Player: On created -> Set hp to 1; Set invuln to false; Set respawnX to X; Set respawnY to Y

Si el layout se recarga al morir, decidirás qué variables reiniciar aquí. Por ejemplo, gScore podría mantenerse entre intentos o reiniciarse según tu diseño.

Paso 2: Grupo 10_Player (daño, muerte y respawn)

Daño con trigger:

Enemy: On collision with Player AND gGameState = "PLAY" AND Player.invuln = false -> Player: Subtract 1 from hp; Set invuln = true
System: Wait 1.0 -> Player: Set invuln = false

Muerte y vidas:

System: Player.hp <= 0 AND gGameState = "PLAY" -> Subtract 1 from gLives

Si aún quedan vidas: respawn:

System: Player.hp <= 0 AND gGameState = "PLAY" AND gLives > 0 -> Player: Set position to (respawnX, respawnY); Set hp to 1; Set invuln to true
System: Wait 1.0 -> Player: Set invuln = false

Si no quedan vidas: perder:

System: gLives <= 0 AND gGameState = "PLAY" -> Set gGameState to "LOSE"

El uso de gGameState evita que la derrota se dispare múltiples veces o que el jugador siga recogiendo monedas durante la transición.

Paso 3: Grupo 20_Items (monedas y puntuación)

Coin: On collision with Player AND gGameState = "PLAY" -> Add 10 to gScore; Add 1 to gCoinsCollected; Destroy Coin

Victoria alternativa por coleccionar todo:

System: gCoinsCollected >= gCoinsTotal AND gGameState = "PLAY" -> Set gGameState to "WIN"

Paso 4: Grupo 30_Checkpoints (opcional)

Checkpoint: On collision with Player AND gGameState = "PLAY" AND Checkpoint.activated = false -> Set activated = true; Player: Set respawnX to Player.X; Set respawnY to Player.Y

Paso 5: Grupo 40_WinLose (meta, tiempo y transiciones)

Victoria por llegar a la meta:

Goal: On collision with Player AND gGameState = "PLAY" -> Set gGameState to "WIN"

Derrota por tiempo:

System: Every tick AND gGameState = "PLAY" -> Subtract dt from gTimeLeft
System: gTimeLeft <= 0 AND gGameState = "PLAY" -> Set gGameState to "LOSE"

Transición a siguiente escena (layout) al ganar:

System: gGameState = "WIN" -> (Opcional) Wait 0.5 -> Go to layout ("NextLevel")

Reintento al perder:

System: gGameState = "LOSE" -> (Opcional) Wait 0.5 -> Go to layout ("GameOver")

Si prefieres reiniciar el mismo nivel al perder, cambia "GameOver" por Layout name actual o por un layout de reintento.

Paso 6: Control de duplicados y “bloqueo” de gameplay durante transiciones

Una fuente común de bugs es que, al ganar o perder, aún se ejecuten eventos de gameplay (daño, monedas, etc.). Solución: añadir gGameState = "PLAY" como condición en todos los eventos de gameplay (daño, pickups, checkpoints, temporizador).

También puedes desactivar grupos completos:

System: gGameState != "PLAY" -> Deactivate group "10_Player"; Deactivate group "20_Items"; Deactivate group "30_Checkpoints"

Esto hace explícito que el juego está en transición.

Paso 7: Depuración rápida con un texto de estado (opcional)

Para verificar que el orden y los estados funcionan, muestra variables clave en un texto:

System: Every tick -> TextStatus: Set text to "State:" & gGameState & " Lives:" & gLives & " Score:" & gScore & " Time:" & floor(gTimeLeft)

Cuando todo esté correcto, puedes desactivar el grupo 90_Debug sin borrar nada.

Checklist de calidad: errores típicos y cómo corregirlos

  • Me quita muchas vidas de golpe: estás usando Is overlapping en vez de On collision, o no estás usando Player.invuln.
  • La victoria/derrota se dispara varias veces: falta gGameState o no bloqueas grupos durante transiciones.
  • El respawn no funciona: no estás guardando respawnX/respawnY al inicio o al activar checkpoint.
  • El orden “rompe” la lógica: revisa que el evento que modifica variables (daño, recoger moneda) esté por encima del que evalúa el resultado (muerte, victoria).

Ahora responde el ejercicio sobre el contenido:

¿Qué combinación de condiciones es la más adecuada para evitar que, al ganar o perder, sigan ejecutándose eventos de gameplay como daño o recolección de monedas?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

Usar gGameState como condición (por ejemplo, solo en PLAY) o desactivar grupos al salir de PLAY bloquea explícitamente el gameplay durante transiciones y evita duplicados de daño, pickups o temporizador.

Siguiente capítulo

Interacciones, colisiones y reglas de juego en Construct

Arrow Right Icon
Portada de libro electrónico gratuitaConstruct desde Cero: Aprende a Crear Juegos Sin Programar
50%

Construct desde Cero: Aprende a Crear Juegos Sin Programar

Nuevo curso

10 páginas

Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.