122 lines
5.4 KiB
Markdown
122 lines
5.4 KiB
Markdown
# Cozy Train
|
||
|
||
Low-Poly-Zugspiel in Godot 4.7. Eine Crew verwaltet gemeinsam einen Zug:
|
||
einer fährt, die anderen kontrollieren Tickets, servieren Getränke und
|
||
laden Güter um. First-Person, entspannter Ton, alles aus Primitiven gebaut.
|
||
|
||
## Starten
|
||
|
||
~/bin/godot --path . # Spiel
|
||
~/bin/godot --editor --path . # Editor
|
||
./tests/run.sh # Tests (Spiellogik, Eingabe, Netzwerk)
|
||
|
||
Im Menü: **Einzelspieler**, **Sitzung hosten** oder **Beitreten** mit
|
||
Adresse und Port (Standard 7654). Der Host simuliert alles, Clients
|
||
schicken Wünsche und bekommen den Zustand zurück.
|
||
|
||
Die Eingabe-Tests brauchen ein Fenster, die anderen laufen headless.
|
||
Sie schieben echte Input-Events durch die Godot-Kette (GUI -> `_unhandled_input`)
|
||
und prüfen die Wirkung im Spiel, nicht nur den Aufruf. `direction_test.gd`
|
||
vergleicht jede Laufrichtung mit den Achsen der Kamera – ein Vorzeichenfehler
|
||
beim Seitwärtsgehen fällt damit sofort auf.
|
||
|
||
## Steuerung
|
||
|
||
| Taste | Wirkung |
|
||
|-------------------|------------------------------------------|
|
||
| Maus | Umsehen |
|
||
| W A S D | Laufen (im Führerstand: W Gas, S Bremse) |
|
||
| Shift | Rennen |
|
||
| E | Benutzen; am Güterwagen halten |
|
||
| H | Pfeife (nur wer fährt) |
|
||
| M | Musik an/aus |
|
||
| V | Außenkamera (A/D drehen, R/F neigen, Rad zoomen) |
|
||
| Esc | Maus freigeben / Terminal schließen |
|
||
|
||
## Was es zu tun gibt
|
||
|
||
**Fahren.** Im Führerstand am Pult E drücken. Nur ein Spieler kann fahren;
|
||
E gibt die Steuerung wieder frei. Am Bahnsteig anhalten – der Zug gilt als
|
||
angekommen, wenn seine Mitte nah genug am Bahnsteig steht.
|
||
|
||
**Fahrgäste.** Sie warten am Bahnsteig, steigen beim Halt ein und wollen
|
||
kontrolliert werden. Ein Blick auf den Gast, E – das Ticket bringt sofort
|
||
Geld. Wer bis zum Ziel unkontrolliert bleibt, fährt schwarz und kostet
|
||
Ansehen.
|
||
|
||
**Servieren.** Mit einem Speisewagen bekommen Gäste nach einer Weile Durst.
|
||
Getränk an der Theke holen (E), zum Gast, E. Bringt Trinkgeld und hält die
|
||
Laune oben. Schlechte Laune kostet beim Aussteigen Ansehen.
|
||
|
||
**Güter.** Im Güterwagen steht eine Ladekonsole. Im Halt E gedrückt halten:
|
||
Erst wird abgeliefert, was der Bahnhof annimmt, danach geladen, was er
|
||
produziert.
|
||
|
||
| Bahnhof | produziert | nimmt an |
|
||
|-------------|-----------|-------------------|
|
||
| Waldkirch | Holz | Getreide |
|
||
| Kohlberg | Kohle | – |
|
||
| Eisenwerk | – | Kohle, Holz |
|
||
| Grüntal | Getreide | – |
|
||
| Ahornstadt | – | Getreide, Holz |
|
||
|
||
**Depot-Terminal.** Hinten im Führerstand. Dort kaufst und verkaufst du
|
||
Waggons, tauschst die Lok und schaltest Ausbauten frei. Bessere Loks und
|
||
Waggons brauchen **Ansehen** – das steigt mit zufriedenen Fahrgästen und
|
||
gelieferten Waren.
|
||
|
||
## Aufbau
|
||
|
||
Die Welt entsteht komplett zur Laufzeit, `scenes/main.tscn` ist nur der
|
||
Einstiegspunkt.
|
||
|
||
| Datei | Inhalt |
|
||
|-------|--------|
|
||
| `shaders/flat.gdshader` | Facettierte Optik über Screen-Space-Normalen |
|
||
| `scripts/game.gd` | Weltaufbau, Spielstand, Aktionen, Netzwerk |
|
||
| `scripts/car.gd` | Ein Fahrzeug: Hülle, Innenraum, Sitze, Hotspots |
|
||
| `scripts/car_defs.gd` | Stammdaten für Loks, Waggons, Ausbauten |
|
||
| `scripts/train.gd` | Verband, Fahrphysik, Zug- zu Weltkoordinaten |
|
||
| `scripts/player.gd` | First-Person-Bewegung in Zugkoordinaten |
|
||
| `scripts/passenger.gd` | Fahrgast mit Ticket, Wunsch und Laune |
|
||
| `scripts/station.gd` | Bahnsteig, Lager, Warteplätze |
|
||
| `scripts/world.gd` | Gelände und Vegetation (MultiMesh) |
|
||
| `scripts/track.gd` | Gleiskurve und Gleisoptik |
|
||
| `scripts/shop.gd`, `hud.gd`, `menu.gd` | Oberflächen |
|
||
| `scripts/camera_rig.gd` | Außenkamera |
|
||
| `scripts/synth.gd` | Wavetable-Synth: Töne, Rauschen, Hüllkurven |
|
||
| `scripts/sfx.gd` | Alle Klänge und das Musikstück als Rezept |
|
||
| `scripts/audio.gd` | Wiedergabe, Fahrgeräusch, Radschläge, Schritte |
|
||
|
||
|
||
### Zugkoordinaten
|
||
|
||
Spieler bewegen sich nicht in Weltkoordinaten, sondern in einer
|
||
Längsposition `s` entlang des Zuges plus einer Querposition `x`.
|
||
`train.locate(s)` liefert den passenden Waggon, dessen Transform die
|
||
Weltposition ergibt. Dadurch bleibt der Innenraum auch bei voller Fahrt
|
||
und in Kurven stabil begehbar, ohne Physik-Plattformen.
|
||
|
||
### Klang
|
||
|
||
Es gibt keine Audiodateien. `sfx.gd` beschreibt jeden Klang als Rezept aus
|
||
Sinustönen, Rauschen und Hüllkurven; `synth.gd` rechnet daraus PCM. Das
|
||
läuft beim Start in einem Thread (rund drei Sekunden), bis dahin bleibt es
|
||
still – das Spiel ruckelt dabei nicht.
|
||
|
||
Die Musik ist ein 27-Sekunden-Stück in 72 bpm: Flächen über Am7–Fmaj7–
|
||
Cmaj7–G6, dazu Bass, sparsame Glockentöne und ein leiser Shaker. Der
|
||
Ausklang wird auf den Anfang gemischt, dadurch ist die Schleife nahtlos.
|
||
|
||
Das Fahrgeräusch ist eine Rauschschleife, deren Lautstärke und Tonhöhe am
|
||
Tempo hängen. Die Radschläge kommen nicht per Timer, sondern alle 8,5
|
||
gefahrene Meter – deshalb passen sie automatisch zur Geschwindigkeit.
|
||
|
||
### Netzwerk
|
||
|
||
Godot-Hochsprachen-RPCs über ENet. Der Host ist maßgeblich für Zug,
|
||
Fahrgäste, Lager und Kasse. Clients senden ihre Pose (15 Hz) und
|
||
Aktionswünsche; der Host verteilt Zustandspakete (4 Hz). Die Welt wird auf
|
||
allen Rechnern aus demselben Seed erzeugt und muss deshalb nicht
|
||
übertragen werden.
|