Adding alternative input controls

The last and rather short topic in this chapter will show you how to use the peripheral devices using the example of accelerometers, which are very common types of sensors in today's smartphones and tablets. Accelerometers are subsystems that reliably and accurately detect and measure acceleration, tilt, shock, and vibration. Basically, we just need to read the sensor data that is being measured by the accelerometer hardware and later translate the data into values and/or ranges suitable for our game.

Accelerometers in Android and iOS devices are exposed by LibGDX using the three axes x, y, and z, which can be queried via the Gdx.input module. For instance, the current acceleration value for the x axis can be easily retrieved as follows:

float ax = Gdx.input.getAccelerometerX();

This is great, but what does the value that we just stored in ax actually mean? Moreover, what will influence it? So, to better understand how sensors work, we need to know what exactly is measured.

Let's start with the range of values. In the documentations of Android and LibGDX, the values for accelerometers are said to range between -10.0f and 10.0f. This roughly resembles a value of what we know as the constant for gravity on earth, approximately 9.81 meters per square second. However, what we still do not know about is the internal orientation of the sensor hardware inside a device. This poses a problem to us because we cannot tell which axis is which. Luckily, LibGDX comes to the aid and is able to make an educated guess that is also reliable. There is a blog post by Mario Zechner that describes the issue about the different so-called native orientations in more detail at http://www.badlogicgames.com/wordpress/?p=2041.

All we have to remember is that LibGDX will make sure that the y axis always coincides with the bigger side while the x axis coincides with the smaller one. The z axis comes out of the screen.

An image taken from Android's SDK developer website that nicely illustrates the sensor coordinate system is as follows:

Adding alternative input controls

We will now move on to Canyon Bunny and implement alternative input controls using the accelerometer. The screen needs to be rotated by 90 degrees to the left in order to be able to play Canyon Bunny on a smartphone, since it is using the so-called landscape mode for display. It is important to understand that the orientation of the sensors will always remain the same no matter how the smartphone is moved and rotated around.

The new controls will allow you to tilt the screen to the left and right sides to move into the very same direction. The tilt angle for the y axis will determine the maximum velocity of the player character.

Add the following new constants to the Constants class:

// Angle of rotation for dead zone (no movement)
public static final float ACCEL_ANGLE_DEAD_ZONE = 5.0f;

// Max angle of rotation needed to gain max movement velocity
public static final float ACCEL_MAX_ANGLE_MAX_MOVEMENT = 20.0f;

Then, add the line of code to the WorldController class:

import com.badlogic.gdx.Input.Peripheral;

Next, add the following line to the WorldController class:

private boolean accelerometerAvailable;

After this, make the following changes to the same class:

private void init () {
accelerometerAvailable = Gdx.input.isPeripheralAvailable(Peripheral.Accelerometer);
cameraHelper = new CameraHelper();
lives = Constants.LIVES_START;
livesVisual = lives;
timeLeftGameOverDelay = 0;
initLevel();
}

private void handleInputGame (float deltaTime) {
if (cameraHelper.hasTarget(level.bunnyHead)) {
    // Player Movement
if (Gdx.input.isKeyPressed(Keys.LEFT)) {
        ...
      } else {
      // Use accelerometer for movement if available
if (accelerometerAvailable) {
        // normalize accelerometer values from [-10, 10] to [-1, 1]// which translate to rotations of [-90, 90] degrees
float amount = Gdx.input.getAccelerometerY() / 10.0f;
amount *= 90.0f;
        // is angle of rotation inside dead zone?
if (Math.abs(amount) <Constants.ACCEL_ANGLE_DEAD_ZONE) {
amount = 0;
          } else {
          // use the defined max angle of rotation instead of// the full 90 degrees for maximum velocity
amount /= Constants.ACCEL_MAX_ANGLE_MAX_MOVEMENT;
          }
level.bunnyHead.velocity.x = level.bunnyHead.terminalVelocity.x * amount;
        }
      // Execute auto-forward movement on non-desktop platform
else if (Gdx.app.getType() != ApplicationType.Desktop) {
level.bunnyHead.velocity.x = level.bunnyHead.terminalVelocity.x;
        }
      }
    }
  }

The new variable accelerometerAvailable is set once in the init() method, which in turn is used to select the input mode in handleInputGame(). If an accelerometer hardware is detected, the alternative input controls for player movement will be used. In this case, however, we first normalize the accelerometer values to make them stay in a range between -1.0f and 1.0f, which can now also be interpreted by us as the percentage of desired movement in relation to the amount of tilt. The sign of the percentage also nicely describes the direction of the horizontal movement. A negative sign means movement to the left, whereas a positive sign means movement to the opposite direction. The percentage currently maps a movement of 100 percent in one direction to 90 degrees of tilting the screen in the same direction. It is very inconvenient to have to turn the device over the full range of 180 degrees, which also prevents fast player reactions.

This is why we introduced a new constant named ACCEL_MAX_ANGLE_MAX_MOVEMENT that allows you to define the maximum tilt angle that is needed to reach maximum velocity. The other new constant ACCEL_ANGLE_DEAD_ZONE is used to define a dead zone (here 5.0 degrees) in the positive and negative directions where no movement will occur. So, the dead zone makes it easier for the player to find a neutral position to let the bunny head stand still. Finally, we end up with a percentage of the desired movement stored in an amount that is simply multiplied with the terminal velocity to calculate the correct velocity value.

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

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