Detecting accelerometer input

The final input method we will be considering in this chapter is the accelerometer, which allows us to detect the orientation that the user is currently holding the device at. An accelerometer is a sensor that can measure the forces applied to a device, be they static forces such as gravity, or dynamic forces generated by waving the device around.

Most devices will have three accelerometers aligned perpendicularly to each other, as shown in the following diagram. This configuration allows us to discover exactly how the user is holding the device at any time and so provides a method of controlling our game.

Detecting accelerometer input

The directions of the arrows in the previous diagram show the directions in which acceleration will yield a positive value. This means that if you hold the device level with the display upwards in front of you, tipping it to the right will yield a positive value on the x axis accelerometer, tipping it away from you will generate positive y axis values and moving the device vertically upwards will generate a positive z axis value.

The Marmalade SDK provides us with access to the accelerometers of a device using the s3eAccelerometer API, which we can use in our code by including the s3eAccelerometer.h file.

Starting and stopping accelerometer input

Before attempting to use the accelerometer in our program, we must first check to see if accelerometer input is available on our device. If support is available, then we can start receiving accelerometer input. We do this with the following check:

if (s3eAccelerometerGetInt(S3E_ACCELEROMETER_AVAILABLE) != 0)
{
  // Accelerometer is available!  Start receiving input.
  s3eAccelerometerStart();
}

When we have finished using the accelerometers, we just make a call to s3eAccelerometerStop and we will receive no further inputs.

Note

It is good practice on mobile devices to ensure that we only enable parts of the hardware when we are actually using them, since this helps to conserve battery power. In the case of accelerometers, the power use is probably so small that it is insignificant, but this is an area of mobile game programming that is always worth keeping in mind.

Reading accelerometer input

Finding the current accelerometer input values is really very simple. Marmalade provides three functions which return the current accelerometer value for each axis. These functions are called s3eAccelerometerGetX, s3eAccelerometerGetY, and s3eAccelerometerGetZ. Unsurprisingly, they return the current value of the accelerometer for the specified axis.

The values returned by these functions use a value of 1000 (though we should use the handy definition S3E_ACCELEROMETER_1G to avoid magic numbers in our code!) to represent an acceleration equivalent to normal Earth gravity.

When a sharp, quick movement is made to the device, the forces being applied to it will be greater than the normal gravitational force. In this case, the magnitude of the vector formed from the accelerometer values will be greater than S3E_ACCELEROMETER_1G. This can be a useful way of detecting whether the user has been shaking the device.

If the device were to be horizontally on a table, we should get a value of 0 returned for both the X and Y axes, and -1000 for the z axis, since gravity acts downwards! As we rotate the device, the values returned will form a vector showing the direction in which gravity is acting, and we can then use this to determine the orientation of the device.

Using some trigonometry, we can work out the angle of tip around the x axis (forward/backward) and Y-axis (left/right). The angle around the X-axis can be found by taking the arc tan of the Y-accelerometer value divided by the Z value.

The angle around the y axis is a little trickier. First we have to find the length of the accelerometer vector projected onto the YZ plane, then we can find the arc tan of the X-accelerometer value divided by the projected length.

If all this sounds like too much scary math, the following code snippet does it all for us. Note than when calculating the rotation around the x axis using the IwGeomAtan2 function, we negate both the Y- and Z-accelerometer values in order to yield a more usable result range, with 0 degrees returned when the device is level and increasing values when tipped away from the user.

iwangle xAngle = IwGeomAtan2(-accY, -accZ);
int32 lYZProjection = (int32) sqrtf((float) ((accY * accY) +
                                             (accZ * accZ)));
iwangle yAngle = IwGeomAtan2(accX, lYZProjection);

Smoothing accelerometer input

One problem we will encounter when using the accelerometer for input is that the values returned from it tend to be a bit "jumpy". Even the steadiest hand will be unable to hold the device still enough to see a steady value being returned from the accelerometer. This can cause your game to register movements when you don't want it to.

A common approach for solving this problem is to smooth the accelerometer values by combining the current readings with the previous readings. The easiest way of doing this is shown in the following code:

int32 accX = 0, accY = 0, accZ = 0;
int32 lSmoothFactor = IW_GEOM_ONE / 4;
// The following loop shows how we generate the smoothed accelerometer
// inputs.  In a real application the code within the loop would be called once
// per game frame.
while (TRUE)
{
  int32 deltaX = s3eAccelerometerGetX() - accX;
  int32 deltaY = s3eAccelerometerGetY() - accY;
  int32 deltaZ = s3eAccelerometerGetZ() - accZ;
  accX += IW_FIXED_MUL(lSmoothFactor, deltaX);
  accY += IW_FIXED_MUL(lSmoothFactor, deltaY);
  accZ += IW_FIXED_MUL(lSmoothFactor, deltaZ);
}

The variables accX, accY, and accZ are the smoothed accelerometer values that we will use in our program for input. The lSmoothFactor value determines how much smoothing we are applying to the inputs. If it is set to IW_GEOM_ONE, no smoothing will be applied and the results will be exactly what is coming in from the accelerometers.

Lower values for the smoothing factor will generate less jittery input values, but this will be at the expense of adding a certain amount of lag to the inputs. The degree of lag depends on how often the smoothing code is executed, which in turn depends on the frame rate of your game.

Working out a good value to use for the smoothing factor is really just a case of trial and error. You just need to keep tweaking the value until you achieve a suitable result.

Note

IW_FIXED_MUL is a useful function provided by Marmalade for doing fixed point multiplication where IW_GEOM_ONE (4096) is equivalent to one. It multiplies the two parameters together and then shifts the result back down to be in the correct range.

Testing accelerometer input on the Windows simulator

Given that computers don't tend to feature accelerometer inputs of any kind, testing this form of input in the Windows simulator may appear to be impossible. Fortunately, Marmalade does provide us with a way of doing so.

When running an application in the simulator, select the menu item Configuration | Accelerometer… and a window showing a small 3D representation of a mobile device will be displayed:

Testing accelerometer input on the Windows simulator

By clicking and dragging on this virtual device, we can alter the accelerometer inputs being fed into the simulator. It's a little tricky to use for playing a game but it normally suffices, so you can at least test applications that rely solely on accelerometer inputs.

The window also provides some edit boxes that show the current values of the accelerometer inputs as you rotate the 3D device about. These can also be used to enter exact values should you have need to do so.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.136.84