Friday, August 28, 2009

[game] Fun with the WiiMote

I have been enjoying some time off and, as always, I tried to explore a few new things. I have seen many cool applications exploiting Wiimotes, and I decided it was about time for me to give it a try.

To start with something, I decided to hack in Ragdoll Smasher and to use the accelerometer to drive the ragdoll.

I plugged in the bluetooth USB dongle that some vendor convinced me to buy with my first mobile phone - I'd have never guessed that I would actually use it one day! - and I downloaded what seemed to be the main library for talking to a WiiMote from C++: WiiYourself!

WiiYourself! comes as a single cpp file, and a commented demo code - that's just perfect to start. Everything works very well, and apart from the painful part of downloading and installing the Windows Driver Kit it was really easy to get the wiimote working, and to call WiiYourself from my own code.

I put all the WiiYourself intialization in a separate thread, so that it can handle gracefully waiting for new Wiimotes or Wiimote disconnections.

Now, here is when the interesting part kicks in. What I wanted to achieve is to let the user give some impulses to the Wiimote to throw the ragdoll in one direction or another.

However, this is an accelerometer, and you do not get a nice, clean vector telling you in which direction the user moved the Wiimote. On the images below, I have overlaid the output of the Wiimote accelerometer x,y and z axis. The user has applied a left ( +x ) impulse. The x axis is shown in red.

Now the same for a right ( -x ) impulse:

You can probably see the pattern appearing: For a left impulse, the curve goes up first, then down and then comes back to low values. For a right impulse the curve goes down first, and then up. I used this property to implement a simple 'impulse' detector on each axis. The idea is illustrated by the image below:

The blue line is the 'zero' (Note: the z axis is not centered on zero due to gravity! On my Wiimote it is centered on 1). I am using a threshold to detect when the curve goes up and down. By simply tracking whether the curve does a up/down or down/up impulse - in a limited time window - I can easily detect impulses applied by the user to the controller. The 'height' of the bumps gives me an indication of the strength.

This very simple approach works quite well in practice, and I can throw the ragdoll in all directions with small impulses applied to the Wiimote.