# Sense the Rhythm > Rhythm game where you have to headbang in the right direction to hit the notes. [Source Code](https://source.orangerot.dev/university/sense_the_rhythm)
## Idee Das Rhythmusspiel **Sense the Rhythm** ist eine Flutter-App für Android, bei dem der Nutzer durch Neigen des Kopfes im richtigen Moment Noten eines Liedes treffen muss, die ihm in Form von Pfeilen entgegenkommen. ## Benutzung > Getestet auf einem Oneplus 6 mit Android 13 Um die App nutzen zu können, werden Simfiles benötigt, welche Lieder, Bilder und Notendaten enthalten. Getestet wurde mit den Dateien, die man über 'Alle herunterladen' von dem [In the Groove Pack](https://drive.google.com/drive/folders/1sIhv4_STnyqXiauMx3BUco0m-a5VEpYy) bekommt. Die ZIP-Datei muss in einen Ordner auf dem Android-Gerät entpackt werden. Generell sind `Beginner Packs`, zum Beispiel von itgpacks.com, zu empfehlen, bei denen wenige Noten hintereinander und keine Noten parallel gespielt werden. Sobald sich ein Ordner mit Simfiles auf dem Gerät befindet, kann dieser über den `+`-Knopf ausgewählt werden, woraufhin die Level in der Levelauswahl zu sehen sind. Soll das ESense Earable als Eingabe genutzen werden (Pfeiltasten auf der Tastatur als Backup), muss das Bluetooth-Symbol oben rechts berührt werden. Daraufhin erscheint ein Dialog, in welchem der Name des linken Earbuds eingegeben wird. Der Name kann herausgefunden werden, indem der linken Earbud in den Bluetooth-Pairing-Modus gebracht und in den Bluetooth-Einstellungen des Betriebssystems nach den verfügbaren Geräten geschaut wird. Mehr Informationen gibt es in der offiziellen eSense-User-Documentation. Wurde der Name in den Dialog eingegeben, wird auf `Connect` gedrückt und gewartet bis der Text `connected` (nicht nur `connecting...`!) erscheint. Jetzt kann der Dialog mit `Close` geschlossen werden. In der Levelauswahl kann nun ein Level ausgewählt werden, worauf das Level startet. Hier kann das Level pausiert und verlassen werden. Um das Level abzuschließen müssen die Noten getroffen werden, indem das ESense in die richtige Richtung geneigt oder die richtige Pfeiltaste in die auf einer Tastatur gedrückt wird. Am Ende erscheint eine Statistik wie viele Noten getroffen und verfehlt wurden, sowie die Option das Level zu wiederholen oder zu verlassen. ## Code-Qualität Der Code ist in eine Ordnerstruktur gegliedert, welche aufgeteilt ist in `/models`, `/utils`, `/screens` und `/widgets`. Alle Imports sind durch absolute Pfade repräsentiert. Alle Dateien wurden einheitlich mit dem Code-Formatter des Dart-Language-Servers formatiert. ## Dokumentation Alle Methoden werden durch dart doc comments `///` beschrieben. Komplizierte Code-Stellen werden durch Kommentare erweitert. Diese `README` dient dem Nutzer als Dokumentation zur Nutzung der App. ## Technische Raffinesse > Ihre Umsetzung ist nicht trivial (zum Beispiel verarbeiten Sie Sensordaten, Nutzen APIs etc.), Gesamtumfang > 400 Zeilen Für die Umsetzung der App wurde ein eigener Parser für [Simfiles](https://github.com/stepmania/stepmania/wiki/sm) geschrieben. Dieser kann Tags, wie Titel, BPM oder Dateinamen zu Banner und Musik einlesen. Außerdem werden die `Charts` mit sämtlichen Noten eingelesen. Diese Daten werden sowohl in den Levels, als auch in der Levelauswahl benutzt. Zum Laden des ITG Packs wird das `file-picker` Plugin benutzt und Berechtigungen im Manifest und zur Laufzeit gesetzt (für neue Android-Versionen ist dafür leider kompletter Speicherzugriff nötig). Damit der ausgewählte Ordner beim nächsten Starten der App bestehen bleibt, wird der Pfad mit dem Plugin `shared_preferences` persistent gespeichert. Die Musik wird mit dem `audioplayer` Plugin abgespielt. Außerdem werden die Zeitinformationen genutzt, um die Noten als Pfeile zu zeigen, welche sich basierend auf dem Fortschritt des Liedes bewegen. Die Daten des ESense und Tastatur werden in den Zeitabfragen genutzt, um zu prüfen, ob die Note getroffen oder verfehlt wurde und die entsprechende Nachricht anzuzeigen. Für die Nachricht wurde sich mit dem AnimationController befasst. Das `esense_flutter` Plugin wird direkt vom GitHub-Repo bezogen, damit es bei aktuellen Flutter-Versionen benutzt werden kann. Der ESense-Input wird als globaler Service implementiert, wodurch er in jedem Widget verfügbar ist, ohne dass man es jedem Widget übergeben müsste. Von dem ESense Earable werden Daten über die Verbindung, den Zustand des Knopfes und Gyroskop-Daten abgefragt. Über den Knopf lässt sich das Level pausieren und weiterspielen. Die Neigung des ESense wird über die Gyroskop-Daten berechnet, indem die Bewegungsänderungen mit dem Standard-Skalierungsfaktor und der Delta-Zeit skaliert und für jede Messung mit der bisherigen Neigung verrechnet wird. Die Neigung wird bei jeder getroffenen Note neu kalibriert. Ob die Note getroffen wurde wird geprüft, indem getestet wird ob sich die Neigung in einem definierten Wertebereich befindet. Die Launcher-Icons und Launcher-Name wurden durch die Plugins `flutter_launcher_icons` und `flutter_app_name` automatisch für Größen und gewünschten Plattformen erstellt. ## Präsentation Siehe `/presentation` ## Used Libraries - https://github.com/cph-cachet/flutter-plugins.git - https://pub.dev/packages/shared_preferences - https://pub.dev/packages/file_picker - https://pub.dev/packages/audioplayers - https://pub.dev/packages/permission_handler - https://pub.dev/packages/flutter_launcher_icons - https://pub.dev/packages/flutter_app_name ## License This project is licensed under the GPL-3 License - see the `LICENSE` file for details