Folge 1 komplett in Remotion: Szenen 3–7 und Lied; Szene 2 Pino blickt zu Noa, Aufrollen ohne Clip; Apfel tiefer (für Lulu erreichbar); Geh-Ersatz mit Überblendung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3c5620ef6e
commit
88d2ae0f01
10 changed files with 733 additions and 18 deletions
|
|
@ -119,8 +119,16 @@ export const ClipFigur: React.FC<ClipProps> = ({name, start, hoehe, tempo = 1, s
|
||||||
// Clip noch nicht freigestellt: Standbild der Figur als Ersatz
|
// Clip noch nicht freigestellt: Standbild der Figur als Ersatz
|
||||||
const figurName = name.split('_')[0] as FigurName;
|
const figurName = name.split('_')[0] as FigurName;
|
||||||
if (name.endsWith('_C1_gehen-schleife')) {
|
if (name.endsWith('_C1_gehen-schleife')) {
|
||||||
const bild = 1 + (Math.floor(((frame - start) * tempo * 6) / fps) % 4);
|
// vier Geh-Bilder, jeweils kurz ineinander übergeblendet
|
||||||
return <Figur pose={`${figurName}_A7-${bild}_gehen`} hoehe={hoehe} blende={1} {...lage} />;
|
const schritt = fps / (6 * tempo);
|
||||||
|
const t = Math.max(0, frame - start);
|
||||||
|
const k = Math.floor(t / schritt);
|
||||||
|
const bild = (n: number) => `${figurName}_A7-${1 + (((n % 4) + 4) % 4)}_gehen`;
|
||||||
|
const folge: Posenfolge = [
|
||||||
|
[(k - 1) * schritt, bild(k - 1)],
|
||||||
|
[k * schritt, bild(k)],
|
||||||
|
];
|
||||||
|
return <Figur pose={folge} frame={t} hoehe={hoehe} blende={Math.max(1, Math.min(4, schritt / 2))} {...lage} />;
|
||||||
}
|
}
|
||||||
return <Figur pose={ersatz ?? ({pino: 'pino_ref_sitzend', noa: 'noa_ref_stehend', lulu: 'lulu_A6_blick-rechts'} as const)[figurName]} hoehe={hoehe} {...lage} />;
|
return <Figur pose={ersatz ?? ({pino: 'pino_ref_sitzend', noa: 'noa_ref_stehend', lulu: 'lulu_A6_blick-rechts'} as const)[figurName]} hoehe={hoehe} {...lage} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -315,7 +315,7 @@ export const GartenHerbstSVG: React.FC<{abend?: boolean}> = ({abend = false}) =>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</g>
|
</g>
|
||||||
<AlterBaum x={340} y={905} s={0.95} abend={abend} apfel={[232, -770]} />
|
<AlterBaum x={340} y={905} s={0.95} abend={abend} apfel={[274, -576]} />
|
||||||
<Korn staerke={0.18} />
|
<Korn staerke={0.18} />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,14 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {INTRO_OPTIONEN, Intro, OUTRO, Outro, introZeilen} from '../baukasten/buch';
|
import {INTRO_OPTIONEN, Intro, OUTRO, Outro, introZeilen} from '../baukasten/buch';
|
||||||
import {baueFolge, type SzenenEintrag} from '../baukasten/folge';
|
import {baueFolge, type SzenenEintrag} from '../baukasten/folge';
|
||||||
|
import {LIED, Lied} from './lied';
|
||||||
import {TITEL, plane} from './plan';
|
import {TITEL, plane} from './plan';
|
||||||
import {S2, Szene2} from './szene2';
|
import {S2, Szene2} from './szene2';
|
||||||
|
import {S3, Szene3} from './szene3';
|
||||||
|
import {S4, Szene4} from './szene4';
|
||||||
|
import {S5, Szene5} from './szene5';
|
||||||
|
import {S6, Szene6} from './szene6';
|
||||||
|
import {S7, Szene7} from './szene7';
|
||||||
|
|
||||||
// Folge 1 „Zu klein, zu groß“ – wie Folge 2 per Code aus der Figuren-Bibliothek.
|
// Folge 1 „Zu klein, zu groß“ – wie Folge 2 per Code aus der Figuren-Bibliothek.
|
||||||
|
|
||||||
|
|
@ -11,7 +17,13 @@ const INTRO = plane('intro', introZeilen(TITEL), INTRO_OPTIONEN);
|
||||||
export const SZENEN: SzenenEintrag[] = [
|
export const SZENEN: SzenenEintrag[] = [
|
||||||
{name: 'Intro', datei: 'Folge01.tsx', plan: INTRO, K: () => <Intro plan={INTRO} titel={TITEL} posen={['pino_A3_lachen', 'noa_A3_lachen', 'lulu_A3_lachen']} />},
|
{name: 'Intro', datei: 'Folge01.tsx', plan: INTRO, K: () => <Intro plan={INTRO} titel={TITEL} posen={['pino_A3_lachen', 'noa_A3_lachen', 'lulu_A3_lachen']} />},
|
||||||
{name: 'Wer raschelt da', datei: 'szene2.tsx', plan: S2, K: Szene2},
|
{name: 'Wer raschelt da', datei: 'szene2.tsx', plan: S2, K: Szene2},
|
||||||
{name: 'Outro', datei: 'Folge01.tsx', plan: OUTRO, K: () => <Outro posen={['pino_A3_lachen', 'noa_A_arm-hoch-winken', 'lulu_A3_lachen']} />},
|
{name: 'Der Apfel ist zu hoch', datei: 'szene3.tsx', plan: S3, K: Szene3},
|
||||||
|
{name: 'Ein Baum mit Flecken', datei: 'szene4.tsx', plan: S4, K: Szene4},
|
||||||
|
{name: 'Die Blume ist zu tief', datei: 'szene5.tsx', plan: S5, K: Szene5},
|
||||||
|
{name: 'Zusammen gehts', datei: 'szene6.tsx', plan: S6, K: Szene6},
|
||||||
|
{name: 'Lied', datei: 'lied.tsx', plan: LIED, K: Lied},
|
||||||
|
{name: 'Pino ist muede', datei: 'szene7.tsx', plan: S7, K: Szene7},
|
||||||
|
{name: 'Outro', datei: 'Folge01.tsx', plan: OUTRO, K: () => <Outro posen={['pino_B3_schlafen', 'noa_A_arm-hoch-winken', 'lulu_A3_lachen']} />},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const F01 = baueFolge('F01', SZENEN);
|
export const F01 = baueFolge('F01', SZENEN);
|
||||||
|
|
|
||||||
93
remotion/src/folge01/lied.tsx
Normal file
93
remotion/src/folge01/lied.tsx
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {random, useCurrentFrame} from 'remotion';
|
||||||
|
import {Figur, Kamera} from '../baukasten/figur';
|
||||||
|
import {Blende, Vignette} from '../baukasten/helfer';
|
||||||
|
import {Blume, Laubhaufen} from '../baukasten/natur';
|
||||||
|
import {BODEN, Ort} from '../baukasten/orte';
|
||||||
|
import {SCHRIFT, Untertitel} from '../baukasten/untertitel';
|
||||||
|
import {TEXTE, plane} from './plan';
|
||||||
|
import {HAUFEN_X} from './szene2';
|
||||||
|
|
||||||
|
// Lied „Einer klein und einer groß“: Refrain (alle), Strophe (Erzählstimme), Refrain.
|
||||||
|
// Die drei stehen nebeneinander – klein, mittel, groß – und wippen im Takt.
|
||||||
|
|
||||||
|
const TAKT = 19; // Frames pro Schlag (ca. 95 bpm)
|
||||||
|
|
||||||
|
export const LIED = plane(
|
||||||
|
'lied',
|
||||||
|
[
|
||||||
|
{id: 'r1', wer: 'ALLE', dauer: 3.2},
|
||||||
|
{id: 'r2', wer: 'ALLE', dauer: 3.2},
|
||||||
|
{id: 'r3', wer: 'ALLE', dauer: 3.2},
|
||||||
|
{id: 'r4', wer: 'ALLE', dauer: 3.6},
|
||||||
|
{id: 's1', wer: 'ERZ', dauer: 3.2},
|
||||||
|
{id: 's2', wer: 'ERZ', dauer: 3.2},
|
||||||
|
{id: 's3', wer: 'ERZ', dauer: 3.2},
|
||||||
|
{id: 's4', wer: 'ERZ', dauer: 3.6},
|
||||||
|
{id: 'w1', wer: 'ALLE', dauer: 3.2},
|
||||||
|
{id: 'w2', wer: 'ALLE', dauer: 3.2},
|
||||||
|
{id: 'w3', wer: 'ALLE', dauer: 3.2},
|
||||||
|
{id: 'w4', wer: 'ALLE', dauer: 3.6},
|
||||||
|
],
|
||||||
|
{vorlauf: 1.0, nachlauf: 1.0},
|
||||||
|
);
|
||||||
|
|
||||||
|
const Note: React.FC<{x: number; y: number; s: number; farbe: string}> = ({x, y, s, farbe}) => (
|
||||||
|
<svg width={60} height={80} viewBox="0 0 60 80" style={{position: 'absolute', left: x, top: y, transform: `scale(${s})`}}>
|
||||||
|
<ellipse cx={18} cy={64} rx={15} ry={11} fill={farbe} transform="rotate(-20 18 64)" />
|
||||||
|
<rect x={30} y={8} width={6} height={58} fill={farbe} />
|
||||||
|
<path d="M 36 8 C 50 18, 56 30, 46 44 C 50 30, 44 24, 36 22 Z" fill={farbe} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Lied: React.FC = () => {
|
||||||
|
const f = useCurrentFrame();
|
||||||
|
const {z, dauer} = LIED;
|
||||||
|
const schlag = Math.abs(Math.sin((f * Math.PI) / TAKT));
|
||||||
|
const wipp = (phase: number, h: number) => -Math.abs(Math.sin((f * Math.PI) / TAKT + phase)) * h;
|
||||||
|
const schwank = (phase: number, g: number) => Math.sin((f * Math.PI) / (2 * TAKT) + phase) * g;
|
||||||
|
// Strophe: „Lulu holt ihn mit dem Mund“ / „Pino pflückt sie“
|
||||||
|
const luluPose: [number, string][] = [
|
||||||
|
[0, 'lulu_A3_lachen'],
|
||||||
|
[z.s2.start, 'lulu_A_apfel'],
|
||||||
|
[z.s3.start, 'lulu_A3_lachen'],
|
||||||
|
];
|
||||||
|
const pinoPose: [number, string][] = [
|
||||||
|
[0, 'pino_A3_lachen'],
|
||||||
|
[z.s4.start, 'pino_A_hinterbeine'],
|
||||||
|
[z.w1.start, 'pino_A3_lachen'],
|
||||||
|
];
|
||||||
|
const noaPose: [number, string][] = [
|
||||||
|
[0, 'noa_A3_lachen'],
|
||||||
|
[z.r4.start, 'noa_A_arme-hoch'],
|
||||||
|
[z.s1.start, 'noa_A3_lachen'],
|
||||||
|
[z.w4.start, 'noa_A_arme-hoch'],
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Kamera x={1000} y={600} zoom={1.3}>
|
||||||
|
<Ort name="garten_herbst" />
|
||||||
|
<Laubhaufen x={HAUFEN_X + 380} y={BODEN + 6} />
|
||||||
|
<Figur pose={luluPose} x={1300} y={BODEN} drehung={schwank(0.5, 2.2)} stauchY={1 - 0.012 * schlag} blende={8} />
|
||||||
|
<Figur pose={noaPose} x={980} y={BODEN + wipp(0.3, 10)} drehung={schwank(0, 3)} blende={8} />
|
||||||
|
<Figur pose={pinoPose} x={760} y={BODEN + wipp(0, 16)} drehung={schwank(1, 4)} stauchY={1 - 0.03 * schlag} blende={8} />
|
||||||
|
{f >= z.s4.start && f < z.w1.start && <Blume x={764} y={BODEN - 40} s={0.5} />}
|
||||||
|
</Kamera>
|
||||||
|
{new Array(8).fill(0).map((_, i) => {
|
||||||
|
const t = ((f + i * 25) % 200) / 200;
|
||||||
|
const x = 200 + random(`n${i}`) * 1500 + Math.sin(t * 6 + i) * 30;
|
||||||
|
return (
|
||||||
|
<div key={i} style={{opacity: Math.sin(t * Math.PI) * 0.9}}>
|
||||||
|
<Note x={x} y={700 - t * 600} s={0.8 + random(`ns${i}`) * 0.6} farbe={['#c8642c', '#3f5a8a', '#5f8a4a', '#a0526b'][i % 4]} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<div style={{position: 'absolute', top: 60, left: 0, right: 0, textAlign: 'center', fontFamily: SCHRIFT, fontWeight: 600, fontSize: 40, color: '#8a6a4a', opacity: Math.min(1, f / 20)}}>
|
||||||
|
♫ {TEXTE.lied} ♫
|
||||||
|
</div>
|
||||||
|
<Vignette />
|
||||||
|
<Untertitel zeilen={LIED.liste} />
|
||||||
|
<Blende dauer={dauer} rein={12} raus={12} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {useCurrentFrame} from 'remotion';
|
import {useCurrentFrame} from 'remotion';
|
||||||
import {kurve} from '../bewegung';
|
import {kurve} from '../bewegung';
|
||||||
import {ClipFigur, Figur, Geher, Kamera} from '../baukasten/figur';
|
import {Figur, Geher, Kamera} from '../baukasten/figur';
|
||||||
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt, ruck} from '../baukasten/helfer';
|
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt, ruck} from '../baukasten/helfer';
|
||||||
import {Apfel, Blaetterregen, Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur';
|
import {Apfel, Blaetterregen, Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur';
|
||||||
import {BODEN, Ort} from '../baukasten/orte';
|
import {BODEN, Ort} from '../baukasten/orte';
|
||||||
|
|
@ -12,7 +12,7 @@ import {plane} from './plan';
|
||||||
|
|
||||||
// Lage im Herbstgarten (gilt für alle Szenen der Folge)
|
// Lage im Herbstgarten (gilt für alle Szenen der Folge)
|
||||||
export const HAUFEN_X = 1180; // Laubhaufen
|
export const HAUFEN_X = 1180; // Laubhaufen
|
||||||
export const APFEL = {x: 560, y: 205}; // der letzte Apfel, ganz oben im Baum
|
export const APFEL = {x: 600, y: 390}; // der letzte Apfel: zu hoch für Noa, Lulu reicht mit dem Maul hin
|
||||||
export const BLUME_X = 1560; // blaue Blume am Zaun
|
export const BLUME_X = 1560; // blaue Blume am Zaun
|
||||||
export const BLUME_Y = 805;
|
export const BLUME_Y = 805;
|
||||||
export const NOA_X = 960; // Noa neben dem Haufen
|
export const NOA_X = 960; // Noa neben dem Haufen
|
||||||
|
|
@ -101,27 +101,27 @@ export const Szene2: React.FC = () => {
|
||||||
|
|
||||||
// Pino: als Stachelkugel im Haufen, kommt hoch, öffnet sich bei bild4
|
// Pino: als Stachelkugel im Haufen, kommt hoch, öffnet sich bei bild4
|
||||||
const auf = z.bild4.start; // Einroll-Clip rückwärts
|
const auf = z.bild4.start; // Einroll-Clip rückwärts
|
||||||
const AUF_FRAMES = 75; // 121 Clip-Bilder (24 fps) bei Tempo 2
|
const AUF_FRAMES = 30;
|
||||||
const oeffnet = f >= auf && f < auf + AUF_FRAMES;
|
const oeffnen = f >= auf && f < auf + AUF_FRAMES ? Math.sin(((f - auf) / AUF_FRAMES) * Math.PI) : 0;
|
||||||
const zuNoa = f >= auf; // die Bilder schauen nach rechts, Noa sitzt links
|
const zuNoa = f >= auf; // die Bilder schauen nach rechts, Noa sitzt links
|
||||||
const pinoY = kurve(f, [
|
const pinoY = kurve(f, [
|
||||||
[schreck - 10, PINO_HAUFEN_Y + 140],
|
[schreck - 10, PINO_HAUFEN_Y + 140],
|
||||||
[schreck + 6, PINO_HAUFEN_Y],
|
[schreck + 6, PINO_HAUFEN_Y],
|
||||||
[auf + 20, PINO_HAUFEN_Y],
|
[auf + 20, PINO_HAUFEN_Y],
|
||||||
[auf + AUF_FRAMES, PINO_HAUFEN_Y - 40],
|
[auf + AUF_FRAMES, PINO_HAUFEN_Y - 22],
|
||||||
]);
|
]);
|
||||||
const pinoDa = f >= schreck - 10;
|
const pinoDa = f >= schreck - 10;
|
||||||
const pinoPose: [number, string][] = [
|
const pinoPose: [number, string][] = [
|
||||||
[0, 'pino_A_kugel'],
|
[0, 'pino_A_kugel'],
|
||||||
[auf + AUF_FRAMES, 'pino_ref_sitzend'],
|
[auf + 4, 'pino_ref_sitzend'],
|
||||||
[z.p1.start, 'pino_B_blick-nach-oben'],
|
[z.p1.start, 'pino_A6_blick-rechts'],
|
||||||
[z.p1.start + 40, 'pino_A4_staunen'],
|
[z.p1.start + 40, 'pino_A4_staunen'],
|
||||||
[z.p2.start, 'pino_B_blick-nach-oben'],
|
[z.p2.start, 'pino_B_blick-nach-oben'],
|
||||||
[z.p2.ende - 10, 'pino_A3_lachen'],
|
[z.p2.ende - 10, 'pino_A3_lachen'],
|
||||||
];
|
];
|
||||||
// Stacheln zittern vor Angst, solange er eine Kugel ist
|
// Stacheln zittern vor Angst, solange er eine Kugel ist
|
||||||
const angst = f < auf ? Math.sin(f * 1.7) * 1.5 : 0;
|
const angst = f < auf ? Math.sin(f * 1.7) * 1.5 : 0;
|
||||||
const pinoStauch = atmen(f, 1, 0.01) * hopfStauch(f, schreck);
|
const pinoStauch = atmen(f, 1, 0.01) * hopfStauch(f, schreck) * (1 + 0.06 * oeffnen);
|
||||||
|
|
||||||
const kam = kamFahrt(f, [
|
const kam = kamFahrt(f, [
|
||||||
[0, 960, 540, 1.0],
|
[0, 960, 540, 1.0],
|
||||||
|
|
@ -143,12 +143,7 @@ export const Szene2: React.FC = () => {
|
||||||
<Ort name="garten_herbst" />
|
<Ort name="garten_herbst" />
|
||||||
<Apfel x={APFEL.x} y={APFEL.y} s={0.9} />
|
<Apfel x={APFEL.x} y={APFEL.y} s={0.9} />
|
||||||
<Blume x={BLUME_X} y={BLUME_Y} s={0.8} />
|
<Blume x={BLUME_X} y={BLUME_Y} s={0.8} />
|
||||||
{pinoDa &&
|
{pinoDa && <Figur pose={pinoPose} spiegeln={zuNoa} x={HAUFEN_X + 10} y={pinoY} stauchY={pinoStauch} drehung={angst} schatten={false} blende={14} />}
|
||||||
(oeffnet ? (
|
|
||||||
<ClipFigur name="pino_C7_einrollen" start={auf} tempo={2} rueckwaerts spiegeln x={HAUFEN_X + 10} y={pinoY} schatten={false} ersatz="pino_ref_sitzend" />
|
|
||||||
) : (
|
|
||||||
<Figur pose={pinoPose} spiegeln={zuNoa} x={HAUFEN_X + 10} y={pinoY} stauchY={pinoStauch} drehung={angst} schatten={false} blende={8} />
|
|
||||||
))}
|
|
||||||
{/* Im Haufen steht Noa hinter den vorderen Blättern */}
|
{/* Im Haufen steht Noa hinter den vorderen Blättern */}
|
||||||
{imHaufen && <Figur pose={noaPose} x={noaX} y={noaY} stauchY={atmen(f, 2) * hopfStauch(f, landung)} schatten={false} />}
|
{imHaufen && <Figur pose={noaPose} x={noaX} y={noaY} stauchY={atmen(f, 2) * hopfStauch(f, landung)} schatten={false} />}
|
||||||
<Laubhaufen x={HAUFEN_X} y={BODEN + 6} wackeln={wackeln} flach={flach} />
|
<Laubhaufen x={HAUFEN_X} y={BODEN + 6} wackeln={wackeln} flach={flach} />
|
||||||
|
|
|
||||||
114
remotion/src/folge01/szene3.tsx
Normal file
114
remotion/src/folge01/szene3.tsx
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {useCurrentFrame} from 'remotion';
|
||||||
|
import {kurve} from '../bewegung';
|
||||||
|
import {Figur, Geher, Kamera} from '../baukasten/figur';
|
||||||
|
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt} from '../baukasten/helfer';
|
||||||
|
import {Apfel, Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur';
|
||||||
|
import {BODEN, Ort} from '../baukasten/orte';
|
||||||
|
import {Untertitel} from '../baukasten/untertitel';
|
||||||
|
import {plane} from './plan';
|
||||||
|
import {APFEL, BLUME_X, BLUME_Y, HAUFEN_X} from './szene2';
|
||||||
|
|
||||||
|
// Szene 3: Der Apfel ist zu hoch. Pino hüpft, Noa streckt sich – beide zu klein.
|
||||||
|
// Pino-Bilder schauen nach rechts (zum Apfel); zu Noa (links) wird er gespiegelt.
|
||||||
|
|
||||||
|
export const PINO_BAUM_X = 500; // Pino unter dem Apfel
|
||||||
|
export const NOA_BAUM_X = 330; // Noa am untersten Ast
|
||||||
|
|
||||||
|
export const S3 = plane('s3', [
|
||||||
|
{id: 'bild0', dauer: 2.6},
|
||||||
|
{id: 'p1', wer: 'PINO'},
|
||||||
|
{id: 'bild1', dauer: 2.4},
|
||||||
|
{id: 'p2', wer: 'PINO', dauer: 2.2},
|
||||||
|
{id: 'p3', wer: 'PINO'},
|
||||||
|
{id: 'n1', wer: 'NOA'},
|
||||||
|
{id: 'bild2', dauer: 2.8},
|
||||||
|
{id: 'n2', wer: 'NOA'},
|
||||||
|
{id: 'e1', wer: 'ERZ'},
|
||||||
|
{id: 'e2', wer: 'ERZ', pause: 3},
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const Szene3: React.FC = () => {
|
||||||
|
const f = useCurrentFrame();
|
||||||
|
const {z, dauer} = S3;
|
||||||
|
|
||||||
|
// Pino: schaut hoch, stellt sich auf die Hinterbeine, hüpft zweimal, ist traurig
|
||||||
|
const hopp1 = z.p2.start + 2;
|
||||||
|
const hopp2 = z.p2.start + 32;
|
||||||
|
const pinoPose: [number, string][] = [
|
||||||
|
[0, 'pino_B_blick-nach-oben'],
|
||||||
|
[z.bild1.start, 'pino_A_hinterbeine'],
|
||||||
|
[z.p3.start, 'pino_B1_traurig'],
|
||||||
|
[z.n1.start + 8, 'pino_A4_staunen'],
|
||||||
|
[z.n2.start, 'pino_B1_traurig'],
|
||||||
|
[z.e1.start + 20, 'pino_B_blick-nach-oben'],
|
||||||
|
];
|
||||||
|
const zuNoa = f >= z.n1.start && f < z.e1.start + 20;
|
||||||
|
const strecken = kurve(f, [
|
||||||
|
[z.bild1.start, 0],
|
||||||
|
[z.bild1.start + 20, 1],
|
||||||
|
[z.p3.start, 1],
|
||||||
|
[z.p3.start + 12, 0],
|
||||||
|
]);
|
||||||
|
const pinoY = BODEN + huepfer(f, hopp1, 46, 16) + huepfer(f, hopp2, 46, 16);
|
||||||
|
const pinoStauch = atmen(f, 1, 0.01) * (1 + 0.05 * strecken) * hopfStauch(f, hopp1 + 16) * hopfStauch(f, hopp2 + 16);
|
||||||
|
|
||||||
|
// Noa kommt von links, streckt sich zum untersten Ast – reicht nicht
|
||||||
|
const noaAn = z.n1.start + 6;
|
||||||
|
const noaX = kurve(f, [
|
||||||
|
[z.p3.start - 70, -150],
|
||||||
|
[noaAn, NOA_BAUM_X],
|
||||||
|
]);
|
||||||
|
const noaGeht = f >= z.p3.start - 70 && f < noaAn;
|
||||||
|
const noaDa = f >= z.p3.start - 70;
|
||||||
|
const greifen = z.bild2.start + 6;
|
||||||
|
const noaPose: [number, string][] = [
|
||||||
|
[0, 'noa_A3_lachen'],
|
||||||
|
[greifen, 'noa_A_arm-hoch-winken'],
|
||||||
|
[z.n2.start, 'noa_B1_traurig'],
|
||||||
|
[z.e1.start + 20, 'noa_A4_staunen'],
|
||||||
|
[z.e2.start, 'noa_A3_lachen'],
|
||||||
|
];
|
||||||
|
// auf die Zehenspitzen: strecken und zweimal kurz hochfedern
|
||||||
|
const zehen = kurve(f, [
|
||||||
|
[greifen, 0],
|
||||||
|
[greifen + 14, 1],
|
||||||
|
[z.n2.start - 6, 1],
|
||||||
|
[z.n2.start + 8, 0],
|
||||||
|
]);
|
||||||
|
const noaY = BODEN + huepfer(f, greifen + 22, 14, 12) + huepfer(f, greifen + 46, 14, 12);
|
||||||
|
|
||||||
|
const kam = kamFahrt(f, [
|
||||||
|
[0, PINO_BAUM_X + 60, 830, 2.0],
|
||||||
|
[z.p1.start, 560, 560, 1.7],
|
||||||
|
[z.p1.ende, 560, 560, 1.7],
|
||||||
|
[z.bild1.start + 10, PINO_BAUM_X + 40, 800, 1.9],
|
||||||
|
[z.p3.ende, 520, 740, 1.6],
|
||||||
|
[z.n1.ende, 470, 720, 1.5],
|
||||||
|
[z.bild2.start + 30, 500, 600, 1.35],
|
||||||
|
[z.e1.start, 560, 560, 1.2],
|
||||||
|
[dauer, 600, 560, 1.15],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Kamera {...kam}>
|
||||||
|
<Ort name="garten_herbst" />
|
||||||
|
<Apfel x={APFEL.x} y={APFEL.y} s={0.9} r={Math.sin(f * 0.05) * 4} />
|
||||||
|
<Blume x={BLUME_X} y={BLUME_Y} s={0.8} />
|
||||||
|
<Laubhaufen x={HAUFEN_X} y={BODEN + 6} />
|
||||||
|
{noaDa &&
|
||||||
|
(noaGeht ? (
|
||||||
|
<Geher figur="noa" spiegeln x={noaX} y={BODEN} tempo={1.5} />
|
||||||
|
) : (
|
||||||
|
<Figur pose={noaPose} x={noaX} y={noaY} stauchY={atmen(f, 2) * (1 + 0.04 * zehen)} blende={10} />
|
||||||
|
))}
|
||||||
|
<Figur pose={pinoPose} spiegeln={zuNoa} x={PINO_BAUM_X} y={pinoY} stauchY={pinoStauch} blende={10} />
|
||||||
|
</Kamera>
|
||||||
|
<Blaetterwind anzahl={4} />
|
||||||
|
<Vignette />
|
||||||
|
<Untertitel zeilen={S3.liste} />
|
||||||
|
<Blende dauer={dauer} rein={12} raus={0} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
147
remotion/src/folge01/szene4.tsx
Normal file
147
remotion/src/folge01/szene4.tsx
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {useCurrentFrame} from 'remotion';
|
||||||
|
import {kurve} from '../bewegung';
|
||||||
|
import {Figur, Geher, Kamera} from '../baukasten/figur';
|
||||||
|
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt} from '../baukasten/helfer';
|
||||||
|
import {Apfel, Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur';
|
||||||
|
import {BODEN, Ort} from '../baukasten/orte';
|
||||||
|
import {Untertitel} from '../baukasten/untertitel';
|
||||||
|
import {plane} from './plan';
|
||||||
|
import {APFEL, BLUME_X, BLUME_Y, HAUFEN_X} from './szene2';
|
||||||
|
import {NOA_BAUM_X, PINO_BAUM_X} from './szene3';
|
||||||
|
|
||||||
|
// Szene 4: Ein Baum mit Flecken? Lulu kommt, pflückt den Apfel und reicht ihn Pino.
|
||||||
|
// Lulus Bilder schauen nach links (zu Noa und Pino), Pinos nach rechts (zu Lulu).
|
||||||
|
|
||||||
|
// Lulus Maul mit dem Apfel (lulu_A_apfel) liegt 149 px links und 542 px über dem Fußpunkt:
|
||||||
|
// so steht sie, dass sie den Apfel am Baum erreicht.
|
||||||
|
export const LULU_APFEL_X = APFEL.x + 149;
|
||||||
|
// Mit gesenktem Hals (lulu_A_hals-unten) liegt das Maul 244 px links vom Fußpunkt, knapp über dem Boden.
|
||||||
|
const LULU_UNTEN_X = 840;
|
||||||
|
const LULU_WARTE_X = 930; // bis zum Pflücken etwas rechts vom Apfel
|
||||||
|
const MAUL_UNTEN = {x: LULU_UNTEN_X - 244, y: BODEN - 22};
|
||||||
|
const APFEL_BODEN = {x: 578, y: BODEN - 14};
|
||||||
|
|
||||||
|
export const S4 = plane('s4', [
|
||||||
|
{id: 'bild0', dauer: 3.4},
|
||||||
|
{id: 'n1', wer: 'NOA'},
|
||||||
|
{id: 'p1', wer: 'PINO'},
|
||||||
|
{id: 'bild1', dauer: 3.2},
|
||||||
|
{id: 'l1', wer: 'LULU'},
|
||||||
|
{id: 'e1', wer: 'ERZ'},
|
||||||
|
{id: 'e2', wer: 'ERZ'},
|
||||||
|
{id: 'p2', wer: 'PINO'},
|
||||||
|
{id: 'l2', wer: 'LULU'},
|
||||||
|
{id: 'l3', wer: 'LULU'},
|
||||||
|
{id: 'bild2', dauer: 3.4},
|
||||||
|
{id: 'p3', wer: 'PINO'},
|
||||||
|
{id: 'l4', wer: 'LULU'},
|
||||||
|
{id: 'p4', wer: 'PINO'},
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const Szene4: React.FC = () => {
|
||||||
|
const f = useCurrentFrame();
|
||||||
|
const {z, dauer} = S4;
|
||||||
|
|
||||||
|
// Lulu stakst langsam von rechts herein (tapp, tapp)
|
||||||
|
const luluAn = z.bild0.ende + 10;
|
||||||
|
const essen = z.bild2.start + 10;
|
||||||
|
const unten = z.bild2.start + 52;
|
||||||
|
const ablegen = z.bild2.ende - 6;
|
||||||
|
const luluX = kurve(f, [
|
||||||
|
[0, 1650],
|
||||||
|
[luluAn, LULU_WARTE_X],
|
||||||
|
[essen - 16, LULU_WARTE_X],
|
||||||
|
[essen + 2, LULU_APFEL_X],
|
||||||
|
[unten, LULU_APFEL_X],
|
||||||
|
[unten + 14, LULU_UNTEN_X],
|
||||||
|
]);
|
||||||
|
const luluGeht = f < luluAn;
|
||||||
|
const luluPose: [number, string][] = [
|
||||||
|
[0, 'lulu_A4_staunen'],
|
||||||
|
[z.l1.start, 'lulu_A3_lachen'],
|
||||||
|
[z.l2.start, 'lulu_A5_blick-links'],
|
||||||
|
[z.l3.start + 20, 'lulu_A4_staunen'],
|
||||||
|
[essen, 'lulu_A_apfel'],
|
||||||
|
[unten, 'lulu_A_hals-unten'],
|
||||||
|
[z.p4.ende - 4, 'lulu_A3_lachen'],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Der Apfel: am Baum → in Lulus Maul (im Bild lulu_A_apfel) → am Maul nach unten → vor Pino
|
||||||
|
const apfelAmBaum = f < essen + 6;
|
||||||
|
const apfelAmMaul = f >= unten + 8;
|
||||||
|
const apfel = apfelAmMaul
|
||||||
|
? {
|
||||||
|
x: kurve(f, [
|
||||||
|
[ablegen, MAUL_UNTEN.x],
|
||||||
|
[ablegen + 12, APFEL_BODEN.x],
|
||||||
|
]),
|
||||||
|
y: kurve(f, [
|
||||||
|
[ablegen, MAUL_UNTEN.y],
|
||||||
|
[ablegen + 12, APFEL_BODEN.y],
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
: APFEL;
|
||||||
|
|
||||||
|
// Pino staunt, freut sich; Stacheln halb hoch bei „noch viel größer“ (kurz aufplustern)
|
||||||
|
const pinoPose: [number, string][] = [
|
||||||
|
[0, 'pino_A4_staunen'],
|
||||||
|
[z.bild1.start + 40, 'pino_B_blick-nach-oben'],
|
||||||
|
[z.p2.start, 'pino_A4_staunen'],
|
||||||
|
[z.l2.start, 'pino_B_blick-nach-oben'],
|
||||||
|
[z.p3.start, 'pino_A4_staunen'],
|
||||||
|
[z.p4.start, 'pino_A3_lachen'],
|
||||||
|
];
|
||||||
|
const pinoY = BODEN + huepfer(f, z.p4.start + 10, 34, 14) + huepfer(f, z.p4.start + 34, 22, 12);
|
||||||
|
const pinoStauch = atmen(f, 1, 0.01) * hopfStauch(f, z.p2.start, 16) * hopfStauch(f, z.p4.start + 24);
|
||||||
|
|
||||||
|
const noaPose: [number, string][] = [
|
||||||
|
[0, 'noa_A4_staunen'],
|
||||||
|
[z.n1.start, 'noa_B_zeigen'],
|
||||||
|
[z.p1.start + 10, 'noa_A3_lachen'],
|
||||||
|
[z.bild1.start + 40, 'noa_A4_staunen'],
|
||||||
|
[z.l2.start, 'noa_A3_lachen'],
|
||||||
|
];
|
||||||
|
const noaY = BODEN + huepfer(f, z.l1.ende, 16, 10);
|
||||||
|
|
||||||
|
const kam = kamFahrt(f, [
|
||||||
|
[0, 1000, 860, 2.2],
|
||||||
|
[luluAn, 820, 850, 2.1],
|
||||||
|
[z.n1.start, 620, 820, 1.7],
|
||||||
|
[z.bild1.start, 700, 840, 1.9],
|
||||||
|
[z.bild1.start + 60, 660, 380, 1.9],
|
||||||
|
[z.l1.ende, 660, 400, 1.8],
|
||||||
|
[z.e1.start + 20, 700, 560, 1.05],
|
||||||
|
[z.e2.ende, 700, 560, 1.05],
|
||||||
|
[z.p2.start + 10, 520, 800, 1.8],
|
||||||
|
[z.l2.start + 10, 640, 430, 1.6],
|
||||||
|
[z.l3.ende, 620, 420, 1.7],
|
||||||
|
[unten - 10, 620, 440, 1.6],
|
||||||
|
[unten + 30, 570, 800, 1.8],
|
||||||
|
[z.p3.start, 560, 780, 1.7],
|
||||||
|
[dauer, 600, 700, 1.4],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Kamera {...kam}>
|
||||||
|
<Ort name="garten_herbst" />
|
||||||
|
<Blume x={BLUME_X} y={BLUME_Y} s={0.8} />
|
||||||
|
{apfelAmBaum && <Apfel x={APFEL.x} y={APFEL.y} s={0.9} r={Math.sin(f * 0.05) * 4} />}
|
||||||
|
{luluGeht ? (
|
||||||
|
<Geher figur="lulu" x={luluX} y={BODEN - 6} tempo={0.6} />
|
||||||
|
) : (
|
||||||
|
<Figur pose={luluPose} x={luluX} y={BODEN - 6} stauchY={atmen(f, 3, 0.006)} blende={14} />
|
||||||
|
)}
|
||||||
|
<Laubhaufen x={HAUFEN_X} y={BODEN + 6} />
|
||||||
|
<Figur pose={noaPose} x={NOA_BAUM_X} y={noaY} stauchY={atmen(f, 2)} blende={10} />
|
||||||
|
<Figur pose={pinoPose} x={PINO_BAUM_X} y={pinoY} stauchY={pinoStauch} blende={10} />
|
||||||
|
{apfelAmMaul && <Apfel x={apfel.x} y={apfel.y} s={0.62} />}
|
||||||
|
</Kamera>
|
||||||
|
<Blaetterwind anzahl={4} />
|
||||||
|
<Vignette />
|
||||||
|
<Untertitel zeilen={S4.liste} />
|
||||||
|
<Blende dauer={dauer} rein={12} raus={0} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
114
remotion/src/folge01/szene5.tsx
Normal file
114
remotion/src/folge01/szene5.tsx
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {useCurrentFrame} from 'remotion';
|
||||||
|
import {kurve} from '../bewegung';
|
||||||
|
import {Figur, Kamera} from '../baukasten/figur';
|
||||||
|
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt} from '../baukasten/helfer';
|
||||||
|
import {Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur';
|
||||||
|
import {BODEN, Ort} from '../baukasten/orte';
|
||||||
|
import {Untertitel} from '../baukasten/untertitel';
|
||||||
|
import {plane} from './plan';
|
||||||
|
import {BLUME_X, BLUME_Y, HAUFEN_X} from './szene2';
|
||||||
|
|
||||||
|
// Szene 5: Die Blume ist zu tief. Lulu beugt sich, wackelt, kommt nicht hinunter.
|
||||||
|
// Lulu steht rechts der Blume und schaut nach links; Pino und Noa stehen links davon.
|
||||||
|
|
||||||
|
export const LULU_BLUME_X = 1760;
|
||||||
|
export const PINO_BLUME_X = 950;
|
||||||
|
export const NOA_BLUME_X = 820;
|
||||||
|
|
||||||
|
export const S5 = plane('s5', [
|
||||||
|
{id: 'bild0', dauer: 2.6},
|
||||||
|
{id: 'l1', wer: 'LULU'},
|
||||||
|
{id: 'l2', wer: 'LULU'},
|
||||||
|
{id: 'bild1', dauer: 3.6},
|
||||||
|
{id: 'l3', wer: 'LULU'},
|
||||||
|
{id: 'l4', wer: 'LULU'},
|
||||||
|
{id: 'bild2', dauer: 1.8},
|
||||||
|
{id: 'e1', wer: 'ERZ'},
|
||||||
|
{id: 'e2', wer: 'ERZ', pause: 3},
|
||||||
|
{id: 'n1', wer: 'NOA'},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Kichern wie in Folge 2: kleine Hüpfer mit Wiegen, schwillt an und ab
|
||||||
|
export const kichern = (f: number, a: number, e: number, phase = 0) => {
|
||||||
|
const huelle = f > a && f < e ? Math.sin(((f - a) / (e - a)) * Math.PI) : 0;
|
||||||
|
const p = (f - a) * (0.42 + 0.08 * Math.sin((f - a) * 0.05)) + phase;
|
||||||
|
return {
|
||||||
|
y: -Math.abs(Math.sin(p)) * 7 * huelle,
|
||||||
|
stauch: 1 - 0.035 * Math.abs(Math.cos(p)) * huelle,
|
||||||
|
dreh: (Math.sin(p * 0.5) * 2.5 + 2) * huelle,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Szene5: React.FC = () => {
|
||||||
|
const f = useCurrentFrame();
|
||||||
|
const {z, dauer} = S5;
|
||||||
|
|
||||||
|
// Lulu neigt sich zur Blume (nach links), wackelt, richtet sich wieder auf
|
||||||
|
const beugA = z.bild1.start;
|
||||||
|
const beugE = z.l4.ende;
|
||||||
|
const neigen = kurve(f, [
|
||||||
|
[beugA, 0],
|
||||||
|
[beugA + 36, 1],
|
||||||
|
[beugE - 10, 1],
|
||||||
|
[beugE + 18, 0],
|
||||||
|
]);
|
||||||
|
const wackeln = neigen * (Math.sin(f * 0.55) * 3 + Math.sin(f * 0.23) * 2);
|
||||||
|
const luluDreh = -24 * neigen + wackeln * 1.4;
|
||||||
|
const luluPose: [number, string][] = [
|
||||||
|
[0, 'lulu_A4_staunen'],
|
||||||
|
[z.l1.start + 10, 'lulu_A3_lachen'],
|
||||||
|
[beugA + 10, 'lulu_A1_augen-zu'],
|
||||||
|
[z.l3.start, 'lulu_B2_erschrocken'],
|
||||||
|
[z.bild2.start, 'lulu_B1_traurig'],
|
||||||
|
[z.n1.start + 20, 'lulu_A4_staunen'],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Pino und Noa kichern, während Lulu wackelt
|
||||||
|
const kA = z.bild1.start + 20;
|
||||||
|
const kE = z.l4.ende;
|
||||||
|
const kp = kichern(f, kA, kE);
|
||||||
|
const kn = kichern(f, kA, kE, 1.3);
|
||||||
|
const pinoPose: [number, string][] = [
|
||||||
|
[0, 'pino_A4_staunen'],
|
||||||
|
[kA, 'pino_A3_lachen'],
|
||||||
|
[z.bild2.start, 'pino_A2_augen-halb'],
|
||||||
|
[z.e2.start, 'pino_A4_staunen'],
|
||||||
|
[z.n1.start + 10, 'pino_A3_lachen'],
|
||||||
|
];
|
||||||
|
const noaPose: [number, string][] = [
|
||||||
|
[0, 'noa_A4_staunen'],
|
||||||
|
[kA, 'noa_A3_lachen'],
|
||||||
|
[z.bild2.start, 'noa_A4_staunen'],
|
||||||
|
[z.n1.start, 'noa_A3_lachen'],
|
||||||
|
[z.n1.start + 30, 'noa_B_zeigen'],
|
||||||
|
];
|
||||||
|
|
||||||
|
const kam = kamFahrt(f, [
|
||||||
|
[0, BLUME_X, 760, 2.4],
|
||||||
|
[z.l1.start, 1650, 560, 1.4],
|
||||||
|
[z.l2.ende, 1600, 560, 1.3],
|
||||||
|
[z.bild1.start + 40, 1560, 600, 1.3],
|
||||||
|
[z.bild2.start, 1500, 620, 1.25],
|
||||||
|
[z.e2.start, 1480, 640, 1.3],
|
||||||
|
[z.n1.start, 900, 760, 1.8],
|
||||||
|
[dauer, 910, 770, 1.9],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Kamera {...kam}>
|
||||||
|
<Ort name="garten_herbst" />
|
||||||
|
<Laubhaufen x={HAUFEN_X} y={BODEN + 6} />
|
||||||
|
<Blume x={BLUME_X} y={BLUME_Y} s={0.8} r={Math.sin(f * 0.07) * 3} />
|
||||||
|
<Figur pose={luluPose} x={LULU_BLUME_X} y={BODEN - 6} drehung={luluDreh} stauchY={atmen(f, 3, 0.006)} blende={12} />
|
||||||
|
<Figur pose={noaPose} x={NOA_BLUME_X} y={BODEN + kn.y + huepfer(f, z.n1.start, 18, 10)} stauchY={atmen(f, 2) * kn.stauch} drehung={kn.dreh} blende={10} />
|
||||||
|
<Figur pose={pinoPose} x={PINO_BLUME_X} y={BODEN + kp.y + huepfer(f, z.n1.ende - 10, 26, 12)} stauchY={atmen(f, 1, 0.01) * kp.stauch * hopfStauch(f, z.n1.ende + 2)} drehung={kp.dreh} blende={10} />
|
||||||
|
</Kamera>
|
||||||
|
<Blaetterwind anzahl={4} />
|
||||||
|
<Vignette />
|
||||||
|
<Untertitel zeilen={S5.liste} />
|
||||||
|
<Blende dauer={dauer} rein={12} raus={0} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
153
remotion/src/folge01/szene6.tsx
Normal file
153
remotion/src/folge01/szene6.tsx
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {useCurrentFrame} from 'remotion';
|
||||||
|
import {kurve} from '../bewegung';
|
||||||
|
import {Figur, Geher, Kamera} from '../baukasten/figur';
|
||||||
|
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt} from '../baukasten/helfer';
|
||||||
|
import {Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur';
|
||||||
|
import {BODEN, Ort} from '../baukasten/orte';
|
||||||
|
import {Untertitel} from '../baukasten/untertitel';
|
||||||
|
import {plane} from './plan';
|
||||||
|
import {BLUME_X, BLUME_Y, HAUFEN_X} from './szene2';
|
||||||
|
import {LULU_BLUME_X, NOA_BLUME_X, PINO_BLUME_X} from './szene5';
|
||||||
|
|
||||||
|
// Szene 6: Zusammen geht's. Pino pflückt die Blume, Noa hält sie hoch, Lulu riecht daran.
|
||||||
|
|
||||||
|
const PINO_AN_BLUME = {x: BLUME_X - 40, y: BLUME_Y + 50};
|
||||||
|
// Lulus Nase in lulu_A1 (Augen zu, schaut nach links): Leinwand (597, 167), Fuß (714, 734)
|
||||||
|
const LULU_NASE = {x: LULU_BLUME_X - 117, y: BODEN - 6 - 567};
|
||||||
|
|
||||||
|
export const S6 = plane('s6', [
|
||||||
|
{id: 'bild0', dauer: 5.6},
|
||||||
|
{id: 'bild1', dauer: 2.6},
|
||||||
|
{id: 'l1', wer: 'LULU'},
|
||||||
|
{id: 'e1', wer: 'ERZ'},
|
||||||
|
{id: 'e2', wer: 'ERZ'},
|
||||||
|
{id: 'e3', wer: 'ERZ'},
|
||||||
|
{id: 'e4', wer: 'ERZ'},
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const Szene6: React.FC = () => {
|
||||||
|
const f = useCurrentFrame();
|
||||||
|
const {z, dauer} = S6;
|
||||||
|
|
||||||
|
// Pino tippelt zur Blume (nach rechts), pflückt sie, tippelt zurück zu Noa
|
||||||
|
const hin = z.bild0.start + 4;
|
||||||
|
const da = hin + 80;
|
||||||
|
const pflueck = da + 6;
|
||||||
|
const zurueck = pflueck + 34;
|
||||||
|
const wieder = zurueck + 80;
|
||||||
|
// Weg vor dem Laubhaufen entlang (weiter vorn = tiefer im Bild)
|
||||||
|
const VORN = {x: HAUFEN_X + 10, y: BODEN + 70};
|
||||||
|
const mitteHin = (hin + da) / 2;
|
||||||
|
const mitteZurueck = (zurueck + wieder) / 2;
|
||||||
|
const pinoX = kurve(f, [
|
||||||
|
[hin, PINO_BLUME_X],
|
||||||
|
[mitteHin, VORN.x],
|
||||||
|
[da, PINO_AN_BLUME.x],
|
||||||
|
[zurueck, PINO_AN_BLUME.x],
|
||||||
|
[mitteZurueck, VORN.x],
|
||||||
|
[wieder, NOA_BLUME_X + 120],
|
||||||
|
]);
|
||||||
|
const pinoBoden = kurve(f, [
|
||||||
|
[hin, BODEN],
|
||||||
|
[mitteHin, VORN.y],
|
||||||
|
[da, PINO_AN_BLUME.y],
|
||||||
|
[zurueck, PINO_AN_BLUME.y],
|
||||||
|
[mitteZurueck, VORN.y],
|
||||||
|
[wieder, BODEN],
|
||||||
|
]);
|
||||||
|
const pinoGehtHin = f >= hin && f < da;
|
||||||
|
const pinoGehtZurueck = f >= zurueck && f < wieder;
|
||||||
|
const pinoPose: [number, string][] = [
|
||||||
|
[0, 'pino_A4_staunen'],
|
||||||
|
[da, 'pino_A_hinterbeine'],
|
||||||
|
[wieder, 'pino_A_hinterbeine'],
|
||||||
|
[z.l1.start, 'pino_A3_lachen'],
|
||||||
|
];
|
||||||
|
const s = 136 / 571; // Pino: Bildschirm-Pixel je Leinwand-Pixel
|
||||||
|
const pfoten = {x: pinoX + 4, y: pinoBoden - 210 * s};
|
||||||
|
|
||||||
|
// Die Blume: am Zaun → in Pinos Pfoten → zu Noa, die sie hochhält
|
||||||
|
const geben = z.bild1.start + 6;
|
||||||
|
const hoch = geben + 26;
|
||||||
|
// rechte Hand in noa_A_arme-hoch: Leinwand (800, 190), Fuß (675, 700), Maßstab 340/535
|
||||||
|
const NOA_HAENDE = {x: NOA_BLUME_X + 79, y: BODEN - 310};
|
||||||
|
let blume: {x: number; y: number; s: number} = {x: BLUME_X, y: BLUME_Y, s: 0.8};
|
||||||
|
if (f >= pflueck && f < geben) blume = {x: pfoten.x, y: pfoten.y + 20, s: 0.55};
|
||||||
|
if (f >= geben)
|
||||||
|
blume = {
|
||||||
|
x: kurve(f, [
|
||||||
|
[geben, NOA_BLUME_X + 120],
|
||||||
|
[hoch, NOA_HAENDE.x],
|
||||||
|
]),
|
||||||
|
y: kurve(f, [
|
||||||
|
[geben, BODEN - 20],
|
||||||
|
[hoch, NOA_HAENDE.y],
|
||||||
|
]),
|
||||||
|
s: 0.62,
|
||||||
|
};
|
||||||
|
|
||||||
|
const noaPose: [number, string][] = [
|
||||||
|
[0, 'noa_A3_lachen'],
|
||||||
|
[geben, 'noa_A_arme-hoch'],
|
||||||
|
[z.e1.start, 'noa_A_arme-hoch'],
|
||||||
|
[z.e3.start, 'noa_A3_lachen'],
|
||||||
|
];
|
||||||
|
const blumeImBild = f < z.e3.start;
|
||||||
|
|
||||||
|
// Nahaufnahme: Lulu riecht an der Blume (die Blume kommt von unten ins Bild)
|
||||||
|
const nahA = z.l1.start - 20;
|
||||||
|
const nahE = z.l1.ende + 10;
|
||||||
|
const nah = f >= nahA && f < nahE;
|
||||||
|
const luluPose: [number, string][] = [
|
||||||
|
[0, 'lulu_A4_staunen'],
|
||||||
|
[nahA, 'lulu_A1_augen-zu'],
|
||||||
|
[z.l1.start + 30, 'lulu_A3_lachen'],
|
||||||
|
];
|
||||||
|
const nahBlumeY = kurve(f, [
|
||||||
|
[nahA, LULU_NASE.y + 260],
|
||||||
|
[nahA + 24, LULU_NASE.y + 92],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const kam = kamFahrt(f, [
|
||||||
|
[0, 1150, 760, 1.4],
|
||||||
|
[da, 1450, 780, 1.7],
|
||||||
|
[zurueck, 1350, 780, 1.6],
|
||||||
|
[wieder, 960, 740, 1.6],
|
||||||
|
[hoch, 960, 660, 1.5],
|
||||||
|
[nahA - 1, 960, 660, 1.5],
|
||||||
|
[nahA, LULU_NASE.x - 20, LULU_NASE.y + 60, 3.2],
|
||||||
|
[nahE - 1, LULU_NASE.x - 20, LULU_NASE.y + 60, 3.0],
|
||||||
|
[nahE, 1500, 560, 1.1],
|
||||||
|
[z.e1.start + 10, LULU_BLUME_X - 150, 420, 1.9],
|
||||||
|
[z.e2.start, PINO_BLUME_X + 80, 840, 2.0],
|
||||||
|
[z.e3.start, NOA_BLUME_X, 700, 1.8],
|
||||||
|
[z.e4.start, 1300, 600, 1.15],
|
||||||
|
[dauer, 1300, 600, 1.1],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Kamera {...kam}>
|
||||||
|
<Ort name="garten_herbst" />
|
||||||
|
<Laubhaufen x={HAUFEN_X} y={BODEN + 6} />
|
||||||
|
{f < pflueck && <Blume x={BLUME_X} y={BLUME_Y} s={0.8} r={Math.sin(f * 0.07) * 3} />}
|
||||||
|
<Figur pose={luluPose} x={LULU_BLUME_X} y={BODEN - 6} stauchY={atmen(f, 3, 0.006)} blende={12} />
|
||||||
|
<Figur pose={noaPose} x={NOA_BLUME_X} y={BODEN + huepfer(f, hoch, 14, 10)} stauchY={atmen(f, 2) * hopfStauch(f, hoch + 10)} blende={10} />
|
||||||
|
{pinoGehtHin ? (
|
||||||
|
<Geher figur="pino" spiegeln x={pinoX} y={pinoBoden} tempo={1.4} />
|
||||||
|
) : pinoGehtZurueck ? (
|
||||||
|
<Geher figur="pino" x={pinoX} y={pinoBoden} tempo={1.4} />
|
||||||
|
) : (
|
||||||
|
<Figur pose={pinoPose} x={pinoX} y={pinoBoden + huepfer(f, z.l1.ende, 24, 12)} stauchY={atmen(f, 1, 0.01)} blende={10} />
|
||||||
|
)}
|
||||||
|
{f >= pflueck && blumeImBild && !nah && <Blume x={pinoGehtZurueck ? pinoX - 10 : blume.x} y={pinoGehtZurueck ? pinoBoden - 40 : blume.y} s={blume.s} />}
|
||||||
|
{nah && <Blume x={LULU_NASE.x - 10} y={nahBlumeY} s={0.9} r={-8} />}
|
||||||
|
</Kamera>
|
||||||
|
<Blaetterwind anzahl={4} />
|
||||||
|
<Vignette />
|
||||||
|
<Untertitel zeilen={S6.liste} />
|
||||||
|
<Blende dauer={dauer} rein={12} raus={0} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
79
remotion/src/folge01/szene7.tsx
Normal file
79
remotion/src/folge01/szene7.tsx
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {useCurrentFrame} from 'remotion';
|
||||||
|
import {kurve} from '../bewegung';
|
||||||
|
import {Figur, Kamera} from '../baukasten/figur';
|
||||||
|
import {Blende, Vignette, atmen, kamFahrt} from '../baukasten/helfer';
|
||||||
|
import {Apfel, Blaetterwind, Laubhaufen, Zzz} from '../baukasten/natur';
|
||||||
|
import {BODEN, Ort} from '../baukasten/orte';
|
||||||
|
import {Untertitel} from '../baukasten/untertitel';
|
||||||
|
import {plane} from './plan';
|
||||||
|
import {HAUFEN_X} from './szene2';
|
||||||
|
|
||||||
|
// Szene 7: Pino ist müde. Abendlicht, die drei sitzen unter dem Apfelbaum, Pino gähnt.
|
||||||
|
// Lulu liegt links und schaut nach rechts, Noa sitzt rechts und schaut nach links, Pino in der Mitte.
|
||||||
|
|
||||||
|
const LULU_X = 600;
|
||||||
|
const PINO_X = 840;
|
||||||
|
const NOA_X = 1080;
|
||||||
|
|
||||||
|
export const S7 = plane('s7', [
|
||||||
|
{id: 'bild0', dauer: 2.6},
|
||||||
|
{id: 'p1', wer: 'PINO'},
|
||||||
|
{id: 'n1', wer: 'NOA'},
|
||||||
|
{id: 'e1', wer: 'ERZ'},
|
||||||
|
{id: 'e2', wer: 'ERZ', pause: 3},
|
||||||
|
{id: 'e3', wer: 'ERZ'},
|
||||||
|
{id: 'e4', wer: 'ERZ'},
|
||||||
|
{id: 't1', wer: 'ALLE', leise: true},
|
||||||
|
{id: 'bild1', dauer: 1.6},
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const Szene7: React.FC = () => {
|
||||||
|
const f = useCurrentFrame();
|
||||||
|
const {z, dauer} = S7;
|
||||||
|
|
||||||
|
// Pino knabbert, gähnt lang (strecken), wird schläfrig, schläft am Ende ein
|
||||||
|
const gaehnA = z.p1.start;
|
||||||
|
const gaehn = kurve(f, [
|
||||||
|
[gaehnA, 0],
|
||||||
|
[gaehnA + 14, 1],
|
||||||
|
[gaehnA + 48, 1],
|
||||||
|
[gaehnA + 64, 0],
|
||||||
|
]);
|
||||||
|
const pinoPose: [number, string][] = [
|
||||||
|
[0, 'pino_A3_lachen'],
|
||||||
|
[gaehnA + 2, 'pino_A4_staunen'],
|
||||||
|
[gaehnA + 60, 'pino_A2_augen-halb'],
|
||||||
|
[z.e3.start, 'pino_A2_augen-halb'],
|
||||||
|
[z.t1.start + 10, 'pino_A1_augen-zu'],
|
||||||
|
[z.bild1.start, 'pino_B3_schlafen'],
|
||||||
|
];
|
||||||
|
const pinoStauch = atmen(f, 1, f > z.t1.start ? 0.02 : 0.01) * (1 + 0.07 * gaehn);
|
||||||
|
|
||||||
|
const kam = kamFahrt(f, [
|
||||||
|
[0, 840, 620, 1.25],
|
||||||
|
[z.p1.start, PINO_X, 760, 1.7],
|
||||||
|
[z.n1.ende, 900, 720, 1.5],
|
||||||
|
[z.e2.start, 860, 700, 1.4],
|
||||||
|
[z.t1.start, 860, 720, 1.5],
|
||||||
|
[dauer, PINO_X, 790, 2.0],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Kamera {...kam}>
|
||||||
|
<Ort name="garten_herbst_abend" />
|
||||||
|
<Laubhaufen x={HAUFEN_X + 220} y={BODEN + 6} />
|
||||||
|
<Figur pose="lulu_B_liegt" x={LULU_X} y={BODEN + 10} stauchY={atmen(f, 3, 0.008)} />
|
||||||
|
<Figur pose="noa_B_sitzt" x={NOA_X} y={BODEN + 10} stauchY={atmen(f, 2, 0.008)} />
|
||||||
|
<Apfel x={PINO_X + 70} y={BODEN - 6} s={0.62} r={-20} />
|
||||||
|
<Figur pose={pinoPose} x={PINO_X} y={BODEN + 4} stauchY={pinoStauch} blende={12} />
|
||||||
|
<Zzz x={PINO_X + 30} y={BODEN - 150} start={z.bild1.start} s={0.6} />
|
||||||
|
</Kamera>
|
||||||
|
<Blaetterwind anzahl={3} />
|
||||||
|
<Vignette staerke={0.45} />
|
||||||
|
<Untertitel zeilen={S7.liste} />
|
||||||
|
<Blende dauer={dauer} rein={12} raus={0} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue