Cyclops-Saber

Aus toolbox_interaktion
Wechseln zu: Navigation, Suche

Problembeschreibung

Das Projekt orientiert sich an dem gleichnamigen Videospiel „Beat Saber“. Dabei handelt es sich um ein Rhythmus-betontes VR-Spiel, bei dem quadratische Blöcke auf den Spieler zugeflogen kommen und diese mit VR-Controllern im Takt zerschlagen werden müssen. Geschieht dies im richtigen Moment, spielt das Spiel die vorgegebene Melodie ab. Da VR-Brillen und das dazugehörige Equipment im Moment noch sehr teuer sind, erreicht das Spiel nur ein begrenztes Publikum.

Ziel

Es soll ein Gesamtkonzept erarbeitet werden, mit dem das Spiel auch ohne VR-Brillen und Controller gesteuert werden kann. Dabei wird ein neues Spiel programmiert, welches sich im Spielumfang und in der Komplexität vom Original unterscheidet. Um zu spielen, sollen nur eine Webcam und ggf. farbige Schwerter nötig sein. Da der zeitliche Rahmen des Projektes auf wenige Monate begrenzt ist, wird erstmal nur ein Spielmodus implementiert und nur bei vorhandener Zeit das Projekt auf weitere Spielmodi (wie z.B. vorgegebene Schlagrichtung; Bomben statt Blöcke, die nicht getroffen werden dürfen; etc.) erweitert.

Ressourcen

An dem Projekt haben 7 Teilnehmer gearbeitet, die die Aufgabenbereiche untereinander aufgeteilt haben. Besondere Anschaffungen bezüglich der Hardware waren dafür nicht nötig.

openFrameworks

Zur Ansteuerung des Spieles dient lediglich das Webcam-Bild. Um möglichst fehlerfrei und auch bei schlechten Lichtverhältnissen korrekte Werte zu ermitteln, wurde das Bild in mehreren Schritten verarbeitet. Dazu diente das Toolkit openFrameworks. Dieser teilt sich in mehrere Funktionen auf, die angepasst werden können. Die erste Funktion ist die setup() Funktion, welches die anfänglichen Initialisierungen beim Programmstart ausführt. Im Programm müssen mehrere Anwendungen initialisiert werden. Dazu gehören:

- Die Webcam

- Die OSC-Verbindung

- Timer

- Variablenwerte, wie z. B. minimale und maximale Konturgröße

Die zweite Funktion ist die Update() Funktion. Diese wird abwechselnd mit der Draw() Funktion aufgerufen und wird dafür eingesetzt Berechnungen durchzuführen, Objekte (wie z. B. die Webcam) und Bildanalysetools zu aktualisieren. In unserem Projekt wird zuerst das Webcam-Bild aktualisiert, falls die Webcam seit dem letzten Aufruf ein neues Bild geschossen hat. Ist dies der Fall, wird eine Kontur mit einer zuvor ausgewählten Farbe gesucht. Die Auswahl der Farbe wird im weitere Verlauf des Kapitels bei der Funktion mousePressed() erläutert. Die Suche nach den jeweiligen in Frage kommenden Konturen geschieht mit dem Contourfinder aus dem fertigen openFrameworks Addon ofxCv. Da in einem Bild die gleiche Farbe öfter auftauchen kann oder durch Lichtreflexion eine einzelne Fläche als mehrere kleine Flächen erkannt werden kann, wurde mithilfe einer FOR-Schleife jede Kontur durchgegangen und die Kontur mit der maximalen Größe rausgesucht. Aus dieser Kontur wurde der Mittelpunkt mit der folgenden Zeile abgefragt:

 center = contourRight.getCenter(maxIndex);

Dieser Mittelpunkt unterliegt großen Schwankungen, da sich die größte Kontur oft nur sehr wenig von der Zweitgrößten unterscheidet. Meistens liegen diese Konturen nebeneinander und sind Teile eines einzigen Objektes. Um hier verlässlichere Werte zu bekommen, wurde der Mittelpunkt mithilfe der Funktion updateAverage() geglättet.

Interaktion FrameworksBild.png

Jede Kontur wird mit einem Rechteck so umschlossen, dass alle Eckpunkte in diesem Rechteck drin sind. Die Orientierung kann damit nur durch die Höhe und Breite des Objektes und den vier Eckpunkten bestimmt werden. Die Höhe und Breite des detektierten Objektes berechnet sich durch den Satz des Pythagoras:

Hoehe breite formel.PNG

Da das Objekt waagrecht oder senkrecht liegen könnte wird hierbei zwischen zwei Fällen unterschieden: Die Höhe ist größer als die Breite Die Breite ist größer als die Höhe

Mit der längeren Seite wird die Orientierung im 2D-Raum bestimmt.

Phi formel.PNG

Der berechnete Mittelpunkt und die Orientierung werden mittels OSC-Verbindung an Unity weitergeleitet. Dies erfolgt mit der Funktion updatePosition(). Die dritte openFrameworks Funktion ist Draw(). Hier erfolgt die Ausgabe des Webcam Bildes. Das zuvor in der update() Funktion erkannte Objekt wird mit einer Linie überlagert. Die Enden dieser Linie werden aus dem Mittelpunkt und dem zuvor ermittelten Vektor ermittelt. Die Farbe der zu findenden Kontur wird rechts neben dem Webcam-Bild eingeblendet. Die openFrameworks Funktion mousePressed() wird aufgerufen, wenn die Computermaus gedrückt wurde. Mit der linken Maus kann hier auf dem eigenen Webcam-Bild die Schwertfarbe angeklickt werden. Somit ist das Spiel nicht auf eine bestimmte Farbe eingeschränkt. Um hier eine möglichst gute Farberkennung zu gewährleisten, wurde mit dem HSB-Wert des angeklickten Pixels gearbeitet. Dieser Wert wird in der Variable color1 gespeichert und an Unity mittels der eigenen Funktion updateHSB() weitergeleitet.

CounturBild.png

OSC Sender-Schnittstelle

OpenFrameworks wird für die Eingabe und Verarbeitung der Kameradaten verwendet. Unity wurde als Software zur Ausgabe gewählt. Daher war es notwendig eine Schnittstelle zu konfigurieren. In OpenFrameworks ist dabei die Sender Schnittstelle. Für diese OSC-Verbindung wurde das Addon ofxOsc.h verwendet. Datentypen und Funktionen sind in dieser schon vordefiniert und erleichtern die Übertragung der Daten. Für diese Sender-Übertragung müssen zwei Variablen initialisiert werden:

ofxOscSender sender

ofxOscMessage message

Über die Funktion sender.setup(IP-Name, Portnummer) wird die Zieladresse der Nachricht eingestellt. Aufbau eines Nachrichtenblocks:

TabelleNachrichtenblock.PNG

Die festgelegte Adresse ist eine zwischen Sender und Empfänger bekannter Name, um die gesendeten Nachrichten identifizieren zu können. Im Projekt werden an der Schnittstelle nur Variablen übergeben, die den Datentyp float haben. In einem Nachrichtenlock wird die normierte Position des Schwertes auf dem Bildschirm und die dazugehörige Neigung des Schwertes übertragen. Diese Daten sollen nahezu in Echtzeit gesendet werden und werden daher in einem Nachrichtenblock zusammengefasst. Des Weiteren wird die Farbe des rechteckigen Gegenstandes übergeben, damit das Schwert in der Game-Engine sich dieser anpasst. Da diese Daten jedoch nur übertragen werden müssen, wenn der Spieler auf dem Bildschirm der Kamera mit der Maustaste diesen Gegenstand anklickt, werden diese Daten in einem gesonderten Nachrichtenblock aufgeführt.

HSB-Farbraum

Um eine Farbe eindeutig identifizieren zu können gibt es verschiedene Möglichkeiten diese zu beschreiben. Im Programmcode von Cyclops Saber handelt es sich hierbei um das HSB-Farbmodell. Durch die Bestimmung der Variablen hue, saturation und brightness lassen sich die Farben direkt bestimmen. Im Folgenden ist eine Tabelle die den Wertebereich der einzelnen Variablen und einem Beispiel, wie diese Werte zu interpretieren sind.

TabelleHSB.PNG

Unity (Spiel-Engine)

Um das Spiel dreidimensional darstellen zu können, wurde die Entwicklungsplattform Unity als Spiel-Engine verwendet. Hierbei ist es möglich dreidimensionale Umgebungen mit Animationen zu erstellen und Musik und Geräusche hinzuzufügen. Spielabläufe und Logik werden durch selbst geschriebene Programme, sogenannte Skripts, ergänzt.

Stefan.png

Die Gestaltung des Spiels ist nicht mehr an das Video Spiel „Beat Saber“ angelehnt. Nun wirft ein Zyklop Holzstücke auf den Anwender, welcher diese mit einem Schwert abwehren soll. Die Umgebung des Spiels ist an einen Wald angelehnt, wobei der Anwender immer aus der gleichen Perspektive auf den Zyklopen schaut. Die Zeitabstände zwischen den geworfenen Holzstücken, sowie der Winkel werden pro Wurf neu und zufällig ausgewählt. Das Abwehren findet durch ein im Raum schwebendes Schwert statt, welches durch den Anwender mithilfe des farbigen rechteckigen Gegenstandes vor der Webcam bewegt wird. Bei Start des Spiels beginnt der Zyklop die Holzstücke zu werfen. Zu Beginn dieser Animation wird bereits die Funktion zum Erstellen des nächsten Holzstückes aufgerufen. Bewegt der Anwender das Schwert in die richtige Position, um das Holzstück zu treffen, wird dieses bei Kollision mit einem Geräusch in kleinere Teile zersplittert. Ein Zähler im Bild gibt die Anzahl der getroffenen Blöcke wieder, wobei verfehlte Blöcke subtrahiert werden. Die dreidimensionalen Objekte und Animationen stammen größtenteils aus Unity selbst oder anderen Internetquellen. Einige der Objekte wurden zusätzlich mit der 3D Software Blender bearbeitet.

Ausblick

Das größte Potenzial, um das Spiel auszubauen, besteht in Logik und Ablauf innerhalb von Unity. Hier sind der Kreativität keine Grenzen gesetzt. Um dem Spiel „Beat Saber“ noch näher zu kommen, wäre die Implementierung von Musik und dem Zerspalten der Blöcke synchron zum Beat eine Möglichkeit. Zudem kann auch ein weiteres Schwert für die zweite Hand möglich. Auch der Einsatz von verschiedenen Spielmodi oder unterschiedlichen Spielumgebungen ist möglich.

Link zum erstellten Programmcode

Programmcode

Video

Verwendete Links

Beat Saber:

https://de.wikipedia.org/wiki/Beat_Saber

https://www.youtube.com/watch?v=pa4vrynwkwY

https://beatsaber.com

OSC:

https://openframeworks.cc/documentation/ofxOsc/

HSB:

http://www-home.fh-konstanz.de/~mfranz/ibv_files/lect12_farbe.pdf