App-Doku erstellt, doku aufgeräumt
All checks were successful
Deploy Docs / build-and-deploy (push) Successful in 22s

This commit is contained in:
2026-01-10 10:21:36 +01:00
parent ce4d0d1a44
commit f464fcbf1b
8 changed files with 112 additions and 254 deletions

View File

@@ -0,0 +1,107 @@
# Mobile App
Um das Spiel zu steuern, wird eine mobile App entwickelt. Sie soll anfangs für Android verfügbar sein. Wenn die Hürden nicht zu groß sind, wird auch eine iOS-Version in Betracht gezogen. Dazu wird die Entwicklung in Flutter stattfinden.
## Übersicht
Der grundsätzliche Ablauf sieht so aus:
```mermaid
flowchart TD
start([App-Start])
choose_leader[1. Leader bestimmen]
check_state{Leader-Status?}
lobby[2a. Lobby-Phase]
game[2b. Spiel-Phase]
evaluation[2c. Auswertungs-Phase]
start-->choose_leader
choose_leader-->check_state
check_state-->|Kein Spiel läuft|lobby
check_state-->|Spiel läuft|game
check_state-->|Spiel abgeschlossen|evaluation
lobby-->|Spiel starten|game
game-->|Spiel abbrechen|lobby
game-->|Spielende|evaluation
evaluation-->|Neues Spiel|lobby
classDef phase fill:#eef4ff,stroke:#6c8be0,stroke-width:1px,color:#0d1b2a
class lobby,game,evaluation phase
```
### 1. Leader bestimmen
- Beim Start der App wird geschaut, ob der zuletzt gewählte Game-Leader über BLE erreichbar ist.
- Ist der nicht erreichbar, wird nach allen verfügbaren Leader-Knoten gescannt und zur Auswahl angeboten.
### 2a. Lobby-Phase
In der Lobby-Phase wird das Spiel vorbereitet: Spielmodus wählen, Teams/Spieler zuordnen und Parameter konfigurieren.
#### Thread-Netzwerk & Provisionierung
- Thread-Parameter werden am Leader konfiguriert und über das Thread-Netzwerk an alle verbundenen Geräte verteilt
- Im Hintergrund läuft permanent ein BLE-Scan nach neuen Geräten
- Neu gefundene Geräte werden automatisch mit den Thread-Parametern provisioniert und dem Netzwerk hinzugefügt
#### Geräte-Discovery & Monitoring
- Die App triggert den Leader in regelmäßigen Abständen, eine "Who is there"-Multicast-Abfrage im Thread-Netzwerk auszuführen
- Zurückgemeldete Geräte werden in einer Liste erfasst
- Beim ersten Erscheinen eines Geräts werden dessen Parameter abgerufen: Name, Typ, spezifische Eigenschaften
- Geräte, die sich über einen bestimmten Zeitraum nicht mehr melden, werden ausgegraut
- **Auto-Synchronisation:** Meldet ein Gerät Spieler- oder Team-Zuordnungen (z.B. "Spieler 3, Team 2"), die in der App noch nicht existieren, werden diese automatisch angelegt (z.B. "Spieler 3" und "Team 2"), um Konfigurationskonflikte zu vermeiden
#### Benutzeroberfläche
**Geräteliste:**
- Zeigt alle verfügbaren Geräte an
- Antippen eines Geräts blendet zusätzliche Icons ein:
- **Verbindungsstatus:** Zeigt an, ob das Gerät kürzlich gesehen wurde
- **Zuordnungsstatus:** Ob das Gerät einem Spieler/Team zugeordnet ist
- **Identifikation:** Lässt das Gerät blinken (3x) oder LED atmen zur physischen Identifikation
- **Entfernen:** Nur aktiv bei ausgegrauten Geräten
- **Einstellungen:** Geräteeinstellungen bearbeiten
**Teamliste:**
- Zeigt alle Teams an
- Antippen erweitert die Ansicht mit den zugewiesenen Spielern
**Spielerliste:**
- Zeigt alle Spieler mit Teamzuordnungsstatus an
- Spieler können angelegt, gelöscht und umbenannt werden
#### Spielkonfiguration
- Spielkonfigurationen können gespeichert und später neu geladen werden
- Alle Spielparameter (Dauer, Respawns, etc.) sind hier einstellbar
#### Spielstart-Bedingungen
Das Spiel kann nur gestartet werden, wenn folgende Bedingungen erfüllt sind:
- Alle Westen und Waffen sind zugeordnet
- Jede Weste ist genau einem Spieler zugeordnet (und umgekehrt)
- Der Spielmodus ist gesetzt und konfiguriert
- Alle Basen, Power-Ups etc. sind konfiguriert
- Kein ausgegrautes Gerät ist vorhanden
- Je nach Spielmodus: Alle Spieler sind einem Team zugeordnet
Sind nicht alle Bedingungen erfüllt, werden die Gründe angezeigt.
#### Übergang zur Spiel-Phase
- Beim "Spiel starten" wird eine zufällige Spiel-ID generiert und an den Leader übermittelt
- Die aktuelle Spielkonfiguration wird gespeichert
- Dadurch kann das Spiel auch nach App-Neustart ausgewertet werden
### 2b. Spiel-Phase
- Laufendes Spiel: Status/Timer anzeigen, optional Live-Events (Treffer, Bases) und Admin-Aktionen wie "Spiel abbrechen".
- Spielende erfolgt je nach Modus (Timer, Score, Objective) und wechselt in die Auswertungs-Phase.
- Sollte die App während der Spielphase gestartet werden, wird geprüft, ob die Spiel-ID auf dem gewählten Leader-Knoten mit der gespeicherten ID zusammenpasst. Wenn ja, schaltet sich die App auf das Spiel auf. Wenn nein, meldet die App einen Fehler, dass eine Verbindung aufgrund eines laufenden Spieles nicht möglich ist.
Je nach Spielmodus ist es der App möglich, in das Spielgeschehen einzugreifen (zum Beispiel Power-Ups senden etc.).
### 2c. Auswertungs-Phase
- Geräte auslesen, Scores sammeln, Rangliste erzeugen und anzeigen.
- Optionen: "Neues Spiel" führt zurück in die Lobby; Export/Share der Ergebnisse möglich.
- Sollte die App während der Auswertungsphase gestartet werden, wird geprüft, ob die Spiel-ID auf dem gewählten Leader-Knoten mit der gespeicherten ID zusammenpasst. Wenn ja, schaltet sich die App auf das Spiel auf. Wenn nein, meldet die App einen Fehler, dass die Spiel-ID unbekannt ist und somit eine Auswertung nicht möglich ist.
Eine Auswertung erfolgt erst, wenn alle Geräte, die zur Auswertung erforderlich sind, abgerufen werden konnten. Ist das innerhalb einer bestimmten Zeit nicht möglich, wird dem Benutzer angezeigt, welche fehlen. Er kann dann dafür sorgen, dass diese in Reichweite kommen und die Auswertung abschliessen.

View File

@@ -12,7 +12,7 @@ Kurzer Überblick über das DIY-Lasertag-System auf Basis von nRF52840, Thread u
- Konzept Software: Rolle Leader/Weste/Waffe, Game Loop, CoAP-API.
- Konzept Hardware: Aufbau der Einheiten, LED-Treiber, Akku-Setup.
- Gameplay & Modi: [konzept/gameplay.md](konzept/gameplay.md) Kurz erklärt, Rollen, Power-Ups und Spielmodi.
- Gameplay & Modi: [concepts/gameplay.md](concepts/gameplay.md) Kurz erklärt, Rollen, Power-Ups und Spielmodi.
- Planung: Zephyr-Workspace-Struktur und Roadmap.
**Lizenz**

View File

@@ -1,56 +0,0 @@
# Hardware-Konzept
Dieses Dokument beschreibt die physischen Komponenten des Lasertag-Systems. Alle Knoten basieren auf dem Nordic nRF52840 SoC.
## 1. Waffe (Weapon Unit)
Die Waffe ist das primäre Interaktionsgerät. Sie muss robust und reaktionsschnell sein.
* **Controller:** nRF52840 (Dongle oder Modul).
* **IR-Sender:**
* High-Power IR-LED (940nm oder 850nm).
* Optik/Linse zur Bündelung des Strahls (Reichweite > 50m).
* Transistor-Treiberstufe für hohe Impulsströme.
* **Feedback:**
* **Muzzle Flash:** Helle weiße/gelbe LED an der Mündung (sichtbares Feedback).
* **Haptik:** Vibrationsmotor (aktiv bei Schuss).
* **Audio:** Lautsprecher/Piezo für Schussgeräusche ("Piu Piu") und "Leer"-Klicken.
* **Eingabe:**
* **Abzug (Trigger):** Taster.
* **Nachladen (Reload):** Taster am Magazinschacht oder Boden.
* **Modus-Wahl:** Optionaler Schalter für Feuermodus (Einzel/Auto).
* **Stromversorgung:** 2S LiPo (7.4V) mit Step-Down auf 3.3V.
## 2. Weste (Player Hub)
Die Weste ist die zentrale Recheneinheit des Spielers und trägt die Sensorik.
* **Controller:** nRF52840 DK oder Custom Board.
* **Sensorik (IR-Empfänger):**
* Verteilt auf 3 Gruppen für 360° Abdeckung.
* **Kopf:** 3 Sensoren (Stirn, Links, Rechts) an Stirnband/Helm.
* **Torso:** Sensoren an Brust und Rücken.
* **Schultern:** Optionale Sensoren an den Seiten.
* *Technik:* TSOP4838 oder kompatible 38kHz Empfänger.
* **Beleuchtung (Status):**
* Adressierbare RGB-LEDs (WS2812B) an den Sensor-Positionen.
* Funktion: Teamfarbe anzeigen, Treffer blinken, "Zombie"-Status (Grün).
* **Audio:**
* Leistungsstärkerer Lautsprecher für Sprachausgabe ("Game Over", "Respawn in 10s").
* **Verbindung:**
* Zentrale Box am Rücken mit Steckverbindern zu den Sensorgruppen.
## 3. Leader Box (Game Controller)
Die Leader Box dient zur Spielsteuerung und als Infrastruktur-Knoten.
* **Controller:** nRF52840.
* **Modi (Hardware-Schalter):**
* 2 DIP-Schalter zur Wahl von Leader / Repeater / Base.
* **Ausstattung:**
* **IR-Empfänger:** Um als Ziel (Base) zu fungieren.
* **RGB-LEDs:** Großflächige Anzeige der Base-Farbe (wer hält die Base?).
* **Bluetooth:** Dient als Gateway zum Smartphone des Spielleiters.
* **Stromversorgung:** Großer Akku für lange Laufzeit (da oft stationär ohne Stromnetz).
*Stand: 03.04.2025*

View File

@@ -5,9 +5,10 @@ repo_url: https://gitea.iten.pro/edi/lasertag
nav:
- Übersicht: index.md
- Konzept:
- Hardware: konzept/hardware.md
- Software: konzept/software.md
- Gameplay & Modi: konzept/gameplay.md
- Hardware: concepts/hardware.md
- Software: concepts/software.md
- Gameplay & Modi: concepts/gameplay.md
- Mobile App: concepts/mobile_app.md
- Spezifikationen:
- IR-Protokoll: specifications/ir_protocol.md
- Planung: planung.md

View File

@@ -1,194 +0,0 @@
# Software-Konzept & Spielablauf
Dieses Dokument beschreibt die Software-Architektur, die Rollenverteilung und die Kommunikationsabläufe des Lasertag-Systems.
## 1. System-Rollen & Hardware-Typen
Das System basiert auf nRF52840-Chips, die über OpenThread (802.15.4) kommunizieren.
### A. Leader Box (Game Controller)
* **Funktion:** Zentrale Spielsteuerung, Zeitgeber, Gateway zur Smartphone-App.
* **Modi (wählbar via DIP-Schalter):**
* `00` **Leader:** Spielleiter, BLE-Gateway, sammelt Punkte.
* `01` **Repeater:** Router im Mesh zur Reichweitenverlängerung (z.B. am Baum).
* `11` **Base:** Interaktives Ziel (z.B. für "Domination"-Modus).
### B. Weste (Player Hub)
* **Funktion:** Zentrale Einheit des Spielers. Verwaltet Lebenspunkte, empfängt Treffer, steuert Audio.
* **Kommunikation:** Hält die Verbindung zur Waffe (Pairing) und zum Leader.
### C. Waffe
* **Funktion:** Aussenden der IR-Signale, haptisches Feedback, Muzzle-Flash.
* **Logik:** Sendet "Schuss"-Events, empfängt "Sperren"-Befehle von der Weste (wenn tot).
---
## 2. Provisionierung & Setup (Lobby-Phase)
Bevor das Spiel startet, müssen Geräte dem Netzwerk beitreten und Spielern zugeordnet werden.
### Schritt 1: Netzwerk-Beitritt (Provisioning)
* **Szenario:** Neue Hardware wird zum ersten Mal verwendet.
* **Ablauf:**
1. Spielleiter verbindet App via BLE mit **Leader Box**.
2. Leader Box öffnet das Thread-Netzwerk (Commissioning).
3. Neue Geräte (Waffe/Weste) werden in den Pairing-Modus versetzt (z.B. Tastenkombination).
4. Geräte erhalten Netzwerk-Credentials und treten dem Mesh bei.
### Schritt 2: Spieler-Konfiguration (Assignment)
* **Ziel:** Zuordnung von Hardware zu einer logischen `PlayerID` und einem `Team`.
* **Identifikation:** Jedes nRF52-Board hat eine eindeutige **EUI-64** (MAC).
* **Ablauf:**
1. App scannt **QR-Code** oder **NFC-Tag** an der Weste/Waffe.
2. Payload: Enthält die EUI-64 Adresse.
3. App sendet Konfiguration an Leader Box: `EUI-64 -> {PlayerID: 5, Team: Rot, Name: "Rambo"}`.
4. **Waffen-Setup:** Waffe meldet ihren Typ (z.B. "Sniper") an Leader.
5. Leader sendet Konfigurations-Paket (CoAP Unicast) an das Gerät:
* **Weste:** Erhält PlayerID, TeamID, MaxHealth.
* **Waffe:** Erhält Damage-Wert, Nachladezeit, Magazingröße.
---
## 3. Spielablauf (Game Loop)
### Phase A: Vorbereitung
* **Leader:** Sendet Multicast `GAME_STATE_LOBBY`.
* **Geräte:** Spielen Idle-Animation ab, warten auf Start.
* **Check:** Leader kann "Ping" an alle senden, um Anwesenheit zu prüfen.
### Phase B: Countdown
* **Leader:** Sendet Multicast `GAME_START_COUNTDOWN` (Payload: 10 sek).
* **Westen:** Zählen laut herunter: "10, 9, 8...".
### Phase C: Spiel läuft (Running)
* **Status:** `GAME_STATE_RUNNING`.
* **Aktion:** Waffen sind entsperrt. Sensoren sind scharf.
* **Treffer-Logik (Dezentral):**
1. Waffe A schießt (sendet IR-Code mit `ShooterID` + `Damage` + `TeamID`).
2. Weste B empfängt IR-Signal.
3. Weste B berechnet Schaden (unter Berücksichtigung von Trefferzone-Multiplikator).
4. Weste B zieht Lebenspunkte ab.
5. **Feedback:** Weste B leuchtet/vibriert/spielt Sound ("Ugh!").
6. **Speicherung:** Weste B speichert den Treffer im internen Flash-Log (`Timestamp, ShooterID, Zone, Damage`).
7. *(Optional)* Weste B sendet UDP-Paket an Leader für Live-Scoreboard (Best Effort).
### Phase D: Spieler eliminiert
* **Bedingung:** Lebenspunkte <= 0.
* **Weste B:**
* Spielt "Dead"-Sound.
* Leuchtet dauerhaft in Teamfarbe (oder aus).
* Sendet CoAP Unicast an **eigene Waffe**: `CMD_DISABLE`.
* **Respawn (falls aktiv):**
* Nach Zeitablauf (z.B. 30s) sendet Weste an Waffe: `CMD_ENABLE`.
* Lebenspunkte werden zurückgesetzt.
### Phase E: Spielende & Auswertung
* **Leader:** Sendet Multicast `GAME_STATE_FINISHED`.
* **Ablauf:**
1. Alle Spieler kommen zusammen.
2. Spielleiter drückt in App "Daten abrufen".
3. Leader Box fragt nacheinander (Unicast) alle bekannten Westen ab: `GET /game/log`.
4. Westen übertragen ihre Treffer-Historie.
5. App berechnet Highscores, MVP, Trefferquoten.
---
## 4. Spielmodi
Die Logik für die Modi wird primär auf den Westen implementiert (Regelwerk), gesteuert durch Flags vom Leader.
### Team Deathmatch
* Klassisch Rot gegen Blau.
* Friendly Fire konfigurierbar (an/aus).
* Siegbedingung: Meiste Kills oder wenigste Tode nach Zeitablauf.
### Last Man Standing (Free-for-all)
* Jeder gegen Jeden.
* Keine Teams (oder jeder hat eigene Team-ID).
* Kein Respawn.
### Zombie (Infected)
* **Start:** 1 Spieler ist "Zombie" (Team Grün), Rest "Mensch" (Team Rot).
* **Regel:**
* Zombie hat unendlich Leben (oder sehr viel).
* Mensch hat 1 Leben.
* Wird Mensch getroffen -> Wechselt Team zu Zombie (Weste leuchtet grün, Waffe sendet ab jetzt Zombie-ID).
* Wird Zombie getroffen -> "Stunned" (Waffe 5s gesperrt).
* **Ziel:** Überleben bis Zeitablauf.
### Base Domination
* **Hardware:** Leader-Boxen im Modus `11` (Base) verteilt im Gelände.
* **Ablauf:**
* Spieler schießt auf Base-Box.
* Base-Box wechselt Farbe zu Teamfarbe des Schützen.
* Base-Box zählt Zeit für das haltende Team.
* Am Ende fragt Leader alle Base-Boxen ab: "Wie lange warst du Rot? Wie lange Blau?".
---
## 5. Technische Spezifikation (API & Datenstrukturen)
Die Kommunikation erfolgt über CoAP (UDP). Alle Payloads sind binär (`__packed` C-Structs, Little Endian für nRF52, aber Network Byte Order Big Endian empfohlen für Portabilität - hier vereinfacht Little Endian da homogene Hardware).
### 5.1 CoAP Endpunkte
| Ressource | Methode | Typ | Beschreibung | Payload |
| :--- | :--- | :--- | :--- | :--- |
| `game/state` | PUT | Multicast | Globaler Spielstatus (Start/Stop/Zeit) | `struct game_state_packet` |
| `game/conf` | PUT | Unicast | Konfiguration für einen Spieler | `struct player_config_packet` |
| `game/hit` | POST | Unicast | Treffer-Meldung (Live-Ticker) | `struct hit_report_packet` |
| `game/wconf` | PUT | Unicast | Konfiguration für eine Waffe | `struct weapon_config_packet` |
| `game/log` | GET | Unicast | Abruf der gespeicherten Trefferdaten | `struct flash_log_entry[]` |
### 5.2 Datenstrukturen
#### Spielstatus (Multicast)
```c
struct game_state_packet {
uint8_t state; // 0=Idle, 1=Lobby, 2=Running, 3=Paused, 4=Finished
uint8_t game_mode; // 0=TeamDeathmatch, 1=Zombie, 2=Base
uint16_t game_id; // Rolling Counter zur Deduplizierung
uint16_t remaining_sec; // Restzeit in Sekunden
uint8_t flags; // Bitmaske (z.B. FriendlyFire)
} __packed;
```
#### Spieler-Konfiguration (Provisioning)
```c
struct player_config_packet {
uint16_t player_id; // Logische ID (1-65535)
uint8_t team_id; // 0=Rot, 1=Blau, 2=Grün (Zombie), ...
uint8_t health_max; // Maximale Lebenspunkte
char name[16]; // Anzeigename (null-terminated)
} __packed;
```
#### Waffen-Konfiguration
```c
struct weapon_config_packet {
uint8_t base_damage; // Schaden pro Schuss
uint16_t reload_time_ms;// Zeit für Nachladen
uint8_t magazine_size; // Schuss pro Magazin
} __packed;
```
#### Treffer-Bericht (Live & Log)
```c
struct hit_report_packet {
uint32_t timestamp; // ms seit Spielstart
uint16_t shooter_id; // ID des Schützen (aus IR)
uint16_t victim_id; // Eigene ID
uint8_t damage; // Erlittener Schaden
uint8_t hit_location; // 0=Unbekannt, 1=Kopf, 2=Brust, 3=Rücken
} __packed;
```
---
## 6. IR-Protokoll (Physical Layer)
Das IR-Signal nutzt eine 38kHz Trägerfrequenz (NEC-ähnlich).
Payload (32-bit):
* `8bit` Protokoll-ID (Magic Byte zur Unterscheidung von Fernbedienungen)
* `16bit` Shooter ID
* `8bit` Info (4bit Team, 4bit Damage Class)