Files
elements-autochess/README.md
2026-09-16 12:09:33 +02:00

7.1 KiB

Elements Autochess

Auto-Battler nach TFT-Vorbild in Godot 4.7, in 3D. Primitive Assets: Hexfelder sind Zylinder mit 6 Segmenten, Einheiten sind Würfel (Tank), Kegel (DPS) und Kugeln (Heiler). Alles wird im Code erzeugt.

Starten

godot --path . scenes/Main.tscn

Steuern

  • Shop-Karte anklicken = kaufen. Neutrale Avatare fragen dabei nach der Spezialisierung, Element-Avatare kommen fertig.
  • Die Bank sind die 9 Hexplätze vor dem eigenen Spielfeld, ebenfalls in 3D.
  • Avatare per Drag & Drop verschieben: Bank -> Feld, Feld -> Bank, Feld -> Feld und Bank -> Bank. Ist das Ziel belegt, tauschen die beiden die Plätze.
  • Klick ohne Ziehen = auswählen. Info rechts, dort auch Aufwerten.
  • Rechtsklick auf dem Feld = zurück auf die Bank, auf der Bank = verkaufen.
  • Klicks treffen über einen Strahl von der Kamera auf die Feldebene.
  • D neu würfeln, F Shop einfrieren, X XP kaufen, Leertaste Kampf, P Pause, Esc Auswahl lösen
  • Rechtsklick auf eine neutrale Shop-Karte kauft direkt mit der zuletzt gewählten Spezialisierung
  • Spielername rechts anklicken = sein Brett oben ansehen. Der nächste Gegner steht schon in der Planung fest.
  • Q/E oder mittlere Maustaste drehen die Kamera, das Mausrad zoomt
  • Die Planung dauert 30 Sekunden, dann startet der Kampf von selbst
  • Startbildschirm und Pause haben einen Lautstärkeregler

Regeln

Anforderung Umsetzung
1-Star bis 3-Star, zweimal aufwertbar Avatar.star, Data.MAX_STAR
Tank / DPS / Heiler Data.Role, eigene Werte und Fähigkeiten
Spezialisierung beim Kauf Popup beim Kauf eines neutralen Avatars
Weitere Spezialisierung beim Aufwerten Popup beim Upgrade, bis zu 3 Elemente
Shop startet elementlos PlayerState.unlocked beginnt leer
Aufgestellte Elemente kommen in den Shop PlayerState.unlock() beim Aufstellen
Mein Shop zeigt nur meine Elemente und Neutral PlayerState.shop_elements() je Spieler
Neutrale Chance -25% je aufgestelltem Element Data.neutral_chance(), multiplikativ
Bank ist 3D am Spielfeld BoardView3D.bench_pos(), 9 Hexplätze
Avatare zwischen Bank und Board verschieben PlayerState.move_slot()
Drag & Drop Main._begin_drag() / _end_drag(), Avatar klebt flach am Zeiger
Aufwertung zeigt, was sich ändert Popup nennt die neue Fähigkeit, je Auswahl eine Zeile
Zinsen je 10 Gold bis 50 Gold Data.interest(), max +5
Neutral 1 Gold, Element 2 Gold Data.PRICE_NONE / PRICE_ELEMENT
1-Star Feuer + 2 Feuer = 2-Star Avatar.upgrade_cost()
2-Star Feuer/Wind + 3 Feuer + 3 Wind = 3-Star Avatar.upgrade_cost()
Stats und Fähigkeiten pro Stufe Data.STAR_MULT, Avatar.ability_text(), Combat._cast()
Elemente kombinierbar wie Traits Data.ELEMENT_TRAITS, Data.COMBO_TRAITS
5 Gold pro Runde, 1 für Sieg, mehr bei Serie PlayerState.round_income()
100 Leben Data.START_HP
Begrenzte Elementmenge für alle Spieler Pool.element_left, 100 pro Element
7 Bots Game.BOT_NAMES, BotAI
Keine Items nicht vorhanden

Nicht in den Anforderungen, aber „Basis wie TFT":

  • Level statt fester Kaderplätze. Start Level 3, jede Runde 2 XP, 4 XP für 4 Gold. Level = Kaderplätze, Maximum 9 (Data.XP_TABLE, PlayerState.buy_xp()).
  • Schaden steigt mit der Runde. Grundschaden 2, alle vier Runden +1, dazu die Sternsumme der Überlebenden (Data.round_base_damage(), Combat.survivor_stars).
  • Planungsuhr 30 s (Game.tick_planning()), Tests schalten sie ab.
  • Gegner ansehen über die Spielerliste (Main._on_scout(), BoardView3D.scout_player).
  • Heiler heilen nur im Umkreis 2 (Data.HEAL_RANGE), Aufstellung zählt also.
  • Lesbarer Kampf: Schadens- und Heilzahlen, Krit mit „!", Sterbe-Animation, Zustände als Tönung und Marke (B Brand, S langsam, Z betäubt), Schildstreifen.
  • Klänge werden im Code erzeugt (Sfx), keine Audiodateien.
  • Sichtbare Angriffe: Fernkampf schickt eine Kugel, Nahkampf einen Hieb (BoardView3D.spawn_attack).
  • Element-Profile: das Hauptelement prägt die Werte, z. B. Feuer +18% Angriff, Erde +22% Leben (Data.ELEMENT_PROFILE). Dazu ein Kennzeichen am Körper: Flamme, Tropfen, Finne, Zacke, Schultern, Kristall.
  • Gegner vorab: Paarungen entstehen beim Rundenstart (Game._make_pairings in _next_round). Bots stellen dagegen auf: Tanks vor gegnerische Schützen, Schützen weg von Tanks (BotAI.arrange).
  • Shop einfrieren (PlayerState.shop_locked), Schnellkauf mit der letzten Wahl (last_element).
  • Rückblick nach jedem Kampf: Ergebnis, Überlebende, stärkste Einheit, gefährlichster Gegner (Combat.recap, Game.human_recap).
  • Start, Pause, Lautstärke als Overlays in Main, Kamera mit Zoom und Drehung um die Brettmitte.

Der neutrale Avatar selbst ist unbegrenzt. Knapp ist das Element, das man ihm beim Kauf gibt: das zieht einen Platz aus dem geteilten Vorrat. Die 100 pro Element sind gemessen: mit den Bots, die jetzt gezielt Futter jagen und Level kaufen, läuft bei 80 in 2 von 10 Partien ein Element leer, bei 100 keines, Tiefstand rund ein Fünftel.

Die Neutral-Chance ist multiplikativ (0,75 hoch Anzahl Elemente) statt in Prozentpunkten. So verschwindet Neutral nie ganz: ohne eigene Elemente 100%, mit einem 75%, mit sechs noch 18%.

Elemente und Traits

Feuer, Wasser, Wind, Blitz, Erde, Eis. Stufen bei 2 / 4 / 6 Einheiten. Kombinationen (beide Elemente ab 2 Einheiten): Feuersturm, Frost, Magnetsturm, Magma, Sturmfront, Dampf.

Aufbau

scripts/core/   Data, Avatar, Pool, ShopEntry, PlayerState, Hex, Combat, BotAI, Game
scripts/ui/     Main (Szene, Kamera, Eingabe, Overlays), TopBar, InfoColumn, PlayersPanel,
                ShopPanel (je ein Panel, melden per Signal), BoardView3D, HudOverlay, Sfx, UiKit
scenes/Main.tscn
tests/          sim_test.gd (kopflos), Probe2, Probe3, CamCal

Combat ist reine Logik und wird in Schritten gerechnet. Bot-Kämpfe laufen sofort durch (run_to_end), der eigene Kampf wird pro Frame gesteppt.

Die Darstellung hängt nicht an der Logik: BoardView3D liest nur Game. Lebens- und Manabalken zeichnet HudOverlay in 2D über die projizierten Weltpositionen, damit sie in jeder Entfernung lesbar bleiben.

Main._fit_camera() rechnet Abstand und Blickpunkt so aus, dass das Spielfeld genau in die freie Bildmitte passt. Links stehen Elemente, Einheit und Rundenlog, rechts die Spielerliste, unten der Shop. Das läuft bei jeder Fenstergröße neu.

Tests

Kernlogik ohne Fenster:

godot --headless --path . --script tests/sim_test.gd

UI-Durchläufe mit Screenshots (Ordner als Argument):

godot --path . tests/probe2.tscn  -- /pfad/zu/screenshots   # 3-Star, Spielende, Neustart
godot --path . tests/probe3.tscn  -- /pfad/zu/screenshots   # echte Maus- und Tastatureingaben
godot --path . tests/camcal.tscn  -- /pfad/zu/screenshots   # Kamerabild und Trefferprüfung

probe3 schickt Klicks und Drags über Viewport.push_input wie ein Nutzer und prüft danach den Zustand. camcal prüft, dass alle 28 Felder und 9 Bankplätze unter ihrer eigenen Bildschirmposition auch getroffen werden.