Einleitung

Dieses kleine Tutorial soll in den grundlegenden Umgang mit dem von Thibault Imbert und Joa Ebert erstellten WiiFlashServer einführen, der es ermöglicht, die verschiedenen Eingabegeräte für die Nintendo Wii mit Flash anzusprechen.
Konkret geht es an dieser Stelle nur um die Wiimote, obwohl es damit auch möglich ist das BalanceBoard oder die Nunchuk usw. anzusteuern.
Als Hinweis vorweg sei gesagt, dass es Unterschiede zwischen der Syntax der PC- und Mac-Version des Servers gibt. Bis jetzt zeigten sich diese nicht besonders gravierend und zu umgehen.

Die PDF zu dem Tutorial lässt sich hier herunterladen.


Erste Schritte // Einrichten der Serververbindung

Zuerst wird das Serverprogramm installiert, die Macversion ist unter lab.tojio.com und die PC-Version unter wiiflash.org zu finden.
Wenn der heruntergeladene Server entpackt ist, wird die Wiimote mit dem Bluetooth synchronisiert. Das funktioniert auf den verschiedenen Systemen leicht unterschiedlich. Man startet zuerst den Bluetooth-Dialog und stellt dann die Verbindung mit der Wiimote her, die dann zum Beispiel als „NINTENDO-RVL-CNT-01“ angezeigt wird. Die Wiimote selbst beginnt die Synchronisation über das gleichtzeitigen Druck auf den „1“- und „2“-Button oder auf den Synchronisationsbutton im Batteriefach. Im Bluetooth-Dialog selbst muss man meist erst die Geräte durchsuchen und dann die gefundene Wiimote verbinden.
Der nächste Schritt ist es, den Server zu starten. Dieser erkennt die Wiimote automatisch, wenn sie korrekt verbunden ist und das Symbol für die angeschlossene Wiimote erscheint in der Serveranzeige (beim PC vibriert die Wiimote dann auch).


Erste Schritte // Anlegen der Flashdatei

Wenn dann die Arbeitsdatei in Flash erstellt wird muss auf Folgendes geachtet werden: Die Datei muss in ActionScript 3 angelegt werden und es empfiehlt sich, sie sofort in einem Extraordner zu speichern. Das ist sehr wichtig, weil Flash sonst nicht die notwendigen WiiFlash-Klassen finden kann (eine echte Fehlerquelle).
Als Nächstes wird der .org-Ordner, der sich in dem heruntergeladenen Paket befindet, in das Arbeitsverzeichnis kopiert.
Nun kann Flash auf die Klassen zugreifen, die für den WiiFlash-Server notwendig sind und es kann die eigentliche Programmierung beginnen.


Erste Schritte // Import der WiiFlash-Klassen in ActionScript

Zunächst werden die notwendigen Klassen in das erste Bild, dass den ActionScript-Code enthält, importiert.

import org.wiiflash.Wiimote;
import org.wiiflash.events.ButtonEvent;
import org.wiiflash.events.WiimoteEvent;
import flash.events.*;

Hier sieht man, dass Flash auf den Ordner „.org“ zugreift. import ist standardmäßig bei AS die Methode, mit der Klassen importiert werden. Danach wird auf das Verzeichnisse „.org.wiimote“ und „.org.wiimote.events“ verwiesen, in dem sich die Klassen für die Wiimote befinden. Mit import flash.events.*; werden alle Eventklassen von AS3 importiert.

Als nächstes wird das Wiimote-Objekt instanziert, mit dem weitergearbeitet werden soll.

var myWiimote:Wiimote = new Wiimote();

myWiimote ist ein neues Objekt der Klasse Wiimote und erbt damit ihre ganzen Events, Eigenschaften und Methoden. Der Name des instanzierten Objekts steht frei, die berühmten Beispiele „hund“ oder „katze“ können natürlich auch verwendet werden.

Gibt es mehrere Wiimotes, die verbunden sind, muss man mehrere Wiimote-Objekte instanzieren. Diesen wird eine ID zugewiesen (mehr dazu später).

Danach verbindet man das Wiimote-Objekt über die Methode connect.

myWiimote.connect ();

Damit ist die Wiimote verbunden und die Grundlagen für die weitere Programmierung gelegt.


Programmierung // EventListener

Mit AS3 wurde das Konzept des Eventlisteners erweitert und es ersetzt einiges, was in AS2 grundlegend war. Eventlistener können an Objekte gehängt werden und haben die Funktion, das Eintreten bestimmter Ereignisse (wie Eingaben durch den Nutzer oder das Betreten eines Schlüsselbilds) zu überwachen. Treten die erwarteten Ereignisse ein, werden andere, festgelegte Ereignisse ausgelöst, was ungefähr dem Konzept des „on“ in AS2 entspricht.

Das Wiimote-Objekt besitzt auch einige dieser Eventlistener. Diese funktionieren so:

myWiimote.addEventListener( ButtonEvent.A_PRESS,
onAPressed );

myWiimote erhält den Eventlistener ButtonEvent.A_PRESS über die Methode addEventListener. Dieser fragt ab, ob der „A“-Button gedrückt wird. Tritt dieses Ereignis ein wird die Funktion onAPressed ausgelöst die dann folgendermaßen definiert werden könnte:

function onAPressed ( pEvt:ButtonEvent ):void {
trace(“A wird gedrückt”);
}

Es ist wichtig, dass bei der Funktionsdefinition darauf geachtet wird, welche Art von Ereignis eintritt, hier trat zum Beispiel mit pEvt:ButtonEvent,ein ButtonEvent ein. Dringend zu beachten ist, dass pEvt nur bei den Button- und den Wiimote- events eingesetzt wird. Bei den anderen wird pEvent geschrieben.

Die anderen Eventlistener können dann einfach an der Stelle, an der jetzt ButtonEvent.A_PRESS stand, eingefügt werden.

Folgende ButtonEvents sind noch möglich:

„A“ wird losgelassen

 ButtonEvent.A_RELEASE

„B“ wird gedrückt

 ButtonEvent.B_PRESS

„B“ wird gedrückt

 ButtonEvent.B_RELEASE

Das Steuerkreuz wird nach links, rechts, oben oder unten gedrückt

ButtonEvent.LEFT_PRESS, 
ButtonEvent.RIGHT_PRESS, 
ButtonEvent.UP_PRESS, 
ButtonEvent.DOWN_PRESS

Das Steuerkreuz wird links, rechts, oben oder unten losgelassen

ButtonEvent.LEFT_RELEASE,
ButtonEvent.RIGHT_RELEASE,
ButtonEvent.UP_RELEASE,
ButtonEvent.DOWN_RELEASE

Genauso funktioniert das bei der „Minus“-, der „Plus“, der „Home“-, der „1“- und der „2“-Taste

ButtonEvent.MINUS_RELEASE,
ButtonEvent.PLUS_PRESS,
ButtonEvent.PLUS_RELEASE,
ButtonEvent.HOME_PRESS
ButtonEvent.HOME_RELEASE,
ButtonEvent.ONE_PRESS,
ButtonEvent.ONE_RELEASE,
ButtonEvent.TWO_PRESS,
ButtonEvent.TWO_RELEASE

Hier treten die Ereignisse ein, wenn die Wiimote verbunden wurde, es dabei einen Fehler gab oder die Verbindung getrennt wurde.

Event.CONNECT,
IOErrorEvent.IO_ERROR,
Event.CLOSE

Bei diesem Eventlistener wird ein Ereignis ausgelöst, wenn von der Wiimote Daten empfangen werden. Das hat eine recht hohe Frequenz und kann somit als besserer Ersatz für Event.ENTER_FRAME verwendet werden.

WiimoteEvent.UPDATE

Programmierung // Eigenschaften

Die Wiimote besitzt verschiede Eigenschaften, also Variablen, die abgefragt oder zurückgesandt werden können. Diese können ganz einfach verwendet werden. Beispielsweise so:

kreis_mc.rotation = myWiimote.roll;

Will man eine Variable an das Wiimote-Objekt senden funktioniert das beispielsweise so :

myWiimote.mouseControl = true;

Hier sollen die wichtigesten aufgelistet werden:

Gibt an, ob die Wiimote nach vorne oder hinten gedreht ist. Der Wert ist bei +1, wenn die Wiimote 90 Grad nach vorn und bei -1, wenn sie 90 Grad nach hinten gekippt ist

myWiimote.roll

Gibt an, ob die Wiimote nach rechts oder links gedreht ist. Der Wert ist bei +1, wenn die Wiimote 90 Grad nach rechts und bei -1, wenn sie 90 Grad nach links gekippt ist

myWiimote.pitch

Diese Variable entspricht der Drehung der Wiimote entlang der Längsachse. +1 entspricht der „normalen“ Lage und -1 der Drehung nach unten. 0 entspricht einer 90°-Drehung zur Seite

myWiimote.yaw

Diese drei Variablen entstammen dem Beschleunigungssensor der Wiimote. Je nachdem wie stark die Wiimote in eine bestimmte Richtung (entlang der x-, y- und z-Achse) bewegt wird enstehen Werte zwischen 0 und ca. 1.5. Dabei ist zu beachten, dass die Achsen anders angeordnet sind als im Standardkoordinatensystem (siehe Abb. unten).

myWiimote.sensorX,
myWiimote.sensorY,
myWiimote.sensorZ

Gibt mit einem Wert zwischen 0 und 1 an, wie voll die Batterie der Wiimote ist

myWiimote.batteryLevel

Eine boolsche Variable, die angibt, ob die Wiimote verbunden ist

myWiimote.connected

Löst die Vibration der Wiimote aus, der Wert wird in Millisekunden angegeben

myWiimote.rumbleTimeout

Boolesche Variable, mit der die Mauskontrolle aktiviert werden kann. Ist die Mauskontrolle aktiviert entspricht die Lage des Cursors dem x- und y-Wert des Sensorpunkts 1 (siehe unten unter ir). Bei der PC-Version heißt „Mauskontrolle“ zusätzlich, dass das Drücken der B-Taste an der Wiimote dem Drücken der linken Maustaste entspricht

myWiimote.mouseControl

Wenn man mit mehreren Wiimotes arbeiten will, kann man die IDs der WiiMotes abfragen, was über den Wert myWiimote.id funktioniert. Der Wert kann eine Ganzzahl von 1 bis 4 sein. So können vier verschiedene Wiimote-Objekte erstellt werden, die jeweils eine festgelegte ID besitzen.

myWiimote.id

leds ist eine Eigenschaft, mit der sich die LED-Leiste der Wiimote ansteuern lässt. Hier gibt es auch Unterschiede in der PC- und Mac-Syntax. Beim PC kann man 15 verschiedene Ganzzahlen angeben,
die 15 verschiedene Stellungen der LEDs bedeuten.

myWiimote.leds

Eine Besonderheit stellt die Variable ir dar. Sie ist eigentlich vielmehr ein Array-Objekt, da sie mehrere Werte enthält. Die Wiimote kann über ihren Infrarotsensor bis zu vier Lichtpunkte erkennen. Daraus ergeben sich die folgenden Variablen:

Boolesche Variablen, die angeben, ob die Wiimote einen Punkt erkennt. Ergibt myWiimote.ir.p3 den Wert true heißt das, dass die Wiimote drei Punkte bzw. den dritten Punkt erkennt

myWiimote.ir.p1,
myWiimote.ir.p2,
myWiimote.ir.p3,
myWiimote.ir.p4

Die Variablen geben den x-Wert des jeweiligen Punkts an

myWiimote.ir.x1,
myWiimote.ir.x2,
myWiimote.ir.x3,
myWiimote.ir.x4

Die Variablen geben den y-Wert des jeweiligen Punkts an

myWiimote.ir.y1,
myWiimote.ir.y2,
myWiimote.ir.y3,
myWiimote.ir.y4
myWiimote.ir.size1,
myWiimote.ir.size2,
myWiimote.ir.size3,
myWiimote.ir.size4

Dazu, wie die einzelnen Werte sich aus der Bewegung der Wiimote ergeben, habe ich eine Beispieldatei erstellt. Die Abbildung unten zeigt, wie das Koordinatensystem der Wiimote funktioniert (Quelle: www.wiili.org).


Programmierung // Methoden

Als wichtige Methoden sind, neben den bereits bekannten myWiimote.connect und MyWiimote.addEventListener nur noch myWiimote.close , die die Verbindung zur Wiimote trennt, und removeEventlistener, die  EventListener wieder enfernt, zu nennen.


Troubleshooting

Bei dem Umgang mit dem Wiiflash-Server sind bei mir ein paar typische Fehler
aufgetreten, die ich natürlich nicht geheim halten will. Anhand der Checkliste unten kann man überprüfen, ob einer der Fehler vielleicht der Grund ist, warum nichts funktioniert.

Steht die Verbindung zwischen der Wiimote und Flash?
Erstens kann es immer wieder passieren, dass man vergessen hat, überhaupt die Verbindung herszustellen und zweitens hat der Wiiflash-Server beim PC die Tendenz, einfach auszugehen. Flash bringt dann meistens folgende Fehlermeldung:
Error #2044: ioError unverarbeitet. text=Error #2031: Socketfehler. URL: 127.0.0.1.

Befindet sich der .org-Ordner im gleichen Verzeichnis wie meine Arbeitsdatei bzw. habe ich meine Datei überhaupt gespeichert?
Wie bereits gesagt, muss der org-Ordner sich als Unterverzeichnis in dem gleichen Ordner wie meine Datei befinden, dass Flash auf die notwendigen Klassen zugreifen kann. Dazu muss, logischerweise, die Datei bereits irgendwo abgespeichert sein. Flash beschwert sich darüber, dass man auf nicht definierte Methoden oder Eigenschaften zugreifen will.

Stimmt die Reihenfolge bei der Programmierung?
Mir ist es beispielsweise passiert, dass ich die Wiimote über connect(); verbinden wollte bevor ich überhaupt das Wiimote-Objekt instanziert hatte.

Habe ich den richtigen Eventlistener eingesetzt?
Wie oben bereits beschrieben muss man darauf achten, welches Ereignis abgefragt wird.


SecurityError: Sandbox ‘local-with-filesystem’ beheben

Eine häufige Fehlermeldung beim Programmieren mit Flash und XML-Daten ist dieser. Für dessen Behebung gibt es zwei Möglichkeiten:

1. Global Flash Player Trust directory

Damit gewährt man SWF Dateien den Zugriff auf lokale Resourcen. Dazu bei Mac OS X unter “Interne Festplatte/ Library/ Application Support/ Macromedia/ FlashPlayerTrust” eine Textdatei (z.B. “myTrustedFlash.cfg”) anlegen mit dem Pfad, der zu der/den swf-Datei/en führt, die den Fehler gemeldet hat/haben. In dieser Datei kann man dann die Ordner bzw. swf-Dateien angeben, für die die Security Sandbox nicht gilt. z.B.:

/Users/max_muster/Documents/myFlashWork/test.swf

oder 2. Globale Sicherheitseinstellungen

Im Browser diesen Link Flash Support öffnen und im Einstellungsmanager den Punkt “Immer zulassen” anwählen und unter “Bearbeiten” und “Hinzufügen” den betreffenden Ordner auswählen. Anschließend den Browser schließen.


Beispiel Zoom und Infraroterkennung

The Flash plugin is required to view this object.

//Klassenimport
import org.wiiflash.Wiimote;
import org.wiiflash.events.ButtonEvent;
import org.wiiflash.events.WiimoteEvent;
import flash.events.*;
 
// Wiimote-Objekt erzeugen
var myWiimote:Wiimote = new Wiimote();
 
// mit Wii-Server verbinden
myWiimote.connect();
 
stage.addEventListener(Event.ENTER_FRAME, folgen);
 
function folgen (evt:Event) { //x und y-Position verändern; ir= Infaroterkennung/Daten auswertet
quadrat_mc.x = (1-myWiimote.ir.x1)*stage.stageWidth; //mal stageWidth=Bühnenbreite
quadrat_mc.y = myWiimote.ir.y1*-stage.stageHeight; //mal stageHeight=Bühnenhöhe
//Quadrat folgt der Bewegung der Wiimote
 
quadrat2_mc.x = (1-myWiimote.ir.x2)*stage.stageWidth;
quadrat2_mc.y = myWiimote.ir.y2*-stage.stageHeight;
 
quadrat_mc.scaleX = myWiimote.ir.size1;
quadrat_mc.scaleY = myWiimote.ir.size1;
 
trace(myWiimote.ir.size1);}

Beispiel Mauskontrolle

The Flash plugin is required to view this object.

//Klassenimport
import org.wiiflash.Wiimote;
import org.wiiflash.events.ButtonEvent;
import org.wiiflash.events.WiimoteEvent;
import flash.events.*;
 
// Wiimote-Objekt erzeugen
var myWiimote:Wiimote = new Wiimote();
 
// mit Wii-Server verbinden
myWiimote.connect();
 
//variablen
var schalter:Boolean = false;
 
//leertastendruck
stage.addEventListener(KeyboardEvent.KEY_DOWN, leertaste);
 
//funktion
function leertaste(evt:KeyboardEvent):void {
	if (schalter == false) {
		schalter = true;
		myWiimote.mouseControl = true;
 
	} else if (schalter == true) {
		schalter = false;
		myWiimote.mouseControl = false;
	}
}

Beispiel Drag and Drop

The Flash plugin is required to view this object.

//Klassenimport
import org.wiiflash.Wiimote;
import org.wiiflash.events.ButtonEvent;
import org.wiiflash.events.WiimoteEvent;
import flash.events.*;
 
// Wiimote-Objekt erzeugen
var myWiimote:Wiimote = new Wiimote();
 
// mit Wii-Server verbinden
myWiimote.connect();
 
//variablen
var dif:Number;
var dif2:Number;
 
//eventlistener
addEventListener(Event.ENTER_FRAME, folgen);
addEventListener(Event.ENTER_FRAME, drag);
 
//funktion
function folgen(evt:Event) {//x und y-Position verändern; ir= Infaroterkennung/Daten auswertet
	quadrat_mc.x = (1-myWiimote.ir.x1)*stage.stageWidth;//mal stageWidth=Bühnenbreite
	quadrat_mc.y = myWiimote.ir.y1*-stage.stageHeight;//mal stageHeight=Bühnenhöhe
	//Quadrat folgt der Bewegung der Wiimote
 
}
 
function drag(evt:Event) {
	if (quadrat_mc.hitTestObject(quadrat3_mc) == true && myWiimote.a == true) {//es wird abgefragt ob das quadrat, das quadrat3 berührt und ob a gedrückt ist
		quadrat3_mc.x = quadrat_mc.x + dif;
		quadrat3_mc.y = quadrat_mc.y + dif2;
	} else {
		dif = quadrat3_mc.x - quadrat_mc.x;
		dif2 = quadrat3_mc.y - quadrat_mc.y;
	}
}

Beispiel Generierung von Grafiken

Dieses Beispiel befindet sich in der Kategorie Game.

// Klassenimport ////
 
import org.wiiflash.Wiimote;import org.wiiflash.events.ButtonEvent;import org.wiiflash.events.WiimoteEvent;import flash.events.*;
 
// Wiimote-Objekt erzeugen ////
 
var myWiimote:Wiimote = new Wiimote();
 
// mit Wii-Server verbinden ////
 
myWiimote.connect ();
 
//variablen ////var schalter:Boolean = false;
 
//leertastendruck ////stage.addEventListener(KeyboardEvent.KEY_DOWN, leertaste);
 
function leertaste(evt:KeyboardEvent):void {if (schalter == false) {schalter = true;myWiimote.mouseControl = true;Mouse.hide();
 
} else if (schalter == true) {schalter = false;myWiimote.mouseControl = false;Mouse.show();}trace(schalter);}
 
// the rest ////
 
var anzahl:int = 70;var quads:Array = new Array (anzahl);
 
stage.addEventListener(Event.ENTER_FRAME, addieren);
 
for (var i:int = 1; i < anzahl; i++) {quads[i] = new quad();addChild(quads[i]);quads[i].x = i * 30;quads[i].y = i * 30;quads[i].scaleX = i / 10;quads[i].scaleY = i / 10;}
 
function addieren (Evt:Event):void {for (var i:int = 1; i < anzahl; i++) {quads[i].x += (mouseX - (quads[i].x))/(i*2);quads[i].y += (mouseY - (quads[i].y))/(i*2);quads[i].rotation += i/80;}}

Links

http://lab.tojio.com - die Seite für den Mac-Server

http://www.wiiflash.org - die Seite für den PC-Server

http://www.wiiflash.org/wiiflash-asdoc - die Dokumentation

http://code.google.com/p/wiiflash - Wiiflash bei Google Code

http://www.wiili.org - eine Wiki über die Wii für Linux, hier gibt es auch eine genauere Beschreibung der Wiimote