Folge-Issue zu #132 (Stufe 2 der Tilemap-Kollision, Stufe 3, das Polygon pro Frame, steht in #141).
Befund
Seit #132 blockiert eine Zelle mit einem Tile, das Solid hat, immer mit ihrer vollen Zellfläche. Die blockierenden Zellen werden zeilenweise zu Rechtecken zusammengefasst (mergeCells, src/core/model/tilemapCollision.ts:60) und als box an das CollisionSystem gegeben (cellRectShape, ebd. :115).
Das Zusammenfassen setzt voraus, dass jede Zelle ihre Fläche ganz füllt: Nur dann stoßen zwei Nachbarn lückenlos aneinander. Eine Größe pro Tile gibt es noch nicht.
Zu bauen
Neue Property am Tile: Collision scale (Vorgabe 1.0). Sie bestimmt, wie groß die Kollisionsbox einer Zelle im Verhältnis zur Zelle ist. Kleiner als 1 lässt Figuren näher heran (z. B. ein Busch, eine schmale Säule), größer als 1 hält sie weiter weg.
Verschmelzen mit den Nachbarn, vor allem bei < 1.0: Eingezogen wird nur an den Seiten, an denen kein blockierender Nachbar liegt. Zwischen zwei blockierenden Zellen bleibt die Seite bündig, es entsteht also keine Lücke, durch die eine Figur schlüpft. Eine Wand aus zwanzig Busch-Zellen ist dann ein schmaleres Rechteck, keine Perlenkette aus zwanzig Einzelboxen.
Das Zusammenfassen berücksichtigt den Einzug: Zu einem Rechteck verschmolzen wird nur, was denselben Einzug an denselben Seiten hat. Die Formen bleiben so wenige wie möglich, und das Gleiten an Nahtstellen (Test aus #132) bleibt heil.
Die Umrandung im Scene-View zeigt die eingezogenen Formen.
Tests: Unit-Tests für Einzug und Verschmelzen (einzelne Zelle, Reihe, L-Form mit Innenecke, zwei Tiles mit verschiedenem Wert nebeneinander, Wert > 1) und für das Gleiten ohne Hängenbleiben. e2e: eine Figur kommt an einer verkleinerten Zelle näher heran als an einer vollen.
Offen (mit Vorschlag)
Ein Wert oder Breite/Höhe getrennt? Vorschlag: ein Wert, zentriert in der Zelle. Getrennte Achsen und ein Anker (z. B. unten bündig für Wände in der Draufsicht) erst bei Bedarf.
Nachbarn mit anderem Wert: Liegen zwei blockierende Tiles mit verschiedenem Wert nebeneinander, bleibt die gemeinsame Seite trotzdem bündig? Vorschlag: ja, jede blockierende Nachbarzelle zählt als „dicht", egal welcher Wert. Sonst entsteht genau die Lücke, die das Issue vermeiden will.
Innenecken einer L-Form: Wird dort die Ecke der eingezogenen Form sauber geschlossen? Vorschlag: ja, über die Zerlegung in Rechtecke. Das kann ein Rechteck mehr ergeben als bei 1.0, das ist in Ordnung.
Diagonale Nachbarn (nur über die Ecke verbunden): Vorschlag: zählen nicht als verbunden, die Ecke bleibt eingezogen. Sonst entsteht ein Durchgang, der optisch zu ist, oder umgekehrt eine Wand, die optisch offen ist.
Folge-Issue zu #132 (Stufe 2 der Tilemap-Kollision, Stufe 3, das Polygon pro Frame, steht in #141).
## Befund
- Seit #132 blockiert eine Zelle mit einem Tile, das **Solid** hat, immer mit ihrer **vollen Zellfläche**. Die blockierenden Zellen werden zeilenweise zu Rechtecken zusammengefasst (`mergeCells`, `src/core/model/tilemapCollision.ts:60`) und als `box` an das `CollisionSystem` gegeben (`cellRectShape`, ebd. `:115`).
- Das Zusammenfassen setzt voraus, dass jede Zelle ihre Fläche ganz füllt: Nur dann stoßen zwei Nachbarn lückenlos aneinander. Eine Größe pro Tile gibt es noch nicht.
## Zu bauen
- Neue Property am Tile: **Collision scale** (Vorgabe `1.0`). Sie bestimmt, wie groß die Kollisionsbox einer Zelle im Verhältnis zur Zelle ist. Kleiner als 1 lässt Figuren näher heran (z. B. ein Busch, eine schmale Säule), größer als 1 hält sie weiter weg.
- **Verschmelzen mit den Nachbarn**, vor allem bei `< 1.0`: Eingezogen wird nur an den Seiten, an denen **kein** blockierender Nachbar liegt. Zwischen zwei blockierenden Zellen bleibt die Seite bündig, es entsteht also keine Lücke, durch die eine Figur schlüpft. Eine Wand aus zwanzig Busch-Zellen ist dann ein schmaleres Rechteck, keine Perlenkette aus zwanzig Einzelboxen.
- Das Zusammenfassen berücksichtigt den Einzug: Zu einem Rechteck verschmolzen wird nur, was denselben Einzug an denselben Seiten hat. Die Formen bleiben so wenige wie möglich, und das Gleiten an Nahtstellen (Test aus #132) bleibt heil.
- Die Umrandung im Scene-View zeigt die eingezogenen Formen.
- Tests: Unit-Tests für Einzug und Verschmelzen (einzelne Zelle, Reihe, L-Form mit Innenecke, zwei Tiles mit verschiedenem Wert nebeneinander, Wert `> 1`) und für das Gleiten ohne Hängenbleiben. e2e: eine Figur kommt an einer verkleinerten Zelle näher heran als an einer vollen.
## Offen (mit Vorschlag)
- **Ein Wert oder Breite/Höhe getrennt?** Vorschlag: **ein Wert**, zentriert in der Zelle. Getrennte Achsen und ein Anker (z. B. unten bündig für Wände in der Draufsicht) erst bei Bedarf.
- **Nachbarn mit anderem Wert:** Liegen zwei blockierende Tiles mit verschiedenem Wert nebeneinander, bleibt die gemeinsame Seite trotzdem bündig? Vorschlag: **ja**, jede blockierende Nachbarzelle zählt als „dicht", egal welcher Wert. Sonst entsteht genau die Lücke, die das Issue vermeiden will.
- **Innenecken einer L-Form:** Wird dort die Ecke der eingezogenen Form sauber geschlossen? Vorschlag: ja, über die Zerlegung in Rechtecke. Das kann ein Rechteck mehr ergeben als bei `1.0`, das ist in Ordnung.
- **Diagonale Nachbarn** (nur über die Ecke verbunden): Vorschlag: zählen **nicht** als verbunden, die Ecke bleibt eingezogen. Sonst entsteht ein Durchgang, der optisch zu ist, oder umgekehrt eine Wand, die optisch offen ist.
Ein Wert oder Breite/Höhe getrennt? Vorschlag: ein Wert - passt
Nachbarn mit anderem Wert: gemeinsame Seite trotzdem bündig? Vorschlag: ja - passt
Innenecken einer L-Form: Vorschlag, ja - passt
Diagonale Nachbarn: Vorschlag: zählen nicht als verbunden - passt
- Ein Wert oder Breite/Höhe getrennt? Vorschlag: ein Wert - passt
- Nachbarn mit anderem Wert: gemeinsame Seite trotzdem bündig? Vorschlag: ja - passt
- Innenecken einer L-Form: Vorschlag, ja - passt
- Diagonale Nachbarn: Vorschlag: zählen nicht als verbunden - passt
Umgesetzt in bffa508 (Wiki e5e9f65), nach den Antworten in #issuecomment-1083 — alle vier Vorschläge gelten.
Was sich ändert
Neue Tile-Property „Collision scale“ unter Solid: Vorgabe 1, Bereich 0.1–2, Schritt 0.05. Normale Property mit Undo, Gold-Markierung und Speichern; ein Wert außerhalb des Bereichs in der Datei wird beim Lesen begrenzt.
Kleiner als 1: Jede blockierende Zelle wird in ein 3 × 3-Raster geteilt (src/core/model/tilemapCollision.ts):
Die Mitte blockiert immer.
Ein Randstreifen blockiert nur, wenn auf dieser Seite ein blockierender Nachbar liegt, egal mit welchem Wert.
Eine Ecke blockiert nur, wenn beide Seiten und die Zelle über Eck blockieren.
Ergebnis: eine Wand aus Büschen wird schmaler, aber ohne Lücken; die Innenecke eines L schließt sauber; Zellen, die sich nur diagonal berühren, bleiben getrennt.
Größer als 1: Die Zelle wächst an ihren offenen Seiten.
Mehrere Layer mit blockierendem Tile auf einer Zelle: Es gilt der größte Wert (eigene Entscheidung, das Issue sagte dazu nichts).
Zusammenfassen geht jetzt über Bruchteile von Zellen. Bei 1 kommt exakt dasselbe heraus wie vorher, die 16 alten Tests laufen unverändert.
Die Umrandung im Scene-View zeigt die eingezogenen bzw. vergrößerten Formen, ohne Änderung am Zeichencode.
e2e lokal: GM_STEPS=39,40 → 68 Checks, GM_STEPS=1-16,24,25,33,36,38,39,40 → 612 Checks, beide ALL PASSED.
9 neue Unit-Tests in tests/core/tilemap-collision.test.ts: Einzelzelle, Reihe, Block, L mit Innenecke, gemischte Werte, Wert > 1, Diagonale, die Property (Vorgabe, Grenzen, Speichern/Laden, größter Wert über Layer), Anhalten und Gleiten an einer eingezogenen Wand ohne Hängenbleiben an Nahtstellen, Abstand bei vergrößerter Wand. Dazu ein Vergleich über 20 Zufallsverteilungen gegen eine punktgenaue Vorgabe (Fläche und keine Doppelabdeckung).
Gegenprobe mit 4 absichtlichen Fehlern (Diagonale ignoriert, Einzug auch zu Nachbarn, kleinster statt größter Wert, Grenzen nicht angewandt): alle gefangen, Originale per cmp zurück.
2 neue e2e-Checks in Modul 40 (40l): 0.5 im echten Feld eingetippt → Umrandung [{0.25,0.25,2.5,2.5},{4.25,0.25,0.5,0.5}]; die Kiste hält im Spiel bei x = −158 statt −170.
Nicht per Screenshot angesehen, belegt über die Rechteckdaten im Check.
Doku
Wiki: Tilemaps.md (Unterabschnitt Collision scale), Tiles.md, Architecture.md, Development.md. Check-Summe 1042 (1040 + 2) in README und Wiki — gerechnet, CI-Bestätigung steht noch aus.
Weiter geht es mit #141 (Kollisions-Polygon pro Frame, v3).
Umgesetzt in bffa508 (Wiki e5e9f65), nach den Antworten in #issuecomment-1083 — alle vier Vorschläge gelten.
## Was sich ändert
- **Neue Tile-Property „Collision scale“** unter Solid: Vorgabe 1, Bereich 0.1–2, Schritt 0.05. Normale Property mit Undo, Gold-Markierung und Speichern; ein Wert außerhalb des Bereichs in der Datei wird beim Lesen begrenzt.
- **Kleiner als 1:** Jede blockierende Zelle wird in ein 3 × 3-Raster geteilt (`src/core/model/tilemapCollision.ts`):
- Die Mitte blockiert immer.
- Ein Randstreifen blockiert nur, wenn auf dieser Seite ein blockierender Nachbar liegt, egal mit welchem Wert.
- Eine Ecke blockiert nur, wenn beide Seiten **und** die Zelle über Eck blockieren.
- Ergebnis: eine Wand aus Büschen wird schmaler, aber ohne Lücken; die Innenecke eines L schließt sauber; Zellen, die sich nur diagonal berühren, bleiben getrennt.
- **Größer als 1:** Die Zelle wächst an ihren offenen Seiten.
- **Mehrere Layer mit blockierendem Tile auf einer Zelle:** Es gilt der größte Wert (eigene Entscheidung, das Issue sagte dazu nichts).
- **Zusammenfassen** geht jetzt über Bruchteile von Zellen. Bei 1 kommt exakt dasselbe heraus wie vorher, die 16 alten Tests laufen unverändert.
- Die Umrandung im Scene-View zeigt die eingezogenen bzw. vergrößerten Formen, ohne Änderung am Zeichencode.
## Tests
- `npm run check`: 102 Files, 1380 Tests (+9), CHECK EXIT 0. Build grün.
- e2e lokal: `GM_STEPS=39,40` → 68 Checks, `GM_STEPS=1-16,24,25,33,36,38,39,40` → 612 Checks, beide ALL PASSED.
- **9 neue Unit-Tests** in `tests/core/tilemap-collision.test.ts`: Einzelzelle, Reihe, Block, L mit Innenecke, gemischte Werte, Wert > 1, Diagonale, die Property (Vorgabe, Grenzen, Speichern/Laden, größter Wert über Layer), Anhalten und Gleiten an einer eingezogenen Wand ohne Hängenbleiben an Nahtstellen, Abstand bei vergrößerter Wand. Dazu ein Vergleich über 20 Zufallsverteilungen gegen eine punktgenaue Vorgabe (Fläche und keine Doppelabdeckung).
- **Gegenprobe** mit 4 absichtlichen Fehlern (Diagonale ignoriert, Einzug auch zu Nachbarn, kleinster statt größter Wert, Grenzen nicht angewandt): alle gefangen, Originale per `cmp` zurück.
- **2 neue e2e-Checks in Modul 40 (40l):** 0.5 im echten Feld eingetippt → Umrandung `[{0.25,0.25,2.5,2.5},{4.25,0.25,0.5,0.5}]`; die Kiste hält im Spiel bei x = −158 statt −170.
- Nicht per Screenshot angesehen, belegt über die Rechteckdaten im Check.
## Doku
Wiki: `Tilemaps.md` (Unterabschnitt *Collision scale*), `Tiles.md`, `Architecture.md`, `Development.md`. Check-Summe **1042** (1040 + 2) in README und Wiki — gerechnet, CI-Bestätigung steht noch aus.
Weiter geht es mit #141 (Kollisions-Polygon pro Frame, v3).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Folge-Issue zu #132 (Stufe 2 der Tilemap-Kollision, Stufe 3, das Polygon pro Frame, steht in #141).
Befund
mergeCells,src/core/model/tilemapCollision.ts:60) und alsboxan dasCollisionSystemgegeben (cellRectShape, ebd.:115).Zu bauen
1.0). Sie bestimmt, wie groß die Kollisionsbox einer Zelle im Verhältnis zur Zelle ist. Kleiner als 1 lässt Figuren näher heran (z. B. ein Busch, eine schmale Säule), größer als 1 hält sie weiter weg.< 1.0: Eingezogen wird nur an den Seiten, an denen kein blockierender Nachbar liegt. Zwischen zwei blockierenden Zellen bleibt die Seite bündig, es entsteht also keine Lücke, durch die eine Figur schlüpft. Eine Wand aus zwanzig Busch-Zellen ist dann ein schmaleres Rechteck, keine Perlenkette aus zwanzig Einzelboxen.> 1) und für das Gleiten ohne Hängenbleiben. e2e: eine Figur kommt an einer verkleinerten Zelle näher heran als an einer vollen.Offen (mit Vorschlag)
1.0, das ist in Ordnung.Umgesetzt in
bffa508(Wiki e5e9f65), nach den Antworten in #issuecomment-1083 — alle vier Vorschläge gelten.Was sich ändert
src/core/model/tilemapCollision.ts):Tests
npm run check: 102 Files, 1380 Tests (+9), CHECK EXIT 0. Build grün.GM_STEPS=39,40→ 68 Checks,GM_STEPS=1-16,24,25,33,36,38,39,40→ 612 Checks, beide ALL PASSED.tests/core/tilemap-collision.test.ts: Einzelzelle, Reihe, Block, L mit Innenecke, gemischte Werte, Wert > 1, Diagonale, die Property (Vorgabe, Grenzen, Speichern/Laden, größter Wert über Layer), Anhalten und Gleiten an einer eingezogenen Wand ohne Hängenbleiben an Nahtstellen, Abstand bei vergrößerter Wand. Dazu ein Vergleich über 20 Zufallsverteilungen gegen eine punktgenaue Vorgabe (Fläche und keine Doppelabdeckung).cmpzurück.[{0.25,0.25,2.5,2.5},{4.25,0.25,0.5,0.5}]; die Kiste hält im Spiel bei x = −158 statt −170.Doku
Wiki:
Tilemaps.md(Unterabschnitt Collision scale),Tiles.md,Architecture.md,Development.md. Check-Summe 1042 (1040 + 2) in README und Wiki — gerechnet, CI-Bestätigung steht noch aus.Weiter geht es mit #141 (Kollisions-Polygon pro Frame, v3).