How to: Make a Light Saber from a Wii Remote in .NET (C#)
Here’s a quick and fun project that I just used as a fun coding exercise. I was just walking through Toys R Us the other day, and saw a Light Saber shell designed to enclose a Wiimote. I thought that would be cool, but even though I’m not much of a Star Wars nerd, I do know that most light sabers fall short of a quality audio experience.
So wouldn’t it be cool if my PC could simulate the light saber sound effects from a Wiimote?
Here we go…
Pair The Wiimote with your PC
Your PC needs to be Bluetooth capable (or have a Bluetooth adapter installed). With your Wiimote in hand, press the 1 and 2 buttons until the blue LEDs start flashing. While they’re flashing, you can add it as a Bluetooth device to your PC.
If prompted for a pairing code, just select “Pair without using a code”, and the Nintendo input device will appear.
Plan a little (How to make Light Saber Audio)
A light saber essentially has 2 ongoing sounds. The first is the low, droning “hummmmmmm” that’s always there. So we’ll need a constant “hummmmm” wave file. And the second is a higher-pitched “swing” sound. Our app should just play both in a loop, and increase the volume of the “swing” sound proportional to the amount of motion detected in the Wii controller. Spec – done.
Getting The Code Together
I got the following components to make this come together:
- WiimoteLib (.NET code library for Wiimote) – http://wiimotelib.codeplex.com/
- Googled “Light Saber Sound Effect” to find the droning, constant “hum”
- Found a Sci-Fi electricity sound to be the “swing” (I must admit, this could be better, but it’s good enough for this app)
- DirectX / DirectSound managed wrappers (Microsoft.DirectX.dll and Microsoft.DirectX.DirectSound.dll)
Use DirectSound and WAV Files
Because we’re looping sounds, we need a bit higher performance than MP3 files and Windows Media Player components. That’s why it’s important to use the DirectSound library with playback loop buffering and uncompressed audio files.
Make sure you compile the application as 32-bit (x86) as DirectX may complain with 64-bit or Any CPU compilation.
Calculating Light Saber Motion
So, I’ve got the following app set up (hit Turn On to enable the Saber sounds, and if you have a Wiimote connected, it will detect it on app startup):
To calculate the Wiimote “swing” motion, this gets a little difficult. Wiimotes report what position they’re in (X, Y, and Z) axis, but there’s no way to tell how fast they’re moving through the air (i.e., true acceleration). If you’ve ever been able to trick your Wii and become an accomplished Wii bowler from the couch, then you know what I mean.
So after a few different methods, here’s the way I’ve calculated the Saber “swing” motion:
- Re-evaluate the Wii controller position no more than every 50 milliseconds
- Measure the most recent X, Y, and Z positions with the previously reported ones, and calculate the differences
- Add the differences together (X+Y+Z) to get the cumulative “motion change factor” (I called this the “Saber Force”)
- Use the “Saber Force” to set the volume of the Swing WAV file.
This works okay, but could probably be improved to make it smoother and more responsive.
I would suggest playing with the “Constant Hum” and “Swing Intensity” sliders after turning the saber on, just to get the feel of how this thing works. Once you hit the “Turn Wiimote into Saber” button, the Swing Intensity slider is disabled and controlled by the Wiimote motion calculations. There’s little to no exception handling or app state management as this is a quick and dirty play application. If you wanted to actually create something with this, it does provide a good starting point with ideas.
The .zip contains the compiled application (if you just want to run it and play), the Visual Studio solution, and the reference DLLs and sound files that I used.