Carbon Controller Library

Category: 

LibGDX contains an extension for controller support, but handling different kinds of controllers isn't so easy. This is caused by the different mappings. The A-button on a Xbox 360 controller has a different code than the A-button on an Ipega controller. The Ipega also has different codes on different platforms. The arbitrary codes are also har to remember. To overcome these problems, I developed the CarbonController library, which solves these problems.

For more information look at the Projekt Wiki
Download: carbon-controller-1.0.jar

Usage

All in all the library is used like gdx-controllers. The main difference is that you use enumerations instead of some magic integers, so all axes and buttons are uniform.

//with gdx-controllers:
xbox.getButton(0); // bottom button (A)
ouya.getButton(96); // bottom button (O)
//with CarbonControllers
controller.getButton(CarbonKey.A); // on every controller the same button (A on XBox, O on Ouya, etc.)

As you can see, you don't have to handle the different kinds of controllers.

CarbonController needs gdx-controller library.

Enumerating Controllers

If you want to query all connected devices, you would use the following:

for(CarbonController controller : CarbonControllers.getControllers()) {
  Gdx.app.log(TAG, controller.getName());
}

Like the Controller class from LibGDX, all methods of a controller must be executed in the rendering thread.

Polling Controller State

Onve you have a CarbonController instance, you can get it's current state.

hat, kann man den aktuellen Zustand einer jeden Komponente abfragen. Dabei gilt es zu beachten, dass die Komponenten etwas anders sind als die der LibGDX controller. Insbesondere werden sie nicht nur durch arbiträre Integer abgefragt, sondern durch Enumerationen. In contrast to the gdx-controller, there are some differences in the components of a controller. The following components are used by a CarbonController:

  • CarbonKey: usual buttons, named after the corresponding XBox 360 button. A, B, X, Y, L1, R1, ...
  • CarbonAxis: usually provided via analogsticks and triggers. The value of the triggers (LT and RT) are in range [0, 1], while all other axes are in range [-1, 1]
  • a single POV: provide discrete directional state, like north, south, etc.
  • CarbonVector: most controllers don't have this, but some may use this for motion sensing, like acceleration.

Polling for the state of a component is as simple as it is in the gdx-controller extension. But instead of using some magic integer values, you just use an enumeration.

boolean buttonPressed = controller.getButton(CarbonKey.A);
float axis = controller.getAxis(CarbonAxis.LX);
PovDirection pov = controller.getPov();
Vector3 acc = controller.getVector(CarbonVector.ACCELEROMETER);

Event based Controller Input

When polling a controller, you might lose some input events. For some tasks, event based input is also more suited than polling based input. You can either register your listener globally (to match every controller) or to a specific controller. The interface you have to implement is called CarbonControllerListener.

public interface CarbonControllerListener {
  public void connected(CarbonController controller);
  public void disconnected(CarbonController controller);
  public boolean buttonDown(CarbonController controller, CarbonKey key);
  public boolean buttonUp(CarbonController controller, CarbonKey key);
  public boolean axisMoved(CarbonController controller, CarbonAxis axis, float value);
  public boolean povMoved(CarbonController controller, PovDirection value);
  public boolean vectorChanged(CarbonController controller, CarbonVector vector, Vector3 newVector);
}

Each method receives the Controller instance for which the event was triggered. The first two methods are called when a controller is connected or disconnected. But unfortunately this only works on Android. The other methods should be self-explanatory.

A CarbonControllerListener can be either added to specific CarbonController, to get only the events of this instance, or to the CarbonControllers class, in which it will listen for events of all CarbonControllers.

controller.addListener(listener); // receive events only from this instance
Controllers.addListener(listener); // receive events from all CarbonControllers

If you don't want to implement all these metods, but only a few of them, you can subclass CarbonControllerAdapter.
Like the gdx ControllerListener, some of the methods return a boolean. This is used if multiple listeners were registered globally or with a specific controller. If such a method returns false, the event will be handed to the next listener. If it returns true, the event is handled and will not be propagated any further.