Typically, there are a couple of approaches when it comes to detecting user input. The most straightforward approach is event polling, which involves actively querying the state of a specific input peripheral whenever we want to make a decision based on it. This can happen either in every frame or on demand for specific bits of game logic.
Throughout this recipe, we will work with an example where you will learn how to query the keyboard, mouse, accelerometer, and compass of the device. The updated state of these devices will be shown on the screen.
The sample projects are required to follow this recipe; please make sure that you already have them in your Eclipse workspace.
The code for this recipe is found in the
InputPollingSample
class. We have the classic members to support regular rendering: camera, viewport, and sprite batch. Besides these, we add a BitmapFont
object to draw the state of the input devices on the screen, rather than using logging and spamming the console in every frame. In the create()
method, we instantiate our members and in the
dispose()
method, we deallocate the batch and font resources.
Take a peek at Chapter 6, Font Rendering, for more details on how BitmapFont
works.
The actual polling takes place inside the
render()
method, which means it will run in every frame. We will proceed on a per device basis; you will see that this is extremely simple.
We can retrieve the mouse or touch coordinates with
Gdx.input.getX()
and
Gdx.input.getY()
. Keep in mind that they come in screen space, so you have to call unproject()
on your camera to transform them into world space. Computer mice typically have three buttons: left, right, and middle. We can check the state of these buttons with Gdx.input.isButtonPressed()
, passing in the appropriate constant. Alternatively, on mobile devices, you can use Gdx.input.isTouched()
.
Screen space means the actual pixels on your device's screen, while world space refers to the virtual units you use to model your game world. A camera knows how to convert between the two spaces. Refer to Chapter 2, Working with 2D Graphics, for more details.
Have a look at the following lines of code:
float mouseX = Gdx.input.getX(); float mouseY = Gdx.input.getY(); boolean leftPressed = Gdx.input.isButtonPressed(Buttons.LEFT); boolean rightPressed = Gdx.input.isButtonPressed(Buttons.RIGHT); boolean middlePressed = Gdx.input.isButtonPressed(Buttons.MIDDLE);
To know whether a given key is pressed or not, we can use the
Gdx.input.isKeyPressed()
method, passing in the corresponding constant, as shown in the following lines of code. These constants live inside the Keys
static class; please check the official documentation at http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/Input.Keys.html to access the whole list.
boolean wPressed = Gdx.input.isKeyPressed(Keys.W); boolean aPressed = Gdx.input.isKeyPressed(Keys.A); boolean sPressed = Gdx.input.isKeyPressed(Keys.S); boolean dPressed = Gdx.input.isKeyPressed(Keys.D);
Most tablets and phones come with accelerometers. These sensors detect the device acceleration along the three axes relative to the Earth's gravitational field. Axes are queried separately using methods similar to Gdx.input.getAccelerometerX()
. The values we obtain lie within the [-10.0, 10.0] range:
float accelerometerX = Gdx.input.getAccelerometerX(); float accelerometerY = Gdx.input.getAccelerometerY(); float accelerometerZ = Gdx.input.getAccelerometerZ();
Other devices also feature a compass, which is often used for map applications such as Google Maps. The Gdx.input.getPitch()
function returns the device's orientation in degrees around its x axis, where positive x points to the west. The Gdx.input.getRoll()
function returns the y axis rotation in degrees, where positive y points to the north. Finally, Gdx.input.getAzimuth()
gives us the z axis rotation in degrees, where positive z points to the Earth's center:
float pitch = Gdx.input.getPitch(); float roll = Gdx.input.getRoll(); float azimuth = Gdx.input.getAzimuth();
The following diagram illustrates a phone's axes:
The result of each one of the queries we have made is shown on the screen using the draw()
method in the BitmapFont
class. Check the sample source code for more details.
The input is one of the Libgdx main subsystems and is statically accessible from the Gdx
environment class. Every backend is responsible for implementing all the functionality offered by the interface. Feel free to dig in to the Libgdx repository to find out on your own, but here is how each backend achieves it:
Peripherals can be disabled or enabled using the configuration parameters that are passed to the launcher class. See the Understanding the project structure and application life cycle recipe of Chapter 1, Diving into Libgdx, for more details.
A couple of extra useful things that you can do with the input interface is check the peripheral availability and show or hide the on-screen keyboard.
Desktop platforms always have a keyboard and a mouse, but they tend to lack touch screens and definitely do not have a compass or an accelerometer. On the other hand, smartphones typically have a compass and an accelerometer. It would not be rare to find yourself with the need to check whether a particular peripheral is available or not at runtime.
This is really easy to achieve with the Gdx.input.isPeripheralAvailable()
method, passing in a constant that represents the device in question. The following code fragment has been added to InputPollingSample
in order to check for input availability:
Gdx.input.isPeripheralAvailable(Peripheral.Accelerometer); Gdx.input.isPeripheralAvailable(Peripheral.Compass); Gdx.input.isPeripheralAvailable(Peripheral.HardwareKeyboard); Gdx.input.isPeripheralAvailable(Peripheral.MultitouchScreen); Gdx.input.isPeripheralAvailable(Peripheral.OnscreenKeyboard); Gdx.input.isPeripheralAvailable(Peripheral.Vibrator);
18.118.2.240