Drachenschnur als Linie in Remotion für noa_A_drachenschnur

- baukasten/drachenschnur.tsx: <Drachenschnur von nach> zeichnet die Schnur
  als Kurve mit Durchhang und leichtem Flattern im Wind (durchhang, wind,
  staerke, deckkraft einstellbar); spulenPunkt(x, y, hoehe, spiegeln) liefert
  den Ansatz an Noas Spule mit denselben Lage-Werten wie <Figur>
- Ansatzpunkt in der Leinwand (770, 405) am Rohbild gemessen: die Schnur
  kommt oben aus der Wicklung
- Prüfszene DrachenschnurTest (Noa normal und gespiegelt/größer,
  Platzhalter-Drachen pendelt)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lara 2026-11-07 10:59:18 +01:00
parent d88a3bfd8f
commit 21324b0ef6
4 changed files with 99 additions and 1 deletions

View file

@ -46,7 +46,7 @@ unter `figuren/bibliothek/`. Die **Clips** (MP4) sind nicht im Git (siehe
| noa_A_arme-hoch | beide Arme hoch | 1 | 1,5 | | | noa_A_arme-hoch | beide Arme hoch | 1 | 1,5 | |
| noa_A_klatschen | klatscht, Fäustlinge vor der Brust (02.11.2026, Nano Banana 2 aus noa_ref_stehend, für das Lied) | 1 | 1,5 | ohne rembg freigestellt | | noa_A_klatschen | klatscht, Fäustlinge vor der Brust (02.11.2026, Nano Banana 2 aus noa_ref_stehend, für das Lied) | 1 | 1,5 | ohne rembg freigestellt |
| noa_A_laterne | Laterne in rechter Hand | 2 | 3 | 1. Versuch ohne Laterne; 2. gespiegelt; Laterne ragt seitlich weit heraus | | noa_A_laterne | Laterne in rechter Hand | 2 | 3 | 1. Versuch ohne Laterne; 2. gespiegelt; Laterne ragt seitlich weit heraus |
| noa_A_drachenschnur | steht leicht nach rechts gedreht, hält eine Drachenspule mit beiden Fäustlingen, schaut nach oben rechts (07.11.2026, Nano Banana Pro 1k aus noa_ref_stehend, für „Lulu und der Drachen“) | 2 | 4 | 1. Versuch mit losem Schnurende am Boden; Schnur beim Freistellen entfernt, wird in Remotion als Linie ab der Spule (rechtes Ende ca. x 790, y 400 in der Leinwand) gezeichnet; ohne rembg freigestellt | | noa_A_drachenschnur | steht leicht nach rechts gedreht, hält eine Drachenspule mit beiden Fäustlingen, schaut nach oben rechts (07.11.2026, Nano Banana Pro 1k aus noa_ref_stehend, für „Lulu und der Drachen“) | 2 | 4 | 1. Versuch mit losem Schnurende am Boden; Schnur beim Freistellen entfernt, wird in Remotion als Linie gezeichnet: `Drachenschnur` + `spulenPunkt` in `remotion/src/baukasten/drachenschnur.tsx` (Ansatz x 770, y 405 in der Leinwand), Prüfszene `DrachenschnurTest`; ohne rembg freigestellt |
| noa_A_haende-oben | steht frontal, Fäustlinge über dem Kopf, fröhlich-stolz (07.11.2026, Nano Banana Pro 1k aus noa_ref_stehend) | 1 | 2 | Arme eher jubelnd auseinander statt dicht beieinander, Zöpfe kaum sichtbar – so abgenommen; ohne rembg freigestellt | | noa_A_haende-oben | steht frontal, Fäustlinge über dem Kopf, fröhlich-stolz (07.11.2026, Nano Banana Pro 1k aus noa_ref_stehend) | 1 | 2 | Arme eher jubelnd auseinander statt dicht beieinander, Zöpfe kaum sichtbar – so abgenommen; ohne rembg freigestellt |
| noa_B1_traurig | traurig | 2 | 1,5 | 1. Versuch abgebrochen, erstattet | | noa_B1_traurig | traurig | 2 | 1,5 | 1. Versuch abgebrochen, erstattet |
| noa_B2_erschrocken | kurz erschrocken | 1 | 1,5 | | | noa_B2_erschrocken | kurz erschrocken | 1 | 1,5 | |

View file

@ -4,6 +4,7 @@ import {HintergrundAbend, PapierStruktur, VordergrundAbend} from './szenen/Hinte
import {LaterneTest} from './szenen/LaterneTest'; import {LaterneTest} from './szenen/LaterneTest';
import {GANGTEST_DAUER, GangTest} from './szenen/GangTest'; import {GANGTEST_DAUER, GangTest} from './szenen/GangTest';
import {VerformTest} from './szenen/VerformTest'; import {VerformTest} from './szenen/VerformTest';
import {DrachenschnurTest} from './szenen/DrachenschnurTest';
import {FolgenKompositionen} from './baukasten/folge'; import {FolgenKompositionen} from './baukasten/folge';
import {NEST_BILD} from './baukasten/natur'; import {NEST_BILD} from './baukasten/natur';
import {NestStill, ORTE, OrtStill} from './baukasten/orte'; import {NestStill, ORTE, OrtStill} from './baukasten/orte';
@ -28,6 +29,7 @@ export const Root: React.FC = () => (
<Composition id="GangTest" component={GangTest} durationInFrames={GANGTEST_DAUER} {...BILD} /> <Composition id="GangTest" component={GangTest} durationInFrames={GANGTEST_DAUER} {...BILD} />
<Composition id="LaterneTest" component={LaterneTest} durationInFrames={420} {...BILD} /> <Composition id="LaterneTest" component={LaterneTest} durationInFrames={420} {...BILD} />
<Composition id="VerformTest" component={VerformTest} durationInFrames={240} {...BILD} /> <Composition id="VerformTest" component={VerformTest} durationInFrames={240} {...BILD} />
<Composition id="DrachenschnurTest" component={DrachenschnurTest} durationInFrames={150} {...BILD} />
<Composition id="HintergrundAbend" component={HintergrundAbend} durationInFrames={1} {...BILD} /> <Composition id="HintergrundAbend" component={HintergrundAbend} durationInFrames={1} {...BILD} />
<Composition id="VordergrundAbend" component={VordergrundAbend} durationInFrames={1} {...BILD} /> <Composition id="VordergrundAbend" component={VordergrundAbend} durationInFrames={1} {...BILD} />
<Composition id="PapierStruktur" component={PapierStruktur} durationInFrames={1} {...BILD} /> <Composition id="PapierStruktur" component={PapierStruktur} durationInFrames={1} {...BILD} />

View file

@ -0,0 +1,64 @@
import React from 'react';
import {useCurrentFrame} from 'remotion';
import {GROESSE, NOA_HOEHE} from './figur';
import {punkt} from './helfer';
// Drachenschnur für die Pose noa_A_drachenschnur („Lulu und der Drachen“).
// Im Bild hält Noa nur die Holzspule; die gemalte Schnur ist beim Freistellen
// entfernt worden. Hier wird sie als Linie von der Spule bis zum Drachen gezogen,
// mit leichtem Durchhang und etwas Wind.
// Austritt der Schnur aus der Wicklung (oben, vor der rechten Scheibe), in der Bild-Leinwand
// von noa_A_drachenschnur (1376 × 768), gemessen am Rohbild.
export const NOA_SPULE = {cx: 770, cy: 405};
// Bildschirmpunkt der Spule für eine Noa mit denselben Lage-Werten wie <Figur>.
export const spulenPunkt = (x: number, y: number, hoehe = NOA_HOEHE * GROESSE.noa, spiegeln = false) =>
punkt('noa', x, y, NOA_SPULE.cx, NOA_SPULE.cy, hoehe, spiegeln);
type SchnurProps = {
von: {x: number; y: number}; // meist spulenPunkt(...)
nach: {x: number; y: number}; // Haltepunkt am Drachen
durchhang?: number; // Anteil der Schnurlänge, um den die Mitte nach unten hängt (straff = 0.02, locker = 0.12)
wind?: number; // Stärke des Flatterns in px
staerke?: number; // Linienbreite in px
farbe?: string;
deckkraft?: number;
frame?: number;
};
export const Drachenschnur: React.FC<SchnurProps> = ({
von,
nach,
durchhang = 0.06,
wind = 6,
staerke = 2.2,
farbe = '#5b4636',
deckkraft = 1,
frame,
}) => {
const jetzt = useCurrentFrame();
const f = frame ?? jetzt;
const dx = nach.x - von.x;
const dy = nach.y - von.y;
const laenge = Math.hypot(dx, dy) || 1;
// Senkrechte zur Schnur, so gewählt, dass sie nach unten zeigt (Durchhang)
let nx = -dy / laenge;
let ny = dx / laenge;
if (ny < 0) {
nx = -nx;
ny = -ny;
}
// Durchhang atmet ein wenig mit dem Wind; die Schnur schlängelt sich leicht
const hang = laenge * durchhang * (1 + 0.15 * Math.sin(f * 0.09));
const welle1 = Math.sin(f * 0.21) * wind;
const welle2 = Math.sin(f * 0.17 + 1.3) * wind * 0.6;
const k1 = {x: von.x + dx * 0.33 + nx * (hang * 0.9 + welle1), y: von.y + dy * 0.33 + ny * (hang * 0.9 + welle1)};
const k2 = {x: von.x + dx * 0.66 + nx * (hang * 0.7 - welle2), y: von.y + dy * 0.66 + ny * (hang * 0.7 - welle2)};
const d = `M ${von.x} ${von.y} C ${k1.x} ${k1.y}, ${k2.x} ${k2.y}, ${nach.x} ${nach.y}`;
return (
<svg style={{position: 'absolute', left: 0, top: 0, width: 1920, height: 1080, overflow: 'visible', pointerEvents: 'none', opacity: deckkraft}}>
<path d={d} fill="none" stroke={farbe} strokeWidth={staerke} strokeLinecap="round" opacity={0.85} />
</svg>
);
};

View file

@ -0,0 +1,32 @@
import React from 'react';
import {AbsoluteFill, useCurrentFrame} from 'remotion';
import {Figur, NOA_HOEHE} from '../baukasten/figur';
import {Drachenschnur, spulenPunkt} from '../baukasten/drachenschnur';
// Prüfszene: Noa mit Drachenspule, Schnur zu einem Platzhalter-Drachen, der pendelt.
// Links normal, rechts gespiegelt und größer (prüft die Umrechnung).
const Platzhalter: React.FC<{x: number; y: number}> = ({x, y}) => (
<div style={{position: 'absolute', left: x - 40, top: y - 55, width: 80, height: 110}}>
<svg width={80} height={110}>
<polygon points="40,0 80,45 40,110 0,45" fill="#c8402c" opacity={0.8} />
</svg>
</div>
);
export const DrachenschnurTest: React.FC = () => {
const f = useCurrentFrame();
const drachen1 = {x: 760 + Math.sin(f * 0.05) * 60, y: 160 + Math.sin(f * 0.08) * 25};
const drachen2 = {x: 1180 - Math.sin(f * 0.05) * 60, y: 200 + Math.cos(f * 0.07) * 25};
const noa1 = {x: 420, y: 900, hoehe: NOA_HOEHE};
const noa2 = {x: 1560, y: 980, hoehe: NOA_HOEHE * 1.5, spiegeln: true};
return (
<AbsoluteFill style={{background: '#f4ead8'}}>
<Platzhalter {...drachen1} />
<Platzhalter {...drachen2} />
<Figur pose="noa_A_drachenschnur" {...noa1} />
<Drachenschnur von={spulenPunkt(noa1.x, noa1.y, noa1.hoehe)} nach={{x: drachen1.x, y: drachen1.y + 55}} />
<Figur pose="noa_A_drachenschnur" {...noa2} />
<Drachenschnur von={spulenPunkt(noa2.x, noa2.y, noa2.hoehe, true)} nach={{x: drachen2.x, y: drachen2.y + 55}} staerke={3} durchhang={0.1} />
</AbsoluteFill>
);
};