Alternative Gamepad Support Library "Jamepad"

Jamepad is created by William Hartman

When working on one of my games, I wanted to find a library to support gamepad input that wasn’t GameControlPlus, because I found it hard to use and understand. In my search, I found a java library called Jamepad that provides plug-and-play controller support for java programs. It touts support for Xbox 360 controllers, and it even works with my Nintendo Switch Pro Controller. If it supports both, it’ll likely support every traditional gamepad on the market. However, custom mappings for non-traditional controllers are harder to implement, but not impossible.
Important to note: the latest version that will easily work with processing is Jamepad 1.3.2 because the 1.4 version requires a separate dependency.


Installation instructions:
  1. Download Source code (zip) and Jamepad.jar
  2. Unzip Jamepad-1.3.2.zip
  3. In the Jamepad-1.3.2 folder make a new folder called library
  4. Move Jamepad.jar into the library folder
  5. Rename the Jamepad-1.3.2 folder to just Jamepad because processing won’t recognize the library if the .jar name and folder name don’t match
  6. Move the Jamepad folder into the libraries folder, on windows usually located in Documents/Processing/libraries
  7. In your sketch, go to the “sketch” section of the menu bar, then open the “import library” dropdown, and Jamepad should be in the “Contributed” section. Clicking on it should automatically import everything Jamepad needs to run.

The Using Jamepad section of the Github page gives a good introduction to how to set up Jamepad.

If you want to see every piece of information you can grab from the ControllerState object, you can read its code here.

Benefits of using Jamepad

  • Easy to install and implement into programs
  • Easy to understand its core functionality
  • Rumble support
  • Hotplugging controllers (You can connect and disconnect controllers during runtime)

Possible problems with Jamepad (depends on your use case)

  • Order of controllers (like which one is player 1) is hard to manage when connecting multiple controllers. Recommendations for how to deal with this are on the Github page. Fix for single-player games: you can make a ControllerManager with a connection limit of 1 controller to prevent other connected controllers from taking the player 1 spot.
  • Rumble is simple for compatibility reasons: you can only tell the controller to rumble at a certain strength on a left and right channel for a certain duration, nothing more complex. So, you won’t be able to take advantage of the Nintendo Pro Controller’s HD rumble with this library.
  • No Gyro support
  • No built-in calibration or deadzone checking. You must manually implement these features. For easy deadzones, use the constrain() function. To calibrate controllers on Windows, go to Control Panel > Hardware and Sound > Devices and Printers > Right click on desired game controller > Game Controller Settings > Settings > Calibrate
  • Performance may be an issue on very low-power devices because the ControllerManager.getState() method updates every controller’s connection status and creates a new ControllerState object every time it is called. On my Ryzen 3600 at ~4 GHz, calling getState() once takes 0.04ms. Barely anything, but on a really old CPU, it is something to consider.
  • Speaking of performance, connecting a controller at runtime causes significant slowdown for a few frames, so you may want to consider making your games work with variable framerates using a frame time variable to scale every time-based action by the amount of time it takes to complete 1 frame. Example:
//using millis()
int deltaTime, pTime; //pTime for "previous time"
void draw(){
  deltaTime = millis() - pTime;
  pTime = millis();
}
//using System.nanoTime() is MUCH more accurate, noticeably smoother, but less performant
long pTime;
float deltaTime; //using a float in the previous example doesn't provide any extra precision
void draw(){
  long curTime = System.nanoTime();
  //nanoTime() is slower to call, so calling it once actually improves performance a lot.
  //You can use the same strategy in the previous example, but the difference is negligible
  //because millis() is much faster.
  deltaTime = ((curTime - pTime) * 0.000001); //convert nanoseconds to milliseconds
  pTime = curTime;
}
//keep in mind that at 60fps, deltaTime will be about 16-17 milliseconds
  • Also, the last possible issue is the inability to send lighting data to controllers, so you can’t change the LEDs on the PS4 controller or the Pro controller. In the Pro Controller’s case, the Home button LED with turn on at 100% brightness whenever it connects to Jamepad and will stay lit until the controller gets turned off or goes to sleep.
1 Like