TRXTD/README.md
Tronax b506ffad55
feat(docker): add self-hosted all-in-one container setup
- Add Dockerfile (multi-stage build, unprivileged user, healthcheck),
  docker-compose.yml and .dockerignore
- Server now serves static dist/ frontend and WebSocket relay on a
  single port (PORT, default 3001) with path-traversal protection,
  immutable asset caching and SPA fallback
- Client connects via same origin in production; dedicated ws port is
  only used for vite dev/preview
- Document Docker usage, env vars and manual production mode in README
2026-08-16 12:15:52 +02:00

148 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
```bash
npm install
```
2. Frontend (Vite) und Multiplayer-Server starten:
```bash
# 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.
```bash
# 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 |
**Manuell ohne Docker im Produktionsmodus starten:**
```bash
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.
---
## Türme
| Turm | Kosten | Upgrade 2/3 | Besonderheit |
| --- | --- | --- | --- |
| 🏹 Bogenturm | 50 🪙 | 60 / 110 🪙 | Günstig, schnelle Einzelschüsse, trifft Luft |
| 🧨 Kanone | 110 🪙 | 100 / 180 🪙 | Flächenschaden, trifft **keine** Flieger |
| ❄️ Eisturm | 80 🪙 | 70 / 130 🪙 | Verlangsamt alle Gegner im Umkreis um bis zu 65 % |
| ⚡ Teslaturm | 130 🪙 | 120 / 200 🪙 | Kettenblitz springt auf bis zu 5 Gegner über |
| 💫 Laserturm | 160 🪙 | 150 / 260 🪙 | Soforttreffer, maximale Reichweite & Durchschlag |
- **Verkauf:** 70 % der Gesamtinvestition (Kauf + Upgrades) werden erstattet.
- **Zielmodi:** Erster / Letzter / Stärkster / Nächster.
---
## 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