Vandaag gaan we een Wiimote controlled lightsaber bouwen met WiiFlash en Papervision3D. Het doel van deze zelfstudie is om te leren hoe je een wiimote in de flits gebruikt en hoe je hem combineert met papervision3D. Naderhand kunt u deze app natuurlijk gebruiken om te trainen voor uw Jedi-meesterschap.
De eerste stap is ook de eenvoudigste; download de pakketten die we nodig hebben. Ga naar blog.papervision3d.org en wiiflash.bytearray.org om de nieuwste versie van beide pakketten te downloaden. Pak beide pakketten uit en plaats de bibliotheken (een map genaamd 'org') in uw werkdirectory.
Aangezien dit project volledig in ActionScript 3.0 zal worden geschreven, is het eerste wat we moeten doen een nieuw Flash-document maken en een verwijzing naar onze hoofdklasse maken: LightSaber. Sla het op als "lightsaber.fla" in je werkmap.
Maak vervolgens een lege klasse genaamd "LightSaber". Dit wordt de hoofdklasse waar alles wordt geïnitialiseerd. Sla het op als "LightSaber.as" in de werkdirectory.
package public class LightSaber openbare functie LightSaber ()
De volgende klasse die we gaan maken, wordt LightSaber3D genoemd en deze bevat alle 3D-logica. Sla het op als 'LightSaber3D.as' in je werkmap.
pakket public class LightSaber3D openbare functie LightSaber3D ()
Nu alle klassen en bibliotheken aanwezig zijn, kunnen we beginnen ze in te vullen. We beginnen met het opzetten van de wiimote-communicatie. De volgende code is de volledige code voor de klasse LightSaber; in de volgende stappen zullen we het in meer detail bespreken.
pakket import flash.display. *; import flash.events. *; import org.wiiflash.Wiimote; import org.wiiflash.events. *; importeer LightSaber3D; openbare klasse LightSaber breidt Sprite uit private var wiimote: Wiimote; privé var lightSaber3D: LightSaber3D; openbare functie LightSaber (): void stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; wiimote = nieuwe Wiimote (); wiimote.addEventListener (Event.CONNECT, onWiimoteConnect); wiimote.connect (); private function onWiimoteConnect (pEvent: Event): void lightSaber3D = new LightSaber3D (); addChild (lightSaber3D) lightSaber3D.buildLightSaber (); lightSaber3D.turnOffLightSaber (); wiimote.addEventListener (WiimoteEvent.UPDATE, updateWiimote); wiimote.addEventListener (ButtonEvent.B_PRESS, buttonPressed); wiimote.addEventListener (ButtonEvent.B_RELEASE, buttonReleased); persoonlijke functie updateWiimote (pEvent: WiimoteEvent): void lightSaber3D.updateLightSaber3D (wiimote.pitch); knop privéfunctie ingedrukt (pEvent: ButtonEvent): void lightSaber3D.turnOnLightSaber (); knop privéfunctieReleased (pEvent: ButtonEvent): void lightSaber3D.turnOffLightSaber ();
import flash.display. *; import flash.events. *; import org.wiiflash.Wiimote; import org.wiiflash.events. *; importeer LightSaber3D;
Voordat we iets kunnen doen met de wiimote binnen de flits, moeten we de wiiflash-bibliotheken in onze klas opnemen. Voor dit specifieke project hebben we de hoofdklasse WiiMote en de wiimote-evenementen nodig. We nemen ook onze klasse LightSaber3D op, maar dat wordt later besproken.
Voordat we bespreken wat de code nu precies doet en waarom we die nodig hebben, is het erg belangrijk om het 'algemene concept' achter deze toepassing te kennen. We bouwen een 3d lightsaber die we kunnen rondzwaaien met een wiimote en als een extra functie zullen we het kunnen in- en uitschakelen met de "B" knop aan de achterkant van de wiimote.
Hoe bereiken we dit allemaal? Welnu, ik heb besloten het in twee klassen op te splitsen; een die de wiimote behandelt en een die alle 3D-aspecten bestuurt. De wiimote-klasse ontvangt de gegevens van de wiimote en geeft deze door aan de 3D-klasse. Dit wordt gedaan door event handlers uit de wiimote-klasse.
openbare functie LightSaber (): void stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; wiimote = nieuwe Wiimote (); wiimote.addEventListener (Event.CONNECT, onWiimoteConnect); wiimote.connect ();
Eerst maken we een nieuw exemplaar van de wiimote-klasse en voegen we een gebeurtenislistener toe met de naam "Event.CONNECT" aan dit object. Dit wordt gedaan omdat we alleen willen dat de applicatie wordt uitgevoerd als er een verbinding is met een wiimote. Vervolgens proberen we verbinding te maken met de wiimote-server. Als het werkt, wordt de gebeurtenis "CONNECT" verzonden en start de toepassing.
De werking van de wiimote-server zal aan het einde van deze tutorial worden uitgelegd.
private function onWiimoteConnect (pEvent: Event): void lightSaber3D = new LightSaber3D (); addChild (lightSaber3D) lightSaber3D.buildLightSaber (); lightSaber3D.turnOffLightSaber (); wiimote.addEventListener (WiimoteEvent.UPDATE, updateWiimote); wiimote.addEventListener (ButtonEvent.B_PRESS, buttonPressed); wiimote.addEventListener (ButtonEvent.B_RELEASE, buttonReleased);
Als we verbonden zijn met de wiimote-server en een wiimote wordt gevonden, zal deze functie worden uitgevoerd. Het maakt een nieuw exemplaar van de klasse lightsaber3D en voegt dit toe aan het werkgebied. Vervolgens worden een aantal interne functies aangeroepen die een 3D-lichtzwaard maken en deze "aan" zetten. De volgende 3 regels zijn nu belangrijker voor ons. Ze voegen 3 gebeurtenislisteners toe aan het wiimote-object en deze luisteraars geven de benodigde gegevens door aan de klasse lightsaber3D.
Voor meer informatie over de beschikbare wiimote-evenementen, bekijk de wiiflash API, deze is opgenomen in het pakket dat je eerder hebt gedownload op.
persoonlijke functie updateWiimote (pEvent: WiimoteEvent): void lightSaber3D.updateLightSaber3D (wiimote.pitch); knop privéfunctie ingedrukt (pEvent: ButtonEvent): void lightSaber3D.turnOnLightSaber (); knop privéfunctieReleased (pEvent: ButtonEvent): void lightSaber3D.turnOffLightSaber ();
Deze 3 functies noemen de 3 openbare functies binnen de klasse lightsaber3D. Het is vrij eenvoudig, zolang je op de "B" -knop drukt, wordt de lichtzaag ingeschakeld en als je de wiimote beweegt, wordt de waarde van de pitch-sensor doorgegeven aan de functie die de beweging van de lichtzaag regelt.
Door deze klassen op te breken en gebeurtenislisteners te gebruiken, is het heel eenvoudig om beide klassen in andere projecten opnieuw te gebruiken. Ze zijn niet afhankelijk van elkaar, dus je kunt de wiimote vervangen door een normaal toetsenbord of muis zonder een van de lightsaber3D-codes aan te passen. Vandaar de kracht van objectgeoriënteerd programmeren :-)
Omdat alle wiimote-communicatie is ingesteld, is het tijd om wat 3D-programmering te beginnen. Hiervoor gebruiken we Papervision3D. We zullen één klas gebruiken om een 3D-omgeving in te stellen en onze lightsaber erin te bouwen. Normaal gesproken zou je het opdelen in verschillende klassen, maar omdat we maar één lightsaber hebben, is het niet echt nodig om het hier te doen. Zeggen dat, het is nogal een flink stuk van de code, dus om te voorkomen dat je browser omvalt, kun je het LightSaber3D.as bestand downloaden om te bekijken.
Ten eerste zullen we de nodige klassen uit de bibliotheek van papervsion3D nodig hebben om een 3D-omgeving te bouwen. Dit bestaat uit een kijkvenster, een scène, een camera en een rendering-engine. Raadpleeg de website van papervision3D voor meer informatie over het concept van 3D-programmeren.
Omdat onze lichtzwaard zal bestaan uit 2 cilinders met een klein gloeifilter eraan, hebben we alleen de 3 bovengenoemde klassen nodig. Het gloeifilter dat we gebruiken, maakt deel uit van de standaard flashbibliotheek.
openbare functie LightSaber3D (): void viewport = new Viewport3D (600, 450, true); addChild (kijkvenster); renderer = nieuwe BasicRenderEngine (); scène = nieuwe Scene3D (); camera = nieuwe Camera3D ();
Nu we alle beschikbare klassen hebben, is het tijd om de lichtzwaard te bouwen - maar voordat we dat kunnen doen hebben we een 3D-omgeving nodig. We zullen een kijkvenster opzetten, een soort venster waardoor we kijken, een scène waarin we onze objecten plaatsen, een camera die als het "oog" fungeert en tenslotte de rendering-engine die het allemaal weergeeft.
We gebruiken de constructor hiervoor, omdat dat de meest logische plaats is. Zoals je je waarschijnlijk herinnert uit stap 5, noemen we deze constructor wanneer er een verbinding is met de wiimote-server, net op tijd wanneer we ze nodig hebben.
public function buildLightSaber (): void lsHolder = new DisplayObject3D (); var handleColor = nieuw ColorMaterial (0xCCCCCC); var bladeColor = nieuw ColorMaterial (0x99FF33, 0.6); // geef de lichtzwaard een kleurhendel = nieuwe cilinder (greepkleur, 16, 150, 8, 3, 16); lemmet = nieuwe cilinder (bladeColor, 12, 500, 8, 3, 8);
De functie buildLightSaber is degene die alle 3D-objecten daadwerkelijk aan het werkgebied toevoegt. De lichtzwaard bestaat uit een mes en een handvat, die in een container worden geplaatst. Blad en handvat zijn eenvoudige cilinders, met een kleurmateriaal op het oppervlak. Merk op dat het blad enigszins transparant is gemaakt door een extra parameter toe te voegen aan de fabrikant van het kleurenmateriaal.
blade.useOwnContainer = true; blade.filters = [nieuw GlowFilter (0x66FF33)];
Het blad heeft een zeer eenvoudig glowfilter eraan bevestigd, dus het zal die echte lichtzwaard er omheen doen gloeien. Op dit punt zou je het kleurenmateriaal kunnen vervangen door een bitmap-materiaal om wat texturen toe te voegen, maar hier gebruiken we gewoon een eenvoudige kleur.
// plaats het mes en de handgreep.y = 0; blade.y = 325; lsHolder.addChild (handgreep); lsHolder.addChild (lemmet); // plaats de houder enigszins in het midden van het scherm lsHolder.y = -200; scene.addChild (lsHolder);
Nu voegen we beide objecten toe aan een container met de naam "lsHolder". We doen dit omdat we een object willen dat we kunnen manipuleren. Ten slotte voegen we de container toe aan de scène, zodat deze zichtbaar is wanneer we alles weergeven.
// beweeg de camera nu enigszins naar rechts voor een goede hoek op de lichtzwaard camera.x = -200; // ... maar het moet nog steeds naar de lightsaber camera kijken .lookAt (lsHolder);
Als laatste stap verplaatsen we de camera 200 pixels naar links, dus we hebben een lichte hoek op de lichtzwaard. Dit is puur gedaan om wat we doen zichtbaarder te maken. Natuurlijk moeten we de camera ook vertellen waar hij moet kijken, dus dat doen we in de laatste regel.
// render nu de scène zodat we de lightsaber renderer.renderScene (scène, camera, viewport) kunnen zien;
De laatste regel van de buildLightSaber-functie is erg belangrijk en heeft enige aandacht nodig. Wat je ook in 3D programmeert, is onzichtbaar totdat je het rendert, dus dat is wat we hier doen.
Eerder hebben we besloten dat we de lichtzwaard alleen actief willen hebben wanneer de "B" -knop op de achterkant van de wiimote wordt ingedrukt. Daarom hebben we twee gebeurtenislisteners toegevoegd, een die wordt verzonden wanneer op de knop "B" wordt gedrukt - en een andere wanneer de knop "B" wordt losgelaten. De volgende twee functies worden aangeroepen voor die evenementen.
openbare functie turnOnLightSaber (): void blade.visible = true; public function turnOffLightSaber (): void blade.visible = false;
Om een aan / uit-effect te creëren voor onze lichtzwaard maken we het blad gewoon zichtbaar of onzichtbaar. Met wat extra inspanning zou je een routine kunnen toevoegen die het blad doet groeien en krimpen, maar dat is niet nodig voor deze tutorial.
publieke functie updateLightSaber3D (pitch: Number) // calcaulte het verschil in graden van de toonhoogte var newPitch: Number = 90 + Math.round (pitch * (180 / Math.PI) - lsHolder.rotationX); // apply it lsHolder.pitch (newPitch); // en render het. renderer.renderScene (scène, camera, viewport);
Dit is de functie waar de magie gebeurt. Telkens wanneer de wiimote gegevens naar onze applicatie verzendt, wordt deze functie geactiveerd. Voor onze kleine applicatie hebben we alleen de waarde van de pitch-sensor nodig, dus die wordt doorgegeven als een parameter voor deze functie. Zoals eerder uitgelegd, zou het gemakkelijk moeten zijn om de wiimote te vervangen door een muis of toetsenbord zonder deze code te hoeven veranderen.
var newPitch: Number = 90 + Math.round (pitch * (180 / Math.PI) - lsHolder.rotationX);
De pitchwaarde van de wiimote wordt in radialen gegeven, maar de pitchfunctie van papervision3D verwacht graden, dus we moeten wat berekeningen doen. Omdat de pitch-functie een relatieve hoek gebruikt, moeten we de huidige hoek aftrekken van de waarde van de pitch-sensor. Anders zou de lichtzaag uit de hand lopen.
// apply it lsHolder.pitch (newPitch); // en render het. renderer.renderScene (scène, camera, viewport);
Nadat de container op zijn nieuwe waarde is geplaatst, moeten we de scène opnieuw weergeven.
En we zijn klaar! Met slechts 151 regels code hebben we ons eigen Jedi lightsaber trainingsprogramma gemaakt! Hoewel niet voordat we het natuurlijk exporteren. Om de beste prestaties te krijgen, zouden we het moeten uitvoeren als een stand-alone projector. Ga naar je publicatie-instellingen, tik op de projectordozen en gebruik de onderstaande instellingen.
Publiceer het nu en je bent klaar.
Niet helemaal ... Voordat we deze applicatie kunnen uitvoeren, moeten we de wiiflash-server starten en de wiimote daarop aansluiten. Dit zou heel eenvoudig moeten zijn. Start de server (je vindt hem in het pakket dat je in stap 1 hebt gedownload) en druk op de knoppen 1 + 2 op je wi-fioot.
Een korte opmerking over het bouwen van applicaties en games die de wiimote gebruiken. De sensorgegevens die u van de wiimote ontvangt, zijn niet extreem nauwkeurig. Dat merk je in de applicatie die we net hebben gebouwd. Daarom zijn de meeste spellen die je op de Wii vindt gebaseerd op bewegingsherkenning. Dit betekent dat het systeem (in dit geval de Wii) een bepaalde beweging herkent die gemaakt is met een wiimote en daaraan een bepaalde (visuele) actie koppelt. Als je bijvoorbeeld een beweging maakt die lijkt op het dienen van een tennisbal, zal de Wii je snelheid en richting berekenen aan de hand van de sensorgegevens en die vertalen naar een vloeiende 3d animatie. De berekeningen die met deze routines zijn gemoeid, zijn erg complex en daarom niet opgenomen in deze zelfstudie.
Moge de kracht bij je zijn ...