Orquestador de Escenas#
Una escena aquí es un clip cinemático horneado a un flipbook de PNG: un mp4 importado
una vez (ffmpeg lo extrae cuadro a cuadro en el momento de importar) y reproducido como una
secuencia plana de imágenes, exactamente igual que una animación de personaje. No es lo
mismo que una cinemática (core/cutscene.js, autorada por el Editor de Cinemáticas): una
cinemática es una lista ordenada de pasos escriptados del motor (caminatas de NPC, líneas de
SAY, esperas) delimitada a una sola sala. El paso PLAYSCENE de una cinemática reproduce
una escena del Orquestador de Escenas como uno de sus pasos y bloquea hasta que termina; las dos
herramientas editan dos formas de datos distintas y no son intercambiables. No hay ningún
códec de video en el runtime, por diseño (ver la nota de cierre): una escena es solo cuadros
PNG avanzando sobre un reloj, así que se reproduce igual en cada plataforma que el motor
soporta, incluidos los ports que no pueden depender de <video>.
Llegas a él desde el Hub (con el dev server corriendo). La barra de herramientas tiene un desplegable Escena, + Nuevo, Guardar (Ctrl+S, escribe el descriptor y lo registra), un gestor de Clips, una herramienta Replace Color (cuentagotas + tolerancia/mezcla, hornea un PNG recoloreado para un clip), Deshacer/Rehacer, y GC (barre los recursos de escena sin usar a una carpeta de basura reversible). La columna izquierda es una vista previa (con paneo/zoom y controles de transporte) sobre una línea de tiempo de pistas; el panel derecho muestra propiedades de lo que esté seleccionado: pista, keyframe o cue.
Al volver, el editor reabre la escena que estabas editando en vez de la primera de la lista. Un enlace desde otro editor siempre le gana a esa memoria; un enlace a una escena que ya no existe cae a esa memoria, y solo si tampoco existe, a la primera. Se lleva por proyecto.
Límites: cuánto video cabe en una escena#
Esta sección habla de las pistas de Clip, los flipbooks de PNG. Para material de más de unos segundos usa una pista de Video (ver Pistas de video más abajo): reproduce el mp4 directamente y ninguno de estos límites le aplica.
Una pista de Clip reproduce cuadros PNG, y el player decodifica todos los cuadros de todos los clips de la escena antes de arrancarla: eso es lo que hace que se vea igual en todas las plataformas, y también es el techo. El presupuesto que importa no es el tamaño del mp4 sino cuadros × ancho × alto × 4 bytes ya decodificados. El importador muestra esa cifra junto a la estimación de disco y la usa como compuerta: ámbar arriba de 1 GB (carga, pero lento, y una máquina modesta puede no lograrlo), rojo arriba de 3 GB (el import se rechaza; baja los fps o la escala, o recorta). El mismo límite se aplica durante el import mismo, así que no hay forma de colar un clip.
En segundos, con los tamaños de cuadro y las tasas que más vas a usar:
| Tamaño de cuadro | fps | cómodo (≤ 1 GB) | límite duro (3 GB) |
|---|---|---|---|
| 1920 × 1080 | 24 | ~5 s | ~16 s |
| 1920 × 1080 | 12 | ~11 s | ~32 s |
| 960 × 540 | 24 | ~22 s | ~65 s |
| 960 × 540 | 12 | ~43 s | ~2 min |
Las escenas son para piezas cinemáticas cortas: un logo, una title card, unos segundos de movimiento. Lo más largo va en un editor de video, recortado a las piezas que de verdad necesitas.
Cómo grabar para importar (OBS o cualquier grabador de pantalla):
- Resolución = la de tu proyecto (1920 × 1080 para un proyecto 1080p), nunca mayor. Un cuadro más grande se escala al dibujar de todos modos; solo cuesta disco, RAM y tiempo de import. Si le pasas una grabación 4K, el importador baja la escala solo para ajustar al ancho del proyecto.
- 24 a 30 fps. A 60 fps duplicas los cuadros sin ganancia visible en un flipbook. El importador remuestrea a los fps que elijas, así que una fuente a 60 funciona, solo decodifica el doble de cuadros.
- El bitrate casi no importa. Cada cuadro se decodifica completo al importar, así que un master de alta calidad no cuesta nada extra; lo que pesa es la cantidad y el tamaño de los PNG en que se convierte.
- Clips de segundos, no de minutos, y recorta en el importador (desde + cantidad) cuando la grabación trae más que la toma que quieres.
Anatomía de una escena#
Un descriptor de escena ({ id, duration, bg?, format?, endMode?, keepMusic?, onEnd?, tracks: [...] })
es un objeto de datos
puro, serializado como un pequeño módulo ES y guardado en projects/<id>/scenes/<sceneId>.js.
Guardar también agrega, de forma idempotente, una entrada a core/scenes/index.js, pero ese
archivo es solo un mapa chico id→descriptor; en la práctica el runtime nunca necesita ese
registro hecho al guardar, porque _ensureScene() de shell/main.js importa dinámicamente el
descriptor de forma perezosa en el primer PLAYSCENE/REWINDSCENE y lo registra ahí. El core
queda totalmente desacoplado de las rutas del proyecto.
bg es un campo con dos significados, y el editor entiende los dos: un color CSS
(#101018, rgb(10,200,30), hsl(210,90%,40%)) rellena el lienzo con ese color, y cualquier
otra cosa se toma como la ruta de una imagen relativa al proyecto
(assets/rooms/cocina.png), que se dibuja estirada al tamaño de la escena. Si la ruta no carga,
el fondo queda negro, igual que si no pusieras bg, así que un archivo que falta nunca hornea un
cartel de depuración dentro de un export. El fondo lo pinta el mismo código en la vista previa y
en Exportar MP4, así que lo que ves en el lienzo es lo que queda en el video.
Una escena tiene seis tipos de pista, todas compartiendo una sola línea de tiempo:
- Pistas de clip (la opción por defecto, sin
kind; en el editor se llaman Clip): un clip (unFrame[]con nombre, del registro de clips del proyecto) más una lista de keyframes ({ t, x, y, scale, rot, alpha, ease }) que maneja una curva de transformación independiente encima de la reproducción cuadro a cuadro propia del clip.in/outacotan cuándo la pista es visible en el tiempo de la escena;zordena las capas;anchory un preset opcional defx(un filtro visual por clip, resuelto a un filtro real solo en el shell) completan el cuadro; unlaneopcional nombra la fila del timeline que la pista comparte con otras (campo solo del editor, ver Canales más abajo; el runtime nunca lo lee); unspeedopcional escala la reproducción de cuadros del propio clip (ver Velocidad de la pista más abajo). Aquí corren dos relojes en paralelo: la línea de tiempo maestra (keyframes, navegable, con ease) y el reloj interno del clip (ciclo de cuadros, reusando exactamente el mismo primitivotickAnim()que usan las animaciones de personaje). El registro en sí (scenes/clips.js) es unFrame[]plano por clip ({ sprite, ms }por cuadro). Una entrada con cualquier otra forma aparece como omitida en el gestor de Clips, con su id, y se vuelve a escribir intacta cuando guardas, nunca se pierde. Guardar también conserva el encabezado de comentario del propio archivo, así que un registro que escribió un script generador (con su nota de "no editar a mano" arriba) sigue diciéndolo después de que lo toques en el editor. - Pistas de video (
kind: 'video'): un mp4 real (src) que reproduce el decodificador de video de la plataforma en lugar de un flipbook de PNG, con los mismos keyframes,z,anchor,fx,in/outyspeedque una pista de clip, mástrimStart,volymutedpara su audio integrado. Ver Pistas de video más abajo. - Pistas de audio (
kind: 'audio'): un clip de audio posicionado y recortable (src,at,trimStart/trimEnd,vol,fadeIn/fadeOut,muted). Cuando el reloj maestro cruzaat, dispara un único token, disparado por flanco,SCENEAUDIO:<src>|<trimStart>|<dur>|<vol>|<fadeIn>|<fadeOut>; el shell lo reproduce como un one-shot en el bus de música (GameAudio.playMusic), detenido automáticamente (con el propio fade-out del clip) cuando termina la escena, salvo que la escena tengakeepMusic(ver Cómo termina una escena). - Pistas de cue (
kind: 'cue'): una lista de pares{ t, token }, tokens de efecto arbitrarios disparados en el instante en que el reloj maestro llega at. Así es como una escena dispara cualquier cosa a mitad de reproducción (una flag, un sonido, un warp de sala) sin esperar a que la escena termine. - Pistas de FX (
kind: 'fx'): un preset de filtro de pantalla completa (glitch/blur/etc.) con su propia ventanain/outyopacity, dibujado sobre todo el cuadro en vez de como un sprite posicionado. El preset Pixelado corre exactamente la misma matemática que el tokenADJUST:pixelatedel juego, con las mismas perillas: bloque (px, 1 a 16), niveles por canal (2 a 256), fuerza (0 a 1), dither (none / b4 / b8) y reducción (area = suave, nearest = duro). Bloque, niveles y fuerza aceptan keyframes, así que una escena puede disolverse desde (o hacia) un look de baja resolución con el tiempo. No hay perilla de "alcance": lazde la pista ya dice qué capas quedan bajo el efecto. El export a MP4 pinta por el mismo camino que el preview, así que el pixelado también llega al video. - Pistas de texto (
kind: 'text'): un rótulo o título en pantalla. Como una pista de sprite lleva una lista de keyframes (posición, escala, rotación, alpha en el tiempo, con easing por segmento) y unz, pero en vez de un clip dibuja una línea de texto con un lote completo de estilo: fuente y tamaño, color, alineación, negrita / cursiva / subrayado / tachado, un contorno (outlineWidth), una sombra, ylineHeight/letterSpacing. El texto en sí se autora monolingüe y va respaldado por unlid, así el Editor de Traducción completa los demás idiomas después, la misma regla content-i18n que las líneas habladas y los nombres de objeto. Se renderiza idéntico en el preview del editor, la exportación MP4 y en el juego (el core lleva la forma; el shell resuelve ellidy elfont).
El cuadro de la escena: una forma por escena#
Por defecto una escena se autora y se exporta a la resolución del proyecto, y eso sigue valiendo para todas las escenas que ya tienes. El selector formato del panel de escena deja que una escena elija su propia forma: 9:16 (1080x1920), 1:1 (1080x1080), 4:5 (1080x1350) o 16:9 (1920x1080). Si eliges proyecto, la escena vuelve a seguir al proyecto.
Lo que cambia el formato es el cuadro en el que trabajas: el lienzo de la vista previa, Fill y
Fit, y el tamaño del MP4 exportado. Así, un mismo proyecto puede tener promo_1x1 y
promo_9x16 conviviendo, dos armados de las mismas fotos, compartiendo un solo registro de
clips y una sola tabla de textos. El formato es cosa de autoría y exportación: una escena que se
reproduce dentro de un juego sigue corriendo a la resolución del proyecto.
Al lado de los controles de zoom hay un botón de zona segura (el cuadrito). Préndelo y la vista previa oscurece la franja donde una superficie a pantalla completa pone su propia interfaz encima de tu video, con una línea punteada marcando lo que queda a salvo. Es una guía solo para tus ojos: se dibuja después del cuadro, así que no puede terminar en un video exportado. Las formas que no reservan nada (un post cuadrado o horizontal, donde el texto y los botones van fuera de la imagen) no tienen nada que mostrar, y para ellas el botón queda apagado.
Duplicar a formato... (en el panel de escena, debajo del selector) crea una segunda escena
en otra forma. Eliges el formato y un modo, y el id se completa solo como <escena>_<formato>:
- Cover llena el cuadro nuevo por su eje dominante, así una foto a sangre queda a sangre y los bordes del armado se van para afuera.
- Contain mete el armado completo dentro del cuadro nuevo, con márgenes.
Todo lo que se mide en píxeles se reencuadra con el mismo factor: posiciones, escala, tamaño de texto, grosor del contorno, espaciado entre letras y los desplazamientos de la sombra. Los tiempos, los colores, los clips, los lids y los tokens se copian tal cual. Toma el resultado como un punto de partida que acomodas a mano, no como un armado terminado: un título que entraba en una línea en el cuadrado suele querer dos en el vertical. La copia se hace de lo que está en pantalla, así que si la escena tiene cambios sin guardar se guardan primero. Si ese guardado falla, no se hace la copia y te quedas en la original.
Edición en la línea de tiempo#
Dos herramientas de puntero viven en la barra. ➤ Seleccionar (V) es la default: haz clic en una pista o clip para seleccionarlo, arrastra para moverlo por su carril. ✂ Cortar (C) parte un clip en el marcador del cabezal: haz clic en cualquier clip y se vuelve dos clips consecutivos. Cada mitad reinicia su propia reproducción desde el frame 0, así que un corte es una partición genuina en dos clips independientes, no un recorte de uno. Las dos mitades se quedan en la fila del clip: si el clip todavía no estaba en un canal, el corte le abre uno con su nombre, así que cortar nunca agrega una fila. El video es el único clip que no reinicia: la segunda mitad retoma el video justo donde cortaste (su inicio de recorte se ajusta solo, velocidad incluida), así que un video cortado se ve igual que antes y puedes meter algo entre las dos mitades.
⧉ Duplicar (en las propiedades de la pista, o ⌘D en Mac y Ctrl+D en Windows) pone una copia
del clip seleccionado justo después de él, en la misma fila: la misma z, el mismo clip y sus
keyframes corridos con él. Si ese hueco ya lo ocupa otro clip del canal, la copia va al final del
canal, que puede quedar después del final de la escena; la barra de estado lo avisa y no se mueve
nada más. La copia de una pista de texto lleva su propio texto, así que editar una no cambia la
otra. La copia de un video reproduce el mismo tramo del video que el original. Las pistas de cue no
se duplican.
Las filas se reordenan verticalmente: agarra el encabezado de una fila y arrástralo arriba o
abajo a un nuevo lugar, y el editor renumera el z según el orden resultante de arriba hacia abajo;
lo que ves apilado en la línea de tiempo es el orden de pintado en pantalla. Arrastrar
verticalmente la barra de un clip hace otra cosa: mueve esa pista a otra fila (ver Canales).
Canales: varios clips en una fila#
Por defecto cada pista es su propia fila, así que un trailer hecho de imágenes fijas se vuelve
rápido una torre de filas (43 para un trailer de 50 segundos). Un canal agrupa pistas del mismo
tipo (sprite, video, texto o fx) en una fila con varias barras, igual que una pista de video en un
editor de video. Por debajo no cambia nada: cada barra sigue siendo una pista completa con su id,
su clip, sus keyframes y su in/out; lo único que el canal se queda es la z, que pasa a ser de
la fila; todos los miembros la comparten, y dentro del canal la barra que empieza después se pinta
después (el editor mantiene a los miembros ordenados por in). Es justo lo que necesita una
disolvencia: dos barras pueden solaparse dentro de un canal, y la que entra baja unos píxeles
con el tramo solapado rayado, para que se lea de un vistazo. Una pista sin lane se comporta como
siempre, así que las escenas existentes cargan sin cambios.
Formas de meter una pista en un canal:
- Arrastrar su barra verticalmente a otra fila. Sobre un canal del mismo tipo, se une (y adopta
la
zde la fila); sobre una pista suelta del mismo tipo, las dos forman un canal nuevo con el nombre de esa pista; debajo de la última fila, sale del canal y recupera una fila propia. Los tipos nunca se mezclan en una fila: un clip PNG y un video nunca comparten una. - Soltar un clip del gestor de Clips sobre un canal de sprites: la pista nueva cae en ese canal en vez de abrir una fila nueva.
- El campo canal en las propiedades de la pista: elige un canal existente, (fila propia) o
Nuevo canal…, y escribir el id de un canal que ya existe se une a él, con las mismas reglas
que arrastrar (los tipos no se mezclan, se adopta la
zde la fila). Para un miembro de canal lazse muestra sin editar; reordena filas para cambiarla. - ▤ Compactar en canales, en el panel de la escena, agrupa las pistas de sprite, video, texto y fx en
el mínimo de filas que respeta el orden de pintado autorado (una barra entra a una fila solo si
no se solapa con nada de ahí más de 300 ms, ni con nada de una fila de arriba), y luego renumera
la
zpor fila. Es una edición normal (Ctrl+Z la deshace) y los cuadros que renderiza la escena son idénticos antes y después (medido tick a tick sobre el trailer de Ignitor: 43 filas → 16, cero cuadros distintos). Volver a correrlo sobre una escena ya compacta no cambia nada: los canales conservan su nombre. El audio no se toca (ver Canales de audio).
El encabezado de la fila muestra el nombre del canal y cuántas barras tiene; su ojo y su candado
afectan a todos los miembros, y el deslizador α edita la barra que está bajo el cabezal.
✂ Cortar y ⧉ Duplicar funcionan dentro de un canal (el clip nuevo se queda en él), y un doble
clic inserta un keyframe en la barra bajo el puntero. Los canales se guardan como el campo lane
de cada pista y el runtime, la exportación a MP4 y el port a Godot lo ignoran, así que una escena
con canales se reproduce exactamente igual que una sin ellos.
Canales de audio#
Los clips de audio también pueden compartir una fila, como un canal en un DAW: una música de fondo
partida en dos tomas, o una voz en off hecha de varias líneas. Un canal de audio solo agrupa la
fila; el audio no tiene z, así que no hay nada que el canal se quede. Sus clips se mantienen
ordenados por inicio, y donde dos se solapan simplemente se mezclan: el solape es el crossfade (la
barra que entra baja unos píxeles para que los dos bordes se sigan leyendo). Se arma a mano, porque
▤ Compactar en canales nunca toca el audio: arrastra la barra de un clip verticalmente sobre
otra fila de audio, o usa el campo canal en las propiedades del clip de audio. Los tipos no se
mezclan, así que un clip de audio no puede unirse a una fila de sprites o de texto.
En el encabezado de un canal de audio, el botón M (silenciar) y el deslizador de volumen 🔊 actúan sobre un clip: el seleccionado, o el que está bajo el cabezal si la selección está en otro lado. El candado cubre la fila entera. Un clic en un tramo vacío de un canal de audio mueve el cabezal y conserva la selección.
Donde dos clips se tocan, los dos bordes quedan a unos pocos píxeles, así que se agarra el borde del clip seleccionado: para recortar el final del primero, haz clic en su cuerpo y después arrastra la costura. Sin nada seleccionado, se agarra el inicio del que empieza después.
Cuando dos clips de audio se solapan en el tiempo, aparece un helper ⤬ crossfade en las
propiedades del clip seleccionado: un clic fija el fadeOut del clip anterior y el fadeIn del
posterior al largo del solape, convirtiéndolo en un crossfade estilo DAW hecho con los campos de
fade que el runtime ya reproduce, sin tipo de pista nuevo, sin datos especiales. Si el clip se
solapa con varios, el helper lo empareja primero con su vecino del mismo canal.
El preview reproduce las pistas de audio con precisión de muestra: todos los clips se agendan sobre el mismo reloj de audio, el cabezal sigue lo que estás oyendo y los fades son las mismas rampas lineales que aplica la exportación a MP4. Una costura o un crossfade de 10 ms que ajustes de oído en el editor suena igual en el video exportado.
Pistas de video#
+ Video (en el panel de la escena, o +🎞 arriba de la línea de tiempo) abre la lista de
videos del proyecto y un botón Importar un video…. Sirve cualquier formato común (mp4, mov,
webm…): al importarlo se convierte con ffmpeg a H.264 + AAC, hasta 1080p y 30
fps, y se guarda en assets/video/. La conversión es a propósito: es la única combinación que
todas las plataformas pueden reproducir, así que un juego nunca se topa con un video que su player
no puede decodificar. Esa conversión necesita ffmpeg, y lo dice antes de tomarte el archivo en
vez de después. Ignitor no trae ffmpeg, pero encuentra solo el que instalaste: en el PATH, o donde
lo dejan Homebrew, MacPorts, winget, Chocolatey o Scoop. Si no encuentra ninguno, + Video te
avisa de entrada, antes de subir nada: instálalo (brew install ffmpeg en una Mac) o, si el tuyo
está en otra carpeta, indica su ruta en Hub Config → ffmpeg. Y un import que falla se limpia
solo: ya no deja una carpeta a medio convertir dentro del proyecto. La pista nueva empieza en el cabezal, dura lo que dura el video, se ajusta a
la pantalla, y la escena crece si el video se pasa de su final.
En las propiedades de la pista: inicio de recorte (desde qué punto del video empezar), volumen y sin sonido para el audio del video, más todo lo que tiene una pista de clip (anchor, filtro por clip, z, entrada/salida, velocidad, Fill/Fit y canal: varios videos pueden compartir una fila, ver Canales). Un video que llega a su final se queda en su último cuadro.
Qué esperar:
- La duración no es problema. El decodificador lee el video sobre la marcha, no lo desarma en cuadros, así que una cinemática de minutos cuesta más o menos lo que pesa su archivo.
- Sigue el reloj de la escena, no cuadro por cuadro. Durante la reproducción el video se mantiene a una fracción de segundo del reloj de la escena y se corrige solo cuando se desfasa; en una máquina lenta puede verse un pequeño salto ocasional. Al arrastrar el cabezal o rebobinar se hace seek, así que tarda un instante en llegar al cuadro.
- La exportación a MP4 es exacta pero más lenta. Cada cuadro exportado espera a que el video llegue a él, así que una escena con video exporta varias veces más lento que una sin video.
- En el juego, su sonido sale por el volumen de la música, igual que las pistas de audio de la escena.
- Las exportaciones llevan el mp4 como archivo suelto junto a los assets empaquetados (un video grande dentro del paquete ocuparía la memoria dos veces).
- Plataformas: medido en macOS (el editor y el player exportado) y en Chromium. Windows, Android, dispositivos iOS, Linux y Steam Deck todavía no están verificados, y el port a Godot todavía no reproduce pistas de video.
Velocidad de la pista#
Las propiedades de una pista de clip o de video traen un control de velocidad (%) (25 a 400 %; escribe 96.95 para frenarla 3.05 %). Cambia qué tan rápido pasan los cuadros del clip solo en esta pista: el clip vive en el registro de todo el proyecto y no se toca, así que el mismo clip conserva su ritmo en cualquier otra escena.
Al cambiar la velocidad, la pista se reajusta como en un editor de video: a 50 % su ventana
dura el doble, y cada keyframe desde su in se estira con ella, así el movimiento sigue
alineado con los cuadros. El nuevo out y los tiempos de los keyframes se guardan como números
normales; la duración de la escena no cambia, así que una pista estirada puede pasarse del final
de la escena, donde se corta como cualquier otra. Aplicar a otros tracks… abre una lista de
las demás pistas de clip y de video de la escena y aplica la misma velocidad a las que marques, en un
solo paso de deshacer. Una pista que no está al 100 % muestra su velocidad en la barra (por
ejemplo 0.97×).
En el runtime, speed solo escala el reloj del clip (el in/out y los keyframes guardados ya
traen el estiramiento), y se reproduce igual en la vista previa, la exportación a MP4, en el
juego y en el port a Godot.
El pipeline de tokens de efecto (una sola gramática, un solo despacho)#
Tanto los tokens de cue como la lista onEnd de la escena son tokens de efecto comunes del
mismo manifiesto compartido que usa cualquier otro sistema (reglas, diálogos, cinemáticas),
autorados con el mismo widget de picker tipado, nunca texto libre para un argumento que porte un
ID. La lista de verbos que se muestra aquí está curada para el contexto de escena: oculta tokens
que solo tienen sentido dentro de la lógica de sala en vivo (scroll de inventario, restaurar
hotspot, guardar/cargar, recoger ítem) y promueve arriba los verbos de warp de sala / audio /
flag / diálogo / cinemática / escena; los pickers de cue además promueven primero el cuarteto de
audio (SOUND/MUSIC/STOPMUSIC/PLAYFX), ya que un cue a mitad de escena casi siempre es un
golpe de audio.
onEnd guarda una lista, y sus filas llevan un asa ⠿; arrastra una para cambiar el orden en
que se disparan los tokens al terminar la escena. Un cue no tiene asa a propósito: guarda una
sola ranura de token, así que no hay nada que reordenar; a un cue lo mueves en el tiempo
arrastrándolo por su pista.
WAIT y WAITFOR quedan afuera por otro motivo: una escena es una línea de tiempo, así que
sus beats se espacian moviéndolos por la pista, no pausando entre tokens. Cuando la demora
pertenece al juego en vivo (una línea hablada que necesita un momento antes de que cambie la
sala), eso es una cadena de reacción, y ahí las dos esperas sí están disponibles.
En runtime, el tickScene() puro de core/scenes/timeline.js devuelve cada cuadro un arreglo
fired con los tokens que vencieron; shell/main.js los pasa por el mismo despacho
applyEffects() de dos niveles que se usa en todo el motor: los tokens de Nivel 1
(SETFLAG, GIVEITEM, WARPTOROOM, etc.) mutan el estado directamente, y lo que sobra
(SCENEAUDIO, SAY, MUSIC) cae al despachador de acciones genérico. Un solo almacén de
reglas, una sola gramática, sin un intérprete separado solo para escenas.
Cómo termina una escena#
La ventana in/out de cada pista es inclusiva en out: una pista sin out propio hereda
scene.duration y se ve hasta el último milisegundo. Cortar a negro antes del final es decisión
del autor: para eso está el out de esa pista. (Antes, el frame que caía justo en duration
cullaba todas las pistas, así que el último frame de cualquier escena salía negro.)
Dos campos a nivel escena deciden qué pasa cuando el reloj llega a duration:
endMode:'end'(por defecto) termina la escena y devuelve el control al juego.'hold'la deja estacionada ahí: el reloj maestro sigue corriendo, así quetransformAtsostiene el último keyframe y los clips en loop siguen ciclando; la toma final queda viva en vez de congelarse en una foto. Una escena en hold termina solo cuando el jugador la salta (el mismo gesto de mantener presionado, o Escape), yonEndse difiere a ese momento: dispararlo al cruzardurationejecutaría justo elWARPTOROOM/ avance de estructura que saca al jugador de la toma que pediste sostener. Es la escena de créditos clásica: un título volando, música de fondo, hasta que el jugador decide salir.keepMusic: por defecto la música de la escena (una pista de audio o un cueMUSIC:; las dos van al bus de música) se corta al salir. Con este campo sobrevive a lo que venga después: el menú, el siguiente bloque de la estructura, el cuarto que estaba atrás.
Ambos se editan en el panel de la escena y solo se serializan cuando difieren del default, así que una escena que termina de la forma habitual queda byte a byte igual que antes.
Reproducción: saltar y rebobinar#
El jugador puede hacer clic para saltar un paso y mantener presionado para saltar toda
una escena: mantener presionado llena una barra de progreso de ~1.1s, y al completarse el reloj
de la escena se adelanta directo a duration para que el siguiente tick cruce el final de
forma natural y dispare onEnd; el runtime nunca anula la escena activa directamente, así que
onEnd no puede quedar varado por un salto. En una escena con endMode: 'hold', el salto
completado termina la escena directamente (adelantar el reloj solo volvería a entrar al hold).
El aviso de todo esto ya no aparece encima del primer frame: sale hasta la primera tecla o clic del jugador durante la escena. Una escena en hold además lo muestra sola tras unos segundos estacionada en el final, para que nadie se quede en los créditos sin saber cómo salir.
REWINDSCENE:<sceneId>[|speed=N] (velocidad por defecto 2) reproduce una escena hacia
atrás con una estética VHS, manejada por el seekScene() puro, un render sin efectos
secundarios en un tiempo absoluto y decreciente. Esto es solo visual: seekScene no dispara
ningún token de cue, audio, u onEnd mientras rebobina, por construcción (nunca toca
sceneState ni el arreglo fired). No hay UI de autoría para esto en el propio Orquestador de
Escenas; es un token a nivel de runtime, alcanzable desde el slot de efecto raw de una
cinemática (la vía de escape del Editor de Cinemáticas) o desde cualquier otro lugar donde se
pueda despachar un token, no es una pista o tipo de paso propio aquí.
Audio mientras corre una escena#
Una escena es dueña del paisaje sonoro: arrancar una agacha (duck) de inmediato el ambiente
de la sala (antes incluso de que termine la carga asíncrona del clip, así nada se cuela debajo
de una escena durante el hueco de carga), y el ambiente se reanuda apenas la escena termina,
incluidas las salidas anormales (un rebobinado que termina, o una carga fallida). Las propias
pistas de audio de una escena viajan por el bus de música compartido vía SCENEAUDIO y no se
ven afectadas por el ducking, ya que son parte intencional de la escena, no de la sala.
La exportación a MP4 lleva ese audio. El Exportar MP4… del panel de escena mezcla las
pistas de audio de la escena dentro del archivo con ffmpeg, respetando la posición, el recorte, el volumen y los fades
de cada una, así que el video exportado suena como el preview. Dos detalles que conviene saber:
una pista silenciada se exporta en silencio, igual que se previsualiza (no hay un silencio
aparte para la exportación), y una pista que se pasaría del último cuadro se corta al largo del
video, nunca al revés (la cantidad de cuadros es la que define cuánto dura el archivo). El sonido
propio de una pista de Video todavía no se mezcla; solo entran las pistas kind: 'audio'. Si
una pista no se puede mezclar (el archivo se movió, o este ffmpeg no puede escribir AAC), la
exportación igual produce el video y te dice qué pista quedó fuera, en vez de tirar el render.
Importar un clip desde video#
Clips → NUEVO CLIP DESDE EL SISTEMA DE ARCHIVOS arma un clip con PNG del disco (es también lo
que abre + Clip → 📁 Desde el sistema de archivos…). El navegador arranca en la carpeta del
proyecto, con atajos a tus unidades en Windows, o a tu carpeta personal, Desktop, Downloads,
Documents y / en una Mac; ↑ sube un nivel. Haz clic en los PNG para elegir los cuadros
(conservan el orden de la carpeta), ponle nombre al clip y presiona + Agregar clip. Los archivos
de fuera del proyecto se copian a assets/scenes/<clip>/, así que el clip viaja con él.
Clips → NUEVO CLIP DESDE VIDEO elige un mp4 y lo extrae en un modo escena que se salta
los pasos exclusivos de personaje (limpieza de chroma key, anclaje al lienzo del personaje) y
escribe los cuadros completos en assets/scenes/<clip>/. Perillas: fps (remuestreo; una
cinemática estilizada suele vivir en 12 a 15 fps), escala (1× / 0.75× / 0.5×, preajustada
para caber en el ancho de tu proyecto cuando la fuente es más ancha), y un recorte de
entrada/salida (desde + cantidad). Tres presets (Ligero 12fps·0.5×, Equilibrado
15fps·0.75×, Calidad 24fps·1×) fijan las dos primeras de un golpe.
Preview frame 0 hace más que mostrar una miniatura: muestrea un puñado de cuadros repartidos por el clip para medir cuánto pesan de verdad los PNG (un primer cuadro oscuro, solo, puede errar por una cuarta parte), y lee el tamaño, los fps y la duración del clip. Desde ahí, la línea bajo los botones muestra los dos costos en vivo mientras mueves las perillas: disco (≈ MB, cuadros × bytes por cuadro) y RAM al reproducir la escena (la cifra decodificada de la que hablan los límites de arriba), y se pone ámbar o roja con la compuerta.
El import corre junto a su destino: los cuadros se extraen directo a una carpeta de trabajo al
lado de assets/scenes/<clip>/, en el disco del proyecto (nunca en la carpeta temporal del
sistema), la barra de progreso sigue a ffmpeg cuadro por cuadro, y al final la carpeta terminada
se pone en su lugar. Antes de arrancar, el importador compara el espacio libre de ese disco con
la estimación y se niega de entrada en vez de fallar a la mitad. Las fuentes opacas se escriben
como RGB; el alpha se conserva solo cuando el video de verdad lo trae. Al importar, el clip nuevo
se agrega al registro de clips del proyecto (persistido la próxima vez que guardes desde el
gestor de Clips). El ffmpeg que se usa es el que apuntaste en Hub Config, o el que Ignitor
encuentra solo (PATH, Homebrew, winget…).
Flujo de trabajo#
- Elige una Escena existente o + Nuevo para arrancar una en blanco.
- Clips → NUEVO CLIP DESDE VIDEO para traer metraje cinemático (o reusa un clip existente), luego +🎬 / +🔊 / +✨ en la línea de tiempo para agregar una pista de sprite, audio, o FX de pantalla completa, más Agregar texto / Agregar trigger desde el panel de agregar pista para un rótulo o una pista de cue.
- Para una pista de sprite, coloca keyframes en la línea de tiempo para mover/escalar/
rotar/desvanecerla en el tiempo, con ease por segmento; arrastra sus manijas
in/outpara acotar su visibilidad. - Agrega tokens de cue en momentos específicos para golpes a mitad de escena (sonido,
flags, warps); define la lista
onEndde la escena para lo que pasa cuando termina. - Previsualiza con los controles de transporte (reproducir/pausar, rebobinar/avanzar al
final, detener) y la línea de tiempo con zoom; usa Replace Color si necesitas una
variante recoloreada de un PNG importado. Exportar MP4… (panel de escena) renderiza la
escena fuera de línea a una tasa de cuadros fija y la codifica con ffmpeg: el preview y la
exportación comparten el mismo dibujado, así que lo que ves es lo que obtienes. Los dos
siguen el
render.pixelArtdel proyecto: un proyecto pixel-art escala vecino más cercano, uno de arte suave (pixelArt: false) escala bilineal, así que un zoom lento sobre una foto o una captura se exporta suave y no pixelado. - Guardar: escribe
projects/<id>/scenes/<sceneId>.jsy registra el id. - Cabléalo desde un token
PLAYSCENE:<id>(oREWINDSCENE:<id>) en cualquier lugar donde se pueda disparar un token. Lo más común: un pasoPLAYSCENEdel Editor de Cinemáticas, una reacción de hotspot, o un bloque scene del Diseñador de Estructura del Juego.
Los tiempos de cue y keyframe de una escena quedan horneados contra la cantidad de cuadros y el fps del clip importado en el momento de la importación. Cada
ten un cue, un keyframe, o una ventanain/outes un offset absoluto en milisegundos dentro del reloj maestro de la escena; no queda ninguna relación de vuelta al mp4 original una vez que los cuadros están extraídos. Volver a importar una versión recortada o re-codificada del mismo metraje (fps distinto, puntos de recorte distintos) produce una secuencia de cuadros nueva cuyo tiempo ya no coincide con los cues y keyframes autorados contra la anterior: van a disparar antes, después, o sobre cuadros en blanco. Trata un clip importado como definitivo antes de gastar tiempo colocando cues y keyframes contra él; si tienes que reimportar, espera tener que revisar cada cue y keyframe de las pistas que usan ese clip.