No description
Find a file
Tronax 914af42210
feat(ui): mobile-friendly game layout for portrait and landscape phones
The game layout stacked HUD, board, and tower shop vertically with
desktop-sized chrome, leaving a tiny unusable board on phones (about
250x136px in landscape). Touch input and responsive canvas scaling
already existed — only the surrounding layout blocked mobile play.

Landscape phones / short viewports (max-height: 560px):
- New .game-main wrapper switches to a row layout: the board keeps the
  full remaining width and the tower shop becomes a vertical column on
  the right edge with one compact row per tower (icon + name + cost)
- HUD compacts to a single row (no 78px wave section, no preview chips,
  smaller stats and buttons); layout padding and gaps shrink
- Board grows from ~250x136 to ~487x268 on a 740x360 viewport

Portrait phones (max-width: 560px):
- Tower shop renders five compact icon tiles in a single row (69px each,
  no horizontal overflow)
- HUD wraps into compact rows; difficulty chip and preview hidden

All screens:
- Overlay panels (tower info, obstacle, pause, end screen) may now scale
  down to 0.65 via --ui-scale so they no longer cover a small board
  (previously clamped to a minimum of 1)

Verified in a real browser: landscape 740x360 (board 487x268, shop column
right), portrait 390x844 (board 366x201, shop row fits, no overflow),
desktop 1280x800 unchanged (column layout, board 1020x561). Touch flow
tested end-to-end: tap shop card -> tap board builds a tower (gold
260->210), tap tower opens the scaled info panel with upgrade/sell.
2026-08-16 19:18:11 +02:00
scripts feat: account system, OIDC, meta-progression research tree, and automated tests 2026-08-16 16:22:38 +02:00
server fix(docker): harden data-dir permissions and surface actionable DB errors 2026-08-16 16:40:45 +02:00
shared feat: account system, OIDC, meta-progression research tree, and automated tests 2026-08-16 16:22:38 +02:00
src feat(ui): mobile-friendly game layout for portrait and landscape phones 2026-08-16 19:18:11 +02:00
.dockerignore feat(docker): add self-hosted all-in-one container setup 2026-08-16 12:15:52 +02:00
.gitignore feat: account system, OIDC, meta-progression research tree, and automated tests 2026-08-16 16:22:38 +02:00
docker-compose.yml feat: account system, OIDC, meta-progression research tree, and automated tests 2026-08-16 16:22:38 +02:00
docker-entrypoint.sh fix(docker): harden data-dir permissions and surface actionable DB errors 2026-08-16 16:40:45 +02:00
Dockerfile fix(docker): make /app/data writable by node user on bind-mounted volumes 2026-08-16 16:35:08 +02:00
index.html feat: initialize TRXTD browser tower defense 2026-08-15 16:07:09 +02:00
package-lock.json feat: initialize TRXTD browser tower defense 2026-08-15 16:07:09 +02:00
package.json feat: account system, OIDC, meta-progression research tree, and automated tests 2026-08-16 16:22:38 +02:00
README.md feat: add 9-level tower evolution system with distinct tier abilities 2026-08-16 13:54:09 +02:00
tsconfig.json feat: initialize TRXTD browser tower defense 2026-08-15 16:07:09 +02:00
vite.config.ts feat: initialize TRXTD browser tower defense 2026-08-15 16:07:09 +02:00

TRXTD Tower Defense im Browser

Ein vollständiges Tower-Defense-Spiel, gebaut mit Vue 3 + TypeScript + Vite. Die Spiellogik läuft in reinem TypeScript auf einem HTML-Canvas (60 FPS), Vue kümmert sich um HUD, Menüs und Panels.

Enthält Solo-Kampagne, 2-Spieler-Coop und 1v1-Duell (Online/Lokal per WebSocket).

Schnellstart

  1. Abhängigkeiten installieren:

    npm install
    
  2. Frontend (Vite) und Multiplayer-Server starten:

    # Terminal 1: Dev-Server
    npm run dev        # → http://localhost:5173
    
    # Terminal 2: Multiplayer-Relay (nur für Coop / 1v1 nötig)
    npm run server     # → ws://localhost:3001
    
  3. Browser öffnen unter http://localhost:5173.


🐳 Docker

Das Spiel gibt es als All-in-One-Container: Frontend (statisch) und Multiplayer-Server teilen sich einen Port ideal für Self-Hosting.

# Image bauen (Multi-Stage-Build: Build → schlankes Runtime-Image)
docker build -t trxtd:latest .

# Container starten
docker run -d --name trxtd -p 3001:3001 trxtd:latest

# Oder mit Docker Compose (empfohlen)
docker compose up -d

Danach läuft das komplette Spiel inkl. Online-Multiplayer unter http://localhost:3001.

Enthaltene Härtung:

  • Multi-Stage-Build (kein Build-Tooling im Runtime-Image)
  • Läuft als unprivilegierter Nutzer (node)
  • HEALTHCHECK über /health
  • /assets/ mit immutablen Cache-Headern, SPA-Fallback für alle anderen Routen
  • WebSocket-Sicherheit: Payload-Limit (4 KB), Rate-Limiting (30 Aktionen/s), Schema-Validierung, Ping/Pong-Heartbeat

Nützliche Umgebungsvariablen:

Variable Default Bedeutung
PORT 3001 HTTP- und WebSocket-Port
DIST_DIR ./dist Ordner mit den statischen Dateien
ALLOWED_ORIGINS Zusätzlich erlaubte WebSocket-Origins (Komma-Liste, z. B. https://spiel.example.com)

Öffentliches Hosting hinter Reverse Proxy (Nginx Proxy Manager / NPMplus):

  1. Container nur im internen Netz erreichbar machen (Port 3001 nicht am Router freigeben!), z. B.:
    # docker-compose.yml — gemeinsames Netzwerk mit dem Proxy
    services:
      trxtd:
        build: .
        restart: unless-stopped
        expose: ["3001"]          # intern, kein ports:-Mapping nach außen
      # networks: proxy_net ...
    
  2. In NPM/NPMplus einen Proxy Host anlegen:
    • Domain: spiel.example.com (DNS-A-Record auf den Server)
    • Scheme: http · Forward Hostname: Containername (gemeinsames Docker-Netz) oder Server-LAN-IP · Port: 3001
    • Websockets Support: ✔ aktivieren (zwingend erforderlich für Multiplayer!)
    • Block Common Exploits: ✔ · Cache Assets: ✘ (der Server setzt eigene Cache-Header)
    • SSL-Tab: Let's-Encrypt-Zertifikat anfordern, Force SSL + HTTP/2 aktivieren
  3. Fertig das Spiel (inkl. Coop/1v1 über wss://) läuft unter https://spiel.example.com.

Serverseitige Härtung (aktiv): CSP-/Frame-/Referrer-Header · Origin-Check gegen Cross-Site-WebSocket-Hijacking · X-Forwarded-For-Auswertung nur aus privaten Proxy-Netzen · max. 500 WebSocket-Verbindungen total / 20 pro IP · max. 300 Räume · Payload-Limit 4 KB · Rate-Limit 30 Aktionen/s · Schema-Validierung · Ping/Pong-Heartbeat · Raum-Timeout 30 min.

Manuell ohne Docker im Produktionsmodus starten:

npm run build
npm run server   # serves dist/ + ws auf :3001

Spielmodi

1. Solo-Kampagne

Verteidige deine Basis gegen 20 handgetunte Wellen (Leicht: 30 Leben, Normal: 20 Leben, Schwer: 12 Leben). Nach Welle 20 geht es auf Wunsch im Endlos-Modus weiter.

2. 🤝 2-Spieler-Coop

  • Gemeinsame Basis & gemeinsames Gold Sprecht euch ab!
  • Eigene Türme: Deine Türme haben einen blauen Ring, die deines Partners einen orangenen Ring (jeder kann nur seine eigenen Türme upgraden oder verkaufen).
  • Gegner haben 70 % mehr Leben, um der doppelten Feuerkraft standzuhalten.
  • Wellen starten automatisch nach Countdown oder per Klick auf „Nächste Welle" (beide können klicken).

3. ⚔ 1v1-Duell (Tower-Battles-Prinzip)

  • Jeder Spieler verteidigt sein eigenes Spielfeld.
  • Über ein Live-Miniaturfenster (PiP) siehst du in Echtzeit das Spielfeld deines Gegners mit allen Türmen und Gegnern.
  • Rush-Mechanik: Schicke gegen Gold (60 🪙 + 8 🪙/Welle) eine Welle schneller Läufer auf die Basis des Gegners!
  • Siegbedingungen:
    • Basis des Gegners fällt auf 0 Leben → Sofortsieg!
    • Nach 20 Wellen gewinnt, wer mehr Leben übrig hat (bei Gleichstand entscheiden die Punkte).

Multiplayer-Raum-System

  • Klicke auf dem Startbildschirm auf „Coop-Raum erstellen" oder „1v1-Raum erstellen".
  • Gib deinem Mitspieler den 4-stelligen Raum-Code (z. B. 5SK7).
  • Der Mitspieler tippt seinen Namen + den Code ein und klickt auf „Beitreten".
  • Der Host startet das Spiel, sobald beide in der Lobby sind.
  • Funktioniert im lokalen Netzwerk (LAN / WLAN) für Freunde über das Internet einfach Port 3001 freigeben oder über ngrok/Tailscale leiten.

🌟 9-Level-Evolutionssystem

Jeder Turm hat 9 Ausbaustufen, aufgeteilt in 3 Evolutions-Stufen:

Tier Level Farbe Bedeutung
Basis 13 🟡 Gelb Höherer Grundschaden, Reichweite & Feuerrate
Evolution I 46 🟠 Orange Neue Spezialfähigkeit schaltet sich frei
Evolution II 79 🔵 Blau Finale Evolutionsstufe mit verheerenden Effekten

Die Evolutionen im Detail

Turm 🟡 Basis (L13) 🟠 Evolution I (L46) 🔵 Evolution II (L79)
🏹 Bogenturm Schneller Einzelschuss Mehrfachschuss: Feuert 23 Pfeile gleichzeitig auf verschiedene Ziele Giftpfeile + 4-Fach: Bis zu 4 Pfeile + starker Gift-DoT (28 Schaden/s)
🧨 Kanone Flächenschaden Brandgeschosse: Hinterlässt brennenden DoT an allen getroffenen Gegnern Flak-Geschütz: Trifft ab L7 auch Flugeinheiten mit voller Explosionskraft!
❄️ Eisturm Verlangsamender Puls Permafrost: Jeder 3. Puls friert alle Gegner komplett ein (Bewegung = 0) Zerbrechlichkeit: Eingefrorene Ziele nehmen +50 % Schaden aus ALLEN Quellen!
Teslaturm Kettenblitz Betäubungs-Schock: Kettenblitze betäuben getroffene Ziele kurzzeitig Gewittersturm: Jeder 4. Schuss schlägt bei ALLEN Gegnern in Reichweite gleichzeitig ein!
💫 Laserturm Soforttreffer Prisma-Brechung: Der Laserstrahl bricht und springt auf 23 Nebenziele über Durchschlag: Der Strahl durchdringt ALLES in einer Linie bis zum Rand der Reichweite

Türme ab Level 4 erhalten im Spiel eine pulsierende Evolutions-Aura (orange ab L4, blau ab L7) und die Sterne im Turm-Panel zeigen die jeweilige Tier-Farbe.


Gegner

  • 🟢 Kriecher: Standard-Einheit, gut für frühes Gold
  • 🟡 Läufer: Sehr schnell Bogentürme oder Eisturm nötig
  • Panzer: Zäh, kostet 2 Leben bei Durchbruch
  • 🟣 Flieger: Ignorieren den Weg und fliegen auf halber Höhe geradeaus (nur Bogenturm, Eisturm, Tesla, Laser!)
  • 🔴 Boss: Riesige Lebensleiste, kostet 5 Leben (Wellen 10, 15, 20 …)

Hindernisse

Bäume (60 🪙) und Felsen (40 🪙) blockieren strategisch wichtige Bauplätze.

  • Klick auf das Hindernis → „⛏ Entfernen" öffnet sich oben rechts.
  • Nach dem Entfernen wird das Feld sofort bebaubar.

Steuerung

  • 15 Turm zum Bauen auswählen, Klick auf freies Feld platziert ihn
  • Klick auf Turm Details, Upgrade, Verkauf, Zielmodus
  • Klick auf Hindernis Entfernen gegen Gold
  • Leertaste nächste Welle früh starten (Frühstart-Bonus!) / Pause (nur Solo)
  • U Upgrade · V Verkaufen · T Zielmodus wechseln
  • P Pause (nur Solo) · M Ton an/aus · Esc Abbrechen
  • Rechte Maustaste Bauauswahl aufheben

Technische Details

  • Client-Side Simulation: Determinister Lockstep-Tick-Loop (30 Hz) beide Clients berechnen den exakten Spielverlauf parallel; der Server (server/server.mjs) vermittelt nur die Räume und leitet Aktionen weiter (minimaler Traffic, kein Lag bei der Bewegung).
  • Renderer: Offscreen-gepufferter HTML-Canvas mit dynamischer Vollbild-Skalierung, Retina-DPR-Support, Partikelsystem und Mündungsfeuer.
  • Sound: Web Audio API mit synthetisierten Klängen (keine externen Audio-Dateien).
  • Automatisierte Tests:
    • npm run sim Headless-Bot spielt die Solo-Kampagne zur Balancing-Prüfung durch
    • npx tsx scripts/test-mp.mts Lockstep-Determinismus-Test (3600 Ticks, byte-identischer Zustand auf beiden Seiten)
    • npx tsx scripts/test-obstacle.mts Feature-Test: Hindernis-Entfernung