Lied 3: Pino hält die gepflückte Blume, Noa zeigt bei der Antwort auf die richtige Seite, Pino wird beim Gag gleichmäßig groß

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lara 2026-11-08 21:10:59 +00:00
parent 6489b61dc3
commit 5a18eeaa51
2 changed files with 28 additions and 18 deletions

View file

@ -95,7 +95,8 @@ const NOA: Posenfolge = [
[s(T.v4z[2]), 'noa_A5_blick-links'], [s(T.v4z[2]), 'noa_A5_blick-links'],
] as Posenfolge) ] as Posenfolge)
: []), : []),
[s(T.m), 'noa_B_zeigen'], // Mitmach-Teil: Noa zeigt erst auf das Gefragte, bei der Antwort auf das andere (Seite: siehe noaZeigtLinks)
...KARTEN.flatMap((c) => c.zeigt.map((seite, k) => [s(k ? c.antwort - 0.2 : c.frage), seite === 'keins' ? 'noa_A3_lachen' : 'noa_B_zeigen'] as [number, string])),
[s(T.gag), 'noa_A4_staunen'], [s(T.gag), 'noa_A4_staunen'],
[s(T.gag + 4.5), 'noa_A3_lachen'], [s(T.gag + 4.5), 'noa_A3_lachen'],
...klatschen(T.c4, T.cz(T.c4)[3]), ...klatschen(T.c4, T.cz(T.c4)[3]),
@ -238,6 +239,12 @@ const Garten: React.FC = () => {
const v4 = T.v4z; const v4 = T.v4z;
const luluReck = v4 ? interpolate(f, [s(v4[1]), s(v4[1] + 0.6), s(v4[2]), s(v4[2] + 0.4)], [1, 1.08, 1.08, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}) : 1; const luluReck = v4 ? interpolate(f, [s(v4[1]), s(v4[1] + 0.6), s(v4[2]), s(v4[2] + 0.4)], [1, 1.08, 1.08, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}) : 1;
const pinoDuck = v4 && T.juchhe !== undefined ? interpolate(f, [s(v4[3]), s(v4[3] + 0.3), s(T.juchhe), s(T.juchhe + 0.15)], [1, 0.8, 0.8, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}) : 1; const pinoDuck = v4 && T.juchhe !== undefined ? interpolate(f, [s(v4[3]), s(v4[3] + 0.3), s(T.juchhe), s(T.juchhe + 0.15)], [1, 0.8, 0.8, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}) : 1;
// Noa zeigt im Mitmach-Teil nach links (gespiegelt), wenn die Antwort bzw. Frage Pino oder die Blume meint
const karte = KARTEN.findIndex((c, k) => f >= s(c.frage) && f < s(KARTEN[k + 1]?.frage ?? T.gag));
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
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);
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'});
@ -263,8 +270,7 @@ const Garten: React.FC = () => {
{(imAbschnitt(f, T.v1 - 1, T.v1z[1] + 0.5) || imAbschnitt(f, KARTEN[1].frage, KARTEN[2].frage)) && ( {(imAbschnitt(f, T.v1 - 1, T.v1z[1] + 0.5) || imAbschnitt(f, KARTEN[1].frage, KARTEN[2].frage)) && (
<Apfel x={1400} y={190 + Math.sin(f * 0.08) * 4} s={1.1} r={Math.sin(f * 0.08) * 6} /> <Apfel x={1400} y={190 + Math.sin(f * 0.08) * 4} s={1.1} r={Math.sin(f * 0.08) * 6} />
)} )}
{(imAbschnitt(f, T.v1z[2] - 0.5, T.v1z[3] + 0.6) || imAbschnitt(f, KARTEN[1].frage, KARTEN[2].frage)) && <Blume x={640} y={BODEN - 20} s={0.9} />} {(imAbschnitt(f, T.v1z[2] - 0.5, T.v1z[3]) || imAbschnitt(f, KARTEN[1].frage, KARTEN[2].frage)) && <Blume x={640} y={BODEN - 20} s={0.9} />}
{imAbschnitt(f, T.v1z[3] + 0.6, T.c2 + 9) && <Blume x={PINO_X + 6} y={BODEN - 40} s={0.5} />}
{luluGeht ? ( {luluGeht ? (
<Geher figur="lulu" spiegeln x={luluX} y={BODEN} tempo={0.8} /> <Geher figur="lulu" spiegeln x={luluX} y={BODEN} tempo={0.8} />
@ -278,7 +284,7 @@ const Garten: React.FC = () => {
blende={8} blende={8}
/> />
)} )}
<Figur pose={NOA} x={NOA_X} y={BODEN + wipp(0.3, 10 * ruhig)} drehung={schwank(0, 3 * ruhig)} blende={3} /> <Figur pose={NOA} x={NOA_X} y={BODEN + wipp(0.3, 10 * ruhig)} drehung={schwank(0, 3 * ruhig)} 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} />
) : ( ) : (
@ -287,10 +293,12 @@ const Garten: React.FC = () => {
x={PINO_X + 230 * gagNah} x={PINO_X + 230 * gagNah}
y={BODEN + wipp(0, 16 * ruhig) - pinoHuepf} y={BODEN + wipp(0, 16 * ruhig) - pinoHuepf}
drehung={schwank(1, 4 * ruhig)} drehung={schwank(1, 4 * ruhig)}
stauchY={(1 - 0.03 * schlag) * pinoDuck * pinoGross} stauchX={pinoGross}
stauchY={(1 - 0.03 * schlag) * pinoDuck * pinoGross} // groß werden: in beide Richtungen, sonst wirkt Pino dünn
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} />}
{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" />

View file

@ -13,7 +13,9 @@ type Zeiten = {
v4?: number; v4z?: number[]; juchhe?: number; m: number; gag: number; c4: number; zw: number; c5: number; ende: number; v4?: number; v4z?: number[]; juchhe?: number; m: number; gag: number; c4: number; zw: number; c5: number; ende: number;
cz: (start: number) => [number, number, number, number]; cz: (start: number) => [number, number, number, number];
}; };
type Karte = {frage: number; antwort: number; wort: string; gegenteil: string}; // zeigt: wohin Noa bei Frage und Antwort zeigt (rechts = Lulu/Apfel, links = Pino/Blume, keins = sie selbst)
type Seite = 'rechts' | 'links' | 'keins';
type Karte = {frage: number; antwort: number; wort: string; gegenteil: string; zeigt: [Seite, Seite]};
const REFRAIN = (z: [number, number, number, number]) => z; const REFRAIN = (z: [number, number, number, number]) => z;
const C_DE = { const C_DE = {
@ -51,10 +53,10 @@ const DAUER_DE = Math.round(139.68 * 30);
// Mitmach-Teil: Frage beginnt, Antwort des Chors // Mitmach-Teil: Frage beginnt, Antwort des Chors
const KARTEN_DE: Karte[] = [ const KARTEN_DE: Karte[] = [
{frage: 74.22, antwort: 78.95, wort: 'groß', gegenteil: 'klein'}, {frage: 74.22, antwort: 78.95, wort: 'groß', gegenteil: 'klein', zeigt: ['rechts', 'links']},
{frage: 79.05, antwort: 83.59, wort: 'oben', gegenteil: 'unten'}, {frage: 79.05, antwort: 83.59, wort: 'oben', gegenteil: 'unten', zeigt: ['rechts', 'links']},
{frage: 83.74, antwort: 88.22, wort: 'laut', gegenteil: 'leise'}, {frage: 83.74, antwort: 88.22, wort: 'laut', gegenteil: 'leise', zeigt: ['keins', 'keins']},
{frage: 88.38, antwort: 92.9, wort: 'schnell', gegenteil: 'langsam'}, // ~ Antwortzeit {frage: 88.38, antwort: 92.9, wort: 'schnell', gegenteil: 'langsam', zeigt: ['links', 'rechts']}, // ~ Antwortzeit
]; ];
const refrain = (z: [number, number, number, number], d = [0, 0, 0, 0]): LiedZeile[] => [ const refrain = (z: [number, number, number, number], d = [0, 0, 0, 0]): LiedZeile[] => [
@ -149,10 +151,10 @@ const T_ES: Zeiten = {
cz: (start: number) => Object.values(C_ES).find((z) => z[0] === start)!, cz: (start: number) => Object.values(C_ES).find((z) => z[0] === start)!,
}; };
const KARTEN_ES: Karte[] = [ const KARTEN_ES: Karte[] = [
{frage: 61.07, antwort: 64.71, wort: 'pequeño', gegenteil: 'grande'}, {frage: 61.07, antwort: 64.71, wort: 'pequeño', gegenteil: 'grande', zeigt: ['links', 'rechts']},
{frage: 65.85, antwort: 69.39, wort: 'arriba', gegenteil: 'abajo'}, {frage: 65.85, antwort: 69.39, wort: 'arriba', gegenteil: 'abajo', zeigt: ['rechts', 'links']},
{frage: 70.73, antwort: 73.79, wort: 'fuerte', gegenteil: 'bajito'}, {frage: 70.73, antwort: 73.79, wort: 'fuerte', gegenteil: 'bajito', zeigt: ['keins', 'links']},
{frage: 75.19, antwort: 78.59, wort: 'rápido', gegenteil: 'despacio'}, {frage: 75.19, antwort: 78.59, wort: 'rápido', gegenteil: 'despacio', zeigt: ['links', 'rechts']},
]; ];
const ZEILEN_ES: LiedZeile[] = [ const ZEILEN_ES: LiedZeile[] = [
'Uno@5.03 pequeño,@6.25 una@6.99 grande,@7.13', 'Uno@5.03 pequeño,@6.25 una@6.99 grande,@7.13',
@ -220,10 +222,10 @@ const T_FR: Zeiten = {
cz: (start: number) => Object.values(C_FR).find((z) => z[0] === start)!, cz: (start: number) => Object.values(C_FR).find((z) => z[0] === start)!,
}; };
const KARTEN_FR: Karte[] = [ const KARTEN_FR: Karte[] = [
{frage: 66.29, antwort: 69.47, wort: 'petit', gegenteil: 'grande'}, {frage: 66.29, antwort: 69.47, wort: 'petit', gegenteil: 'grande', zeigt: ['links', 'rechts']},
{frage: 71.01, antwort: 74.53, wort: 'en haut', gegenteil: 'en bas'}, {frage: 71.01, antwort: 74.53, wort: 'en haut', gegenteil: 'en bas', zeigt: ['rechts', 'links']},
{frage: 76.01, antwort: 78.43, wort: 'fort', gegenteil: 'doucement'}, {frage: 76.01, antwort: 78.43, wort: 'fort', gegenteil: 'doucement', zeigt: ['keins', 'links']},
{frage: 80.13, antwort: 82.69, wort: 'vite', gegenteil: 'lentement'}, {frage: 80.13, antwort: 82.69, wort: 'vite', gegenteil: 'lentement', zeigt: ['links', 'rechts']},
]; ];
const ZEILEN_FR: LiedZeile[] = [ const ZEILEN_FR: LiedZeile[] = [
'Un@11.33 tout@11.95 petit,@12.21 un@12.89 très@12.93 grand,@13.09', 'Un@11.33 tout@11.95 petit,@12.21 un@12.89 très@12.93 grand,@13.09',