Ein Twin-Stick-Shooter. Im Browser. Ohne Build.
Geometry-Wars-Arcade mit 20K Partikeln, deterministischem 60-Hz-Loop und Edge-Leaderboards. Pure ES Modules — jeder Checkout läuft mit python -m http.server.

Warum es das gibt.
Retro-Arcade-Fans und Gelegenheitsspieler wollen direkt im Browser — ohne Install, ohne Account, ohne Ladezeit — einen mechanisch tiefen Twin-Stick-Shooter mit Leaderboards, Daily Challenges und Cosmetics. Existierende Lösungen reichen nicht: Entweder fehlt die Persistenz (anonyme itch.io-Builds) oder die Performance (Canvas2D-Klone ruckeln bei zehntausenden Partikeln).
Shattergrid löst beides: Three.js-WebGL-Renderer mit gepoolten Particle-Systems, deterministischem Fixed-Timestep-Loop und einem schlanken Cloudflare-Backend für Scores, Daily-Seeds und Cosmetics — alles kostenlos im Free Tier.
Der Rahmen, in den es passen musste.
Wie es läuft.
◦ Schematische Darstellung, Zahlen illustrativ.
Vier bewusste Entscheidungen.
Cloudflare Workers + D1 statt Node/Express + Postgres.
ES Modules + Import Maps statt Bundler.
js/lib/three/docker compose up in Nginx-Alpine, und Diff-Reviews zeigen echte Quelldateien, keine transpilierten Outputs. Jeder Checkout läuft lokal mit python -m http.server.Singleton-Manager statt DI-Framework.
storageManager, statsTracker, achievementManager, cosmeticManager, leaderboardManager, accessibilityManagerStorageManager-Key sauber.Polymorpher Spawner statt Mode-Enum-Switch.
activeSpawner-Pattern: SpawnManager (Endless) und WaveManager (Survival) teilen ein Interfaceif (mode === 'wave')-Switches durchs game.jsWas nicht offensichtlich war.
Anti-Cheat ohne Server-Sim
SHA-256-Hash über (score, kills, survivalTime, maxCombo, maxMultiplier, timestamp, secret). Der Worker verifiziert den Hash, checkt das Pro-IP-Rate-Limit (30 s) und flaggt statistische Outlier (Score > 5× aktuellem p99 derselben Spielmodus-Klasse).Kein User-Account nötig, kein Replay-Stream — reicht für ein Hobby-Game, um beiläufige Score-Fälscher draußen zu halten, ohne die UX zu bremsen. Wer mehr will, kann immer noch das Secret aus dem JS extrahieren; dann greift nur noch der Outlier-Filter. Gegen entschlossene Fälscher hilft bei einem Client-Game nur ein autoritativer Server, und den ist mir ein Hobby-Projekt nicht wert.
Dynamischer Soundtrack aus 4 Stems
StemPlayer lädt drums / bass / melody / atmosphere parallel, startet sie gleichzeitig an der Audio-Clock und blendet jeden Stem per GainNode ein, sobald eine intensity-Schwelle (berechnet aus enemyCount + combo + multiplier) erreicht wird.Edge-Case:
AudioContext muss nach User-Gesture resume()d werden (Browser-Policy). Fallback auf eine einzelne bgmusic.mp3, wenn Stems fehlen oder decodeAudioData scheitert — das Spiel bleibt hörbar, auch wenn die dynamische Schicht down ist.Colorblind beim Enemy-Init
EnemyBase-Instanziierung über eine Lookup-Map (Protanopia / Deuteranopia / Tritanopia) — nicht pro Frame in einem Fragment-Shader.Spart GPU-Budget für Bloom / Chromatic-Aberration, und Partikel erben die neuen Farben automatisch, weil sie dem Parent-Color folgen. Reduced-Motion deaktiviert zusätzlich Shake + Bloom + Aberration und senkt Partikel-Dichte auf 25 %.
Fixed-Timestep mit Accumulator
requestAnimationFrame-Render. Auf 144-Hz-Monitoren rendert das Spiel 144 FPS, simuliert aber deterministisch 60 FPS.Konsequenz: Daily-Challenge-Seeds (
mulberry32-PRNG mit Datums-Seed) produzieren auf jeder Hardware exakt dieselben Spawn-Pattern — Speedruns und Daily-Rankings sind vergleichbar, egal ob 60- oder 240-Hz-Monitor.Was läuft.
Was ich gelernt habe.
Zero-Build ist ein Delivery-Feature.
Keine node_modules, keine Transpilation — das heißt auch: keine Supply-Chain-Sorgen, kein npm-Audit-Lärm, keine Lock-File-Merge-Konflikte. Ein statisches Repo, das per docker compose up in ein Nginx-Alpine-Image rollt. Bei der nächsten Hobby-Codebase bleibe ich bei ESM + Import Maps, solange es keine harten node_modules-Abhängigkeiten gibt.
Determinismus vor Skalierung.
Fixed-Timestep + PRNG-Seeds sind billig zu bauen und lösen auf einmal drei Probleme: Daily-Challenges, Speedrun-Fairness, Replay-Fähigkeit für später. Das war einer der günstigsten Architektur-Moves im Projekt und ist jetzt der erste Punkt auf meiner Checkliste für jedes zukünftige Game-Projekt.