Build a Wiimote Controlled Lightsaber Using WiiFlash and Papervision3D

Share

Today we’re going to build a wiimote controlled lightsaber using WiiFlash and Papervision3D. The goal of this tutorial will be to learn how to use a wiimote within flash and how to combine it with papervision3D. Afterwards, of course, you can use this app to train for your Jedi mastership.

Step 1 – Download the Necessary Packages

The first step is also the simplest one; download the packages we need. Go to blog.papervision3d.org and wiiflash.bytearray.org to download the latest version of both packages. Unzip both packages and place the libraries (a directory called ‘org’) in your working directory.

Step 2 – Create the Flash Document

Since this project will be entirely written in ActionScript 3.0, the first thing we’ll need to do is create a new Flash document and make a reference to our main class: LightSaber. Save it as "lightsaber.fla" in your working directory.

Next, create an empty class called "LightSaber". This will be the main class where everything gets initialized. Save it as "LightSaber.as" in the working directory.

package
{
	public class LightSaber
	{
		public function LightSaber()
		{
		}
	}
}

Step 3 – The LightSaber3D Class

The next class we’re going to create is called LightSaber3D and this one will contain all the 3D logic. Save it as ‘LightSaber3D.as’ in your working directory.

package
{
	public class LightSaber3D
	{
		public function LightSaber3D()
		{
		}
	}
}

Step 4 – The Complete LightSaber Class

Now that all the classes and libraries are in place we can start filling them in. We’ll start with setting up the wiimote communication. The following code is the complete code for the LightSaber class; in the following steps we’ll discuss it in more detail.

package
{
	import flash.display.*;
	import flash.events.*;

	import org.wiiflash.Wiimote;
	import org.wiiflash.events.*;

	import LightSaber3D;

	public class LightSaber extends Sprite
	{
		private var wiimote:Wiimote;
		private var lightSaber3D:LightSaber3D;

		public function LightSaber():void
		{
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;			

			wiimote = new 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);
		}

		private function updateWiimote( pEvent:WiimoteEvent ):void
		{
			lightSaber3D.updateLightSaber3D(wiimote.pitch);
		}

		private function buttonPressed( pEvent:ButtonEvent ):void
		{
			lightSaber3D.turnOnLightSaber();
		}

		private function buttonReleased( pEvent:ButtonEvent ):void
		{
			lightSaber3D.turnOffLightSaber();
		}
	}
}

Step 5 – Import..

import flash.display.*;
import flash.events.*;

import org.wiiflash.Wiimote;
import org.wiiflash.events.*;

import LightSaber3D;

Before we can do anything with the wiimote within flash, we’ll need to include the wiiflash libraries in our class. For this particular project we’ll need the main WiiMote class and the wiimote events. We also include our LightSaber3D class, but that will be discussed later on.

Step 6 – General Concept

Before discussing what the code actually does and why we need it, it’s very important to know the "general concept" behind this application. We’re building a 3d lightsaber which we can swing around using a wiimote and as an extra feature we’ll be able to switch it on and off using the "B" button on the back of the wiimote.

How do we achieve all this? Well I’ve decided to break it up into two classes; one that handles the wiimote and one that controls all the 3D aspects. The wiimote class receives the data from the wiimote and passes it on to the 3D class. This is done through event handlers from the wiimote class.

public function LightSaber():void
{
	stage.align = StageAlign.TOP_LEFT;
	stage.scaleMode = StageScaleMode.NO_SCALE;			

	wiimote = new Wiimote();
	wiimote.addEventListener( Event.CONNECT, onWiimoteConnect );

	wiimote.connect();
}

First, we create a new instance of the wiimote class and add an event listener called "Event.CONNECT" to this object. This is done because we only want the application to run when there is a connection with a wiimote. Next, we try to connect to the wiimote server. If it works, the "CONNECT" event will be dispatched and the application will start.

The workings of the wiimote server will be explained at the end of this tutorial.

Step 7 – Function onWiimoteConnect

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);
}

If we’re connected to the wiimote server and a wiimote is found, this function will be executed. It will create a new instance of the lightsaber3D class and add it to the stage. Next, a couple of internal functions will be called which will create a 3D lightsaber and turn it "on". The next 3 lines are more important for us right now. They add 3 event listeners to the wiimote object and these listeners will pass on the necessary data to the lightsaber3D class.

For more information on the available wiimote events, take a look at the wiiflash API, it’s included in the package you downloaded earlier on.

Step 8 – Basic Controls

private function updateWiimote( pEvent:WiimoteEvent ):void
{
	lightSaber3D.updateLightSaber3D(wiimote.pitch);
}

private function buttonPressed( pEvent:ButtonEvent ):void
{
	lightSaber3D.turnOnLightSaber();
}

private function buttonReleased( pEvent:ButtonEvent ):void
{
	lightSaber3D.turnOffLightSaber();
}

These 3 functions will call the 3 public functions inside the lightsaber3D class. It’s pretty straightforward, as long as you press the "B" button the lightaber is turned on and if you move the wiimote, the value of the pitch sensor is passed to the function that controls the movement of the lightsaber.

By breaking these classes up and using event listeners it will be very easy to reuse both classes in other projects. They’re not dependent on each other so you can replace the wiimote with a normal keyboard or mouse without having to adjust any of the lightsaber3D code. Hence, the power of object oriented programming :-)

Step 9 – Papervision3D

Since all wiimote communication is set up, it’s time to start doing some 3D programming. For this we use Papervision3D. We’ll use one class to set up a 3D environment and build our lightsaber in it. Normally you would break it up into several classes but since we only have one lightsaber it’s not really necessary to do it here. Saying that, it’s quite a sizeable chunk of code, so to prevent your browser from falling over, you can download the LightSaber3D.as file for viewing.

First, we’ll need the necessary classes from the papervsion3D library to build a 3D environment. This will consist of a viewport, a scene, a camera and a rendering engine. For more details on the concept of 3d programming, take a look at the website of papervision3D.

Since our lightsaber will consist of 2 cylinders with a little glow filter attached to it we only need the 3 above-mentioned classes. The glow filter we use is part of the standard flash library.

Step 10 – The Lightsaber

public function LightSaber3D():void
{
	viewport = new Viewport3D(600, 450, true);
	addChild(viewport);

	renderer = new BasicRenderEngine();
	scene = new Scene3D();
	camera = new Camera3D();
}

Now that we have all available classes, it’s time to build the lightsaber – but before we can do that we need a 3D environment. We’ll set up a viewport, a sort of window through which we look, a scene where we place our objects, a camera that acts like the "eye" and finally the rendering engine which renders it all.

We use the constructor for this, since that’s the most logical place. As you probably remember from Step 5, we call this constructor when there is a connection with the wiimote server, just in time when we need them.

Step 11 – Adding the 3D Objects to Stage

public function buildLightSaber():void
{
	lsHolder = new DisplayObject3D();

	var handleColor = new ColorMaterial(0xCCCCCC);
	var bladeColor = new ColorMaterial(0x99FF33, 0.6);

	// give the lightsaber some color
	handle = new Cylinder(handleColor, 16, 150, 8, 3, 16);
	blade = new Cylinder(bladeColor, 12, 500, 8, 3, 8);

The function buildLightSaber is the one that actually adds all the 3D objects to the stage. The lightsaber consists of a blade and handle, which are placed in a container. Blade and handle are simple cylinders, with a color material on the surface. Notice that the blade is made slightly transparent by adding an extra parameter to the color material constructor.

			blade.useOwnContainer = true;
			blade.filters = [new GlowFilter(0x66FF33)];

The blade has a very simple glowfilter attached to it, so it will have that genuine lightsaber glow around it. At this point you could replace the color material with a bitmap material to add some textures, but here we’ll just use a simple color.

Step 12 – Lightsaber Container

			// position the blade & handle
			handle.y = 0;
			blade.y = 325;

			lsHolder.addChild(handle);
			lsHolder.addChild(blade);

			// place the holder somewhat in the center of the screen
			lsHolder.y = -200;

			scene.addChild(lsHolder);

Now we add both objects to a container called "lsHolder". We do this because we want one object which we can manipulate. Finally, we add the container to the scene so it will be visible when we render everything.

			// now move the camera somewhat to the right for a good angle on the lightsaber
			camera.x = -200;
			// ...but it still needs to look at the lightsaber
			camera.lookAt(lsHolder);

As a final step we move the camera 200 pixels to the left, so we have a slight angle on the lightsaber. This is purely done to make what we’re doing more visible. Of course, we also need to tell the camera where to look, so that’s what we do in the last line.

Step 13 – Render the Scene

			// now render the scene so we can actually see the lightsaber
			renderer.renderScene(scene, camera, viewport);

The last line of the buildLightSaber function is very important and needs some attention. Whatever you program in 3D will be invisible until you render it, so that’s what we do here.

Step 14 – On and Off

Earlier on we decided that we want the lightsaber to be active only when the "B" button on the back of the wiimote is pressed. Therefore we added two event listeners, one that is dispatched when the "B" button is pressed – and another when the "B" button is released. The next two functions will be invoked on those events.

		public function turnOnLightSaber():void
		{
			blade.visible = true;
		}

		public function turnOffLightSaber():void
		{
			blade.visible = false;
		}

To create an on/off effect for our lightsaber we just make the blade visible or invisible. With some extra effort you could add a routine which makes the blade grow and shrink, but that’s not necessary for this tutorial.

Step 15 – Add a Little Magic

		public function updateLightSaber3D(pitch:Number)
		{
			// calcaulte the difference in degrees of the pitch
			var newPitch:Number = 90 + Math.round(pitch * (180/Math.PI) - lsHolder.rotationX);

			// apply it
			lsHolder.pitch(newPitch);

			// and render it.
			renderer.renderScene(scene, camera, viewport);
		}
		

This is the function where the magic happens. Every time the wiimote sends data to our application this function will be invoked. For our little application we only need the value of the pitch sensor, so that’s passed on as a parameter to this function. As explained before, it should be easy to replace the wiimote with a mouse or keyboard without having to change this code.

		var newPitch:Number = 90 + Math.round(pitch * (180/Math.PI) - lsHolder.rotationX);

The pitch value of the wiimote will be given in radians, but the pitch function of papervision3D expects degrees, so we need to do some calculations. Because the pitch function uses a relative angle we need to subtract the current angle from the value of the pitch sensor. Otherwise the lightsaber would spin out of control.

			// apply it
			lsHolder.pitch(newPitch);

			// and render it.
			renderer.renderScene(scene, camera, viewport);

After pitching the container to its new value, we need to render the scene again.

Step 16 – Finished!

And we’re done! With only 151 lines of code we’ve created our own Jedi lightsaber training program! Though not before we export it of course. To get the best performance we should run it as a stand-alone projector. Go to your publish settings, tap the projector boxes and use the settings as listed below.

Now publish it and you’re done.

Step 17 – WiiFlash Server

Not quite… Before we can run this application we need to start the wiiflash server and connect the wiimote to it. This should be very simple. Run the server (you’ll find it in the package you downloaded in Step 1) and press buttons 1 + 2 on your wiimote.

The final result!

A Final Note.

A quick note on building applications and games that use the wiimote. The sensor data you receive from the wiimote isn’t extremely accurate. You’ll notice that in the application we’ve just built. That’s why most of the games you’ll find on the Wii are based on motion recognition. This means that the system (in this case the Wii) recognizes a certain movement made with a wiimote and attaches a certain (visual) action to it. For example, if you make movement that resembles serving a tennis ball, the Wii will calculate your speed and direction given the sensor data and translate that to a fluent 3d animation. The calculations involved with these routines are very complex and therefore not included in this tutorial.

May the force be with you..

Related Posts

Add Comment

Discussion 34 Comments

  1. chrisberthe says:

    Haha :) That’s awesome.

  2. samBrown says:

    awesome. Unfortunately I’m Wii-less – anyone have any video of this in action?

  3. Wii Flash is awesome a funny, excellent tutorial and I agree with Sam if We can view a video in action will be great.

  4. Clemente G says:

    Nice tutorial, I wish I had a Wii to test this on.

  5. Simon says:

    This looks really cool… I’m gonna try it right away :p

  6. Hassan says:

    What are the hardware requirements for this tut? I mean, except Wii console. Thanks for this great tut.

  7. Abe says:

    I found a video of it in use here…http://www.youtube.com/watch?v=5C-ZmuY-CTE

    It would be great though if we could see this application in action though, great tutorial

  8. Franky says:

    WTFunky this is amazing!
    OMG
    I wish i had a wii to try this out!

    Is there a flash DSi library?

  9. :) thx for the pos. feedback. I tried to make a video of the result, but I couldn’t find a proper screencapture app. for the mac.. If somebody has a suggestion?

    @hassan, you just need a wiimote (you don’t even need the console) and a pc/mac with bluetooth. The website of the wiiflash has some extensive tutorials about connecting your wiimote with your pc/mac.

  10. André says:

    wow, i´ve got a wii just to test this (not mine), but this is f&$#* amazing!!!

    Unfortunatly i am wiiless too, just tested and gave back to the owner, but this tut has inspired me to buy one… your tut is really great tut

    Congratulations!!!!

  11. Mike says:

    This is great!

    I’ve been trying to find a tutorial that goes one step further to make the wii buttons functional to control/work as the mouse and have the “A” button on the Wii equal mouse left click, Wii Trigger/”B” button equal right mouse click.

    Suggestions? Or better yet, could you do a follow up tut to this one? I’ve gotta imagine there’s a huge demand for a tut series on WiiFlash AS3 games.

  12. Mike says:

    Ok, I didn’t scroll down and notice the code to activate the “A” button for the Wiimote on the WiiFlash google code download site.

    But it would still be great and valuable to have a running WiiFlash game tutorial series.

  13. Jake says:

    I did some wiiFlash work last month. Incredibly fun and it’s good to see some nice tutorials showing it off.

    Couple other things to keep in mind while working with wiiFlash:

    1. Its still relatively new, so the server can be unstable at times.

    2.It seems to work best with fewer laptops/computers running with bluetooth, Specially when connecting the wiiMote. I noticed it gets really spotty, unreliable with over 10 computers running.

    3.The newer/better your bluetooth the better connectivity reliability you’ll have. What was some times spotty connectivity on my 3 year old iMac, never failed or lost connection with a brand new macbook pro that has the latest bluetooth technology.(I know this is common sense but you’d be surprised)

  14. Mike says:

    I’m having issues with WiiFlash that I was hoping someone could explain.

    I got the lightsaber working (if anyone needs a demo, just download the “Source: Get the code” at the top of this page) and with the Wii Remote demo test:

    http://wiiflash.bytearray.org/online-demo/

    Problem is, I can’t get my wii remote to work with any of the other posted wii flash games online or the WiiCar demo that comes with the Papervision3D download package.

    I see some blogs mentioning creating a sensor bar with things as basic as two candles.

    Do I need to create or use my current sensor bar to play WiiFlash games?

    And if so, how come I can play both this light saber demo and WiiFlash demo remote without a sensor bar?

    • Mike says:

      Ok, I think I got some clarity on some of this.

      WiiArcade, etc. are normal flash games that can be played with the WiiMote when surfing their site on a Wii, and not from your cpu.

      But it doesn’t explain why I can’t get the Wii 3D car demo to work, since it’s intended to be played on the PC using a bluetooth & WiiFlash server enabled WiiMote like the above lightsaber demo.

      It would be great to get an answer on why the 3d car or other content built for the PC WiiMote doesn’t work.

  15. Akkis says:

    You are perfect!!! What a tutorial! Thank you!

  16. Diego SA says:

    I’d like to see it working. Couldn’t you post the video of it working with a Wiimote?

  17. RUGRLN says:

    Wait a sec…You can get the Wiiiimote to work on the PC with Flash?!?!?! amn this awesome…

  18. kino says:

    Ummmm i hope u can make it with mouse so we can see it in action

  19. Khanhkidy says:

    Oh, awesome. But I’d like it can be used with my phone, not remote . Is it posible ?

  20. uni says:

    Hi is the source code for this still available. it keeps timing out when trying to access the zip.
    Unfortunately I seem incapable of following the tutorial, i’m getting socket error messages.
    i’ve managed to connect the mote to my machine but now I have nothing to test it on.

  21. uni says:

    never mind i tried again and i managed to download it. Very cool. Thanks for that. I’m going to try and extend it to move around on x/y/z axis.
    Will post back if I have success if anyone is interested.

  22. CoOkie Company says:

    This looked awsome ,didnt think you could do something like this in flash ,unlucky i have a wii remote but i don’t have Bluetooth on my comp D:

  23. pim says:

    gurb-disturb, video pleaze!
    ik mis je

  24. Guilherme says:

    Where is the demo man?!?

  25. Anononymous says:

    wow i gotta try this xD

  26. CorvosKK says:

    Hey, I’m having trouble getting it to work. The wiimote is connecting fine and even though the wiiFlash Server recognizes the remote, the Flash file itself isn’t recognizing it. The addChild function isn’t even initializing to add the LightSaber to the screen. Not sure really what’s going wrong with it, but I would like to use the wiiFlash Server for my final project in my AS3.0 class so any help is greatly appreciated. Thanks!

  27. Anonymous says:

    Hi,

    I am having trouble with wiimote connection also. I get as far as the wiiflashserverj log window saying “WiiMoteAdapter 0: starting up” but then it just hangs…

    ..sometimes the application then crashes on me and looking at the error report it seems to be mentioning java and things being blocked.. idk

    any ideas anyone?

    thanks

  28. fad says:

    i gota try this!

  29. bwigahne says:

    any one know how to create a class thats the only thing im stuck on thanx

Add a Comment