Mensajes como comunicación asincrónica (y por qué ayudan a desacoplar)
En Scratch, los mensajes (bloques de difusión) permiten que un sprite o el escenario “anuncie” que ocurrió algo, y que otros elementos reaccionen sin conocer detalles internos de quien lo anunció. Esto se parece a un sistema de “señales”: alguien emite una señal y cualquiera que esté “escuchando” esa señal actúa.
La idea clave es el desacoplamiento de responsabilidades: cada sprite se encarga de su parte (animación, sonido, UI, lógica de nivel) y se coordina por mensajes, en lugar de leer/escribir muchas variables compartidas para enterarse de todo.
- Emisor: difunde un mensaje cuando sucede un evento lógico del juego (por ejemplo, “empezó la partida”).
- Receptor: tiene scripts que comienzan con “cuando reciba …” y ejecuta su respuesta (por ejemplo, mostrar HUD, iniciar música, reiniciar posición).
Ventaja práctica frente a “exceso de variables compartidas”
Si intentas coordinar todo con variables (por ejemplo, estado, fase, pantalla, animacionActiva, musica…), es fácil crear dependencias ocultas: un sprite cambia una variable y otro sprite “supone” que eso significa algo, pero nadie lo documenta. Con mensajes, el significado queda explícito: GAME_START es una intención clara.
“Enviar” vs “Enviar y esperar”: diferencias y cuándo usar cada uno
| Bloque | Qué hace | Cuándo conviene | Riesgo típico |
|---|---|---|---|
enviar [MENSAJE] | Difunde y el emisor sigue inmediatamente con el siguiente bloque. | Cuando quieres que varias cosas arranquen en paralelo: música, animaciones, UI, etc. | Si el emisor asume que “ya terminó” algo que en realidad tarda (por ejemplo, una animación). |
enviar [MENSAJE] y esperar | Difunde y el emisor se queda esperando hasta que todos los receptores terminen sus scripts iniciados por ese mensaje. | Cuando necesitas una barrera de sincronización: “no sigas hasta que termine la transición de escena” o “hasta que se inicialice todo”. | Bloqueos inesperados si algún receptor tiene un bucle largo o espera indefinidamente. |
Regla de oro
- Usa enviar para arranques simultáneos y coordinación flexible.
- Usa enviar y esperar para pasos obligatorios en una secuencia de fases (por ejemplo, transición → juego).
Convención de nombres: mensajes como “API” del proyecto
Trata los mensajes como una pequeña “API” interna del juego. Una convención de nombres consistente evita confusiones y facilita mantener el proyecto.
Convención recomendada
- Mayúsculas con guiones bajos:
GAME_START,GAME_OVER,LEVEL_UP. - Prefijos por subsistema cuando crezca el proyecto:
UI_SHOW_HUD,SFX_PLAY_HIT,SCENE_TO_MENU. - Mensajes “de intención” (qué se quiere lograr) mejor que mensajes “de implementación” (cómo se logra). Ejemplo:
SCENE_TO_GAMEen vez deHIDE_MENU_SHOW_GAME_BG.
Esquema de “señales” del proyecto (ejemplo)
Este esquema sirve como mapa de coordinación. Puedes pegarlo en una nota del proyecto o en un comentario dentro de Scratch.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
SEÑALES PRINCIPALES (alto nivel) - GAME_INIT: preparar variables/posiciones base - GAME_START: comenzar partida - GAME_PAUSE / GAME_RESUME: pausar y reanudar - GAME_OVER: terminar partida - LEVEL_START: iniciar nivel actual - LEVEL_UP: subir de nivel - SCENE_TO_MENU / SCENE_TO_GAME / SCENE_TO_END: cambios de escenaSEÑALES DE EFECTOS (bajo nivel) - SFX_COIN, SFX_HIT, SFX_WIN - FX_SHAKE, FX_FLASH - UI_UPDATE_SCORE, UI_SHOW_MESSAGELa idea es que las señales principales definan el flujo del juego, y las señales de efectos permitan respuestas visuales/sonoras sin mezclar responsabilidades.
Guía práctica 1: cambiar de escena con mensajes (menú → juego → fin)
Objetivo: coordinar el cambio de “escena” sin que un sprite tenga que controlar a todos los demás. Cada sprite decide qué hacer cuando llega una señal de escena.
Paso a paso
Define mensajes de escena:
SCENE_TO_MENU,SCENE_TO_GAME,SCENE_TO_END.En el Escenario, crea scripts receptores para cambiar fondos y/o música:
cuando reciba [SCENE_TO_MENU] cambiar fondo a [Menu] (opcional) detener todos los sonidos (opcional) iniciar música de menúcuando reciba [SCENE_TO_GAME] cambiar fondo a [Juego] (opcional) iniciar música de juegocuando reciba [SCENE_TO_END] cambiar fondo a [Fin] (opcional) música de finEn el sprite Botón Jugar, emite el cambio de escena:
al hacer clic en este objeto enviar [SCENE_TO_GAME]En sprites de UI (por ejemplo, marcador), muestra/oculta según escena:
cuando reciba [SCENE_TO_MENU] ocultarcuando reciba [SCENE_TO_GAME] mostrarcuando reciba [SCENE_TO_END] ocultarEn sprites del juego (enemigos, jugador), activa/desactiva comportamiento por escena:
cuando reciba [SCENE_TO_MENU] ocultar detener otros scripts en este objeto (si aplica)cuando reciba [SCENE_TO_GAME] mostrar (re)inicializar posición/estado iniciar comportamiento
Resultado: el botón solo anuncia SCENE_TO_GAME. No necesita saber qué sprites existen ni qué deben hacer.
Guía práctica 2: iniciar una animación sin acoplar lógica y gráficos
Objetivo: separar “la lógica decide que hay un golpe” de “la animación del golpe se reproduce”.
Diseño recomendado
- La lógica emite:
PLAYER_HIT. - El sprite del jugador (o un sprite de efectos) reacciona con una animación.
- El sonido puede reaccionar también, sin que la lógica lo invoque directamente.
Paso a paso
Crea el mensaje
PLAYER_HIT.En el sprite que detecta el golpe (puede ser el jugador o un “controlador”), cuando corresponda:
enviar [PLAYER_HIT]En el sprite del jugador, reproduce la animación al recibir:
cuando reciba [PLAYER_HIT] cambiar disfraz a [Hit1] esperar (0.1) segundos cambiar disfraz a [Hit2] esperar (0.1) segundos cambiar disfraz a [Normal]En un sprite de sonido (o el escenario), añade:
cuando reciba [PLAYER_HIT] tocar sonido [Golpe] hasta que termine
Observa que la lógica no “llama” a la animación ni al sonido: solo emite la señal. Esto facilita cambiar la animación o el audio sin tocar la lógica.
Guía práctica 3: encadenar fases (inicio → juego → fin) con “enviar y esperar”
Objetivo: construir un flujo donde ciertas tareas deben terminar antes de pasar a la siguiente fase, por ejemplo una transición de entrada antes de permitir el control del jugador.
Mensajes sugeridos
GAME_INIT: reiniciar posiciones/valores, preparar UI.GAME_START: habilitar control y spawns.GAME_OVER: detener spawns, mostrar pantalla final.TRANSITION_INyTRANSITION_OUT: animaciones de transición.
Paso a paso (con sincronización)
Crea un sprite “Transición” (un rectángulo negro o un efecto visual) que pueda animar entrada/salida.
En el sprite Transición, implementa la entrada y salida. Importante: estos scripts deben terminar para que “enviar y esperar” funcione como barrera.
cuando reciba [TRANSITION_IN] mostrar (animar hasta cubrir pantalla) esperar (0.2) segundos ocultarcuando reciba [TRANSITION_OUT] mostrar (animar desde cubierto a descubierto) ocultarEn el Escenario (o controlador), encadena fases usando “enviar y esperar”:
cuando reciba [SCENE_TO_GAME] enviar [TRANSITION_IN] y esperar enviar [GAME_INIT] y esperar enviar [TRANSITION_OUT] y esperar enviar [GAME_START]En sprites que deben inicializarse, cuelga su preparación de
GAME_INIT:cuando reciba [GAME_INIT] ir a x:(...) y:(...) mostrar (reiniciar estado interno)En sprites que deben empezar a actuar, cuelga su comportamiento de
GAME_START:cuando reciba [GAME_START] (activar control / comenzar movimiento / comenzar spawns)
Así evitas un problema común: que el jugador se mueva mientras la transición aún está ocurriendo o antes de que los elementos estén listos.
Patrones útiles y errores comunes al coordinar con mensajes
Patrón: “Controlador emite, sprites reaccionan”
Un solo sprite (o el escenario) puede actuar como “director” del flujo: emite SCENE_TO_GAME, GAME_INIT, GAME_START, GAME_OVER. Los demás sprites no se llaman entre sí; solo escuchan señales relevantes.
Patrón: “Mensajes de dominio” vs “mensajes de efectos”
- Dominio:
LEVEL_UP,GAME_OVER,COIN_COLLECTED. - Efectos:
SFX_COIN,FX_CONFETTI,UI_POPUP.
Separarlos evita que la lógica del juego quede mezclada con detalles audiovisuales.
Error común: usar “enviar y esperar” con receptores que nunca terminan
Si un receptor de un mensaje tiene un comportamiento continuo (por ejemplo, un bucle que corre “para siempre”), entonces enviar [X] y esperar puede quedarse esperando indefinidamente. Para mensajes que activen comportamientos continuos, suele ser mejor enviar [X] y que el receptor gestione su propio ciclo.
Error común: mensajes demasiado específicos
Si creas mensajes como HIDE_SPRITE_A_SHOW_SPRITE_B, estás acoplando el emisor a la implementación. Prefiere mensajes de intención como SCENE_TO_END o GAME_OVER, y deja que cada sprite decida cómo responder.
Mini-checklist para mantener claridad en proyectos medianos
- ¿Existe una lista corta de señales principales (
GAME_INIT,GAME_START,GAME_OVER, escenas)? - ¿Los nombres están en mayúsculas y describen intención?
- ¿Los efectos (sonido/partículas/UI) reaccionan a señales sin que la lógica los invoque directamente?
- ¿Se usa
enviar y esperarsolo cuando realmente se necesita sincronización? - ¿Cada sprite tiene una responsabilidad clara al recibir cada mensaje?