// 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 */}
EN VIVO
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;