169 lines
6 KiB
TypeScript
169 lines
6 KiB
TypeScript
import React from 'react';
|
|
import {useCurrentFrame} from 'remotion';
|
|
import {kurve} from '../bewegung';
|
|
import {ClipFigur, Figur, Geher, Kamera, NoaHocke} from '../baukasten/figur';
|
|
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt} from '../baukasten/helfer';
|
|
import {Blaetterwind, Blatt, Voegel} from '../baukasten/natur';
|
|
import {BODEN, Ort} from '../baukasten/orte';
|
|
import {NOA_X, PINO_X} from './szene2';
|
|
import {Untertitel} from '../baukasten/untertitel';
|
|
import {plane} from './plan';
|
|
|
|
// Szene 3: Lulu sieht es von oben. Winterschlaf wird erklärt, Pino ist traurig.
|
|
|
|
export const LULU_X = 1520;
|
|
|
|
export const S3 = plane('s3', [
|
|
{id: 'bild0', dauer: 3.2},
|
|
{id: 'bild1', dauer: 2.4},
|
|
{id: 'l1', wer: 'LULU', text: 'Guten Morgen, ihr zwei!'},
|
|
{id: 'l2', wer: 'LULU', text: 'Von hier oben sehe ich: Die Vögel fliegen weg, ganz weit in den Süden.'},
|
|
{id: 'l3', wer: 'LULU', text: 'Und die Bäume sind kahl. Der Winter kommt.'},
|
|
{id: 'e1', wer: 'ERZ', text: 'Wenn es kalt wird, finden Igel kaum noch etwas zu fressen.'},
|
|
{id: 'e2', wer: 'ERZ', text: 'Darum machen sie etwas ganz Besonderes. Sie schlafen.'},
|
|
{id: 'e3', wer: 'ERZ', text: 'Den ganzen Winter lang, bis zum Frühling. Das heißt Winterschlaf.'},
|
|
{id: 'p1', wer: 'PINO', text: 'Den ganzen Winter? Aber dann verpasse ich ja das Winterfest!'},
|
|
{id: 'bild2', dauer: 2.4},
|
|
{id: 'e4', wer: 'ERZ', text: 'Schau mal, Pinos Stacheln hängen ganz schlaff herunter.'},
|
|
{id: 'e5', wer: 'ERZ', text: 'Wie fühlt sich Pino jetzt?', pause: 3},
|
|
{id: 'e6', wer: 'ERZ', text: 'Ja. Pino ist traurig.'},
|
|
{id: 'bild3', dauer: 2.6},
|
|
{id: 'n1', wer: 'NOA', text: 'Ach, Pino. Bis zum Winterfest ist es doch noch ganz lange hin.'},
|
|
]);
|
|
|
|
// Das große Blatt, auf das Pino sich setzt
|
|
export const GROSSES_BLATT_X = PINO_X + 50;
|
|
|
|
export const Szene3: React.FC = () => {
|
|
const f = useCurrentFrame();
|
|
const {z, dauer} = S3;
|
|
|
|
// Lulu stakst von rechts herein, beugt dann den Hals herunter (Clip),
|
|
// hebt ihn für „von hier oben“ wieder (Clip rückwärts).
|
|
const luluAn = z.bild0.ende;
|
|
const luluX = kurve(f, [
|
|
[0, 2250],
|
|
[luluAn, LULU_X],
|
|
]);
|
|
const luluGeht = f < luluAn;
|
|
const halsRunter = z.bild1.start;
|
|
const halsHoch = z.l2.start - 10;
|
|
const obenStart = z.l2.start + 50;
|
|
const obenEnde = z.e1.ende + 5;
|
|
const imOben = f >= obenStart && f < obenEnde;
|
|
|
|
let lulu: React.ReactNode;
|
|
const luluY = BODEN - 10;
|
|
if (luluGeht) {
|
|
lulu = <Geher figur="lulu" x={luluX} y={luluY} />;
|
|
} else if (f < halsHoch) {
|
|
lulu = <ClipFigur name="lulu_C9_hals-runter" start={halsRunter} tempo={1.25} x={LULU_X} y={luluY} />;
|
|
} else if (f < halsHoch + 110) {
|
|
lulu = <ClipFigur name="lulu_C9_hals-runter" start={halsHoch} tempo={1.5} rueckwaerts x={LULU_X} y={luluY} />;
|
|
} else {
|
|
lulu = (
|
|
<Figur
|
|
pose={[
|
|
[0, 'lulu_A5_blick-links'],
|
|
[z.bild2.start, 'lulu_B1_traurig'],
|
|
[z.bild3.start, 'lulu_A5_blick-links'],
|
|
]}
|
|
x={LULU_X}
|
|
y={luluY}
|
|
stauchY={atmen(f, 3, 0.006)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// Pino
|
|
const pinoSchreck = z.p1.start;
|
|
const aufsBlatt = z.bild2.start + 10;
|
|
const pinoX = kurve(f, [
|
|
[aufsBlatt, PINO_X],
|
|
[aufsBlatt + 24, GROSSES_BLATT_X],
|
|
]);
|
|
// Das große Blatt segelt vom Apfelbaum herunter und landet neben Pino
|
|
const blattFaellt = aufsBlatt - 80;
|
|
const u = Math.min(1, Math.max(0, (f - blattFaellt) / 70));
|
|
const schaukeln = Math.sin(u * 8) * (1 - u);
|
|
const blattX = GROSSES_BLATT_X - 180 * (1 - u) + schaukeln * 70;
|
|
const blattY = BODEN - 8 - 560 * (1 - u);
|
|
const blattR = 88 + schaukeln * 45;
|
|
const traurig = kurve(f, [
|
|
[aufsBlatt + 20, 0],
|
|
[aufsBlatt + 50, 1],
|
|
]);
|
|
const anlehnen = kurve(f, [
|
|
[z.bild3.start + 40, 0],
|
|
[z.bild3.start + 70, 1],
|
|
]);
|
|
const pinoPose: [number, string][] = [
|
|
[0, 'pino_A2_augen-halb'],
|
|
[z.bild0.start + 40, 'pino_A6_blick-rechts'],
|
|
[z.bild1.start + 20, 'pino_B_blick-nach-oben'],
|
|
[z.l1.start + 20, 'pino_A3_lachen'],
|
|
[z.l2.start, 'pino_B_blick-nach-oben'],
|
|
[z.e2.start, 'pino_A2_augen-halb'],
|
|
[z.e3.start + 30, 'pino_A4_staunen'],
|
|
[pinoSchreck, 'pino_B2_erschrocken'],
|
|
[aufsBlatt + 20, 'pino_B1_traurig'],
|
|
[z.bild3.start + 50, 'pino_A1_augen-zu'],
|
|
];
|
|
const pinoY = BODEN + huepfer(f, pinoSchreck, 34, 12) + huepfer(f, aufsBlatt, 14, 22) - (f > aufsBlatt + 20 ? 6 : 0);
|
|
const pinoStauchY = atmen(f, 1) * hopfStauch(f, pinoSchreck) * (1 - 0.06 * traurig + 0.06 * anlehnen * 0);
|
|
const pinoDreh = -9 * anlehnen + 3 * traurig * (1 - anlehnen);
|
|
|
|
// Noa kniet sich zu Pino
|
|
const knien = z.bild3.start + 10;
|
|
const noaX = kurve(f, [
|
|
[knien - 36, NOA_X],
|
|
[knien, NOA_X + 140],
|
|
]);
|
|
const noaPose: [number, string][] = [
|
|
[0, 'noa_A6_blick-rechts'],
|
|
[z.bild1.start + 20, 'noa_A4_staunen'],
|
|
[z.l1.start + 15, 'noa_A3_lachen'],
|
|
[z.e1.start, 'noa_A6_blick-rechts'],
|
|
[z.bild2.start + 30, 'noa_B1_traurig'],
|
|
];
|
|
const noaGeht = f >= knien - 36 && f < knien;
|
|
|
|
const kam = kamFahrt(f, [
|
|
[0, 1150, 820, 1.7],
|
|
[z.bild0.ende - 10, 1150, 820, 1.7],
|
|
[z.bild1.start + 30, 1150, 640, 1.15],
|
|
[z.l1.ende, 1120, 700, 1.3],
|
|
[z.l2.start, 1250, 520, 1.1],
|
|
[obenStart, 1300, 420, 1.2],
|
|
[obenEnde, 1050, 800, 2.2],
|
|
[z.e3.ende, 1060, 820, 2.4],
|
|
[z.p1.start + 10, 1050, 810, 2.1],
|
|
[z.bild2.start + 20, 1090, 820, 2.5],
|
|
[z.e6.ende, 1100, 830, 2.7],
|
|
[z.bild3.start + 30, 960, 790, 1.9],
|
|
[dauer, 950, 790, 2.0],
|
|
]);
|
|
|
|
return (
|
|
<>
|
|
{imOben ? (
|
|
<Kamera x={kurve(f, [[obenStart, 900], [obenEnde, 1060]])} y={540} zoom={1.05}>
|
|
<Ort name="oben" />
|
|
<Voegel start={obenStart - 40} skala={1.6} />
|
|
</Kamera>
|
|
) : (
|
|
<Kamera {...kam}>
|
|
<Ort name="garten" />
|
|
{noaGeht ? <Geher figur="noa" spiegeln x={noaX} y={BODEN} /> : f >= knien ? <NoaHocke start={knien} x={noaX} y={BODEN} /> : <Figur pose={noaPose} x={noaX} y={BODEN} stauchY={atmen(f, 2)} />}
|
|
{f > blattFaellt && <Blatt x={blattX} y={blattY} r={blattR} s={2.6} farbe="#c8642c" />}
|
|
<Figur pose={pinoPose} x={pinoX} y={pinoY} stauchY={pinoStauchY} drehung={pinoDreh} blende={6} />
|
|
{lulu}
|
|
</Kamera>
|
|
)}
|
|
{!imOben && <Blaetterwind anzahl={4} seed="w3" />}
|
|
<Vignette />
|
|
<Untertitel zeilen={S3.liste} />
|
|
<Blende dauer={dauer} rein={0} raus={0} />
|
|
</>
|
|
);
|
|
};
|