I’m new at JInput and just got it figured out for keyboard input. The doesn’t seem to be alot of documentation about this. There’s tidbits here and there, but there doesn’t seem to be one tutorial that spells everything out.
For this reason, I’m posting this topic about some of the pitfalls. I haven’t figure out mouse and gamepad input yet, but some of these pitfalls should apply to them too.
When you download jinput_combined_dist_latest.zip from https://jinput.dev.java.net/ , you must extract all the files into your classpath somehow. You always need jinput.jar, and you’ll also need one or more binary files depending upon your OS. It’s .dll for Windows, .so for Linux, and .jnilib for Mac OS X. This part isn’t too hard to figure out. If you can get the test programs to work, you should be able to get your own code to work too.
The first thing your program must do is read all the controllers. That only requires the following two lines of code:
ControllerEnvironment controllerEnvironment =
ControllerEnvironment.getDefaultEnvironment();
Controller[] aController = controllerEnvironment.getControllers();
That isn’t hard, but now you need to do something with those controllers. I propose that you split them up by type. You need to store all the controllers of each type so that you can poll them all, not just the first one. Some people store just one controller, and it might be the wrong one. This is probably most often the case when people have all kinds of weird pointer devices that they don’t actually use.
Here’s my code for separating the controllers:
public class ControllerManager {
/**Constructor.
*/
public ControllerManager() {
//find all the controllers
ControllerEnvironment controllerEnvironment =
ControllerEnvironment.getDefaultEnvironment();
Controller[] aController = controllerEnvironment.getControllers();
//separate the controllers into groups
int numControllers = aController.length;
for(int iController = 0; iController < numControllers; iController++) {
Controller controller = aController[iController];
//figure out which group to put the controller into
Controller.Type controllerType = controller.getType();
if(controllerType == Controller.Type.KEYBOARD)
aKeyboard.add((Keyboard)controller);
else if(controllerType == Controller.Type.MOUSE)
aMouse.add((Mouse)controller);
else if(controllerType == Controller.Type.TRACKBALL ||
controllerType == Controller.Type.TRACKPAD)
{
if(controller instanceof Mouse)
aMouse.add((Mouse)controller);
} //end if the controller is a trackball or trackpad
else if(controllerType == Controller.Type.GAMEPAD)
aGamepad.add(controller);
} //end for each controller
//list the types of controllers found
int numKeyboards = aKeyboard.size();
int numMice = aMouse.size();
int numGamepads = aGamepad.size();
System.err.println("Controllers Found" +
"\nGamepads: " + numGamepads +
"\nKeyboards:" + numKeyboards +
"\nMice/trackballs/trackpads: " + numMice +
"\nUnknown: " + (numControllers - (numGamepads + numKeyboards + numMice)));
} //end constructor
//PRIVATE VARIABLES//////////////////////////////////////////////////////////////////////
//controllers
private final MutableArray<Controller> aGamepad = new MutableArray<Controller>();
private final MutableArray<Keyboard> aKeyboard = new MutableArray<Keyboard>();
private final MutableArray<Mouse> aMouse = new MutableArray<Mouse>();
} //end class ControllerManager
MutableArray is just my version of ArrayList. The only other weirdness is that I just dumped trackballs and trackpads in with mice. I’m not sure how this works out, but I imagine that’s what should be done with them.
Now, you need some way to read the controllers. Since I’ve only dealt with keyboards so far, that’s all we’re going to look at. The straightforward way to check all your keyboards is the following:
/*WARNING: THIS CODE WILL NOT WORK*/
Component.Identifier.Key key = /*whatever key you want to poll*/;
int numKeyboards = aKeyboard.size();
for(int iKeyboard = 0; iKeyboard < numKeyboards; iKeyboard++) {
Keyboard keyboard = aKeyboard.get(iKeyboard);
if(keyboard.isKeyDown(key)) {
isPressedNow = true;
break;
}
} //end for each keyboard
This will not work. It will never detect key presses. This is because you have to call the poll method to make the keyboard check which keys are pressed. The correct code is listed below:
Component.Identifier.Key key = /*whatever key you want to poll*/;
int numKeyboards = aKeyboard.size();
for(int iKeyboard = 0; iKeyboard < numKeyboards; iKeyboard++) {
Keyboard keyboard = aKeyboard.get(iKeyboard);
keyboard.poll();
if(keyboard.isKeyDown(key)) {
isPressedNow = true;
break;
}
} //end for each keyboard
There is still one minor issue. Since the controllers are only detected during the constructor, any devices plugged in after the constructor is called won’t be detected. The inverse is not a problem; if a controller is unplugged after the constructor is called, it won’t hurt anything. (I tested this by unplugging a USB keyboard from my laptop while my program was running.) You could just detect all the controllers every time you poll for input, but detecting controllers takes close to 2 seconds on my computer. Clearly, that’s too long.
I’m not going to say anything about what you do with key presses when they happen. That’s covered pretty well in Developing Games in Java, even though that book doesn’t use JInput. I just posted this topic so that anyone who had a problem with JInput would be able to easily find some kind of solution.
If anyone else wants to post any solutions to beginner problems with reading keyboard input using JInput, this would probably be a good thread to post it in.