Files
Habegger_loader_game/docs/ANALYSE.md
T

6.9 KiB
Raw Blame History

Analyse Altstand (01.11.2026)

Grundlage: old_version/loader_game.py (656 Zeilen), old_version/qr_scan.py (188 Zeilen), old_version/qr_scan_old.py (160 Zeilen), old_version/case_sequences.txt (6 Sequenzen).

1. Wie der Altstand funktioniert hat

qr_scan.py  ──►  last_user.txt  ──►  subprocess: python loader_game.py
   │                                        │
   └ Kamera + pyzbar + HTTP-API             └ pygame-Spiel, ein Durchgang, dann sys.exit()
  • qr_scan.py: öffnet die Webcam, liest QR-Codes, fragt eine externe API (hag.putschgi.ch/.../qr.php?action=verify_hash) nach Gültigkeit und Name, schreibt mail/name in last_user.txt und startet das Spiel als Unterprozess. Danach wieder Scanner – so kam der nächste Spieler dran.
  • loader_game.py: ein Durchgang. Ein Koffer läuft von rechts ein; der Spieler kann ihn an die Barriere snappen (Space/A), drehen (←/X) oder auf einen anderen Koffer stapeln (↑/Y). Kollidiert er ungebremst, wird er mit einer Lücke eingereiht. Ist die Barriere hinter dem Heck, ist Schluss. Punktzahl = belegte Fläche im Auflieger, wird per curl an submit_points.php geschickt.
  • case_sequences.txt: 6 Koffersequenzen, Zeilen breite,höhe,rotiert, Sequenzen durch Leerzeilen getrennt. Das Spiel zieht sich zufällig eine.

2. Gefundene Fehler und Risiken

# Fund Wirkung Status im Neustand
1 Secrets im Quellcode: API_SECRET = "ddlK…" in qr_scan.py, api_key=hag-trailer-8051 in loader_game.py Zugangsdaten liegen in der Git-Historie entfernt; Endpunkt + Schlüssel nur noch per HAG_SCORE_URL / HAG_SCORE_API_KEY aus der Umgebung → alte Schlüssel rotieren
2 pygame.event.set_grab(True) Maus/Tastatur werden gefangen; auf macOS unangenehm, Esc kommt nicht mehr durch entfernt
3 Feste 1920×1080-Vollbildannahme MacBook (Retina/1440×900) → Fenster grösser als der Bildschirm virtuelle Auflösung + pygame.SCALED, Fenster/--fullscreen, F11
4 Windows-Annahmen: subprocess.run(["python", …]), pygetwindow/pyautogui, python.exe in der Install-Doku läuft so nicht auf macOS kein Subprozess mehr, Scanner gestrichen
5 Doppelte Drehlogik: Case.rotated und getauschte Masse; draw() skaliert bei rotated auf (height, width) und dreht zusätzlich um 90° verzerrte/falsch gedrehte Koffer, schwer nachvollziehbar nur noch units_w/units_h; Grafik wird einmalig passend erzeugt
6 Zufällige Zusatzdrehung in Case.__init__ (random.choice([True, False])) die „Next"-Vorschau zeigt etwas anderes als der Koffer, der wirklich kommt Zufallsdrehung entfernt, Vorschau stimmt jetzt
7 can_place_on_top() und animate_place_on_top() prüfen unterschiedliche Regeln (Barriere-Ausrichtung fehlt in der Animation) „OnTop möglich!" wird angekündigt, dann landet der Koffer woanders oder gar nicht eine einzige Regel: Trailer.find_platform()
8 Zwei verschiedene Fehlschlag-Pfade (fail_snap einmal mit sound_place, einmal mit sound_fail) inkonsistentes Feedback, verwirrende Punktevergabe ein Pfad (_stack_with_gap), definierter Sound + Shake
9 Blockierende Animationsschleifen (for + pygame.time.delay mitten im Event-Loop) Events stauen sich, keine dt-Basis, Ruckler; 120-fps-Ziel war so nicht erreichbar Animationen laufen über elapsed/duration im Update, 60 fps
10 Case.move() startet den Roll-Sound und kehrt zurück; Sound hängt an Channel(1) erster Frame ohne Bewegung; Kanal-Kollisionen mit anderen Sounds Roll-Sound beim Spawn, Stopp beim Platzieren, eigener Kanal
11 Blankes except: an 6 Stellen (Bilder, Sequenzen, Punkte-Upload) Fehler bleiben unsichtbar, z. B. Tippfehler in case_sequences.txt fallen still auf die Notfall-Sequenz zurück gezielte Exceptions + Warnungen beim Start
12 last_user.txt wird mit utf-8-sig geschrieben und mit utf-8 gelesen BOM landet im Spielernamen; Datei liegt im Programmordner runtime/last_player.json, Ordner ist in .gitignore
13 calculate_load_percent() summiert die Fläche aller Koffer, auch der aufgesetzten Beladung ist „gefühlt" zu hoch; min(100, …) verdeckt das nur bewusst beibehalten (Spielbalance), aber dokumentiert und getestet
14 Toter/doppelter Code: global current_case zweimal in draw_game, can_use_on_top in spawn_case, transition_counter, state/PLAYING, entry_angle (immer 0), frame_color, game_started unnötige Verwirrung entfernt
15 Kein Neustart möglich: Spiel endet mit sys.exit() jeder Spieler braucht einen neuen Prozess (Aufgabe des Scanners) Spiel ist eine Klasse; Aufrufer entscheidet (Neustart/Beenden)
16 cap = cv2.VideoCapture(0) in der Endlosschleife, cv2.namedWindow() pro Frame Kamerahandle-Leak, Flackern mit dem QR-Scanner entfallen (pyzbar/opencv nicht mehr nötig)
17 Keine requirements.txt, kein venv, Installation nur als Windows-Befehlskette auf dem Mac nicht reproduzierbar requirements.txt + run.sh (venv + Auto-Install)
18 Spieler kam nur über die API, ohne Server kein Spielstart Abhängigkeit von einem fremden Server Name kommt künftig vom Controller (Schritt 2)

3. Was der Neustand anders macht

  • Struktur statt Monolith: main.py + Paket loader_game/ mit je einem Modul pro Aufgabe (siehe loader_game/__init__.py).
  • Logik ohne pygame: case.py, trailer.py, sequences.py lassen sich ohne Fenster testen (35 Tests).
  • Zeitbasiert: alles rechnet in Sekunden (dt), nicht in Frames.
  • Eine Wahrheit für Regeln: Stapelregeln leben ausschliesslich in Trailer, Zeichnen ausschliesslich in scene.py.
  • Konfiguration an einer Stelle: config.py (Masse, Tempi, Farben, Texte).
  • Eingabe abstrahiert: input_map.py bildet Tastatur und Controller auf Action.PRIMARY/LEFT/RIGHT/UP/DOWN/BACK ab – die Basis für die Controller-Namenseingabe.
  • Nur noch eine Abhängigkeit: pygame (kein numpy, kein opencv, kein pyzbar, kein requests, kein pyautogui).

4. Bewusst nicht geändert

  • Spielmechanik und Balance (Tempo 720/240 px/s entspricht den alten 6/2 px pro Frame bei 120 fps; Snap-Schwelle, Lücken-Logik, Beladungsformel).
  • case_sequences.txt (Datenbestand bleibt unverändert).
  • Grafiken, Sounds, Fonts.
  • Der Punkte-Upload existiert weiter, ist aber ohne konfigurierten Endpunkt stumm geschaltet.

5. Offene Punkte (nächste Schritte)

  1. Controller-Namenseingabe: Buchstabe für Buchstabe per D-Pad/Stick, alternative Eingabe über die Tastatur. Ersetzt last_user.txt/QR-Scanner.
  2. Mehrere Durchgänge ohne Prozess-Neustart (Rückkehr zur Namenseingabe statt Beenden).
  3. Entscheiden, ob der Punkte-Upload wieder aktiv genutzt wird – und wohin.
  4. images/*.png haben ein defektes sRGB-Profil (libpng-Warnung beim Laden, rein kosmetisch).