Road to 1.0.0
# Roadmap: Abyss Empire – Der Schrecken der Tiefe
Phasenplan vom bestehenden Kotlin-Gerüst (SurfaceView-Game-Loop) bis zum
fertigen Aufbauspiel. Jeder Meilenstein hat ein klares Abnahme-Kriterium:
Erst wenn "Fertig wenn" erfüllt ist, geht es zur nächsten Phase.
**Test-Halbmeilenstein:** Nach jedem Meilenstein Mn folgt ein halber
Meilenstein Mn.5 mit den Unit-Tests fuer die Features von Mn. Das Bestehen
dieser Tests ist Voraussetzung fuer den Start des naechsten Meilensteins
(M1.5 gruen -> M2 beginnt erst dann; M2.5 gruen -> M3; usw.).
## Status-Legende
- [ ] offen · [~] in Arbeit · [x] abgeschlossen
---
## M0 – Projektgerüst (abgeschlossen)
- [x] Gradle/AGP-Build, Repo auf GitHub, Game-Loop (~60 FPS)
- [x] GameState, GameObject-Basis, InputController, Demo-Spiellogik
**Fertig wenn:** App laeuft, Commit auf GitHub. (erfuellt)
---
## M1 – Fundament Aufbau-Loop: Ressourcen & Kernschleife
Das Spiel wird vom Action-Demo zum Aufbauspiel umgebaut. Kern ist der
passive Ressourcen-Loop, alles Spätere baut darauf auf.
- [x] GameState erweitern: MENU, PLAYING (Bau-Modus), GAME_OVER beibehalten
- [x] `ResourceInventory` (Dataclass) in Game.kt: Korallen, Biomasse (zunaechst nur diese zwei)
- [x] Start-Korallenriff (Stufe 1): produziert passiv Korallen pro Sekunde
- [x] Fischschwaerme als GameObject: spawnen am Riff, Rudel jagt sie fuer Biomasse
- [x] HUD: Ressourcen-Anzeige oben, laufend
- [x] Persistenz: Spielstand in `SharedPreferences` speichern/laden (Ressourcen, Riff-Stufe)
- [x] Game-Klasse refactoren: saubere Trennung update/draw, keine Logik im View
**Fertig wenn:** App 5 Minuten im Hintergrund/offen sein kann, Ressourcen
produziert werden, Spielstand uebersteht einen App-Neustart.
Status: Abgenommen auf dem Emulator (05/2026er Stand, Android-API 36).
5-Min-Soak ohne Crash/ANR, Korallen-Produktion exakt 1/s, Jagd liefert
Biomasse, Pause-Save und Kaltstart mit "Weiterspielen" verifiziert
(Spielstand via SharedPreferences geprueft).
---
## M1.5 – Unit-Tests M1 (abgeschlossen)
Voraussetzung fuer M2: Diese Tests muessen komplett gruen sein.
- [x] Test-Rig: JUnit4 + org.json (testImplementation), InMemorySaveStore, lazy Paint fuer pure-JVM-Logik
- [x] Game-Kernschleife: Produktionsrate, Spawn-Intervall, Spawn-Cap, Jagd, States
- [x] Persistenz: Autosave, Save/Load-Roundtrip, Riff-Stufe, korrupter Spielstand
- [x] Entities: CoralReef-Produktion (St. 1/2/3), FishSchool (Spawn-Ring, Bounce, Ruecksteuerung)
- [x] Grundlagen: Vector2, InputController, ResourceInventory
**Fertig wenn:** `./gradlew testDebugUnitTest` komplett gruen.
Status: 34 Tests, 0 Fehler - bestanden. M2 freigegeben.
---
## M2 – Bauwesen: Gebäude, Baumenü, Upgrade-Stufen (abgeschlossen)
- [x] `Building`-Basisklasse (erbt GameObject): Stufe, Kosten, Produktion, Radius
- [x] Baumenü-UI: einfaches Panel (Bau-Knöpfe am unteren Rand), Touch-Auswahl
- [x] Platzierung: Bau-Ghost folgt Finger, validieren gegenOverlap/Revier-Grenzen
- [x] Fressgrund St.1 (automatische Biomasse) + St.2 Blutrausch-Becken
- [x] Hammerhai-Gilde St.1 (Kalkstein-Abbau) + St.2 Druckluft-Höhle
- [x] Upgrade-Logik: bestehendes Gebäude antippen -> Stufe hochziehen gegen Kosten
- [x] Korallenriff St.2 (Nistplaetze, schnellere Fisch-Spawns) und St.3 (Prachtriff, doppelter Ausstoss)
- [x] Persistenz erweitern: alle Gebäude + Stufen speichern (Save v2)
**Fertig wenn:** Alle 4 Gebaeudetypen baubar, auf Stufe 2-3 upgradbar,
Neustart ueberlebt; Produktion stimmt mit Konzept-Tabelle ueberein.
Status: Abgenommen auf dem Emulator (Landschaft, 2400x1080). Bauen, Platzierung,
Upgrade auf St.2, Kalkstein-Produktion und Kaltstart mit geladenen Gebaeuden
verifiziert (Spielstand via SharedPreferences geprueft). Tiefsee-Spalte folgt
in M3 (dort als 4. platzierbarer Typ), Riff-St.2/3 per Tap upgradbar.
---
## M2.5 – Unit-Tests M2 (abgeschlossen)
Voraussetzung fuer M3: Diese Tests muessen komplett gruen sein.
- [x] Building-Basisklasse: Kosten pruefen/abziehen, Max-Stufe, Upgrade-Regeln
- [x] Platzierung: Ghost-Validierung (Overlap gegen Riff/Gebaeude, Revier-Grenzen)
- [x] Produktion aller Gebaeudetypen und Stufen gegen Konzept-Tabelle
- [x] Persistenz: Gebaeude-Liste + Stufen Roundtrip, Autosave-Erweiterung
**Fertig wenn:** `./gradlew testDebugUnitTest` komplett gruen.
Status: 64 Tests gesamt (30 neu), 0 Fehler - bestanden. M3 freigegeben.
Enthaelt einen auf dem Emulator gefundenen und per Regressionstest gesicherten
Fix: Bau-Feedback-Text zog die Gebäude-Position mit (geteilte Vector2-Instanz).
---
## M3 – Hai-Rudel: Arten, Spezialisten, Spezialressourcen (abgeschlossen)
- [x] `Shark`-Entity mit Rolle: Standardjaeger (Player mit SharkType.STANDARD, gesteuert)
- [x] Hammerhai: arbeitet in Gilde, beschleunigt Kalkstein-Abbau (+50% pro Hammerhai)
- [x] Weisser Hai: Kampf-Staerke fuer M4 (Rudel-Kampfkraft im HUD, wirksam ab M4)
- [x] Tiefsee-Spalte St.1: produziert Biolumineszenz
- [x] Tiefseehai: erschliesst Biolumineszenz-Quellen (+50% Spalten-Ertrag pro Tiefseehai)
- [x] Wracks als Sonder-Fundstellen: Schiffs-Wrackteile (2-3 pro Wrack, Spawn alle 60 s, max 2)
- [x] Biomasse als Nahrungs-Drain: Rudel verbraucht pro Minute Biomasse (6/Hai/Min, stoppt bei 0)
- [x] Freischalt-Kosten: neue Hai-Arten gegen Ressourcen kaufen (Rudel-Menue links)
**Fertig wenn:** 4 Hai-Arten spielbar/kaufbar, alle 5 Ressourcen des Konzepts
fliessen im Loop, Wrackteile sind erhaltbar.
Status: Abgenommen auf dem Emulator. Standardjaeger spielbar, Hammerhai live
gekauft (Gilde-Bonus wirksam), Gilde + Tiefsee-Spalte gebaut, Biolumineszenz-
Rate exakt 0.4/s, 2 Wracks per Schwimm-Bahnen eingesammelt (5 Wrackteile),
Kaltstart laedt Rudel + alle 5 Ressourcen. Weisser Hai/Tiefseehai kaufbar
ueber identische Kauflogik (unit-getestet).
---
## M3.5 – Unit-Tests M3 (abgeschlossen)
Voraussetzung fuer M4: Diese Tests muessen komplett gruen sein.
- [x] Hai-Rollen: Hammerhai-Abbau-Bonus, Tiefseehai-Quellen-Erschliessung
- [x] Biomasse-Drain: Verbrauch pro Minute, Rudel-Grenzen (Clamp bei 0)
- [x] Wrack-Fundstellen: Wrackteile-Erhalt als seltene Resource
- [x] Kauflogik: Freischalt-Kosten, Abzug, Ablehnung bei zu wenig Ressourcen
- [x] Persistenz: Hai-Arten + Ressourcen aller 5 Typen Roundtrip
**Fertig wenn:** `./gradlew testDebugUnitTest` komplett gruen.
Status: 87 Tests gesamt (23 neu), 0 Fehler - bestanden. M4 freigegeben.
Enthaelt Fix: Rudel-Laden zaehlte den Standardjaeger doppelt (fresh + Save)
und alte Saves ohne sharks-Feld lieferten ein leeres Rudel - beides
per Test gesichert.
---
## M4 – Revierkämpfe: Verteidigung & Alpha-Raubtiere (abgeschlossen)
- [x] Combat-System: simple Werte (Staerke, Tempo, Panzerung) statt Action-Steuerung
- [x] Nahbereichs-Abwehr Prachtriff (St.3) greift Angreifer an (5 DPS im 200-px-Radius)
- [x] Angreifer-Wellen: verfeindete Meeresbewohner greifen periodisch an (alle 90 s, skalierend)
- [x] Alpha-Raubtier-Bosse: Riesenkrake (jede 3. Welle, 150 HP, Tentakel-Burst x3 alle 6 s)
- [x] Blutrausch-Mechanik: nach Sieg kurze Produktions-/Kampf-Boni (15 s, Faktor 2)
- [x] Game Over bei zerstoertem Korallenriff, Neustart-Runde mit Teil-Ressourcen (50%)
**Fertig wenn:** Eine Angriffswelle und ein Alpha-Kampf komplett spielbar
sind, Verteidigung durch Gebaeude/Stufen den Ausgang beeinflussen.
Status: Abgenommen auf dem Emulator (per Game-Logger in Logcat verfolgt):
Welle 1 spawnt, Riff-Schaden exakt nach DPS-Rate, Game Over bei Riff-Tod,
Neustart-Runde mit exakt halbierten Ressourcen, Riff voll geheilt, Welle
zurueckgesetzt. Krake/Blutrausch/Prachtriff-Abwehr deterministisch per
Unit-Tests verifiziert. Kampfkraft des Rudels (Weisser Hai) ist jetzt
combat-wirksam. Riff-Stufen geben +50 HP und St.3 Abwehr - Gebaeude/
Stufen beeinflussen den Ausgang.
---
## M4.5 – Unit-Tests M4 (abgeschlossen)
Voraussetzung fuer M5: Diese Tests muessen komplett gruen sein.
- [x] Combat-Werte: Staerke/Tempo/Panzerung-Berechnung, Prachtriff-Nahbereichs-Abwehr
- [x] Angriffswellen: Spawn-Timing, Wellenstaerke-Skalierung
- [x] Alpha-Boss: HP, Sieg-/Niederlage-Pfade, Blutrausch-Boni
- [x] Game Over bei Riff-Zerstoerung, Neustart mit Teil-Ressourcen
- [x] Persistenz: laufende Kaempfe/Wellen minim (oder Save-Punkt davor)
**Fertig wenn:** `./gradlew testDebugUnitTest` komplett gruen.
Status: 106 Tests gesamt (19 neu), 0 Fehler - bestanden. M5 freigegeben.
Tests fanden zwei echte Bugs (je per Regressionstest gesichert):
1. ConcurrentModificationException: Riff-Tod leerte die Angreifer-Liste
waehrend der Iteration -> Iteration ueber Snapshot.
2. Riff-Regeneration heilte 0,5 HP ins zerstörte Riff im Todesframe und
CoralReef ignorierte den Blutrausch-Produktionsmultiplikator.
---
## M5 – Sektoren-Karte: Expansion & Nebel (abgeschlossen)
- [x] Sektoren-Datenmodell: Grid aus Zonen, jede mit Ressourcen-Mix, Nebel-Status (3x3)
- [x] Karten-Screen (neue Szene): panning, Nebel verdeckt unerforschte Zonen (MapScene, eigene Klasse)
- [x] Heimatszektor + angrenzende Sektoren erobern (Eroberung ueber das M4-Kampfsystem, oeffnet Zone + Nebel)
- [x] Gebaeude pro Sektor platzierbar, grenzuebergreifende Produktion (Karten-Bau-Buttons + Sektor-Trickle)
- [x] Szenen-Management refactoren: Game-Szene vs. Karten-Szene (Scene-Enum, MapScene-Klasse, Input-Routing)
**Fertig wenn:** Mindestens 3 Sektoren eroberbar und nutzbar, Nebel hebelt
sich korrekt auf, Karte bleibt ueber Neustarts erhalten.
Status: Abgenommen auf dem Emulator (per Game-Logger verfolgt): Eroberung
von Sektor (1,0) im Live-Kampf besiegt ("Nebel der Nachbarn hebt sich"),
Fressgrund im eroberten Sektor gebaut, Trickle (Biolumineszenz) laeuft,
Kaltstart laedt die komplette Karte inkl. Nebel-Zustaenden. Zusaetzlich
live: Riesenkrake besiegt (Wellen-Sieg + Blutrausch). Angriffbar sind die
4 Nachbarn; jede Eroberung oeffnet neue Zonen - alle 8 Sektoren eroberbar
(unit-getestet). Emulator-Hinweis: ein "Too many open files" im
SurfaceFlinger-Fence (Dauerbetrieb, keine App-Exception) verlangte einen
App-Neustart; danach korrektes Verhalten.
---
## M5.5 – Unit-Tests M5 (abgeschlossen)
Voraussetzung fuer M6: Diese Tests muessen komplett gruen sein.
- [x] Sektoren-Datenmodell: Nachbarschaften, Nebel-Status, Alpha-Besetzung
- [x] Eroberungs-Logik: Alpha vertreiben oeffnet Zone, Nebel-Aufhebung
- [x] Grenzuebergreifende Produktion korrekt zugewiesen
- [x] Persistenz: Sektoren-Karte + Nebel-Zustaende Roundtrip
**Fertig wenn:** `./gradlew testDebugUnitTest` komplett gruen.
Status: 130 Tests gesamt (24 neu), 0 Fehler - bestanden. M6 freigegeben.
Tests fanden einen echten Bug: MapScene.resize fehlte in Game.resize
(leere Button-Rechtecke) - per Test gesichert.
---
## M5.75 – Performance-Check (abgeschlossen)
Empfehlung: vor M6 umsetzen - M6 bringt weitere laufende Systeme (XP,
Instinkt-Boni) in den Update-Pfad, mit sauberer Basis ist deren Kosten
messbar. Kein harter Gate.
Analyse des Stands M1-M5 (Code-Verifizierung per Grep, 130 Tests gruen):
- [x] UI-Strings im Render-Pfad: ~30 String-Interpolationen pro Frame
(drawHud ~11x, BuildMenu/SharkMenu Kostentexte je Button - inkl.
shortText mit List-Build + join) -> rund 1.500-2.000 String-
Allokationen/s bei 60 FPS. Fix: Strings cachen und nur bei
Wert-Aenderung neu bauen; Kosten-Texte sind Konfig-Konstanten
und koennen einmalig vorberechnet werden.
- [x] Vector2-Allokationen im Update-Pfad: Player (normalize/*, ~3/Frame),
FishSchool (toReef je Schwarm, bis 8), Attacker (toReef je Angreifer),
Ghost bei onMove -> geschaetzt 30-50 Objekte/Frame (~2.000-3.000/s).
Fix: In-Place-Mathe (Mutieren der Felder statt Operator-Ergebnisse)
bzw. wiederverwendbare Temporaries.
- [x] Renderer: lockCanvas (Software-Puffer, Full-Buffer-Copy je Frame)
-> lockHardwareCanvas ab API 26 (minSdk bleibt 24, Fallback unten).
Post laeuft weiterhin ueber unlockCanvasAndPost (unlockHardware-
CanvasAndPost existiert nur an android.view.Surface, nicht am
SurfaceHolder).
- [x] GameView.run: `continue` bei invalider Surface ohne Sleep ->
Busy-Spin mit vollem Kern. Fix: Thread.yield.
- [x] Game.update: _attackers.toList()-Snapshot pro Frame (allokiert auch
bei leerer Liste) -> Guard isNotEmpty.
- [x] Mikro: CoralReef-Nub-Winkel (cos/sin je Frame) vorberechnet;
MapScreen-Caching bleibt offen fuer M7-Bewertung (statischer Aufbau).
- [x] Messbasis: Perf-Log in GameView (5-s-Fenster: avg/max Arbeit pro
Frame + Budget-UEberschreitungen), sichtbar via logcat -s GameView.
**Fertig wenn:** 5-Min-Soak auf dem Emulator mit stabilen ~60 FPS ohne
sichtbare GC-Ruckler; Allokationsrate im Render-/Update-Pfad messbar
reduziert (vorher/nachher dokumentiert); alle 130 Unit-Tests weiter gruen.
Status: Abgenommen - 3-Min-Soak je Variante (gleiche Bedingungen, Welle 1
im Fenster), 130 Tests gruen, Verhalten unveraendert:
VORHER: avg 9,3-9,5 ms Arbeit/Frame, Spikes 19-39 ms,
2-10 Frames/5 s ueber 16,7-ms-Budget (1-3,5 %).
NACHHER: avg 0,6-0,8 ms Arbeit/Frame (-92 %), Spikes 3-13 ms,
overBudget 0 (einziges Wave-Spawn-Fenster: 2).
Hauptgewinn: Hardware-Canvas (vorher CPU-Rendering + Full-Puffer-Kopie);
zusaetzlich String-/Vector2-Allokations-Caches. Der 91-ms-Ausreisser im
ersten Messfenster ist der Rundenstart (Welt-Aufbau/erster Draw).
---
## M6 – Instinkte: Tech-Baum, XP, Mutationen (abgeschlossen)
- [x] XP-System: Kaempfe + Ausbau geben Erfahrung (Kill = Gegner-HP, Bau = 10, Upgrade = 10 x Stufe, Eroberung = 50)
- [x] Instinkt-Baum (passive Boni): Schwarm-Tempo, Korallen-Wachstum, Jagd-Effizienz (4 Basis-Instinkte + 4 fortgeschrittene mit Voraussetzung)
- [x] Tiefsee-Spalte St.2: Mutationen freischalten (Bio-Panzerung x1.25 Kampfkraft, Tarnung x0.75 Angreifer-Tempo; 120 Korallen + 20 Biolum)
- [x] Balance-Pass: Kostenkurve 100/200/300 XP je Punkt (streng monoton); 10 Instinkte = 18 Punkte = 6.660 XP ≈ 30-60 min Progression; erste ~3-4 min bis Punkt 1 (Abnahme "30-Min-Session sinnvoll")
**Fertig wenn:** Mindestens 8 Instinkte freischaltbar, eine 30-Minuten-Session
fuehlt sich progressionstechnisch sinnvoll an.
Status: 10 freischaltbare Eintraege (8 Instinkte + 2 Mutationen). Abgenommen
auf dem Emulator: XP aus Wellen-Kampf live gesammelt (Wellen-Sieg +
Blutrausch), XP aus Bauen/Upgraden, 1. Instinkt-Punkt nach ~5 min,
Instinkt-Szene geoeffnet, SCHWARM_TEMPO live freigeschaltet (Logcat +
Save v6), Kaltstart haelt den Instinkt. Trench St.2 + Mutationen
deterministisch per Unit-Tests verifiziert.
---
## M6.5 – Unit-Tests M6 (abgeschlossen)
Voraussetzung fuer M7: Diese Tests muessen komplett gruen sein.
- [x] XP-Vergabe aus Kaempfen und Ausbau
- [x] Instinkt-Baum: Freischalt-Regeln, Boni-Wirkung auf Produktions-/Kampfwerte
- [x] Mutationen (Bio-Panzerung, Tarnung) und ihre Werteaenderungen
- [x] Balance-Invarianten (z. B. Kostenkurven monoton, Boni kumulativ korrekt)
**Fertig wenn:** `./gradlew testDebugUnitTest` komplett gruen.
Status: 160 Tests gesamt (30 neu), 0 Fehler - bestanden. M7 freigegeben.
Enthaelt Invarianten-Tests: Kostenkurve streng monoton, Instinkt-Kosten
nicht fallend (Basis <= Fortgeschrittene <= Mutationen), alle Faktoren
neutral ohne Instinkt, jedes Element freischaltbar.
---
## M7 – Polierung & Release (abgeschlossen)
- [x] Sprites: vorgerenderte Bitmap-Sprites statt Kreis-Primitive (SpriteCache; programmatische Silhouetten: Hai m. Rotation Richtung Bewegung, Fisch, Angreifer, Krake - keine Asset-Dateien noetig)
- [x] Sound: SoundPool mit synthetisch generierten WAVs (Jagd/Bau/Kampf/UI/Blutrausch/Eroberung/Instinkt, zur Laufzeit in cacheDir erzeugt - pure-JVM-WAV-Generator ohne Binär-Assets), Ambient-Musik-Loop via MediaPlayer (8-s-Pad, loopt)
- [x] Juice: Partikel-System (Fressen, Kills, Bau, Wracks, Blutrausch, Instinkt), Screen-Shake bei Boss-Burst + Game Over, Bau-/Upgrade-Feedbackpartikel
- [x] Tutorial/Onboarding: 4 Schritt-Hinweise (Bewegen -> Jagen -> Bauen -> Wellen-Warnung), abschaltbar nach Welle 1, Bestands-Spiener ab Save v6 ueberspringen (Save v7)
- [x] Release-Build: signiert (lokaler RSA-2048-Keystore, nicht committet), Minify+ShrinkResources, 61 KB APK (vorher 870 KB debug), Version 1.0.0, mapping.txt erzeugt
- [ ] Play-Store-Vorbereitung (Store-Eintrag, Screenshots) - bewusst offen, optional
**Fertig wenn:** Signierter Release-Build laeuft stabil auf einem Geraet,
Absturz-frei ueber 30 Minuten Spielzeit.
Status: Abgenommen auf dem Emulator (Release-Build, API 36): 30-Min-Soak
mit 0 FATAL / 0 ANR, PID durchgehend konstant, 18 Spielereignisse (Wellen,
Game Over, Neustart) ohne Absturz. Perf im Soak: avg 1,36 ms Arbeit/Frame,
Regelbetrieb 0,5-0,7 ms (worst Fenster 14,7 ms = Welt-Reset-Ereignisse).
ProGuard/R8: keine Missing-class-Warnings, keine Reflection im Save-Pfad,
alle 174 Unit-Tests laufen gegen identischen Code-Pfad.
---
## M7.5 – Release-Regression (abgeschlossen)
Voraussetzung fuer den Release: Suite komplett gruen.
- [x] Gesamt-Regression: alle Unit-Tests nach Sprite-/Sound-/Release-Umbau gruen
- [x] Minify/ProGuard: Save/Load (JSON) und Reflection-Pfade nach Shrinking geprueft
- [x] Signierter Release-Build laeuft die 30-Min-Abnahme ohne Speicher-Fehler
**Fertig wenn:** `./gradlew testDebugUnitTest` gruen und Release-Build abgenommen.
Status: 174 Tests gesamt (14 neu: WAV-Generator, Partikel/Shake, Tutorial),
0 Fehler. Release-APK auf dem Emulator installiert und 30 Minuten
absturzfrei gelaufen (siehe M7). Hinweis: run-as ist auf Release-APKs
erwartungsgemaess nicht verfuegbar (nicht debuggable) - Save/Load ist
per Unit-Tests gegen denselben Code-Pfad verifiziert.
---
## Querschnitts-Aufgaben (immer wiederkehrend)
- Nach jedem Meilenstein: `git commit` + Push, APK auf Geraet testen
- Nach jedem Meilenstein Mn: Halbmeilenstein Mn.5 (Unit-Tests) abschliessen, bevor Mn+1 startet
- Balancing-Zahlen zentral in einer `GameConfig`-Klasse sammeln (keine Magic Numbers)
- Save-Format versionieren (Migrationsfeld in SharedPreferences/JSON)
## Grobe Groessenordnung
| Phase | Aufwand (fokusierte Sessions) |
|--------|-------------------------------|
| M1 | 2-3 |
| M1.5 | 1 |
| M2 | 3-4 |
| M2.5 | 1 |
| M3 | 3-4 |
| M3.5 | 1 |
| M4 | 2-3 |
| M4.5 | 1 |
| M5 | 3-4 |
| M5.5 | 1 |
| M5.75 | 1 |
| M6 | 2 |
| M6.5 | 1 |
| M7 | 3-4 |
| M7.5 | 1 |
