Physik Stufe 2: Capsule und Polygon-Collider (konkav zerlegt) mit Punkt-Editing im Scene-View #151

Closed
opened 2026-09-18 22:18:05 +02:00 by meleki · 1 comment
Owner

Stufe 2 aus #144. Danach setzt #141 (Kollisions-Polygon pro Frame, Tilemap) darauf auf; beides wird in einer Runde gebaut.

Befund

  • Ein Collider kennt nur box und circle (src/core/properties/PropertySchema.ts, ColliderShape in src/core/properties/collider.ts). Überlappung, contactBetween und exitDistance sind für genau diese drei Paare von Hand geschrieben.
  • Seit #150 rechnet Move Treffpunkt und Normale mit dieser eigenen f64-Geometrie, nicht mit Rapiers castShape (f32, landet 3e-6 px in der Wand). Neue Formen brauchen deshalb eigene Geometrie, die Engine allein reicht nicht.
  • Das PhysicsSystem baut pro Collider genau einen Rapier-Collider (ball oder cuboid).

Zu bauen

  • Capsule: neue Form, füllt Width × Height aus und ist entlang der längeren Seite abgerundet (Radius = halbe kürzere Seite). Sind beide gleich, ist sie ein Kreis.
  • Polygon: neue Form mit der Property points (Liste von {x, y} in Collider-Einheiten, Vorgabe ein Dreieck). Punkt-Editing im Scene-View am ausgewählten Collider: Punkt ziehen, Klick auf eine Kante fügt einen Punkt ein, Doppelklick auf einen Punkt löscht ihn (mindestens 3 bleiben). Jeder Schritt ist ein Undo-Schritt. Die Liste ist zusätzlich im Inspector editierbar.
  • Konkave Polygone werden intern in konvexe Teile zerlegt (Ear Clipping, danach Hertel-Mehlhorn). Ein Polygon, das sich selbst schneidet oder keine Fläche hat, kollidiert nicht und wird im Scene-View rot umrandet.
  • Geometrie: ein gemeinsamer Weg für abgerundete konvexe Teile (SAT, bei getrennten Kernen der echte Abstand), in f64. Box/Box, Kreis/Kreis und Box/Kreis behalten ihren bisherigen, exakt getesteten Code.
  • Physik: Capsule als Rapier-capsule, jedes konvexe Teil als eigenes convexPolygon am selben Body. Masse und Dichte verteilen sich nach Fläche.
  • Tests: Unit-Tests für Zerlegung, Überlappung, Normale und exitDistance jeder neuen Paarung, Move an einer Polygon-Schräge und über die Naht eines zerlegten Polygons, Fallen und Liegenbleiben in Play. e2e: Polygon im Scene-View bearbeiten, eine Kapsel fällt auf eine Polygon-Schräge.

Entscheidungen

Getroffen, weil beides direkt umgesetzt werden sollte. Wer etwas anders will, sagt es hier.

  1. Capsule über Width/Height statt eigener Felder für Radius und Richtung, damit "Add collider" sie wie eine Box nach dem Sprite bemisst.
  2. Punkte relativ zum Collider, sie drehen, skalieren und spiegeln also mit dem Objekt.
  3. Eigene Zerlegung statt Rapiers convexDecomposition: Move braucht die Teile ohnehin in unserer Geometrie, und beide Seiten sehen so dieselben Teile.

Später (weiter aus #144, eigene Issues): Kollisionsebenen/Masken, Raycast, Joints, One-Way-Plattformen.

Stufe 2 aus #144. Danach setzt #141 (Kollisions-Polygon pro Frame, Tilemap) darauf auf; beides wird in einer Runde gebaut. ## Befund - Ein Collider kennt nur `box` und `circle` (`src/core/properties/PropertySchema.ts`, `ColliderShape` in `src/core/properties/collider.ts`). Überlappung, `contactBetween` und `exitDistance` sind für genau diese drei Paare von Hand geschrieben. - Seit #150 rechnet `Move` Treffpunkt und Normale mit dieser eigenen f64-Geometrie, nicht mit Rapiers `castShape` (f32, landet 3e-6 px in der Wand). Neue Formen brauchen deshalb eigene Geometrie, die Engine allein reicht nicht. - Das `PhysicsSystem` baut pro Collider genau einen Rapier-Collider (`ball` oder `cuboid`). ## Zu bauen - **Capsule:** neue Form, füllt `Width × Height` aus und ist entlang der längeren Seite abgerundet (Radius = halbe kürzere Seite). Sind beide gleich, ist sie ein Kreis. - **Polygon:** neue Form mit der Property `points` (Liste von `{x, y}` in Collider-Einheiten, Vorgabe ein Dreieck). **Punkt-Editing im Scene-View** am ausgewählten Collider: Punkt ziehen, Klick auf eine Kante fügt einen Punkt ein, Doppelklick auf einen Punkt löscht ihn (mindestens 3 bleiben). Jeder Schritt ist ein Undo-Schritt. Die Liste ist zusätzlich im Inspector editierbar. - **Konkave Polygone** werden intern in konvexe Teile zerlegt (Ear Clipping, danach Hertel-Mehlhorn). Ein Polygon, das sich selbst schneidet oder keine Fläche hat, kollidiert nicht und wird im Scene-View rot umrandet. - **Geometrie:** ein gemeinsamer Weg für abgerundete konvexe Teile (SAT, bei getrennten Kernen der echte Abstand), in f64. Box/Box, Kreis/Kreis und Box/Kreis behalten ihren bisherigen, exakt getesteten Code. - **Physik:** Capsule als Rapier-`capsule`, jedes konvexe Teil als eigenes `convexPolygon` am selben Body. Masse und Dichte verteilen sich nach Fläche. - **Tests:** Unit-Tests für Zerlegung, Überlappung, Normale und `exitDistance` jeder neuen Paarung, `Move` an einer Polygon-Schräge und über die Naht eines zerlegten Polygons, Fallen und Liegenbleiben in Play. e2e: Polygon im Scene-View bearbeiten, eine Kapsel fällt auf eine Polygon-Schräge. ## Entscheidungen Getroffen, weil beides direkt umgesetzt werden sollte. Wer etwas anders will, sagt es hier. 1. Capsule über Width/Height statt eigener Felder für Radius und Richtung, damit "Add collider" sie wie eine Box nach dem Sprite bemisst. 2. Punkte relativ zum Collider, sie drehen, skalieren und spiegeln also mit dem Objekt. 3. Eigene Zerlegung statt Rapiers `convexDecomposition`: `Move` braucht die Teile ohnehin in unserer Geometrie, und beide Seiten sehen so dieselben Teile. **Später** (weiter aus #144, eigene Issues): Kollisionsebenen/Masken, Raycast, Joints, One-Way-Plattformen.
admin added this to the Development project 2026-09-18 22:18:43 +02:00
admin moved this to Next in Development on 2026-09-18 22:18:49 +02:00
Author
Owner

Umgesetzt in 32057a9, Wiki in 1ee4e0e.

Was gebaut ist

  • Capsule: füllt Width × Height, abgerundet entlang der längeren Seite.
  • Polygon: Ecken in der Property points, drehen, skalieren und spiegeln mit dem Objekt. Neue Polygone starten als Dreieck.
  • Punkt-Editing im Scene-View: Ecke ziehen, Klick auf Kante fügt ein, Doppelklick löscht (mindestens 3 bleiben), jeder Schritt ein Undo-Schritt.
  • Konkav → intern in konvexe Teile zerlegt. Selbstschneidende Polygone werden rot gezeichnet und kollidieren mit nichts.
  • Rapier: Kapsel als Kapsel, jedes Polygon-Teil als eigener konvexer Collider am selben Body.
  • Move und Editor-Run rechnen die neuen Formen in unserer f64-Geometrie (convex.ts, SAT mit abgerundeten Teilen), nicht über Rapiers castShape (f32, siehe #150). Box und Kreis behalten ihren bisherigen Code.

Unterwegs gefundene Fehler

  1. Hängen am Fuß einer Schräge: Bei Gleichstand zweier Normalen nahm die Regel aus #150 die Wand. Für Kapsel/Polygon gewinnt jetzt die Normale, die der Bewegung am wenigsten im Weg steht.
  2. Kaputte Ecken beim Laden: JSON macht aus NaN ein null, Number(null) ist 0. pointsOf nimmt nur noch echte Zahlen.

Tests

  • Quadratisches Polygon kollidiert in 400 Zufallsfällen exakt wie die Box.
  • Zerlegung von 200 zufälligen Sternformen deckt genau die Fläche ab.
  • Polygon-Rampe: g·sin − μ·g·cos wie in #150.
  • Physik: Kapsel und U-Form kommen richtig zur Ruhe.
  • Gegenprobe mit 12 eingebauten Fehlern: 11 gefangen, eine Mutation war gleichwertig zum Original.
  • Gemessen: Rapier lässt eine Kapsel beim Aufprall 0,9 px eindringen und drückt sie in ~20 Frames heraus.
  • e2e-Modul 42 shapes (10 Checks, gemeinsam mit #141).

CI zu 32057a9

  • Gate (Task 140): 106 Testdateien grün, CHECK EXIT 0.
  • Suite (Task 141): ALL PASSED – 1067 checks.
  • Smokes: 24 / 19 / 21, alle grün.

Weiter

  • #141 (Umriss pro Frame) baut darauf auf; die erste Fassung ist mit im Commit, wird aber noch überarbeitet und bleibt offen.
  • Die „Später“-Punkte aus #144 sind jetzt eigene Issues: #152 Ebenen, #153 Raycast, #154 Joints, #155 One-Way.
Umgesetzt in `32057a9`, Wiki in `1ee4e0e`. ## Was gebaut ist - **Capsule:** füllt Width × Height, abgerundet entlang der längeren Seite. - **Polygon:** Ecken in der Property `points`, drehen, skalieren und spiegeln mit dem Objekt. Neue Polygone starten als Dreieck. - **Punkt-Editing im Scene-View:** Ecke ziehen, Klick auf Kante fügt ein, Doppelklick löscht (mindestens 3 bleiben), jeder Schritt ein Undo-Schritt. - **Konkav → intern in konvexe Teile zerlegt.** Selbstschneidende Polygone werden rot gezeichnet und kollidieren mit nichts. - **Rapier:** Kapsel als Kapsel, jedes Polygon-Teil als eigener konvexer Collider am selben Body. - **`Move` und Editor-Run** rechnen die neuen Formen in unserer f64-Geometrie (`convex.ts`, SAT mit abgerundeten Teilen), nicht über Rapiers `castShape` (f32, siehe #150). Box und Kreis behalten ihren bisherigen Code. ## Unterwegs gefundene Fehler 1. **Hängen am Fuß einer Schräge:** Bei Gleichstand zweier Normalen nahm die Regel aus #150 die Wand. Für Kapsel/Polygon gewinnt jetzt die Normale, die der Bewegung am wenigsten im Weg steht. 2. **Kaputte Ecken beim Laden:** JSON macht aus `NaN` ein `null`, `Number(null)` ist 0. `pointsOf` nimmt nur noch echte Zahlen. ## Tests - Quadratisches Polygon kollidiert in 400 Zufallsfällen exakt wie die Box. - Zerlegung von 200 zufälligen Sternformen deckt genau die Fläche ab. - Polygon-Rampe: `g·sin − μ·g·cos` wie in #150. - Physik: Kapsel und U-Form kommen richtig zur Ruhe. - Gegenprobe mit 12 eingebauten Fehlern: 11 gefangen, eine Mutation war gleichwertig zum Original. - Gemessen: Rapier lässt eine Kapsel beim Aufprall 0,9 px eindringen und drückt sie in ~20 Frames heraus. - e2e-Modul 42 `shapes` (10 Checks, gemeinsam mit #141). ## CI zu `32057a9` - Gate (Task 140): 106 Testdateien grün, `CHECK EXIT 0`. - Suite (Task 141): `ALL PASSED – 1067 checks`. - Smokes: 24 / 19 / 21, alle grün. ## Weiter - #141 (Umriss pro Frame) baut darauf auf; die erste Fassung ist mit im Commit, wird aber noch überarbeitet und bleibt offen. - Die „Später“-Punkte aus #144 sind jetzt eigene Issues: #152 Ebenen, #153 Raycast, #154 Joints, #155 One-Way.
admin moved this to Done in Development on 2026-09-19 11:07:07 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#151