Files
train-game/README.md
2026-08-29 11:44:31 +02:00

5.4 KiB
Raw Blame History

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.