
Time for action – listeners meet actions
Look at the inner methods of the InputListener
objects:
onAction(String name, boolean isPressed, float tpf)
inactionListener
onAnalog(String name, float intensity, float tpf)
inanalogListener
onTouch(String name, TouchEvent event, float tpf)
intouchListener
(not depicted)
When you implement the actual actions, you write a series of conditionals in these inner methods. When you want to detect several triggers (the most common scenario), add several else if
conditionals. You test for each mapping by name
, and then execute the desired action. In our example, we want the action to affect the blue cube (geom
).
- Make
geom
accessible as a class field. Remember to adjust thegeom
object's constructor call insimpleInitApp()
method accordingly.private Geometry geom; ... geom = new Geometry("Box", mesh);
Now the
InputListener
objects in your class have access to the cube geometry. - Let's handle
MAPPING_COLOR
first. In the inneronAction()
method of theactionListener
object, test whethername
equals toMAPPING_COLOR
. To execute the action when the trigger is released (that is, the key or mouse button is up again), test whether the Boolean is!isPressed
:private ActionListener actionListener = new ActionListener() { public void onAction(String name, boolean isPressed, float tpf) { if (name.equals(MAPPING_COLOR) && !isPressed) { // implement action here } } };
- Implement the color toggle action for
geom
: get the cube's material, and set theColor
property using the return value of the staticrandomColor()
method. Replace the implement action here comment with the following line:geom.getMaterial().setColor("Color", ColorRGBA.randomColor());
- Let's handle
MAPPING_ROTATE
. In the inneronAnalog()
method of theanalogListener
, test whethername
equalsMAPPING_ROTATE
.private AnalogListener analogListener = new AnalogListener() { public void onAnalog(String name, float intensity, float tpf) { if (name.equals(MAPPING_ROTATE)) { // implement action here } } };
- Implement the rotation action for
geom
. To execute the action continuously as long as the trigger is pressed, use the providedintensity
value as a factor in your continuous rotation action. Replace the implement action here comment with the following line:geom.rotate(0, intensity, 0); // rotate around Y axis
When you run UserInput.java
now, you see the blue cube. Press the Space bar and the cube changes its color. Keep the left mouse button pressed and the cube rotates around its y axis. You can even do both at the same time. When you press the C key, however, you notice that the color changes, but the application also prints camera information to the console. Strange! Didn't you just declare the C key as an alternative to the Space bar? You did, but you did not consider the existing default mappings.
SimpleApplication
internally maps the C key to a diagnostic output action. You will notice a similar issue if you map anything to the M (prints memory diagnostics) or Esc keys (stops the game), which are also internally registered by SimpleApplication
. If necessary, you can remove any of the three existing mappings as follows:
inputManager.deleteMapping(INPUT_MAPPING_EXIT); // Key_ESCAPE inputManager.deleteMapping(INPUT_MAPPING_CAMERA_POS); // Key_C inputManager.deleteMapping(INPUT_MAPPING_MEMORY); // Key_M
Tip
You can call the inputManager.clearMappings()
method and define all mappings from scratch. But clearing also removes the preconfigured W, A, S, and D key navigation, which we would like to keep as long as we're looking at examples. So don't clear the mappings for now—until you develop your own game.
What just happened?
Congrats! You now know how to set up individual keys and mouse buttons, and so on to trigger custom game actions that change the game state.
- Start by deciding on a list of actions and default triggers in your game.
- Define triggers and give them unique names that describe the action, not the key.
- Register each name—trigger pair as a mapping to the
inputManager
object. - Create
InputListener
instances for discrete and analog events, and register each mapping to one of them. - Finally, test for each mapping in its
InputListener
object'sonAction()
,onAnalog()
, oronTouch()
method, and implement its action.