2025-01-11 20:31:01 +01:00
|
|
|
<div align="center">
|
|
|
|
<img src="assets/icon/icon.svg" width="300">
|
2024-12-16 16:04:07 +01:00
|
|
|
|
2025-01-11 20:31:01 +01:00
|
|
|
# Sense the Rhythm
|
|
|
|
> Rhythm game where you have to headbang in the right direction to hit the notes.
|
2024-12-16 16:04:07 +01:00
|
|
|
|
2025-01-11 20:31:01 +01:00
|
|
|
[Source Code](https://source.orangerot.dev/university/sense_the_rhythm)
|
|
|
|
</div>
|
2024-12-16 16:04:07 +01:00
|
|
|
|
|
|
|
## Idee
|
2025-01-11 20:31:01 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
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.
|
2024-12-16 16:04:07 +01:00
|
|
|
|
|
|
|
## Code-Qualität
|
|
|
|
|
2025-01-11 20:31:01 +01:00
|
|
|
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.
|
2024-12-16 16:04:07 +01:00
|
|
|
|
|
|
|
## Dokumentation
|
|
|
|
|
2025-01-11 20:31:01 +01:00
|
|
|
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.
|
2024-12-16 16:04:07 +01:00
|
|
|
|
|
|
|
## Technische Raffinesse
|
|
|
|
|
2025-01-11 20:31:01 +01:00
|
|
|
> 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.
|
2024-12-16 16:04:07 +01:00
|
|
|
|
|
|
|
## Präsentation
|
2025-01-11 20:31:01 +01:00
|
|
|
|
|
|
|
Siehe `/presentation`
|
2024-12-16 16:04:07 +01:00
|
|
|
|
|
|
|
## Used Libraries
|
|
|
|
|
2025-01-11 20:31:01 +01:00
|
|
|
- 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
|