# How do I implement tilt controls that work even when the device is not vertical?

I'm using libGDX to develop an Android game. The main character can be moved freely in the 2d plane by tilting the phone. The relevant part of my current implementation looks somewhat like this:

Vector2 mainCharacter;
float speedX, speedY;

public void render(float delta) {
speedX = 0.6f * speedX + 0.4f * -Gdx.input.getAccelerometerX();
speedY = 0.6f * speedY + 0.4f * -Gdx.input.getAccelerometerY();
mainCharacter.move(speedX, speedY);
}

This simple implementation works quite well as long as the player sits or stands upright. But there are two situations where this approach fails:

1. If the player holds his phone almost horizontally (e.g. if he lies in bed, see fig. 1). Neither the computation of speedY nor the computation of speedX works properly in that situation.
2. Inside a moving vehicle. When the vehicle speeds up or slows down, this has a strong impact on the values returned by Gdx.input.getAccelerometerX/Y.

So my question is: Is there anything that can be done to solve these two problems? How can I get satisfying results independent of whether the player is lying, standing or sitting? And is there a reasonable way to reduce the influence that the movement of a vehicle has on the output of the accelerometer?

fig. 1

• I believe you can use Compass to help you normalize the accelerometer values. I'm unsure as to how the values would be calculated in your case. For your second issue, you could implement a limiting value - if the change in your x or y axis in one frame is over this value, skip input processing for that frame. Oct 18, 2015 at 9:50
• Add a button that allows the player to calibrate to its current device position Oct 18, 2015 at 21:57

I've not used the accelerometer's code but know some implications. What I suggest is that you save a variable with the original orientation, this can be set when the user "calibrates" his controls. Then, manage your input relative to that.

One code example I can suggest, tho I have no way of trying it right now is:

Vector2 mainCharacter;
private float cX = 0, cY = 0, speedX = 0, speedY = 0;

public void calibrate(){
cX = Gdx.input.getAccelerometerX();
cY = Gdx.input.getAccelerometerY();
}

public void render(float delta /** you are not using this delta **/) {
float speedX = 0.6f * speedX + 0.4f * - ( cX - Gdx.input.getAccelerometerX());
float speedY = 0.6f * speedY + 0.4f * - ( cY - Gdx.input.getAccelerometerY());
mainCharacter.move(speedX, speedY);
}

Hope this helps, Good luck!

• Sadly, this doesn't really help. For some reason, both AccelerometerX and AccelerometerY seem to run riot when the phone is held horizontally, even if the controls are calibrated at the beginning. Oct 21, 2015 at 19:59
• Just to be clear, (not a native english speaker), you calibrated after the phone was put horizontal? If not, pleas try. If do, I think I might have a solution. Please answer and I'll try to help. Also do they work before you tilt your phone sideways? Oct 22, 2015 at 18:11