Aegidius
 Plüss   Aplulogo
     
 www.aplu.ch      Print Text 
© 2021, V10.4
 
  XboxController
 
 
Runs under Windows Operating System 32 and 64 bit

The XboxController library is efficient but simple to use

The Xbox360 controller is a sophisticated game pad that can be used to pilot game actions but also real robots attached to the PC via a communication link. It has the following controls:

  • 4 analog buttons called LeftThumb, RightThumb, LeftTrigger, RightTrigger
  • 8 digital buttons called A, B, X , Y, START, BACK, LeftShoulder, RightShoulder
  • 1 direction pad called DPAD

LeftThumb and RightThumb controls deliver continuous x-y positions of the knob and may also be pressed/released. LeftTrigger and RightTrigger controls deliver continuous values as a measure of how much the knobs are pressed. The dpad delivers 8 compass directions in 45 degrees steps.

XboxController

The XboxController library maps the LeftThumb and RightThumb positions to polar coordinates (radius 0..1, angle 0..360 degrees) and the LeftTrigger and RightTrigger position to double values 0..1. The dpad position is returned as an integer from 0 to 7. There are a total of 10 buttons that may be pressed or released. Because the library is fully dedicated for the Xbox360 controller and uses the Java event model to report the state of the controls, it is simpler to use than the more general libraries like JInput. Moreover the library fully supports the most recent wireless controller including the left and right vibrators (rumblers).

How it works

The XboxController library consists of a Java wrapper class sitting on top of a native program written in C++. For the communication between Java and C++ the Java API Wrapper framework (JAW) is extensively used, while JAW is based on the Java Native Interface (JNI). In order to provide high performance, the native program polls the controller state in a separate high priority native thread. Only state changes are reported to Java via a large message queue (FIFO). This queue is polled by a Java thread that generates the events and invokes the registered callback methods. With this mechanism there is little risk that an event (e.g. a short button hit) is lost even if the system is heavily loaded.

 

System requirements

Operating system: Windows XP or Windows 7 (32- or 64-bit) with the following additional components:

  • Xbox360 controller driver, language dependent
  • Microsoft Visual C++ 2010 Redistributable Package (x86 or x64) installed
    (download from MS website)
  • XboxController.jar, jaw.jar, xboxcontroller.dll or xboxcontroller64.dll

All additional components are contained in the XboxController distribution.

 

A demonstration example

The following program shows a rumbler demonstration. LeftTrigger and RightTrigger controls are used to vibrate the left and right vibrators depending on how much the controls are pressed.

// RumbleDemo.java

import ch.aplu.xboxcontroller.*;
import javax.swing.JOptionPane;

public class RumbleDemo
{
  private XboxController xc;
  private int leftVibrate = 0; 
  private int rightVibrate = 0; 

  public RumbleDemo()
  { 
    xc = new XboxController();
    
    if (!xc.isConnected())
    {
      JOptionPane.showMessageDialog(null
        "Xbox controller not connected.",
        "Fatal error"
        JOptionPane.ERROR_MESSAGE);
      xc.release();
      return;
    }
    
    xc.addXboxControllerListener(new XboxControllerAdapter()
    {
      public void leftTrigger(double value)
      {
        leftVibrate = (int)(65535 * value * value);
        xc.vibrate(leftVibrate, rightVibrate);
      }
      public void rightTrigger(double value)
      {
        rightVibrate = (int)(65535 * value * value);
        xc.vibrate(leftVibrate, rightVibrate);
      }
    });
    
    JOptionPane.showMessageDialog(null
      "Xbox controller connected.\n" + 
      "Press left or right trigger, Ok to quit.",
        "RumbleDemo V1.0 (www.aplu.ch)"
        JOptionPane.PLAIN_MESSAGE);
    
    xc.release();
    System.exit(0);
  }
    
  public static void main(String[] args)
  {
    new RumbleDemo();
  }
}

Execute RumbleDemo using WebStart.
If the execution fails, check the system requirements (see above)

Discussion: First an XboxController instance is created using the default constructor and a check is made, if the controller is connected (drivers installed, cable plugged in, turned on). Then we register the callback methods leftTrigger() and rightTrigger() using a anonymous XboxControllerAdapter. The use of an adapter is preferable to a listener because we don't want to implement the many listener's methods. The application thread then blocks in a modal dialog and waits for termination.

All work is done in the callback methods, which are called when a trigger button changes its position. Whenever this happens, we call the vibrate() method to change the current amount of left and right vibration.

It is clearly seen in this demonstration that the polling of the controller is completely hidden to the user of the XboxController library.

 

Running native code under 64-bit Windows

The JAW based native code is loaded and run as Windows DLL. xboxcontroller.dll is a Windows 32-bit DLL and xboxcontroller64.dll is it's 64-bit counterpart. The loading of 32-bit and 64-bit DLLs is not optimal, neither with Windows 7 (up) nor with Java. Under 32-bit Windows, 64-bit DLLs are not functional. On the other hand under 64-bit Windows, both 32-bit and 64-bit DLLs are supported. Because the Java Virtual Machine loads the DLL, the decision which DLL version is needed does not depend on the OS, but on the JVM. Because both JVM versions may reside on the same Windows 64-bit machine, problems while loading DLLs are frequent.

To make a Java program portable between 32- and 64-bit JVMs your code must check which JVM is running and load the appropriate DLL. Some of the XboxController constructors perform this action for you. If automatic loading fails, try to load the corresponding DLL explicitely by defining a method is64bit()

static boolean is64bit()
{
  return System.getProperty("sun.arch.data.model").equals("64");
}

and create the XboxController instance with:

XboxController xc = new XboxController(is64bit()? 
    "xboxcontroller64"
 : "xboxcontroller"), 1, 50, 50);