Colisiones: precisión, máscaras y buenas prácticas
En Construct, una “colisión” ocurre cuando las áreas de colisión (collision polygons) de dos objetos se solapan. La calidad de tus interacciones depende de dos cosas: la forma de la máscara y cómo decides resolver el contacto (sólido, plataforma, daño, detección, etc.).
Configurar colisiones precisas (collision polygon)
Una máscara demasiado grande provoca “golpes fantasma”; una demasiado pequeña permite atravesar bordes. Ajustarla es especialmente importante en personajes, enemigos y obstáculos con formas irregulares.
- Cuándo usar máscara simple: cajas/rectángulos para plataformas, paredes, pickups y puertas. Es más estable y eficiente.
- Cuándo usar máscara precisa: pinchos, enemigos con silueta irregular, objetos redondos, elementos decorativos que sí colisionan.
Paso a paso: editar la máscara de colisión
- Selecciona el Sprite en el editor.
- Abre el editor de imagen y busca la opción de Edit collision polygon (polígono de colisión).
- Elige un modo de ajuste: Bounding box (caja), Tight (ajustado) o edición manual.
- Si editas manualmente: coloca pocos puntos, evita picos muy finos y mantén bordes limpios.
- Prueba en el layout: camina, salta y roza esquinas para verificar estabilidad.
Consejo práctico: en plataformas y paredes, usa cajas simples; en el jugador, una caja ligeramente más estrecha que el sprite ayuda a evitar engancharse en bordes.
Sólidos, plataformas unidireccionales y áreas especiales
Sólidos (Solid)
El comportamiento Solid hace que otros objetos con movimiento compatible (por ejemplo, Platform) no puedan atravesarlo. Es ideal para paredes, suelo y bloques.
- Úsalo en: suelo, paredes, cajas, límites del nivel.
- Evita usarlo en: objetos que deban “detectar” sin bloquear (zonas, triggers, pickups).
Plataformas unidireccionales (Jump-thru)
El comportamiento Jump-thru permite atravesar desde abajo y colisionar desde arriba. Es perfecto para plataformas tipo “nube” o pasarelas.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
Paso a paso: crear una plataforma unidireccional
- Crea un sprite para la plataforma.
- Añade el comportamiento Jump-thru.
- Asegúrate de que su máscara sea una caja simple y que el grosor no sea exagerado.
- Prueba: salta desde abajo (debe atravesarse) y cae desde arriba (debe sostener).
Áreas de daño (hazards) vs zonas de detección
Una área de daño es un objeto que no bloquea, pero aplica una consecuencia (restar vida, reiniciar, empujar). Una zona de detección es un trigger que activa lógica (abrir puerta, mostrar mensaje, activar trampa) sin necesariamente hacer daño.
Regla útil: si el objeto no debe impedir el movimiento, no uses Solid. En su lugar, usa condiciones de solapamiento (On collision / Is overlapping) y acciones.
Interacciones comunes: pickups, puertas/llaves, interruptores, trampas y detectores
Pickups (coleccionables)
Un pickup suele requerir: detectar contacto con el jugador, sumar puntuación/recursos, reproducir feedback (sonido/partículas) y destruirse.
Paso a paso: pickup que suma puntuación
- Crea un sprite
Pickupcon máscara simple. - Crea una variable global
Score(número) o una variable en un objeto HUD. - Evento: cuando el jugador toque el pickup, suma puntos y destruye el pickup.
Player On collision with Pickup -> Add 10 to Score; Destroy PickupSi quieres evitar dobles recogidas por múltiples eventos en el mismo tick, usa Trigger once o destruye el pickup inmediatamente antes de otras acciones dependientes.
Puertas y llaves
Patrón típico: la llave incrementa un contador o activa un booleano; la puerta comprueba ese estado y se abre (desaparece, cambia animación o desactiva colisión).
Paso a paso: puerta que requiere 1 llave
- Crea
KeyyDoor. - En el jugador, crea variable
Keys(número) o global. - Al recoger llave: incrementa
Keys. - Al interactuar con la puerta (por colisión o por botón): si
Keys > 0, consume una llave y abre.
Player On collision with Key -> Add 1 to Player.Keys; Destroy KeyPlayer On collision with Door + Player.Keys > 0 -> Subtract 1 from Player.Keys; Door: DestroyVariación: si la puerta debe “abrirse” sin destruirse, puedes desactivar su colisión (por ejemplo, quitando Solid/Jump-thru o cambiando a un sprite sin colisión) y reproducir animación.
Interruptores (switches) y puertas conectadas
Un interruptor suele cambiar un estado persistente: Switch.On o una variable global DoorOpen. Luego, la puerta reacciona a ese estado.
Paso a paso: interruptor que abre una puerta específica
- Asigna a cada puerta un identificador (por ejemplo, variable de instancia
Channel). - Asigna al interruptor el mismo
Channel. - Al activar el interruptor, marca un estado (global o por familia).
- La puerta con ese canal se abre.
Player On collision with Switch -> Set Switch.On = trueSwitch On = true -> Door: Pick where Door.Channel = Switch.Channel; Door: DestroySi quieres que el interruptor sea de “uso” (no por tocar), combina la colisión con una condición de entrada (tecla/botón) y un Trigger once.
Trampas: activación por zona y temporización
Una trampa suele tener dos fases: detección (el jugador entra en una zona) y ejecución (se dispara un proyectil, aparecen pinchos, cae un bloque). Para esto, una zona invisible (trigger) es muy útil.
Paso a paso: trampa de pinchos activada por zona
- Crea un sprite invisible o semitransparente
TriggerZone(sin Solid). - Crea
Spikes(daño por contacto) inicialmente desactivados (por ejemplo, fuera de pantalla, invisibles o con variableActive=false). - Cuando el jugador entra en la zona, activa los pinchos y opcionalmente inicia un temporizador para desactivarlos.
Player Is overlapping TriggerZone + Trigger once -> Spikes: Set Active = trueSpikes Active = true -> Spikes: Set visible; (opcional) Start timer 1.0sSpikes On timer -> Set Active = false; Set invisibleZonas de detección (detección sin colisión física)
Para detectar “cerca de” un objeto (NPC, puerta, punto de guardado), usa un área de detección: un sprite invisible con Is overlapping. Esto separa interacción de colisión física y evita que el jugador se “atasque” en triggers.
Prioridades y conflictos: qué pasa cuando múltiples eventos aplican
En Construct, el orden de evaluación de eventos y la forma en que “seleccionas” instancias (picking) determinan resultados cuando varias reglas podrían ejecutarse a la vez (por ejemplo, tocar un enemigo y un pickup en el mismo frame, o recibir daño y recoger vida simultáneamente).
Herramientas para controlar prioridades
- Orden de eventos: los eventos se evalúan de arriba hacia abajo. Si dos eventos afectan al mismo objeto, el que ocurra primero puede cambiar condiciones del siguiente.
- Sub-eventos: agrupan lógica bajo una condición principal (por ejemplo, “si está invulnerable, entonces…”).
- Trigger once: evita repetición continua mientras se mantiene una condición.
- Variables de estado:
Invulnerable,Dead,Active,CanPick. Permiten “bloquear” acciones. - Else: asegura exclusividad (si pasa A, no pasa B).
- Destroy y selección: destruir un objeto en un evento puede impedir que otros eventos lo vuelvan a usar en el mismo tick, pero es más seguro apoyarse en estados/flags cuando hay varias interacciones complejas.
Ejemplo de conflicto típico y solución
Problema: el jugador toca un enemigo y un pickup a la vez; quieres que el pickup se recoja siempre, pero el daño solo si no está invulnerable.
1) Player On collision with Pickup -> Add 10 to Score; Destroy Pickup2) Player On collision with Enemy + Player.Invulnerable = false -> Apply damageColoca el pickup arriba si quieres que se procese primero. Además, usa Invulnerable para que el daño no se aplique repetidamente cada frame.
Mini-sistema completo: puntuación, daño por contacto, invulnerabilidad temporal y retroceso
Este mini-sistema combina varias reglas comunes en juegos de acción/plataformas: coleccionables que suman puntuación, enemigos que dañan al contacto, un periodo de invulnerabilidad tras recibir daño y un retroceso (knockback) para dar feedback y separar al jugador del peligro.
Preparación: objetos y variables
- Objetos:
Player,Enemy,Pickup, (opcional)HUDScoreText,HUDHealthText. - Global:
Score(número). - Player variables:
HP(número),Invulnerable(boolean),InvulnTime(número, opcional),KnockbackX/KnockbackY(número, opcional).
Nota: el movimiento base del jugador ya existe por capítulos anteriores; aquí solo añadimos reglas de interacción. Para el retroceso, puedes implementarlo con acciones sobre el comportamiento de movimiento que uses (por ejemplo, ajustando vector/velocidad) o con un impulso simple mediante posiciones/velocidades si tu configuración lo permite.
Parte A: coleccionables que incrementan puntuación
Player On collision with Pickup -> Add 10 to Score; Destroy PickupOpcional HUD:
Every tick -> HUDScoreText: Set text to "Score: " & ScoreParte B: daño por contacto con enemigos (con invulnerabilidad)
Objetivo: al tocar un enemigo, el jugador pierde 1 HP, se vuelve invulnerable por un breve tiempo y recibe retroceso. Mientras Invulnerable=true, no puede volver a recibir daño por contacto.
Paso a paso: lógica de daño
- Crea en
Playerla variable booleanaInvulnerable(inicia enfalse). - Crea
HP(por ejemplo inicia en 3). - Evento de contacto con enemigo condicionado a no invulnerable.
- Al recibir daño: resta HP, activa invulnerabilidad, inicia un temporizador para desactivarla, y aplica retroceso.
Player On collision with Enemy + Player.Invulnerable = false -> Subtract 1 from Player.HP; Set Player.Invulnerable = true; Start timer "invuln" for 1.0Parte C: desactivar invulnerabilidad tras un tiempo
Player On timer "invuln" -> Set Player.Invulnerable = falseFeedback visual recomendado: parpadeo mientras invulnerable (sin texto en pantalla). Por ejemplo, alternar visibilidad u opacidad en intervalos cortos mientras Invulnerable=true.
Player Invulnerable = true -> Set opacity to 50Player Invulnerable = false -> Set opacity to 100Parte D: retroceso (knockback) por dirección del impacto
El retroceso debe empujar al jugador alejándolo del enemigo. Una forma simple es comparar posiciones X y aplicar un impulso hacia la izquierda o derecha, más un pequeño impulso vertical.
Ejemplo genérico (ajusta las acciones al comportamiento de movimiento que uses):
Player On collision with Enemy + Player.Invulnerable = false + Player.X < Enemy.X -> (Apply knockback left)Player On collision with Enemy + Player.Invulnerable = false + Player.X >= Enemy.X -> (Apply knockback right)Opciones comunes para implementar “Apply knockback” sin programar:
- Si usas Platform: usa acciones del comportamiento para simular impulso (por ejemplo, establecer vector/velocidad si tu versión lo permite) o fuerza temporal con un estado
Knockbackque durante unos ticks empuje al jugador. - Con estado y movimiento manual temporal: crea
Player.Knockback=truedurante 0.15s y, mientras esté activo, suma/resta X cada tick y aplica un salto pequeño.
Ejemplo de retroceso por estado (simple y controlable):
Player On collision with Enemy + Player.Invulnerable = false -> Set Player.Knockback = true; Start timer "kb" for 0.15Player Knockback = true + Player.X < Enemy.X -> Set X to X - 6; Set Y to Y - 2Player Knockback = true + Player.X >= Enemy.X -> Set X to X + 6; Set Y to Y - 2Player On timer "kb" -> Set Player.Knockback = falseConsejo: durante Knockback=true, puedes desactivar temporalmente el control del jugador (por ejemplo, ignorar entrada) para que el impacto se sienta consistente.
Parte E: evitar múltiples daños en el mismo contacto
Si el jugador permanece solapado con el enemigo, sin invulnerabilidad recibiría daño cada frame. Ya lo evitamos con Invulnerable=false. Aun así, si tienes varios enemigos o varias fuentes de daño, conviene unificar la regla: “si invulnerable, no aplicar ningún daño”.
Player On collision with Enemy + Player.Invulnerable = true -> (no action)Mejor aún: organiza eventos para que el daño esté en un bloque claro y no se duplique por otros eventos similares (por ejemplo, pinchos, fuego, proyectiles). Puedes reutilizar la misma variable Invulnerable para todas las fuentes.
Parte F: integrar áreas de daño (pinchos) con el mismo sistema
Si tienes un objeto Hazard (pinchos), puedes aplicar exactamente la misma lógica que con Enemy, pero sin retroceso direccional o con retroceso vertical.
Player On collision with Hazard + Player.Invulnerable = false -> Subtract 1 from Player.HP; Set Player.Invulnerable = true; Start timer "invuln" for 1.0; Set Player.Knockback = true; Start timer "kb" for 0.15Player Knockback = true -> Set Y to Y - 3Parte G: prioridades recomendadas (orden de eventos)
| Prioridad | Regla | Motivo |
|---|---|---|
| 1 | Pickups (sumar score y destruir) | Evita perder coleccionables por lógica posterior o estados |
| 2 | Interacciones “de uso” (llaves/puertas/interruptores) | Son acciones intencionales; conviene resolverlas antes del daño si están en el mismo punto |
| 3 | Daño por contacto (enemigos/hazards) con chequeo de invulnerabilidad | Debe ser consistente y no repetirse |
| 4 | Estados temporales (invulnerabilidad, knockback) y feedback visual | Se aplican después de decidir el resultado del frame |
Si una puerta está en la misma zona que un enemigo, decide tu diseño: ¿puedes abrir la puerta mientras te golpean? Si no, añade condición: Player.Invulnerable = false o Player.Knockback = false para permitir interacción solo cuando el jugador está estable.