The accelerometer can be a good input method for some genres, think for example of racing games.

Using it is easy, it's just a matter of mapping a value to a direction, right?
Well, let's find out.

Before starting, notice that although in this article I'm talking about HTML5, the concepts are generic enough
to be applied to any technology.

Also, the examples used in this article will refer to a racing game, but the concepts still apply to any type of game
that uses the accelerometer.

In HTML5, the accelerometer data is accessed through the devicemotion event like this:

vartilt=0;window.addEventListener('devicemotion',function(event){// Unless you need complex control schemes,// you can measure how much the device is tilted// by using only 1 of the 3 axes.// In this case I'm using only the y axis.tilt=event.accelerationIncludingGravity.y;},false);

The accelerometer data is divided in 3 axes (x, y and z), and usually using 1 of the 3 axes is enough.

In order to find out which one of the axes is useful to your purposes, I recommend making a very simple application
that continuously outputs all the 3 values, and by tilting the device in the desired positions, see which value changes the most.

By doing this, you will also have a rough estimate on the possible range of values (for example you can have a device that when is perfectly
horizontal has an y value of 0, when tilted to the left goes down to about -5, and tilted to the right goes up to about 5).

And immediately after you try it, you will notice that the game is completely unplayable.

There are a couple of reasons to that:

The most obvious one is that it is impossible to stand perfectly still, so rarely tilt will be equals to 0.
Moreover, the accelerometer data will have some noise in it, so it will constantly change between similar values, even
when perfectly still.

So the next logical step is to use a tolerance, for example instead of comparing to 0, you can compare to -1 and 1 respectively,
and when you try again the game, you will notice that something still doesn't feel right.

I don't know exactly why, while the game behaviour now seems to make perfect sense, the feeling is still not right, but I have a theory:

we should shift our focus from a physical perspective to a psychological one.

Let me explain:

Let's consider what goes through the mind of the player while he tilts the device, for example to the left:

While he's tilting the device to the left, it is obvious that his intention is to turn the car to the left.
Once the car is in the position that the player wanted, he starts tilting the device to the right, in order to return to the horizontal position.

Here's our first problem: Due to the speed of the game (no one likes slow cars in games, right?), the car will continue to turn to the left
until the player reaches the horizontal position, and this will result in the car turning too much to the left.

The player will now try to adjust the position by turning slightly to the right, but the same problem will occur and now the car will be
too much to the right, and so on.

A possible solution to this problem might be to stop turning as soon as we detect that the player is changing direction, and the code to achieve that
may look like this:

var// Constants for the state machineAS_STILL=0,AS_TILTED_LEFT=1,AS_STILL_LEFT=2,AS_TILTED_RIGHT=3,AS_STILL_RIGHT=4,// Constants for the toleranceDYN_TILT=0.5,MIN_TILT=1,tilt,// The tilting of the devicedirection,// The computed direction based on the tiltingaccel_data={status:AS_STILL,min_tilt:0,max_tilt:0};window.addEventListener('devicemotion',function(event){tilt=event.accelerationIncludingGravity.y;if(accel_data.status===AS_TILTED_LEFT){if(tilt<accel_data.min_tilt){// The player is turning leftaccel_data.min_tilt=tilt;direction=-1;}elseif(tilt>=(accel_data.min_tilt+DYN_TILT)){// The player stopped turning leftaccel_data.min_tilt=tilt;accel_data.max_tilt=tilt;direction=0;accel_data.status=AS_STILL_LEFT;}else{// The player is still in the tilted left positiondirection=-1;}}elseif(accel_data.status===AS_STILL_LEFT){if(tilt>=0){// The device is now horizontaldirection=0;accel_data.status=AS_STILL;}elseif(tilt>accel_data.max_tilt){// The player is returning the device to the horizontal positionaccel_data.max_tilt=tilt;direction=0;}elseif(tilt<=(accel_data.max_tilt-DYN_TILT)){// The player has started turning left againaccel_data.min_tilt=tilt;accel_data.max_tilt=tilt;direction=-1;accel_data.status=AS_TILTED_LEFT;}else{// The player is still in the tilted left positiondirection=0;}}elseif(accel_data.status===AS_TILTED_RIGHT){if(tilt>accel_data.max_tilt){// The player is turning rightaccel_data.max_tilt=tilt;direction=1;}elseif(tilt<=(accel_data.max_tilt-DYN_TILT)){// The player stopped turning rightaccel_data.min_tilt=tilt;accel_data.max_tilt=tilt;direction=0;accel_data.status=AS_STILL_RIGHT;}else{// The player is still in the tilted right positiondirection=1;}}elseif(accel_data.status===AS_STILL_RIGHT){if(tilt<=0){// The device is now horizontaldirection=0;accel_data.status=AS_STILL;}elseif(tilt<accel_data.min_tilt){// The player is returning the device to the horizontal positionaccel_data.min_tilt=tilt;direction=0;}elseif(tilt>=(accel_data.min_tilt+DYN_TILT)){// The player has started turning right againaccel_data.min_tilt=tilt;accel_data.max_tilt=tilt;direction=1;accel_data.status=AS_TILTED_RIGHT;}else{// The player is still in the tilted right positiondirection=0;}}else{if(tilt<=-MIN_TILT){// The player has started turning leftaccel_data.min_tilt=tilt;accel_data.max_tilt=tilt;direction=-1;accel_data.status=AS_TILTED_LEFT;}elseif(tilt>=MIN_TILT){// The player has started turning rightaccel_data.min_tilt=tilt;accel_data.max_tilt=tilt;direction=1;accel_data.status=AS_TILTED_RIGHT;}else{// The player is still in the horizontal positiondirection=0;}}if(direction<0){turnLeft();}elseif(direction>0){turnRight();}else{goStraight();}},false);

Wow, that's a lot of code, but it's not as scary as it may seem initially.

First of all we need a state machine that reflects the intention of the player, in theory it should be only 3 states: AS_STILL, AS_TILTED_LEFT, and AS_TILTED_RIGHT.
We also need a variable that holds this state and also the minimum and maximum tilting done by the player, and in this example tis variable is accel_data.

Ok, now when the player tilts the device to the left, the state changes to AS_TILTED_LEFT, and the computed direction will be -1, which means to turn left.
The minimum value of tilt is stored in accel_data.min_tilt, so that we can know when the player stops tilting the device to the left.
So far, so good.

When the player starts tilting the device to the right, we have to stop turning left, and wait until the tilting of the device reaches 0, so that the state
machine can return to the AS_STILL state. In order to achieve such condition, the AS_STILL_LEFT and AS_STILL_RIGHT states exist.

By using this method, the game is much more playable, but I feel that I'm still missing something.

You may ask, what am I missing? I'll tell you... I don't know.

Please let me know in the comments if you have any idea.

How do you use the accelerometer and what are your experiences with accelerometer based games? Please let me know in the comments.