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:
parent
36aabd55f5
commit
704bdcd0a3
1 changed files with 40 additions and 5 deletions
|
|
@ -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" />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue