Files
pirate-dice/README.md
2026-09-05 23:19:46 +02:00

120 lines
5.8 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.
# Liar's Dice 3D
Würfel-Bluffspiel in Godot 4.7 mit echter 3D-Physik, Host/Client-Multiplayer,
KI-Bots und einem Booster-System aus Buffs und Debuffs.
## Starten
godot --path . # oder das Projekt im Godot-Editor öffnen
Das Startmenü hat drei Punkte:
* **Einzelspieler** – nur die Bot-Anzahl (1–7) einstellen und starten. Es wird
kein Netzwerk geöffnet.
* **Mehrspieler** – Name, Server-IP und Bot-Anzahl. **Spiel hosten** öffnet
einen Server auf Port 8910, **Beitreten** verbindet sich mit der eingetragenen
IP. Der Host startet die Partie, sobald mindestens 2 Teilnehmer zusammen
sind (Menschen und Bots zusammengezählt, maximal 8).
* **Beenden** – schließt das Spiel.
Zum Testen auf einem Rechner: eine Instanz hostet, weitere Instanzen verbinden
sich auf `127.0.0.1`.
Das Spiel startet im Vollbild, **F11** schaltet um. **Esc** öffnet ein Menü mit
*Fortsetzen* und *Verlassen*; im Einzelspieler hält es das Spiel samt Zeitlimit
wirklich an, im Mehrspieler läuft die Runde weiter – sonst würde ein geöffnetes
Menü alle anderen am Tisch blockieren.
Die Bildaufteilung: Tisch mittig, aktuelles Gebot oben mittig, Würfel aller
Spieler oben rechts, Verlauf unten links, Ansage unten rechts.
Augenzahlen werden überall als gezeichnete Würfel dargestellt (`DieIcon` in
`hud.gd`), unbekannte Werte als Würfel mit Fragezeichen. Im Panel oben rechts
stehen deshalb deine eigenen Würfel offen, gegnerische verdeckt – bis auf die
per *Spähen* aufgedeckten und beim Aufdecken am Rundenende.
Der Tisch wächst mit der Spielerzahl, damit die Würfelzonen auch bei acht
Plätzen nicht aneinanderstoßen. Die Kamera schaut mit 15° Neigung fast senkrecht
von oben darauf; der eigene Platz liegt unten im Bild. `_frame_camera` in
`table.gd` rechnet den Abstand so aus, dass der Tisch genau das freie Band
zwischen den HUD-Feldern ausfüllt (`HUD_TOP`/`HUD_BOTTOM`) – bei jeder
Spielerzahl und jedem Fensterformat, auch nach dem Ändern der Fenstergröße.
## Physik und Bildrate
Zwei Engine-Vorgaben sind bewusst gesetzt, beide in `project.godot`:
* **`3d/physics_engine="Jolt Physics"`** – GodotPhysics3D hat Kontakt-Toleranzen,
die auf meterhohe Objekte ausgelegt sind (`contact_max_separation` 0.05 bei
0.075 Würfel-Halbkante). Würfel dieser Größe sanken dadurch in die Tischplatte
ein und rollten endlos weiter, sodass jeder Wurf in den Settle-Timeout lief.
Mit Jolt liegt die Wurfphase bei rund 0,9 s statt 7 s.
* **`renderer/rendering_method="mobile"`** – auf integrierten GPUs kostet
Forward+ hier mehr als das Doppelte: 22 statt 47 fps bei 30 Würfeln.
Ein Würfel ist ein einziges Renderobjekt: Körper und Augen stecken in einem
gemeinsamen Mesh mit Vertexfarben, statt 21 Augen als eigene Meshes zu hängen.
Weil Kamera und Deckenlicht beide fast senkrecht stehen, liegt der Glanzpunkt
genau auf der Würfeloberseite. Mit glänzendem Material und starkem Spot klippte
die weiße Fläche bei 255 und riss die schwarzen Augen mit hoch – gemessen lag
kein einziger Punkt-Pixel unter Luminanz 150. Deshalb ist das Würfelmaterial
matt (`roughness` 0.9, `metallic_specular` 0.0) und der Spot schwächer
zugunsten von mehr Umgebungslicht; der Kontrast Auge zu Körper liegt damit bei
rund 11:1.
## Regeln
Klassisches Liar's Dice ohne Joker. Jeder startet mit 5 Würfeln und sieht nur
die eigenen.
1. **Würfeln** – alle Würfel fallen physikalisch in den eigenen Becher.
2. **Boost wählen** – jeder bekommt 3 zufällige Booster angeboten und wählt
einen; er wirkt nur für die laufende Runde.
3. **Ansagen** – reihum wird ein Gebot "Anzahl x Augenzahl" über alle Würfel
am Tisch gemacht. Jedes Gebot muss höher sein: mehr Würfel, oder gleich
viele bei höherer Augenzahl.
4. **Anfechten** – statt zu erhöhen kann man das Vorgebot anzweifeln. Alle
Becher werden gehoben und gezählt: Stimmt das Gebot, verliert der
Anfechter einen Würfel, sonst der Bieter.
Für Boosterwahl und Ansage hat man jeweils **30 Sekunden**; die Restzeit steht
im Booster-Fenster beziehungsweise neben „Deine Ansage" und wird unter zehn
Sekunden rot. Läuft die Zeit ab, entscheidet der Host automatisch – beim Booster
zufällig, beim Gebot mit der Bot-Logik. Ohne dieses Limit würde ein abwesender
oder getrennter Mitspieler den ganzen Tisch dauerhaft blockieren.
Wer keine Würfel mehr hat, scheidet aus. Der Letzte gewinnt.
## Booster
| Booster | Art | Wirkung |
|---|---|---|
| Neuwurf | Buff | Alle eigenen Würfel neu werfen |
| Feinschliff | Buff | Einen gewählten eigenen Würfel neu werfen |
| Glücksgriff | Buff | Ein gewählter Würfel wird zur 6 |
| Zwilling | Buff | Ein anderer eigener Würfel nimmt den Wert des gewählten an |
| Spähen | Buff | Von jedem Gegner wird ein zufälliger Würfel aufgedeckt |
| Rütteln | Debuff | Jeder Gegner wirft einen zufälligen Würfel neu |
| Absenken | Debuff | Bei jedem Gegner sinkt ein zufälliger Würfel um 1 |
| Nebel | Debuff | Jeder Gegner sieht einen eigenen Würfel nicht mehr |
| Störfeuer | Debuff | Gegner müssen diese Runde um mindestens 2 erhöhen |
| Maulkorb | Debuff | Der nächste Spieler muss bieten und darf nicht anfechten |
## Aufbau
| Datei | Inhalt |
|---|---|
| `scripts/net.gd` | Autoload: ENet-Host/Client, Lobby, Spielstart |
| `scripts/boosters.gd` | Autoload: Booster-Katalog |
| `scripts/game.gd` | Spiellogik (host-autoritativ), RPCs, Zustandsabgleich |
| `scripts/table.gd` | Aufbau der 3D-Szene: Tisch, Würfelzonen, Becher, Kamera |
| `scripts/die.gd` | Physik-Würfel, Ablesen der Augenzahl aus der Ruhelage |
| `scripts/ai.gd` | Bot-Entscheidungen (Binomialabschätzung für Gebot/Anfechtung) |
| `scripts/hud.gd` | Spiel-UI |
| `scripts/menu.gd` | Startmenü und Lobby |
Die gesamte Spiellogik und die Würfelphysik laufen beim Host. Clients erhalten
nur ihre eigenen Würfel als Transform-Stream, gegnerische Werte erst beim
Aufdecken – Mitlesen fremder Würfel ist damit nicht möglich.