- 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
148 lines
6.1 KiB
Markdown
148 lines
6.1 KiB
Markdown
# 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
|
||
|
||
- **1–5** – 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
|