Introducing the controllers API

Controllers play a big role in gaming as they are the kings of home consoles. Interestingly, they are also gaining followers among PC users, who had originally praised the mouse. Lots of people have a desktop connected to their living room television just to play from their couches using controllers. Not to mention that some games, such as sports titles, are simply better experienced with gamepads.

After diving into keyboard, mouse, and touch inputs, it is time to pay some attention to such an important icon of games. Libgdx provides a fully featured controllers API; however, it does not belong to the core framework. Instead, it is distributed as an extension, which means that you will not include it in your project unless you actually need it.

Throughout this recipe, we will cover the main aspects of the controllers API, which will be shown in the accompanying sample.

Note

The controllers extension is only supported on the desktop, Android (3.1 or greater), and GWT backends. The iOS backend comes with a stub implementation with no functionality.

Getting ready

For the controllers example, you need to import the sample projects into your Eclipse workspace.

How to do it…

There are quite a few sides to this extension. First, we will see how to include the controllers extension in an existing project, then we will move on to how to enumerate which controllers are connected, and finally we will explain how to do polling and event listening.

Everything in the controllers API is accessible through the Controllers singleton.

Including the controllers extension

Controllers is a Libgdx extension, so you need to edit your Gradle build file to add the new dependency. We already covered this in the Updating and managing project dependencies recipe of Chapter 1, Diving into Libgdx.

Enumerating controllers

Several players can have their controllers plugged in at the same time, and we can query this information with the getControllers() method, which returns an array of the Controller objects:

for (Controller controller : Controllers.getControllers()) {
  Gdx.app.log("Controllers: ", controller.toString());
}

Controller state polling

The Controller interface is implemented by the corresponding backends. Once we have the Controller instance that we are interested in, we can use it to poll its state with the following methods, which we will explain later:

public interface Controller {
  public boolean getButton (int buttonCode);
  public float getAxis (int axisCode);
  public PovDirection getPov (int povCode);
  public boolean getSliderX (int sliderCode);
  public boolean getSliderY (int sliderCode);
  public Vector3 getAccelerometer (int accelerometerCode);

…
}

Controller event listening

We can register a class to be notified on every controller event quite easily, as long as it implements the ControllerListener interface. There are two ways of doing this, depending on whether we are interested in all controllers' events or just those for a specific one.

To listen to events coming from all controllers, you need to register with the Controllers class, as follows:

Controllers.addListener(new ControllerListener() {
…
});

If you only care about a specific controller, you need to register with a specific instance:

Controller player1Controller = Controllers.getControllers().get(0);
player1Controller.addListener(new ControllerListener() {
…
});

The ControllerListener interface looks like the following code snippet:

public interface ControllerListener {
  public void connected(Controller controller);
  public void disconnected(Controller controller);
  public boolean buttonDown (Controller controller, int buttonCode);
  public boolean buttonUp (Controller controller, int buttonCode);
  public boolean axisMoved (Controller controller, int axisCode, float value);
  public boolean povMoved (Controller controller, int povCode, PovDirection value);
  public boolean xSliderMoved (Controller controller, int sliderCode, boolean value);
  public boolean ySliderMoved (Controller controller, int sliderCode, boolean value);
  boolean accelerometerMoved (Controller controller, int accelerometerCode, Vector3 value);
}

Our sample application, located in GamepadSample.java, logs event messages pretty much like the other input samples.

How it works…

Controllers come in all flavors and colors, each with different button layouts and a wide range of components such as buttons, axes, accelerometers, and so on and so forth. The controller interface is supposed to abstract a generic gamepad with the following concepts:

  • Buttons: These are the classic A, B, X, and Y buttons as well as some triggers, such as Start and Select. Each button has a code represented by an integer value and can trigger the buttonDown() and buttonUp() events.
  • Axes: These are analog sticks; their value ranges from -1 to 1, where 0 is the middle. Each axis has an integer code, and its use triggers the axisMoved() events.
  • POVs: These are directional inputs such as digital pads. The povMoved() event takes the pov ID and a PovDirection value, which is simply an enum containing a list of directions such as north or southEast.
  • Sliders: These are controller-specific sliders along the x and y axis.
  • Accelerometer: This is represented by a vector, indicating the acceleration in m/s2 along each axis.

Note

Controller event handlers return true or false depending on whether the event should be distributed to other listeners or not. This is consistent with the InputProcessor interface. However, a controller supports several listeners, so there is no need for multiplexers.

There's more…

Integrating gamepad controls in your game is actually far from simple. While the Libgdx API is quite nice and clean, the variety of devices makes it really hard to handle all the cases. Keep this in mind when trying to officially support controllers in your game.

Controller mappings

As a game programmer, you cannot be aware of the controller your users will plug into the game machine. It could be an Xbox controller, a PlayStation 3, OUYA, or a generic one. Each one of these assigns different buttons and axes to their physical components. The horizontal axis of the right stick will not have the same code across devices and platforms. This can be an awful nightmare!

The com.badlogic.gdx.controllers.mappings package hosts classes with static values representing codes for known controllers. As of now, the only available one is the OUYA mapping set. Obviously, you are free to add support for other controllers in your game following this method:

public class Ouya {
  public static final String ID = "OUYA Game Controller";
  public static final int BUTTON_O;
  public static final int BUTTON_U;
  public static final int BUTTON_Y;
  public static final int BUTTON_A;
  …
}

The following picture illustrates only a fraction of the controllers' variety in the market:

Controller mappings

This approach can be really good if you are only going to support a specific controller, such as the OUYA one, if you are releasing on that platform. However, if you want to support a wide range of controllers, it is not feasible to check for each of the mappings whenever an event fires. In this case, the best approach is usually to provide a controller configuration screen, where the user picks the button or axis of his choice for every action in the game.

Handling disconnections

Detecting when a controller is plugged in or gets disconnected is tricky. You need to listen to the connected() and disconnected() events, but it only works on Android. Whenever possible, it is always good to handle this in the game by triggering a pause screen or something similar.

See also

Most aspects of Libgdx's input system have already been covered. Please find the following related content:

  • The Input mapping for cross-platform development recipe covers how to elegantly handle input in a cross-platform project
  • Chapter 11, Third-party Libraries and Extras, offers a collection of other Libgdx extensions
..................Content has been hidden....................

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