Tilemap: Autotiles in der Szene platzieren und malen #128

Closed
opened 2026-09-17 20:53:55 +02:00 by meleki · 2 comments
Owner

Folge-Issue zu #118. Dort entsteht das Asset autotile samt Tab und Vorschau; ein Autotile ist
damit aber nur in seinem eigenen Tab sichtbar. Hier kommt das, was es in die Szene bringt.

Befund

  • Autotiles sind in #118 bewusst nicht platzierbar (isPlaceableType,
    src/core/model/AssetTypes.ts). Platzierbar wird die Tilemap.
  • Ein Autotile-Asset kennt seine Art (floor 2×3 / wall 2×2), seine Bilder (Animationsschritte),
    mode und fps. Das Zusammensetzen aus Viertelkacheln (47 bzw. 16 Kombinationen) liegt schon
    in src/core/model/autotile.ts und wird hier wiederverwendet, nicht neu geschrieben.

Zu bauen

  • Neues platzierbares Asset tilemap: Kachelgröße, Rastergröße und pro Zelle, welches
    Autotile dort liegt (leer = nichts). Welche Kombination eine Zelle zeigt, wird aus den Nachbarn
    berechnet und nicht gespeichert.
  • Malen im Scene-View: Autotile aus einer Palette wählen, mit der Maus malen, radieren,
    Rechteck füllen. Jeder Strich ist ein Undo-Schritt.
  • Mehrere Layer (Boden, darüber Wand/Dach), Reihenfolge und Sichtbarkeit je Layer.
  • Laufzeit und Export: Die Tilemap muss im laufenden Spiel und im Export gezeichnet werden,
    animierte Autotiles laufen dort mit ihrer Rate weiter. Zeichnen möglichst in einem Batch, nicht
    ein Sprite pro Kachel.
  • Kollision: ob eine Tilemap Kollider beisteuert, ist hier zu entscheiden — sonst eigenes Issue.
  • Tests: Unit-Tests für Nachbarschaft/Kombinationswahl und die Kommandos, e2e für Malen und Undo.
    Doku: Wiki.

Offen (mit Vorschlag)

  • Rastergröße: feste Größe pro Tilemap mit änderbaren Grenzen, oder unbegrenzt in Chunks?
    Vorschlag: feste Größe, änderbar — einfacher und für den ersten Wurf ausreichend.
  • Speicherform der Zellen: Liste pro Layer mit Autotile-Id je Zelle, komprimiert als
    Lauflängen im JSON. Vorschlag: erst unkomprimiert, Format aber so, dass es später geht.
  • Grenze zwischen zwei verschiedenen Autotiles: zählt ein fremdes Autotile als Nachbar
    ("verbunden") oder als leer? Vorschlag: als leer, also jedes Autotile schließt gegen alles andere
    ab — das ist das MZ-Verhalten.
  • Kollision: Vorschlag, hier wegzulassen und als eigenes Issue nachzuziehen.
Folge-Issue zu #118. Dort entsteht das Asset `autotile` samt Tab und Vorschau; ein Autotile ist damit aber nur in seinem eigenen Tab sichtbar. Hier kommt das, was es in die Szene bringt. ## Befund - Autotiles sind in #118 bewusst **nicht platzierbar** (`isPlaceableType`, `src/core/model/AssetTypes.ts`). Platzierbar wird die Tilemap. - Ein Autotile-Asset kennt seine Art (`floor` 2×3 / `wall` 2×2), seine Bilder (Animationsschritte), `mode` und `fps`. Das Zusammensetzen aus Viertelkacheln (47 bzw. 16 Kombinationen) liegt schon in `src/core/model/autotile.ts` und wird hier wiederverwendet, nicht neu geschrieben. ## Zu bauen - **Neues platzierbares Asset `tilemap`:** Kachelgröße, Rastergröße und pro Zelle, welches Autotile dort liegt (leer = nichts). Welche Kombination eine Zelle zeigt, wird aus den Nachbarn berechnet und **nicht** gespeichert. - **Malen im Scene-View:** Autotile aus einer Palette wählen, mit der Maus malen, radieren, Rechteck füllen. Jeder Strich ist ein Undo-Schritt. - **Mehrere Layer** (Boden, darüber Wand/Dach), Reihenfolge und Sichtbarkeit je Layer. - **Laufzeit und Export:** Die Tilemap muss im laufenden Spiel und im Export gezeichnet werden, animierte Autotiles laufen dort mit ihrer Rate weiter. Zeichnen möglichst in einem Batch, nicht ein Sprite pro Kachel. - **Kollision:** ob eine Tilemap Kollider beisteuert, ist hier zu entscheiden — sonst eigenes Issue. - Tests: Unit-Tests für Nachbarschaft/Kombinationswahl und die Kommandos, e2e für Malen und Undo. Doku: Wiki. ## Offen (mit Vorschlag) - **Rastergröße:** feste Größe pro Tilemap mit änderbaren Grenzen, oder unbegrenzt in Chunks? Vorschlag: feste Größe, änderbar — einfacher und für den ersten Wurf ausreichend. - **Speicherform der Zellen:** Liste pro Layer mit Autotile-Id je Zelle, komprimiert als Lauflängen im JSON. Vorschlag: erst unkomprimiert, Format aber so, dass es später geht. - **Grenze zwischen zwei verschiedenen Autotiles:** zählt ein fremdes Autotile als Nachbar ("verbunden") oder als leer? Vorschlag: als leer, also jedes Autotile schließt gegen alles andere ab — das ist das MZ-Verhalten. - **Kollision:** Vorschlag, hier wegzulassen und als eigenes Issue nachzuziehen.
admin added this to the Development project 2026-09-17 20:56:29 +02:00
admin moved this to Next in Development on 2026-09-17 20:56:40 +02:00
Author
Owner

Umgesetzt — Commit 33a7b1b, Wiki 318f00e

Alles in einem Zug, wie entschieden. Die drei Detailfragen habe ich nach den Vorschlägen im Issue umgesetzt: Die Rastergröße ist pro Tilemap fest, die Zellen werden unkomprimiert gespeichert, und ein fremdes Autotile zählt als leer.

Entscheidungen aus der Planung

  • Alles in einem Zug: Asset, Malen, Radieren, Rechteck, Layer, Laufzeit und Export.
  • Keine Kollision. Eine Tilemap ist vorerst reine Grafik. Kollision kommt in ein eigenes Folge-Issue.
  • Palette, Layer und Werkzeuge stehen im Inspector, sobald eine platzierte Tilemap ausgewählt ist. Gemalt wird im Scene-View.

Was jetzt geht

  • Neuer Asset-Typ tilemap, platzierbar. Die Properties sind Columns, Rows und Tile size. Die Karte ist wie jedes Objekt um ihre Position zentriert.
  • Pro Zelle wird nur gespeichert, welches Autotile dort liegt. Welche Kachel davon gezeigt wird, ergibt sich aus den Nachbarn und wird beim Zeichnen bestimmt (das Mapping kommt aus #118). Zwei verschiedene Autotiles schließen nicht aneinander an, und auch außerhalb des Rasters gilt alles als leer.
  • Werkzeuge: Select, Brush, Erase, Rect. Ein Strich ist ein Undo-Schritt. Beim Ziehen werden auch die Zellen zwischen zwei Pointer-Events gemalt. Wer über ein anderes Autotile malt, bekommt beim Undo dieses zurück. Solange ein Malwerkzeug aktiv ist, wird das Zellraster gezeigt, und beim Rechteck eine Vorschau.
  • Layer: Schalter, Name, Reihenfolge ↑/↓, entfernen, hinzufügen. Mindestens ein Layer bleibt immer.
  • Laufzeit und Export: Die Tilemap wird dort genauso gezeichnet wie im Editor. Animierte Autotiles laufen im selben Takt über alle Karten. Gezeichnet wird mit einem Mesh pro Autotile und Layer, nicht mit einem Sprite pro Zelle.
  • Eine Tilemap zählt als Nutzung ihrer Autotiles, das sieht man auch im Löschdialog.

Tests (lokal)

npm run check                                     → 96 Files, 1300 Tests, CHECK EXIT 0
npm run build                                     → BUILD EXIT 0
GM_STEPS=1-16,24,25,33,36,38,39,40 (neu geseedet) → ALL PASSED – 576 checks
  • Neue Unit-Tests in tests/core/tilemap.test.ts für Modell, Nachbarschaft, Kommandos mit Undo, Serialisierung und Zeichengeometrie. Gegenprobe: 4 absichtlich eingebaute Fehler, jeder davon wird von den Tests gefunden. Danach Originale zurückgespielt.
  • Neues e2e-Modul 40 mit 17 Checks: Malen, Radieren, Rechteck, Layer, Undo, Pixel vom Scene-View.
  • Beim Testen gefunden und behoben: Das Node der Tilemap hatte keine Hit-Area, deshalb kam kein Klick an. Dazu kommt ein Testfehler im Scaffold: openTab hat „Scene“ im Szenen-Wähler der Toolbar angeklickt statt den Tab.

Nicht enthalten: Kollision (Folge-Issue), Flood-Fill, Kachel von der Karte aufnehmen, komprimierte Zellen.

Die Check-Summe 1006 (989 + 17) in README und Wiki ist gerechnet. Die CI zu 33a7b1b ist noch nicht gelesen.

## Umgesetzt — Commit `33a7b1b`, Wiki `318f00e` Alles in einem Zug, wie entschieden. Die drei Detailfragen habe ich nach den Vorschlägen im Issue umgesetzt: Die Rastergröße ist pro Tilemap fest, die Zellen werden unkomprimiert gespeichert, und ein fremdes Autotile zählt als leer. **Entscheidungen aus der Planung** - Alles in einem Zug: Asset, Malen, Radieren, Rechteck, Layer, Laufzeit und Export. - **Keine Kollision.** Eine Tilemap ist vorerst reine Grafik. Kollision kommt in ein eigenes Folge-Issue. - Palette, Layer und Werkzeuge stehen **im Inspector**, sobald eine platzierte Tilemap ausgewählt ist. Gemalt wird im Scene-View. **Was jetzt geht** - Neuer Asset-Typ `tilemap`, **platzierbar**. Die Properties sind Columns, Rows und Tile size. Die Karte ist wie jedes Objekt um ihre Position zentriert. - Pro Zelle wird nur gespeichert, *welches* Autotile dort liegt. Welche Kachel davon gezeigt wird, ergibt sich aus den Nachbarn und wird beim Zeichnen bestimmt (das Mapping kommt aus #118). Zwei verschiedene Autotiles schließen nicht aneinander an, und auch außerhalb des Rasters gilt alles als leer. - Werkzeuge: **Select, Brush, Erase, Rect**. Ein Strich ist ein Undo-Schritt. Beim Ziehen werden auch die Zellen zwischen zwei Pointer-Events gemalt. Wer über ein anderes Autotile malt, bekommt beim Undo dieses zurück. Solange ein Malwerkzeug aktiv ist, wird das Zellraster gezeigt, und beim Rechteck eine Vorschau. - **Layer:** Schalter, Name, Reihenfolge ↑/↓, entfernen, hinzufügen. Mindestens ein Layer bleibt immer. - **Laufzeit und Export:** Die Tilemap wird dort genauso gezeichnet wie im Editor. Animierte Autotiles laufen im selben Takt über alle Karten. Gezeichnet wird mit einem Mesh pro Autotile und Layer, nicht mit einem Sprite pro Zelle. - Eine Tilemap zählt als Nutzung ihrer Autotiles, das sieht man auch im Löschdialog. **Tests (lokal)** ``` npm run check → 96 Files, 1300 Tests, CHECK EXIT 0 npm run build → BUILD EXIT 0 GM_STEPS=1-16,24,25,33,36,38,39,40 (neu geseedet) → ALL PASSED – 576 checks ``` - Neue Unit-Tests in `tests/core/tilemap.test.ts` für Modell, Nachbarschaft, Kommandos mit Undo, Serialisierung und Zeichengeometrie. Gegenprobe: 4 absichtlich eingebaute Fehler, jeder davon wird von den Tests gefunden. Danach Originale zurückgespielt. - Neues e2e-Modul 40 mit 17 Checks: Malen, Radieren, Rechteck, Layer, Undo, Pixel vom Scene-View. - Beim Testen gefunden und behoben: Das Node der Tilemap hatte keine Hit-Area, deshalb kam kein Klick an. Dazu kommt ein Testfehler im Scaffold: `openTab` hat „Scene“ im Szenen-Wähler der Toolbar angeklickt statt den Tab. **Nicht enthalten:** Kollision (Folge-Issue), Flood-Fill, Kachel von der Karte aufnehmen, komprimierte Zellen. Die Check-Summe **1006** (989 + 17) in README und Wiki ist gerechnet. Die CI zu `33a7b1b` ist noch nicht gelesen.
admin moved this to Done in Development on 2026-09-18 07:31:20 +02:00
Author
Owner

Folge-Issues angelegt

Was hier unter „Nicht enthalten“ stand, hat jetzt eigene Issues. Dazu kommen zwei Lücken, die beim Durchsehen aufgefallen sind:

# Inhalt
#132 Kollision (zusammengefasste Rechtecke, solid pro Tile als Vorschlag)
#133 Füllen (Flood-Fill) und Tile aufnehmen (Pipette)
#134 Zellen kompakt in der Projektdatei speichern
#135 Zugriff aus Behaviors zur Laufzeit (Zelle abfragen und setzen) held-back
#136 Raster an allen Seiten erweitern und verkleinern held-back

Jedes Issue hat Befund, „Zu bauen“ und die offenen Punkte samt Vorschlag.

## Folge-Issues angelegt Was hier unter „Nicht enthalten“ stand, hat jetzt eigene Issues. Dazu kommen zwei Lücken, die beim Durchsehen aufgefallen sind: | # | Inhalt | | |---|---|---| | #132 | Kollision (zusammengefasste Rechtecke, `solid` pro Tile als Vorschlag) | | | #133 | Füllen (Flood-Fill) und Tile aufnehmen (Pipette) | | | #134 | Zellen kompakt in der Projektdatei speichern | | | #135 | Zugriff aus Behaviors zur Laufzeit (Zelle abfragen und setzen) | `held-back` | | #136 | Raster an allen Seiten erweitern und verkleinern | `held-back` | Jedes Issue hat Befund, „Zu bauen“ und die offenen Punkte samt Vorschlag.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#128