10 KiB
Game Design
Alle Werte stehen zentral in app/static/js/config.js. Die Tabellen hier geben den
Stand zum Zeitpunkt des Schreibens wieder. Bei Abweichungen gilt config.js.
Einheiten: Pixel (px), px/s, Millisekunden (ms), Lebenspunkte (LP).
Welt und Ton
- Setting: Die fiktive „Vereinigte Erde“ wird von zwei außerirdischen Fraktionen angegriffen. Präsident Maximilian Valor verteidigt „den ewigen Frieden“ persönlich.
- Satire: Durchsagen des „Ministeriums für Zuversicht“ zwischen den Wellen,
Briefings, Game-Over-Texte. Der Spott gilt Militarismus und Propaganda im
Allgemeinen, nicht realen Personen, Parteien oder Ländern. Namen und Begriffe sind
eigenständig. Ein Test (
tests/test_assets.py) verhindert Begriffe aus bekannten Vorbildern. - Arena: 2400 × 1600 px, größer als der Bildschirm (1280 × 720). Die Kamera folgt dem Präsidenten. Gegner außerhalb des Bildes zeigt das HUD als Randpfeile an.
Der Präsident
| Wert | |
|---|---|
| Leben | 100 LP |
| Tempo | 240 px/s (diagonal gleich schnell) |
| Hitbox | Kreis, Radius 18 px |
| Unverwundbarkeit nach Treffer | 500 ms (sonst tötet ein Schwarm in einem Frame) |
| Ausweichrolle | 640 px/s für 320 ms, unverwundbar, Abklingzeit 1500 ms. Ohne Bewegung in Blickrichtung. |
| Heilung nach jeder Welle | 15 LP |
Treffer am Präsidenten beenden die Punkteserie. Gegnerprojektile fliegen während der Rolle hindurch, statt verschluckt zu werden.
Waffen
| Karabiner »Zuversicht« | Schrotflinte »Überzeugungskraft« | Dienstpistole »Anstand« | |
|---|---|---|---|
| Taste | 1 | 2 | 3 |
| Modus | Dauerfeuer | Einzelschuss | Einzelschuss |
| Schaden | 14 | 8 × 11 (Schrot) | 16 |
| Feuerpause | 110 ms | 650 ms | 260 ms |
| Magazin / Reserve (Start, max.) | 30 / 180, 270 | 6 / 24, 48 | 12 / unbegrenzt |
| Nachladen | 1,5 s | 1,9 s | 1,1 s |
| Streuung | 3° | 24° Fächer | 2° |
| Reichweite | 820 px | 420 px | 700 px |
| Schaden/s (Feuerstoß / mit Nachladen) | 127 / 88 | 135 / 91 | 62 / 45 |
- Leeres Magazin lädt automatisch nach. Ein Waffenwechsel bricht das Nachladen ab.
- Sind Magazin und Reserve leer, wechselt das Spiel automatisch zur Dienstpistole. Ohne Munition ist man also nie wehrlos.
- Die Nachschubkapsel füllt die Reserve aller Waffen auf das Maximum.
Gegner
Die Schwärmer (insektoid, Nahkampf)
| Krabbler (klein) | Sprungkralle (mittel) | Brutmutter (Elite) | |
|---|---|---|---|
| Leben | 20 | 60 | 450 |
| Tempo | 175 | 125 | 58 |
| Kontaktschaden (Abklingzeit) | 6 (700 ms) | 14 (800 ms) | 28 (1000 ms) |
| Punkte | 10 | 30 | 250 |
| Budgetkosten | 1 | 3 | 15 |
| Gruppengröße | 4–8 | 1–3 | 1 |
| Verhalten | Umzingeln | Sprungangriff | Brüten |
- Umzingeln: Jeder Krabbler bekommt einen eigenen Anflugwinkel auf einem Kreis (130 px) um den Präsidenten. Ab 170 px Abstand greift er direkt an. Ein Rudel kommt dadurch von mehreren Seiten.
- Sprungangriff: Verfolgen. Ab 260 px setzt die Sprungkralle 450 ms an: sie steht still, färbt sich rot und wird größer. Dann springt sie mit 560 px/s für 380 ms in die beim Ansetzen festgelegte Richtung. Wer auf die Vorwarnung reagiert, kann ausweichen. Abklingzeit 2,4 s.
- Brüten: Langsames Verfolgen, alle 5 s schlüpfen bis zu 3 Krabbler, höchstens 6 gleichzeitig lebende Nachkommen.
Die Blechlegion (Roboter, Fernkampf)
| Nieter-Drohne (klein) | Blechsoldat (mittel) | Walzmeister (Elite) | |
|---|---|---|---|
| Leben | 30 | 90 | 700 |
| Tempo | 95 | 78 | 44 |
| Wunschabstand | 220–340 px | 200–380 px | 260–460 px |
| Angriff | Einzelschuss 7, alle 1,5 s | 3er-Salve à 8, alle 2,3 s | Fächer aus 7 × 10 (50°), alle 2,7 s + Mörser |
| Projektiltempo | 330 | 400 | 290 |
| Punkte | 20 | 50 | 400 |
| Budgetkosten | 2 | 4 | 18 |
| Gruppengröße | 2–3 | 1–3 | 1 |
| Verhalten | Abstand halten | Flankieren | Belagern |
- Abstand halten: Zu weit weg → annähern, zu nah → zurückweichen, dazwischen seitlich ausweichen. Die Richtung wechselt zufällig alle 1,4–3,2 s. So sind Fernkämpfer kein stehendes Ziel.
- Flankieren: Ziel ist ein Punkt, der gegenüber der Linie Präsident→Gegner um 70° gedreht ist (Abstand 290 px). Der Blechsoldat schwenkt also seitlich ein, statt frontal anzulaufen. Dort angekommen, hält er Abstand.
- Mörser (Walzmeister): Alle 5,2 s zielt er auf die aktuelle Position des Präsidenten. Eine rote Bodenmarkierung (Radius 90 px) füllt sich 1,4 s lang, dann folgt der Einschlag (26 Schaden). Stehenbleiben ist keine Option.
- Frisch gespawnte Gegner schießen frühestens nach etwa 0,5–1,6 s. Das ist fair, weil sonst Salven aus dem Nichts kämen.
Allgemeine KI
Alle Bewegungen sind Steuerungsvektoren (logic/steering.js), die sich überlagern.
Eine Separation (Radius 34 px + Gegnerradius) schiebt Gegner auseinander und
verhindert Klumpen. Die Geschwindigkeit wird weich nachgeführt (18 % pro Frame),
damit Richtungswechsel nicht ruckeln. Nahkämpfer bleiben am Rand des Präsidenten
stehen, statt sich auf seinen Mittelpunkt zu drängen.
Orbital-Befehle
Eingabe: Q gedrückt halten und die Richtungsfolge mit Pfeiltasten oder WASD eingeben. Während der Eingabe steht der Präsident still. Das Ziel ist die Mausposition, begrenzt auf 560 px Entfernung und die Arena. Falsche Eingaben leeren den Puffer, man kann sofort neu ansetzen. Keine Folge ist der Anfang einer anderen, und jede beginnt mit einer anderen Richtung (wird getestet). Die Codes sind eigene Erfindungen. Der Orbitalschlag-Code ↑ → ↓ ↓ stammt aus der Projektvorgabe. Ein Test stellt sicher, dass keiner der Codes einem Code aus einem bekannten Spiel mit ähnlicher Mechanik entspricht.
| Befehl | Code | Verzögerung | Abklingzeit | Wirkung |
|---|---|---|---|---|
| Orbitalschlag »Morgenröte« | ↑ → ↓ ↓ | 2,5 s | 30 s | Radius 150 px, 260 Schaden an Gegnern, 40 am Präsidenten, falls er im Radius steht |
| Nachschubkapsel »Fürsorgepaket« | ← ← ↓ → | 3 s | 45 s | Einschlag: Radius 70 px, 120 Schaden (20 am Präsidenten). Danach liegt 30 s eine Kapsel: +50 LP, volle Reserve. |
| Geschütz »Wachsamer Nachbar« | → ← → ↑ ↑ | 3 s | 60 s | Einschlag: Radius 60 px, 80 Schaden (15 am Präsidenten). Danach 25 s Geschütz: zielt auf den nächsten Gegner (480 px), 12 Schaden alle 150 ms |
Bis zum Einschlag zeigt eine Bodenmarkierung den genauen Wirkungsradius, einen Strahl aus dem Orbit und einen Countdown. Kapsel und Geschütz blinken in ihren letzten 3 Sekunden.
Wellen
- Budget:
B(n) = 8 + 5 · (n − 1)^1,15, gerundet. Gegner „kosten“ Budget (Tabellen oben). - Fraktionen: Wellen 1–2 nur Schwärmer, 3–4 nur Blechlegion, ab 5 gemischt.
- Eliten: jede 5. Welle, Anzahl = Welle / 5 (max. 4). Die erste Elite ist eine Brutmutter, danach wechselt die Fraktion.
- Zusammenstellung: Zuerst werden Eliten gekauft (mindestens 30 % des Budgets
bleiben für Fußvolk). Dann gehen
10 % + 4 % · (n − 1)des Restbudgets (max. 50 %) in mittlere Gegner, der Rest in kleine. Gruppengrößen je Typ. - Ablauf: Gruppen erscheinen nacheinander (1,3–3 s Abstand, in späten Wellen bis zu 55 % dichter) an zufälligen Arenarändern, nie näher als 420 px am Präsidenten. Leben mehr als 60 Gegner, wartet der Spawner.
- Skalierung ab Welle 6: +7 % Leben und +1,2 % Tempo pro Welle (Tempo max. +30 %).
- Pause: 8 s zwischen den Wellen mit Propaganda-Durchsage (ohne direkte Wiederholung), Wellenbonus und Heilung.
| Welle | Budget | Eliten | Leben × | Tempo × | Ø Gegner |
|---|---|---|---|---|---|
| 1 | 8 | 0 | 1,00 | 1,00 | 8 |
| 3 | 19 | 0 | 1,00 | 1,00 | 9 |
| 5 | 33 | 1 | 1,00 | 1,00 | 14 |
| 10 | 71 | 2 | 1,35 | 1,06 | 23 |
| 15 | 112 | 3 | 1,70 | 1,12 | 37 |
| 20 | 156 | 4 | 2,05 | 1,18 | 52 |
(Ø Gegner ohne ausgebrütete Krabbler, gemittelt über 50 Zufalls-Seeds.)
Punkte
- Abschuss: Punkte des Gegnertyps × Multiplikator
- Serie: Jeder Abschuss innerhalb von 3 s nach dem letzten setzt die Serie fort. Alle 5 Abschüsse steigt der Multiplikator um 0,5, bis maximal ×4.
- Ein Treffer am Präsidenten beendet die Serie.
- Wellenbonus: 100 × Wellennummer (ohne Multiplikator)
Plausibilitätsgrenzen im Backend
app/config.py (GAME_RULE_DEFAULTS) lehnt Einreichungen ab, wenn
- die gemeldete Spieldauer länger ist als die Zeit seit Ausgabe des Run-Tokens (+30 s Toleranz). Pausen zählen nicht zur Spieldauer, daher darf sie kürzer sein.
- die Welle in der Spieldauer nicht erreichbar ist:
Dauer ≥ (Welle − 1) · 5 s, denn jede Pause dauert 8 s. - die Punkte über
2000 + 200 · Dauer in sliegen.
Herleitung der 200 Punkte/s: Testläufe (Bot mit perfektem Zielen) liegen bei etwa
15–20 Punkten/s. Eine grobe Abschätzung für eine sehr starke Runde (Welle 25 nach
20 Minuten, Multiplikator dauerhaft hoch) ergibt 80–120 Punkte/s im Schnitt. 200/s
im Durchschnitt über die ganze Runde lässt also Luft, schneidet aber
Fantasiewerte ab. Der Sockel von 2000 deckt kurze Runden mit Glückstreffern ab. Wer
Punktwerte in config.js stark erhöht, muss diese Grenze mit anpassen.
Wie jede Prüfung im Backend verhindert das kein gezieltes Cheaten (die Spiellogik
läuft im Browser). Für Ausreißer gibt es die Moderationsbefehle (siehe
docs/DEPLOYMENT_CPANEL.md).
Schwierigkeit
Ein Testbot (perfektes Zielen, weicht nur zurück, ohne Rolle, Orbital-Befehle und Nachschub) erreicht Welle 5 nach etwa 2 Minuten. Die erste Elite-Welle mit Brutmutter ist bewusst die erste echte Hürde. Wer Rolle, Orbitalschlag und Nachschub nutzt, kommt deutlich weiter. Stellschrauben, wenn das Spiel zu schwer oder zu leicht wirkt:
WAVES.budgetGrowth/budgetExponent: Größe der WellenWAVES.hpScalePerWave: Zähigkeit in späten WellenPLAYER.waveClearHeal,ORBITAL.commands[supply].heal: HeilungENEMY_TYPES.*.contactDamage/attack.damage: Schaden der Gegner
Rückmeldung (Feedback)
- Trefferblitz (weiß), Funken in Fraktionsfarbe, Punkte als schwebender Text
- neue Multiplikatorstufe als „SERIE ×2“ über dem Präsidenten
- Explosionen mit Feuer, Rauch, Lichtblitz, Brandspur und Wirkungsring (zeigt den Radius)
- Bildschirmwackeln bei Treffern und Explosionen, rote Vignette bei Schaden, pulsierender Rand unter 30 % Leben
- Ausweichrolle mit Nachbild
- Randpfeile für Gegner außerhalb des Bildes (Eliten in Gold)
- Ton: Kenney-Klänge mit leichter Tonhöhenstreuung, synthetischer Ersatz, Marschmusik (in der Pause gedämpft), Jingles für Wellenstart, Wellenende, Elite-Alarm und Game Over