01 · Problem
Wofür braucht man das?
Sand, Wasser und Hindernisse benötigen lokale Nachbarschaftsregeln, deterministische Updates und eine effiziente Darstellung vieler Rasterzellen.
02 · Denkmodell
Das mentale Modell
Jede Zelle enthält einen Materialcode. Ein Simulationsschritt liest den alten Buffer und schreibt Entscheidungen in einen zweiten Buffer; Rendering ist davon getrennt.
Das Paket enthält Interfaces, einen leeren NeighborProvider und Fragmente eines Pixel-Renderers beziehungsweise Shaders. Root-Exports, Engine, Materialregeln und vollständiger GPU-Lebenszyklus fehlen.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Raster als flachen typisierten Buffer mit Breite und Höhe anlegen.
- Für jede aktive Zelle gültige Nachbarn aus dem alten Zustand lesen.
- Materialregel anwenden und Ergebnis konfliktfrei in den nächsten Buffer schreiben.
- Buffer tauschen und den neuen Zustand separat rendern.
04 · Bauteile
Die entscheidenden Verträge
Pixel / Material Interfaces
Unvollständige Datentypen für Zellen und Materialverhalten.
NeighborProvider
Platzhalter für Nachbarschaftsabfragen.
pixel-renderer
Teilweiser WebGL-Renderer ohne vollständige Engineintegration.
05 · Build it yourself
Selbst implementieren
Starte auf der CPU mit einer einzigen Sandregel; danach kann derselbe Zustandsvertrag auf die GPU wandern.
- Leere Zelle und Sand als numerische Codes festlegen.
- Von unten nach oben arbeiten, damit ein Korn pro Tick höchstens einmal fällt.
- Grenzen prüfen und für komplexere Regeln einen zweiten Buffer einführen.
const EMPTY = 0, SAND = 1;
function stepSand(grid: Uint8Array, width: number, height: number) {
const next = grid.slice();
for (let y = height - 2; y >= 0; y--) for (let x = 0; x < width; x++) {
const from = y * width + x, below = from + width;
if (grid[from] === SAND && grid[below] === EMPTY) {
next[from] = EMPTY; next[below] = SAND;
}
}
return next;
}06 · Verifizieren
Was du testen solltest
- Ein Korn fällt genau eine Zelle und verlässt niemals den Rasterrand.
- Blockierter Sand bleibt stehen; Eingabebuffer wird nicht verändert.
- Mehrere Körner erzeugen unabhängig von Iterationsdetails ein dokumentiertes Ergebnis.
07 · Grenzen
Kompromisse und Stolperfallen
- CPU-Regeln sind leicht zu debuggen, skalieren aber schlechter als parallele Shader.
- Double Buffering vermeidet Lese-/Schreibkonflikte und verdoppelt den Zustandsbedarf.
- Zufällige Diagonalwahl wirkt natürlich, erschwert ohne seedbaren RNG die Reproduktion.
GPU-Optimierung lohnt sich erst, wenn Update-Reihenfolge, Konfliktauflösung und Randregeln als Referenz auf der CPU feststehen.
08 · Weiterdenken