Lied 3: Pino legt die Blume ab, Stampfen im Takt, jede Strophe an einem anderen Ort (Garten, Waldrand, Wiese)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lara 2026-11-09 09:40:34 +00:00
parent 36aabd55f5
commit 704bdcd0a3

View file

@ -53,6 +53,14 @@ const KAMERA: [number, number, number, number][] = [
[T.c5, 1120, 660, 1.3], [T.c5, 1120, 660, 1.3],
[T.ende, 1120, 640, 1.2], [T.ende, 1120, 640, 1.2],
]; ];
// Orte der Strophen (Überblendung 0,8 s); ES/FR haben keine Strophe 4
const ORTE = [
{name: 'garten', von: T.v1 - 0.4, bis: T.c2 - 0.4}, // Apfel und Blume: Garten mit Holzstapel
{name: 'waldrand', von: T.v2 - 0.4, bis: T.c3 - 0.4}, // laut/leise und schnell/langsam: am Waldrand
...(T.v4 !== undefined ? [{name: 'garten', von: T.v4 - 0.4, bis: T.m - 0.4}] : []),
{name: 'oben', von: T.gag - 0.4, bis: T.c4 - 0.4}, // Gag: auf der Wiese mit den kahlen Bäumen
];
const kamera = (f: number) => { const kamera = (f: number) => {
const p: [number, number, number, number][] = []; const p: [number, number, number, number][] = [];
KAMERA.forEach(([t, x, y, z], i) => { KAMERA.forEach(([t, x, y, z], i) => {
@ -244,7 +252,21 @@ const Garten: React.FC = () => {
const noaZeigtLinks = karte >= 0 && KARTEN[karte].zeigt[f >= s(KARTEN[karte].antwort - 0.2) ? 1 : 0] === 'links'; const noaZeigtLinks = karte >= 0 && KARTEN[karte].zeigt[f >= s(KARTEN[karte].antwort - 0.2) ? 1 : 0] === 'links';
// Strophe 1: Pino pflückt die Blume – sie fliegt in seine Pfote und bleibt dort bis in Refrain 2 // Strophe 1: Pino pflückt die Blume – sie fliegt in seine Pfote und bleibt dort bis in Refrain 2
const pflueck = interpolate(f, [s(T.v1z[3]), s(T.v1z[3] + 0.8)], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); const pflueck = interpolate(f, [s(T.v1z[3]), s(T.v1z[3] + 0.8)], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'});
const blumeBeiPino = imAbschnitt(f, T.v1z[3], T.c2 + 9); // … und legt sie zu Beginn von Refrain 2 neben sich ins Gras, wo sie verblasst
const blumeBeiPino = imAbschnitt(f, T.v1z[3], T.c2 + 3);
const ablegen = interpolate(f, [s(T.c2 - 0.3), s(T.c2 + 0.5)], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'});
const blumeWeg = interpolate(f, [s(T.c2 + 1.5), s(T.c2 + 3)], [1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'});
// Strophe 3: Stampfen im Takt – Noa und Lulu treten auf, alle federn beim Aufsetzen ein
// („Stampf mit mir“: jeder Schlag, „Stampf ganz langsam“: jeder zweite Schlag)
const stampfPhase = (von: number, bis: number, jeden: number) => {
if (!imAbschnitt(f, von, bis)) return 0;
const p = (((f - s(von)) / (SCHLAG * jeden)) % 1 + 1) % 1;
return p < 0.35 ? Math.sin((p / 0.35) * Math.PI) : 0; // kurzer Hub, dann Aufsetzen
};
const stampf = Math.max(stampfPhase(T.v3z[1], T.v3z[2], 1), stampfPhase(T.v3z[3], T.c3, 2));
const stampfHub = -24 * stampf;
const einfedern = 1 - 0.06 * (stampf > 0 ? 1 - stampf : 0);
const pinoGross = interpolate(f, [s(T.gag + 1), s(T.gag + 1.6), s(T.c4 - 0.6), s(T.c4)], [1, 1.25, 1.25, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); const pinoGross = interpolate(f, [s(T.gag + 1), s(T.gag + 1.6), s(T.c4 - 0.6), s(T.c4)], [1, 1.25, 1.25, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'});
// Gag: Pino und Lulu rücken zusammen („Nase an Nase“) // Gag: Pino und Lulu rücken zusammen („Nase an Nase“)
const gagNah = interpolate(f, [s(T.gag + 3), s(T.gag + 4.5), s(T.c4 - 0.8), s(T.c4)], [0, 1, 1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); const gagNah = interpolate(f, [s(T.gag + 3), s(T.gag + 4.5), s(T.c4 - 0.8), s(T.c4)], [0, 1, 1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'});
@ -262,6 +284,15 @@ const Garten: React.FC = () => {
<> <>
<Kamera {...kam}> <Kamera {...kam}>
<Ort name="garten_herbst" /> <Ort name="garten_herbst" />
{/* Abwechslung: jede Strophe an einem anderen Ort, Refrains im Herbstgarten */}
{ORTE.map((o) => {
const sicht = interpolate(f, [s(o.von) - 18, s(o.von) + 6, s(o.bis) - 6, s(o.bis) + 18], [0, 1, 1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'});
return sicht > 0 ? (
<div key={o.von} style={{position: 'absolute', inset: 0, opacity: sicht}}>
<Ort name={o.name} />
</div>
) : null;
})}
<div style={{position: 'absolute', inset: 0, opacity: abend}}> <div style={{position: 'absolute', inset: 0, opacity: abend}}>
<Ort name="garten_herbst_abend" /> <Ort name="garten_herbst_abend" />
</div> </div>
@ -278,13 +309,13 @@ const Garten: React.FC = () => {
<Figur <Figur
pose={LULU} pose={LULU}
x={luluX - 150 * gagNah} x={luluX - 150 * gagNah}
y={BODEN} y={BODEN + stampfHub * 0.6}
drehung={schwank(0.5, 2.2 * ruhig)} drehung={schwank(0.5, 2.2 * ruhig)}
stauchY={(1 - 0.012 * schlag) * luluReck} stauchY={(1 - 0.012 * schlag) * luluReck * einfedern}
blende={8} blende={8}
/> />
)} )}
<Figur pose={NOA} x={NOA_X} y={BODEN + wipp(0.3, 10 * ruhig)} drehung={schwank(0, 3 * ruhig)} spiegeln={noaZeigtLinks} blende={3} /> <Figur pose={NOA} x={NOA_X} y={BODEN + wipp(0.3, 10 * ruhig) + stampfHub} drehung={schwank(0, 3 * ruhig)} stauchY={einfedern} spiegeln={noaZeigtLinks} blende={3} />
{flitzen ? ( {flitzen ? (
<Figur pose={`pino_A_laufen-${1 + (Math.floor(f / 3) % 4)}`} x={pinoX} y={BODEN + wipp(0, 10)} spiegeln={pinoRichtung < 0} /> <Figur pose={`pino_A_laufen-${1 + (Math.floor(f / 3) % 4)}`} x={pinoX} y={BODEN + wipp(0, 10)} spiegeln={pinoRichtung < 0} />
) : ( ) : (
@ -298,7 +329,11 @@ const Garten: React.FC = () => {
blende={8} blende={8}
/> />
)} )}
{blumeBeiPino && <Blume x={640 + (PINO_X + 58 - 640) * pflueck} y={BODEN - 20 + 4 * pflueck} s={0.9 - 0.3 * pflueck} r={-15 * pflueck} />} {blumeBeiPino && (
<div style={{opacity: blumeWeg}}>
<Blume x={640 + (PINO_X + 58 - 640) * pflueck + 40 * ablegen} y={BODEN - 20 + 4 * pflueck + 22 * ablegen} s={0.9 - 0.3 * pflueck} r={-15 * pflueck + 80 * ablegen} />
</div>
)}
{imAbschnitt(f, T.v2 - 0.3, T.v2z[2]) && <Trommel x={NOA_X + 120} y={BODEN - 90} schlag={schlag} />} {imAbschnitt(f, T.v2 - 0.3, T.v2z[2]) && <Trommel x={NOA_X + 120} y={BODEN - 90} schlag={schlag} />}
<Ruf text={TEXT.bumm} x={NOA_X + 140} y={BODEN - 260} start={s(T.bumm)} dauer={26} groesse={90} /> <Ruf text={TEXT.bumm} x={NOA_X + 140} y={BODEN - 260} start={s(T.bumm)} dauer={26} groesse={90} />
<Ruf text={TEXT.bumm2} x={NOA_X + 60} y={BODEN - 330} start={s(T.v2z[1] + 0.9)} dauer={30} groesse={80} farbe="#c8362c" /> <Ruf text={TEXT.bumm2} x={NOA_X + 60} y={BODEN - 330} start={s(T.v2z[1] + 0.9)} dauer={30} groesse={80} farbe="#c8362c" />