From 1d82aed1c4ab81a4344555a0dd3c5dc078c14879 Mon Sep 17 00:00:00 2001 From: Niklas Haiden Date: Tue, 16 Jun 2026 21:16:12 +0200 Subject: [PATCH] add documentation file --- Documentation.md | 217 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 Documentation.md diff --git a/Documentation.md b/Documentation.md new file mode 100644 index 0000000..ee8f9db --- /dev/null +++ b/Documentation.md @@ -0,0 +1,217 @@ +# Silent FH - Projektdokumentation + +
+ +```text + SSSSS III L EEEEE N N TTTTT FFFFF H H + S I L E NN N T F H H + SSSSS I L EEEE N N N T FFFF HHHHH + S I L E N NN T F H H + SSSSS III LLLLL EEEEE N N T F H H +``` + +**Study. Survive. Submit your ECTS.** + +
+ +## Inhaltsverzeichnis + +- [Projektübersicht](#projektübersicht) +- [Gruppenmitglieder](#gruppenmitglieder) +- [Repository und Installation](#repository-und-installation) +- [Corporate Identity](#corporate-identity) +- [Kurzbeschreibung](#kurzbeschreibung) +- [Features und technische Lösungen](#features-und-technische-lösungen) +- [Dokumentiertes Bugfixing](#dokumentiertes-bugfixing) +- [Problembeschreibung und Learnings](#problembeschreibung-und-learnings) +- [Hyperlinks und Referenzen](#hyperlinks-und-referenzen) + +## Projektübersicht + +**Silent FH** ist ein 2D Survival-Spiel, in dem eine Studentin oder ein Student über Nacht in der FH Joanneum eingeschlossen ist. Während der Nacht verwandeln sich Professoren in Monster und greifen die Räume an. Ziel ist es, möglichst lange zu überleben, ECTS zu sammeln und am Ende einen hohen Score im Leaderboard zu erreichen. Das Spiel wurde mit der Python Bibliothek PyGame geschrieben und es wurde der Package Manager "uv" benutzt. + +Der Einstieg erfolgt über [`main.py`](main.py). Die zentrale Spielsteuerung liegt in [`src/game.py`](src/game.py). Von dort werden Startscreen, Endscreen, Karte, Player, Monster, Items, Shop, Tower, Sound, HUD und Highscore-System koordiniert. + +## Gruppenmitglieder + +Die Namen und Rollen wurden aus der bestehenden [`README.md`](README.md) übernommen. + +- **Baumgartner Kevin** + - UI + - Startscreen + - Endscreen + - Highscore Display + +- **Berger Lena** + - Sound Effects + - HUD + - ECTS-System + - Türen + - Items: Beer und Coffee + +- **Kammerhofer Lukas** + - Tower + - Map + - Game Design + +- **Haiden Niklas** + - Merge Requests + - Sprites + - Zombies / Monster + - Game Loop Logic, Zusammenführen des Spiels + - Dokumentation + +## Repository und Installation + +Das Projekt liegt im Git-Repository: + +- **Repository:** [`git@git-iit.fh-joanneum.at:swd25-bootcamp/silent-fh.git`](git@git-iit.fh-joanneum.at:swd25-bootcamp/silent-fh.git) +- **Branch-Konzept:** Feature-Branches nach dem Muster `feat/feature-name` +- **Code-Review:** Pull Requests mit Merge-Prozess +- **Commit-Stil:** semantische Commits, z. B. `feat(...)`, `fix(...)`, `docs(...)`, `chore(...)` + +Installation und Start: + +```bash +uv sync +source .venv/bin/activate +uv run main.py +``` + + Die Abhängigkeiten stehen in [`pyproject.toml`](pyproject.toml), welches die Convention für den "uv" Package Manager ist. + +## Corporate Identity + +Silent FH nutzt eine dunkle, leicht unheimliche FH-Nacht-Atmosphäre. Bilder und Audio sind KI generiert. +### Farbwelt + +Die Farben orientieren sich an den Konstanten in [`src/settings.py`](src/settings.py). + +| Einsatz | Farbe | RGB | Wirkung | +| --- | --- | --- | --- | +| Hintergrund / Void | `#0A0A0F` | `(10, 10, 15)` | dunkle Nacht, Gefahr | +| Wände | `#1E1428` | `(30, 20, 40)` | FH-Gebäude, Begrenzung | +| Räume | `#4B2837` | `(75, 40, 55)` | Seminar- und Lernräume | +| Gang | `#23412D` | `(35, 65, 45)` | Fluchtweg, Orientierung | +| Türen | `#285A6E` | `(40, 90, 110)` | Übergang zwischen Raum und Gang | +| Startscreen-Akzent | `#00FF00` | `(0, 255, 0)` | Retro-Game-UI | +| Warnung / Lose | `#FF0000` | `(255, 0, 0)` | Gefahr und Scheitern | + +### Tonalität + +- **Atmosphäre:** dunkel, campusnah, leicht ironisch +- **Sprache:** FH- und Studienbegriffe wie `Matriculate`, `Exmatriculate`, `ECTS`, `Study`, `Coffee` +- **UI-Stil:** klare Buttons, Highscore-Tabelle, HUD mit Statusleisten +- **Game-Fantasy:** Lernen bringt Ressourcen, Kaffee rettet die Tür, Bier steigert die ECTS-Produktion + +## Kurzbeschreibung + +Der Spieler startet am Startscreen, gibt einen Namen oder eine ID ein und beginnt danach eine Survival-Runde. Die Spielfigur bewegt sich mit `WASD` oder den Pfeiltasten durch eine tilebasierte FH-Karte. Die Karte besteht aus Räumen, Gängen, Wänden, Startposition und Türen. In jedem Raum steht ein Tisch. + +Sobald der Spieler an einem Tisch lernt, werden ECTS generiert. Gleichzeitig kann dadurch ein Raum-Encounter aktiviert werden: Die Tür schließt sich, Monster werden wach und bewegen sich im Gang zur passenden Raumtür. Die Monster greifen die geschlossene Tür in Intervallen an. Fällt die Tür-HP auf `0`, ist das Spiel verloren und der Endscreen wird angezeigt. + +Der Spieler kann länger überleben, indem er Items kauft und Ressourcen sinnvoll verwendet. `Coffee` heilt die aktive Tür, `Beer` erhöht die ECTS-Generierung. Nach ausreichend langer Tisch-Interaktion kann ein Tower entstehen, der Projektile auf das Monster schießt und es beschädigt. + +## Features und technische Lösungen + +### Steuerung und Screens + +- `WASD` oder Pfeiltasten: Spielfigur bewegen +- `E`: Item kaufen, wenn der Spieler ein Item berührt und genug ECTS besitzt +- `Space`: Spielerzustand umschalten und Transformationssound abspielen +- `ESC` oder `Q`: Spiel beenden +- `ENTER`: Spiel starten oder neu starten + +Der Startscreen in [`src/startscreen.py`](src/startscreen.py) bietet Namenseingabe, Startbutton, Quitbutton, Validierung und Highscore-Anzeige. Der Endscreen in [`src/endscreen.py`](src/endscreen.py) zeigt Ergebnis, gesammelte ECTS, überlebte Zeit, Restart-Option und Leaderboard. + +### Karte und Räume + +Die Map in [`src/map.py`](src/map.py) wird als Liste von Strings modelliert. Jedes Zeichen steht für einen Tile-Typ: + +- `W`: Wall +- `R`: Room +- `S`: Start +- `H`: Hall +- `D`: Door + +Diese Struktur ist einfach lesbar und gut für PyGame geeignet. Zusätzlich speichert die Map Raumrechtecke für `Room 102`, `Room 103` und `Room 105`. Pro Raum wird automatisch ein Tisch in der Mitte erzeugt. Die Funktion `is_accessible()` legt fest, welche Tiles betreten werden dürfen. + +### Player, Sprites und Monster + +Die Actor-Logik in [`src/actors.py`](src/actors.py) kapselt Position, Blickrichtung, Animation, `good`-/`bad`-Status und Kollisions-Rollback. Sprite-Sets werden automatisch aus Asset-Ordnern geladen und müssen `sprite_01.png` bis `sprite_12.png` enthalten. Die Frames werden nach Bewegungsrichtungen gruppiert. + +Die Monsterlogik in [`src/monster.py`](src/monster.py) spawnt Monster auf Gang-Tiles (`H`). Wenn ein Raum getriggert wird, wechseln die Monster in den angry-Zustand, suchen das Gang-Tile vor der Tür und bewegen sich über eine Breadth-First Search dorthin. Türen (`D`) sind für Monster kein begehbarer Pfad. Dadurch bleiben sie logisch im Gang und greifen nur die Tür an. + +### Türen, ECTS, Items und Tower + +[`src/door.py`](src/door.py) beschreibt Türen mit Position, Größe, HP, `is_closed`, `take_damage()`, `reset()` und `rect`-Property. Die Game-Logik erstellt Türen dynamisch passend zu den `D`-Tiles eines Raums. + +Das ECTS-System in [`src/ects.py`](src/ects.py) ist die zentrale Ressource. ECTS werden nur generiert, wenn der Spieler an einem Tisch steht. Beer erhöht die ECTS-Rate, Shop und Tower können ECTS abziehen. Dadurch entsteht ein Risiko-Nutzen-Verhältnis: Am Tisch verdient man Ressourcen, aktiviert aber auch Gefahr. + +Items werden in [`src/item.py`](src/item.py) verwaltet, Käufe in [`src/shop.py`](src/shop.py). Items spawnen in Räumen, laufen nach einem Timer ab und werden gegen Blocker-Rechtecke geprüft. `Coffee` heilt die aktive Tür um `20` HP, `Beer` erhöht die ECTS-Generierung um `2`. Erfolgreiche und fehlgeschlagene Käufe haben Soundfeedback. + +Der Tower in [`src/tower.py`](src/tower.py) ist eine Verteidigungsmechanik: + +- Spawnkosten: `10` ECTS +- Aktivierung nach `5000 ms` Tischkontakt +- Lebensdauer: `30000 ms` +- Projektilschaden: `2` +- Schussintervall: `1000 ms` + +Der Tower erscheint nur einmal pro Raum-Encounter, schießt auf das Monster und wird beim Raumwechsel zurückgesetzt. + +### HUD, Highscore und Sound + +Das HUD in [`src/hud.py`](src/hud.py) zeigt Spielername, Door HP, Zombie HP, ECTS, ECTS pro Sekunde und Überlebenszeit. Der Highscore in [`src/highscore.py`](src/highscore.py) speichert Ergebnisse in [`src/highscore.json`](src/highscore.json). Sortiert wird nach gewonnenen Runs, höheren ECTS, längerer Überlebenszeit und Name als Tie-Breaker. + +[`src/sounds.py`](src/sounds.py) kapselt Soundeffekte und Hintergrundmusik. Geladen werden u. a. Tower-Schuss, Monster-Hit, Kauf erfolgreich, Kauf fehlgeschlagen, Transformation sowie normale und gruselige Hintergrundmusik. Falls eine Sound-Datei fehlt, stürzt das Spiel nicht ab. + +### Architektur + +Die zentrale Game Loop in [`src/game.py`](src/game.py) arbeitet mit den Zuständen `startscreen`, `game` und `endscreen`. Dadurch bleiben Menü, Gameplay und Ergebnisanzeige getrennt. Mehrere Systeme nutzen `pygame.Rect` für Kollisionen und Blocker-Listen. Zeitabhängige Ereignisse basieren auf `pygame.time.get_ticks()`, z. B. ECTS-Generierung, Item-Spawns, Monster-Angriffe, Tower-Aktivierung, Tower-Lebensdauer und Überlebenszeit. + +## Dokumentiertes Bugfixing + +Die Bugfixes wurden aus Code und Git-Historie abgeleitet. + +| Commit | Problem | Lösung | +| ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dd1773e fix: fix buying logic for shop` | Die Shop-Logik gab bei ausreichendem ECTS-Guthaben fälschlich `False` zurück. | Die Bedingung wurde auf `if not self.ects.is_over_balance(cost): return False` geändert. Danach wird der Betrag abgezogen und `True` zurückgegeben. | +| `a218527 fix: readd missing file` | [`src/ects.py`](src/ects.py) fehlte, wodurch Imports des ECTS-Systems brechen konnten. | Die Datei mit ECTS-Kontostand, Rate, Timer und `upgrade_rate()` wurde wieder hinzugefügt. | +| `810a44c fix: import error` und `ba0bb49 feat: fix endscreen imports` | Imports wie `from settings import ...` passten nicht zur Projektstruktur. | Die Imports wurden auf `from src.settings import ...` und `from src.button import Button` geändert. | +| `8c454ed feat(startscreen): change ui texts from german to english and fix button click event` | Button-Klicks und leere Namenseingaben waren nicht sauber behandelt. | Der Button setzt nun einen internen `clicked`-Status, und der Startscreen validiert leere Namen. | +| `ac1085f bugfixes/troubleshooting` und `164e314 bugfixing` | Im Tower gab es falsche Attributnamen wie `self.field.rect`, einen falschen Methodennamen und eine falsch eingerückte `clear()`-Methode. | Die Attribute wurden auf `field_rect` und `tower_rect` korrigiert, `field_spawn()` wird richtig aufgerufen, `clear()` ist wieder eine Instanzmethode. | +| `80f6868 bugfix` | Beim Fehlerladen des Projektilsprites wurde versehentlich `tower_image` statt `projectile_image` auf `None` gesetzt. | Nur `projectile_image` wird zurückgesetzt, der Tower-Sprite bleibt erhalten. | +| `6fbd750 feat(endscreen): fix position of highscore table in endscreen` | Die Highscore-Tabelle überlagerte Inhalte am Endscreen. | Die Position wurde von `(560, 90)` auf `(800, 300)` verschoben. | +| `5149623 fix highscore implementation and decrease projectile damage` | Highscore-Speicherung und Sortierung waren nicht robust genug. | Scores werden beim Endscreen gespeichert, JSON-Daten geprüft, Zeiten formatiert und Werte über `safe_int()` / `parse_time()` abgesichert. | +| `3fcbd8c refactor: replace static door dimensions with dynamic sizing and add rect property` | Statische Türgrößen waren unflexibel. | Türen werden aus den `D`-Tiles berechnet und stellen eine `rect`-Property bereit. | +| `4faad9d feat: implement encounter reset mechanics for rooms and doors` | Beim Raumwechsel konnten alte Monster-, Tür- oder Tower-Zustände weiterlaufen. | `handle_room_change()` setzt Items, Tower, Tür und Monsterzustand zurück. | +| `bce77b8`, `d2b42c5`, `d6bdf22` | Der Tower musste technisch und spielerisch ausbalanciert werden. | Aktivierungszeit, Lebensdauer, Ablaufverhalten und Projektilschaden wurden angepasst. | + +## Problembeschreibung und Learnings + +Silent FH besteht aus vielen voneinander abhängigen Systemen. Wenn der Spieler am Tisch steht, laufen gleichzeitig ECTS-Generierung, Monster-Encounter-Logik, Tower-Timer, Monsterbewegung und HUD-Updates. Die wichtigste technische Lösung ist deshalb eine zentrale Orchestrierung in [`src/game.py`](src/game.py), während die Einzelsysteme in eigenen Klassen bleiben. + +Eine vollständige Monster-KI wäre für den Projektumfang zu groß gewesen. Stattdessen nutzt das Spiel den BFS Algorithmus um den kürzesten Pfad zum Spieler zu finden. Spawnlogik wurde so gelöst: Items, Monster und Tower prüfen Blocker-Rechtecke, damit sie nicht auf Tischen, Türen oder anderen Objekten erscheinen. + +Balancing hatte mehrere Iterationen erfordert. Viele Werte in [`src/settings.py`](src/settings.py) steuern Gameplay: Monster-HP, Tür-HP, Tower-Schaden, ECTS-Rate, Itemkosten, Spawnintervalle und Angriffsgeschwindigkeit. Die Git Historie zeigt, dass die Werte im Laufe der Entwicklung immer wieder angepasst werden mussten, um das Spiel fair und enjoyable zu machen. + +## Hyperlinks und Referenzen + +### Externe Referenzen + +- [PyGame Dokumentation](https://www.pygame.org/docs/) +- [uv Dokumentation](https://docs.astral.sh/uv/) +- https://docs.aws.amazon.com/neptune-analytics/latest/userguide/bfs-algorithms.html + +### Assets im Projekt + +- `assets/niklas_sprites`: Player-Sprites +- `assets/normal_knoll`, `assets/angry_knoll`: Monster-Sprites +- `assets/normal_krainz`, `assets/angry_krainz`: Monster-Sprites +- `assets/normal_schwab`, `assets/angry_schwab`: Monster-Spritepaar +- `assets/items`: Beer, Coffee, Tower, Book +- `assets/furniture`: Tischgrafik-Sprites +- `assets/sounds`: Soundeffekte und Hintergrundmusik + +Für die korrekte Ausformulierung und Überarbeitung wurde KI (ChatGPT 5.5) verwendet. \ No newline at end of file