Skip to content

Instantly share code, notes, and snippets.

@erodozer
Last active December 29, 2015 19:43
Show Gist options
  • Save erodozer/dc0501f34f89686ddf34 to your computer and use it in GitHub Desktop.
Save erodozer/dc0501f34f89686ddf34 to your computer and use it in GitHub Desktop.
Game Controller Abstraction for LibGDX

Game Controller Abstraction for LibGDX

abstract class AxisMapper<V> {
protected final ObjectMap<V, Axis> map;
public AxisMapper() {
map = new ObjectMap<>();
mapping();
}
abstract protected void mapping();
public Axis get(V control) {
return map.get(V, null);
}
protected static class Axis {
final int id;
final float threshold;
public Axis(int id, float threshold) {
this.id = id;
this.threshold = threshold;
}
}
}
abstract class ButtonMapper<V> {
protected final ObjectMap<V, Integer> map = new ObjectMap<>();
public ButtonMapper() {
map = new ObjectMap<>();
mapping();
}
abstract protected void mapping();
public final Integer get(V control) {
return map.get(V, -1);
}
}
public class Controller<V implements Controls>
{
private ObjectMap<V, Long> lastPressed = new ObjectMap<>();
protected ButtonMapper<V> layout;
protected AxisMapper<V> axis;
abstract protected V[] getControls();
abstract public boolean isPressed(V control);
public boolean isPressed() {
boolean pressed = true;
for (int i = 0; i < getControls().length && pressed; i++) {
V c = getControls()[i];
pressed = isPressed(c);
}
return pressed;
}
public void record(V control) {
lastPressed.put(control, TimeUtils.millis());
}
public long when(V control) {
return lastPressed.get(control, 0L);
}
}
public class ControllerMultiplexer extends Controller<GameControls> {
private final Controller[] controllers;
public MultiController(final Controller... controllers) {
this.controllers = controllers;
}
public boolean isPressed(GameControls control) {
for (Controller c : controllers) {
if (c.isPressed(control)) {
return true;
}
}
return false;
}
protected GameControls[] getControls() {
return GameControls.values();
}
}
public interface Controls {}
public enum GameControls implements Controls {
DPAD_UP,
DPAD_DOWN,
DPAD_LEFT,
DPAD_RIGHT,
START,
SELECT,
A,
B,
X,
Y,
L1,
L2,
R1,
R2
}
private void handleInput() {
final float deltaTime = Gdx.graphics.getDeltaTime();
// process user input
ship.vx = 0;
ship.vy = 0;
if (controller.isPressed(GameControls.DPAD_LEFT)) {
ship.vx = -deltaTime;
}
if (controller.isPressed(GameControls.DPAD_RIGHT)) {
ship.vx = deltaTime;
}
if (controller.isPressed(GameControls.DPAD_UP)) {
ship.vy = deltaTime;
}
if (controller.isPressed(GameControls.DPAD_DOWN)) {
ship.vy = -deltaTime;
}
if (controller.isPressed(GameControls.L1)) {
ship.weaponScrollLeft();
}
if (controller.isPressed(GameControls.R1)) {
ship.weaponScrollRight();
}
if (controller.isPressed(GameControls.SELECT)) {
game.setScreen(new GameScreen(game));
}
float[] v = Vector.unit2d(ship.vx, ship.vy);
ship.vx = v[0] * ship.speed;
ship.vy = v[1] * ship.speed;
ship.handle(this);
if (controller.isPressed(GameControls.A)) {
ship.shoot(this);
}
}
public class KeyboardController extends Controller<GameControls> {
public KeyboardController() {
layout = new ButtonMapper() {
protected void mapping() {
map.put(GameControls.DPAD_UP, Input.Keys.UP);
...
map.put(GameControls.R2, Input.Keys.D);
};
};
//we don't have any axis associated with the keyboard
axis = null;
}
public boolean isPressed(GameControls control) {
final boolean pressed = Gdx.input.isKeyPressed(layout.get(control));
if (pressed) { record(control); }
return pressed;
}
protected GameControls[] getControls() {
return GameControls.values();
}
}
/**
* Logitech controller mapping that matches an SNES controller layout
*/
public class SNESController extends Controller<GameControls> {
private com.badlogic.gdx.controllers.Controller controller;
public SNESController() {
this(0);
}
public SNESController(final int controllerNumber) {
if(Controllers.getControllers().size < (controllerNumber + 1)) { return; }
controller = Controllers.getControllers().get(controllerNumber);
layout = new ButtonMapper() {
protected void mapping() {
map.put(GameControls.A, 1);
...
map.put(GameControls.R2, 7);
};
};
// dpad buttons are read from axis's, not button codes directly
axis = new AxisMapper<>() {
protected void mapping() {
map.put(GameControls.DPAD_UP, new Axis(1, -0.75f));
map.put(GameControls.DPAD_DOWN, new Axis(1, 0.75f));
map.put(GameControls.DPAD_LEFT, new Axis(0, -0.75f));
map.put(GameControls.DPAD_RIGHT, new Axis(0, 0.75f));
}
}
}
public boolean isPressed(GameControls control) {
boolean pressed = false;
if (axis.containsKey(control)) {
Axis a = axis.get(control);
if (a.threshold < 0) {
pressed = controller.getAxis(axis.id) < axis.threshold;
}
if (a.threshold > 0) {
pressed = controller.getAxis(axis.id) > axis.threshold;
}
}
else {
pressed = controller.getButton(layout.get(control));
}
if (pressed) { record(control); }
return pressed;
}
protected GameControls[] getControls() {
return GameControls.values();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment