Java LWJFLでジョイスティックの入力を受け取る

Javaでジョイスティックの入力を受け取る方法はJInputなるライブラリでもできるのだが、
ネイティブライブラリ(DLL)をパスの通った場所に置かなくてはならないとか、
どうもMac/Linuxはなさそうとかで、色々嫌だったのでLWJGLなるライブラリを使ってみる。

まずLWJGL3を https://www.lwjgl.org/ から適当にダウンロードしてくる。
必要なjarはwindowsの場合は下記４つ。

- lwjgl.jar
- lwjgl-natives-windows.jar
- lwjgl-glfw.jar
- lwjgl-glfw-natives-windows.jar

Mac/Linuxはnatives-macとかnatives-linuxとかを使えばいけると思う
こんなコードで実験した。

```java:JoyStick.java
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import org.lwjgl.glfw.GLFW;

public class JoyStick {

	public static void main(String[] args) {
		// GLFWを初期化します。これを行わないとほとんどのGLFW関数は機能しない。
		if(!GLFW.glfwInit())
			throw new IllegalStateException("Unable to initialize GLFW");

		GLFW.glfwPollEvents();
		int stick;
		for(stick = 0; stick <= GLFW.GLFW_JOYSTICK_LAST; stick++) {
			if(!GLFW.glfwJoystickPresent(stick)) continue;
			System.out.println("JoyStick(" + stick + ")Name:" +
					GLFW.glfwGetJoystickName(stick) + " " +
					GLFW.glfwGetGamepadName(stick));
			break;
		}
		if(stick > GLFW.GLFW_JOYSTICK_LAST) return;

		for(int i = 0; i < 1000; i++) {
			int count1 = 0;
			FloatBuffer floatBuffer = GLFW.glfwGetJoystickAxes(stick);
			System.out.print("Axes:");
			while (floatBuffer.hasRemaining()) {
				float axes = floatBuffer.get();
				System.out.print(count1 + "," + axes + " ");
				count1++;
			}

			int count2 = 0;
			System.out.print("Button:");
			ByteBuffer byteBuffer = GLFW.glfwGetJoystickButtons(stick);
			while (byteBuffer.hasRemaining()) {
				byte button = byteBuffer.get();
				System.out.print(count2 + "," + button + " ");
				count2++;
			}
			System.out.println();

			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}
	}

}
```
実行結果はこんな風になるはず。

```
JoyStick(0)Name:PC Game Controller        SVEN X-PAD
Axes:0,1.5259022E-5 1,1.5259022E-5 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,1.5259022E-5 1,1.5259022E-5 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,-0.3515526 1,1.5259022E-5 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,-1.0 1,-0.20311284 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,-1.0 1,-0.17967498 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,-1.0 1,1.5259022E-5 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,-1.0 1,1.5259022E-5 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,-1.0 1,1.0 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
Axes:0,1.5259022E-5 1,1.0 2,1.5259022E-5 3,1.5259022E-5 4,1.5259022E-5 Button:0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0 
```
ジョイスティックは無駄に16本まで使える。ここでは最初の１本しか対象にしてない。
glfwGetJoystickAxes()で取得できるfloatバッファの一つ目が左側スティックのX座標、二つ目がY座標となっている。Axesは５つバッファがあるが右側スティックと他にもう一軸。なんだこれ？？？
アナログだろうがデジタルだろうが、スティックのセンターが0.0ではない。絶対値で0.01以下は切り捨てとかしないと0.0は取れない模様。
glfwGetJoystickButtons()で取得できるbyteバッファは素直にボタン番号順のようだ。Buttonsも１６個もバッファがあるが使うのは最初の数個だけだろう。

はまりどころはglfwInit()。これやらなくて動かなかった。
てかInitで失敗ってなんだよ。。。

LWJGLの作法だと、`import static org.lwjgl.glfw.GLFW.*;`とかしなきゃならないらしいが、Javaっぽくないのでフツーにインポートして使ってる。

あとは煮るなり焼くなりご自由に。