From 132e969d034fa79031999e52b80728cf0ead8ee6 Mon Sep 17 00:00:00 2001 From: Lara Date: Mon, 2 Nov 2026 12:29:00 +0100 Subject: [PATCH] =?UTF-8?q?Folge=201,=20Szene=202,=20R=C3=BCckmeldung=201:?= =?UTF-8?q?=20Laubhaufen=20aus=20Ahorn-=20und=20Buchenbl=C3=A4ttern,=20Noa?= =?UTF-8?q?s=20F=C3=BC=C3=9Fe=20im=20Haufen=20verdeckt,=20Hocke=20=C3=BCbe?= =?UTF-8?q?r=20Clip,=20Pino=20rollt=20sich=20auf=20und=20schaut=20zu=20Noa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- remotion/src/baukasten/natur.tsx | 44 +++++++++++++++++++++++--------- remotion/src/folge01/szene2.tsx | 43 +++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/remotion/src/baukasten/natur.tsx b/remotion/src/baukasten/natur.tsx index 3f83532..ef6c7c1 100644 --- a/remotion/src/baukasten/natur.tsx +++ b/remotion/src/baukasten/natur.tsx @@ -308,25 +308,45 @@ export const Blume: React.FC<{x: number; y: number; s?: number; r?: number}> = ( ); -// Folge 1: Laubhaufen (Fuß bei x, y; ca. 340 × 140 px bei s = 1). +// Ahornblatt (Spitze oben, ca. 90 px hoch bei s = 1) und schmales Buchenblatt, für den Laubhaufen +const AHORN = 'M0,40 L4,18 L22,27 L18,12 L40,5 L30,-2 L37,-21 L18,-14 L16,-31 L6,-22 L0,-46 L-6,-22 L-16,-31 L-18,-14 L-37,-21 L-30,-2 L-40,5 L-18,12 L-22,27 L-4,18 Z'; +const AHORN_ADERN = 'M0,52 L0,-38 M0,10 L30,-14 M0,10 L-30,-14 M0,18 L18,24 M0,18 L-18,24'; +const BUCHE = 'M0,-44 C 22,-30 24,0 0,30 C -24,0 -22,-30 0,-44 Z'; +const BUCHE_ADERN = 'M0,40 L0,-36 M0,-14 L12,-24 M0,-2 L14,-12 M0,-8 L-12,-18 M0,4 L-13,-6'; +const HAUFEN_HELL = ['#e07a2e', '#d4522a', '#e9a83a', '#c2412a', '#f0c048', '#d98a3a', '#b8662a']; +const HAUFEN_DUNKEL = ['#9e4a26', '#8a3a22', '#a8682e', '#7a3a24']; + +// Folge 1: Laubhaufen aus großen Herbstblättern (Fuß bei x, y; ca. 400 × 190 px bei s = 1). +// Reicht unten 45 px unter den Fußpunkt, damit Füße darin verschwinden. // `wackeln` 0 … 1 lässt ihn zittern, `flach` 0 … 1 drückt ihn zusammen (Noa springt hinein). export const Laubhaufen: React.FC<{x: number; y: number; s?: number; wackeln?: number; flach?: number}> = ({x, y, s = 1, wackeln = 0, flach = 0}) => { const frame = useCurrentFrame(); const zitter = wackeln * Math.sin(frame * 1.3) * 3; + // hinten/oben zuerst zeichnen, vorne/unten zuletzt + const blaetter = new Array(120).fill(0).map((_, i) => { + const r = (k: string) => random(`lh${k}${i}`); + const u = r('u') * 2.2 - 1.1; + const kuppe = Math.pow(Math.max(0, 1 - u * u), 0.6) * 150; + const ly = 40 - r('y') * (kuppe + 40); + return {i, u, lx: u * 180, ly, ahorn: r('a') < 0.62, s: 0.85 + r('s') * 0.65, w: r('w') * 360, dunkel: ly < -kuppe * 0.55 ? false : r('d') < 0.3, farbe: r('f')}; + }); + blaetter.sort((a, b) => a.ly - b.ly); return ( - - {new Array(70).fill(0).map((_, i) => { - const u = random('lh' + i) * 2 - 1; - const h = 1 - u * u; - const bx = u * 165; - const by = -random('lhy' + i) * 132 * h - 4; - return ; + + {blaetter.map((b) => { + const liste = b.dunkel ? HAUFEN_DUNKEL : HAUFEN_HELL; + return ( + + + + + ); })} ); diff --git a/remotion/src/folge01/szene2.tsx b/remotion/src/folge01/szene2.tsx index 2709271..d9c1280 100644 --- a/remotion/src/folge01/szene2.tsx +++ b/remotion/src/folge01/szene2.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {useCurrentFrame} from 'remotion'; import {kurve} from '../bewegung'; -import {Figur, Geher, Kamera} from '../baukasten/figur'; +import {ClipFigur, Figur, Geher, Kamera, NOA_HOCKE_FRAMES, NoaHocke} from '../baukasten/figur'; import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt, ruck} from '../baukasten/helfer'; import {Apfel, Blaetterregen, Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur'; import {BODEN, Ort} from '../baukasten/orte'; @@ -16,7 +16,7 @@ export const APFEL = {x: 560, y: 205}; // der letzte Apfel, ganz oben im Baum export const BLUME_X = 1560; // blaue Blume am Zaun export const BLUME_Y = 805; export const NOA_X = 960; // Noa neben dem Haufen -export const PINO_HAUFEN_Y = BODEN - 92; // Pino sitzt oben im Haufen +export const PINO_HAUFEN_Y = BODEN - 128; // Pino steckt oben im Haufen (als Kugel) export const S2 = plane('s2', [ {id: 'bild0', dauer: 2.2}, @@ -71,16 +71,18 @@ export const Szene2: React.FC = () => { [schreck, 'noa_B2_erschrocken'], [z.n2.start + 6, 'noa_A4_staunen'], [z.e6.start, 'noa_A6_blick-rechts'], - [hocke, 'noa_B_hocken'], [aufstehen, 'noa_A3_lachen'], [z.p2.start + 10, 'noa_A6_blick-rechts'], ]; + // Hocke: Clip „hinsetzen“ bis zur Hocke, zum Aufstehen rückwärts + const inHocke = f >= hocke && f < aufstehen + NOA_HOCKE_FRAMES; + const hockeStart = f < aufstehen ? hocke : aufstehen; const noaY = BODEN + sprungY + huepfer(f, raus, 60, 16) + ruck(f, schreck, 3) + - huepfer(f, z.n4.start + 20, 14, 10); + huepfer(f, aufstehen + NOA_HOCKE_FRAMES + 4, 14, 10); // Laubhaufen: wird bei der Landung gestaucht, später raschelt er const flach = kurve(f, [ @@ -96,24 +98,28 @@ export const Szene2: React.FC = () => { ]); // Pino: als Stachelkugel im Haufen, kommt hoch, öffnet sich bei bild4 + const auf = z.bild4.start; // Einroll-Clip rückwärts + const AUF_FRAMES = 75; // 121 Clip-Bilder (24 fps) bei Tempo 2 + const oeffnet = f >= auf && f < auf + AUF_FRAMES; + const zuNoa = f >= auf; // die Bilder schauen nach rechts, Noa sitzt links const pinoY = kurve(f, [ - [schreck - 10, PINO_HAUFEN_Y + 110], + [schreck - 10, PINO_HAUFEN_Y + 140], [schreck + 6, PINO_HAUFEN_Y], - [z.bild4.start + 14, PINO_HAUFEN_Y], - [z.bild4.start + 40, PINO_HAUFEN_Y - 42], + [auf + 20, PINO_HAUFEN_Y], + [auf + AUF_FRAMES, PINO_HAUFEN_Y - 40], ]); const pinoDa = f >= schreck - 10; const pinoPose: [number, string][] = [ [0, 'pino_A_kugel'], - [z.bild4.start + 20, 'pino_ref_sitzend'], + [auf + AUF_FRAMES, 'pino_ref_sitzend'], [z.p1.start, 'pino_B_blick-nach-oben'], [z.p1.start + 40, 'pino_A4_staunen'], [z.p2.start, 'pino_B_blick-nach-oben'], [z.p2.ende - 10, 'pino_A3_lachen'], ]; // Stacheln zittern vor Angst, solange er eine Kugel ist - const angst = f < z.bild4.start + 20 ? Math.sin(f * 1.7) * 1.5 : 0; - const pinoStauch = atmen(f, 1, 0.01) * hopfStauch(f, schreck) * (f >= z.bild4.start && f < z.bild4.start + 24 ? kurve(f, [[z.bild4.start, 0.9], [z.bild4.start + 24, 1]]) : 1); + const angst = f < auf ? Math.sin(f * 1.7) * 1.5 : 0; + const pinoStauch = atmen(f, 1, 0.01) * hopfStauch(f, schreck); const kam = kamFahrt(f, [ [0, 960, 540, 1.0], @@ -135,11 +141,22 @@ export const Szene2: React.FC = () => { - {pinoDa && } + {pinoDa && + (oeffnet ? ( + + ) : ( + + ))} {/* Im Haufen steht Noa hinter den vorderen Blättern */} {imHaufen && } - - {imHaufen ? null : noaGeht ? : } + + {imHaufen ? null : noaGeht ? ( + + ) : inHocke ? ( + = aufstehen} x={noaX} y={BODEN} /> + ) : ( + + )}