Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

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

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

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

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本まで使える。ここでは最初の1本しか対象にしてない。
glfwGetJoystickAxes()で取得できるfloatバッファの一つ目が左側スティックのX座標、二つ目がY座標となっている。Axesは5つバッファがあるが右側スティックと他にもう一軸。なんだこれ???
アナログだろうがデジタルだろうが、スティックのセンターが0.0ではない。絶対値で0.01以下は切り捨てとかしないと0.0は取れない模様。
glfwGetJoystickButtons()で取得できるbyteバッファは素直にボタン番号順のようだ。Buttonsも16個もバッファがあるが使うのは最初の数個だけだろう。

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

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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away