// Act 1 — Problem (0–5s): kinetic captions, waveform, chat scroll
function Act1Problem() {
return (
);
}
function Act1Inner() {
const { localTime } = useSprite();
const t = localTime;
// Waveform animated bars — breathing curve, not noise
const breath = Easing.easeInOutSine(clamp(t / 5, 0, 1));
const bars = [];
for (let i = 0; i < 64; i++) {
const phase = i * 0.3 + t * 4;
const dist = Math.abs(i - 32);
const envelope = 1 - dist / 40;
const h = 8 + (Math.abs(Math.sin(phase)) * 60 + Math.abs(Math.sin(phase * 1.7)) * 40) * envelope * (0.5 + breath * 0.7);
bars.push(h);
}
// LIVE badge pulse — sine eased
const pulse = 0.7 + Easing.easeInOutSine((Math.sin(t * 6) + 1) / 2) * 0.3;
// Fake chat lines that scroll — diegetic stream chat (no brand rules apply)
const chatLines = [
{ u: 'gabriela_91', m: '🔥🔥🔥', c: '#F59E0B' },
{ u: 'el_madmax', m: 'NO J*DAS', c: '#EA580C' },
{ u: 'streamfan', m: 'guarda eso pa shorts', c: '#9061f9' },
{ u: 'ana_pdcst', m: 'quéeee', c: '#F59E0B' },
{ u: 'kevin_g', m: 'clip clip clip', c: '#EA580C' },
{ u: 'mariana', m: 'épico jaja', c: '#9061f9' },
];
const visibleChat = Math.min(6, Math.floor(t * 2.4));
// Captions per phase — 3 cápsulas, primera arranca en t=0.0
const captions = [
{ t: 0.0, end: 1.8, text: '3 horas de stream.' },
{ t: 1.9, end: 3.4, text: '0 clips publicados.' },
{ t: 3.5, end: 5.0, text: 'La competencia publica a diario.' },
];
return (
{/* Vignette */}
{/* "Stream" panel — left half, flush with chat */}
{/* Header bar */}
directo · 03:24:18
2.847 espectadores
{/* Waveform area */}
{bars.map((h, i) => {
const dist = Math.abs(i - 32);
const fade = Math.max(0.2, 1 - dist / 32);
return (
);
})}
{/* "Highlight detected" floating tag — appears around t=3 */}
{t > 3 && t < 6 && (
● momento detectado
)}
{/* Stream label placeholder */}
Título del directo
Probando el nuevo update · gameplay caótico
{/* Chat panel — flush against stream panel (sin gap), unidos como una pieza */}
Chat en directo
{chatLines.slice(0, visibleChat).map((c, i) => (
{c.u}
{c.m}
))}
{/* Kinetic captions — bottom center, eased */}
{captions.map((c, i) => {
if (t < c.t || t > c.end) return null;
const local = t - c.t;
const dur = c.end - c.t;
let opacity = 1;
let ty = 0;
let scale = 1;
if (local < 0.3) {
const k = Easing.easeOutCubic(local / 0.3);
opacity = k;
ty = (1 - k) * 30;
scale = 0.92 + k * 0.08;
} else if (local > dur - 0.3) {
const k = Easing.easeInCubic((dur - local) / 0.3);
opacity = k;
ty = -(1 - k) * 20;
}
return (
{c.text}
);
})}
);
}
window.Act1Problem = Act1Problem;