Game Controller Abstraction for LibGDX
Last active
December 29, 2015 19:43
-
-
Save erodozer/dc0501f34f89686ddf34 to your computer and use it in GitHub Desktop.
Game Controller Abstraction for LibGDX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Controls {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public enum GameControls implements Controls { | |
DPAD_UP, | |
DPAD_DOWN, | |
DPAD_LEFT, | |
DPAD_RIGHT, | |
START, | |
SELECT, | |
A, | |
B, | |
X, | |
Y, | |
L1, | |
L2, | |
R1, | |
R2 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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