質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.95%

ゲームパッドが反映されない

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,325

score 27

jinputを使用してゲームパッドをコントローラ代わりにしてクライアントサーバ通信でロボットを操作するということを行おうとしています.ゲームパッドを使用するのはクライアント側でjavafx8を使用してアプリケーションを作成しました.問題点はアプリを起動してスティックを動かすとアプリが応答停止になってしまいます.

応答停止になる原因にはどのようなものがあるのでしょうか?
下記にソースコードを載せますのでどこが悪いのか教えてはくれないでしょうか?

package ieexp3;

import java.util.function.Consumer;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;



public class operateRobot_with_GamepadController   {

    //オブジェクト
    @FXML private Button buttonConnect;
    @FXML private Button buttonDisconnect;
    @FXML private Button buttonRun;
    @FXML private TextField inputIPaddress;
    @FXML private TextField inputPort;
    @FXML private static TextField viewLog;

    //通信クラス
    static CommunicationTask task;

    static robotController task2;





    //イベントハンドラの処理
    @FXML protected void handleButtonConnect(ActionEvent e){
        //接続処理(タスク起動)
        String server = inputIPaddress.getText();
        int port = Integer.parseInt(inputPort.getText());
        task = new CommunicationTask(server,port);

        viewLog.textProperty().bind(task.messageProperty());
        Thread thread = new Thread(task);
        thread.setDaemon(true);
        thread.start();
    }
    @FXML protected void handleButtonDisconnect(ActionEvent e){
        //タスク終了処理
        task.makeMessage("disconnect");
        task.cancel();
        viewLog.textProperty().unbind();
    }
    @FXML protected void handleButtonRun(ActionEvent e){
        task2 = new robotController();
        Thread thread = new Thread(task2);
        thread.setDaemon(true);
        task.makeMessage("run");
        if(ControllerInput.State.x == 1){
            task.makeMessage("right");
        }else if(ControllerInput.State.x == -1){
            task.makeMessage("left");
        }else if(ControllerInput.State.y == 1){
            task.makeMessage("forward");
        }else if(ControllerInput.State.y == -1){
            task.makeMessage("back");
        }else if(ControllerInput.State.catchButtonPushed){
            task.makeMessage("catch");
        }else if(ControllerInput.State.downButtonPushed){
            task.makeMessage("down");
        }else if(ControllerInput.State.upButtonPushed){
            task.makeMessage("up");
        }
    }


}
package ieexp3;

import java.util.Optional;


import net.java.games.input.Controller;
import net.java.games.input.ControllerEnvironment;

public interface ControllerInput  {

    //コントローラーの入力状態を取得する抽象メソッド
    Optional<ControllerInput.State> getState();


    boolean available();

    //コントロールオブジェクトを取得する抽象メソッド
    static Controller detectController(Controller.Type type){
        Controller[] controllers = ControllerEnvironment.getDefaultEnvironment().getControllers();
        for(Controller controller : controllers){
            if(controller != null && controller.getType() == type){
                return controller;
            }
        }
        return NullController.Instance;
    }

    //コントローラーの入力状態
    static final class State {
        static int x;
        static int y;
        static boolean upButtonPushed;
        static boolean downButtonPushed;
        static boolean catchButtonPushed;


        State(int x,int y,boolean upButtonPushed,boolean downButtonPushed,boolean catchButtonPushed){
            this.x = x;
            this.y = y;
            this.upButtonPushed = upButtonPushed;
            this.downButtonPushed = downButtonPushed;
            this.catchButtonPushed = catchButtonPushed;
        }
    }
}
```package ieexp3;  

import java.util.Optional;  

import net.java.games.input.Component.Identifier;  
import net.java.games.input.Controller;  


public final class GamepadControllerInput implements ControllerInput {  

private Controller controller;  


private boolean button2Released;  
private boolean button3Released;  
private boolean button6Released;  

//ゲームコントローラーコンストラクタ生成  
GamepadControllerInput(){  
this.controller = ControllerInput.detectController(Controller.Type.GAMEPAD);  
this.button2Released = true;  
this.button3Released = true;  
this.button6Released = true;  
}  
public Controller getController(){  
return this.controller;  
}  
@Override  
public boolean available(){  
return controller != NullController.Instance;  
}  

@Override  
public Optional<ControllerInput.State> getState(){  
//コントローラの入力が受け付けられた場合  
if(controller.poll()){  
//スティックの状態を取得  
float x0 = controller.getComponent(Identifier.Axis.X).getPollData();  
float y0 = controller.getComponent(Identifier.Axis.Y).getPollData();  
int x = 0;  
int y = 0;  

//x軸  
if(x0 > 0.0f){  
x = 1;  
}else if(x0 < 0.0f){  
x = -1;  
}else{  
x = 0;  
}  
//y軸  
if(y0 > 0.0f){  
x = 1;  
}else if(y0 < 0.0f){  
x = -1;  
}else{  
x = 0;  
}  
//ボタン判定  
boolean button2Pushed = controller.getComponent(Identifier.Button._1).getPollData()>0.0f;  
boolean upButtonPushed = button2Released && button2Pushed;  
button2Released = !button2Pushed;  

boolean button3Pushed = controller.getComponent(Identifier.Button._2).getPollData()>0.0f;  
boolean downButtonPushed = button3Released && button3Pushed;  
button3Released = !button3Pushed;  

boolean button6Pushed = controller.getComponent(Identifier.Button._5).getPollData()>0.0f;  
boolean catchButtonPushed = button6Pushed && button6Released;  
button6Released = !button6Pushed;  

if(x != 0 || y != 0 || upButtonPushed || downButtonPushed || catchButtonPushed){  
return Optional.of(new ControllerInput.State(x, y, upButtonPushed, downButtonPushed, catchButtonPushed));  
}  

}  
return Optional.empty();  
}  

}
package ieexp3;  

import net.java.games.input.*;  
import net.java.games.input.Component.Identifier;  

public final class NullController implements Controller {  
static final Controller Instance = new NullController();  

@Override  
public Controller[] getControllers(){  
return new Controller[0];  
}  
@Override  
public Type getType() {  
return Controller.Type.UNKNOWN;  
}  

@Override  
public Component[] getComponents() {  
return new Component[0];  
}  

@Override  
public Component getComponent(Identifier id) {  
return null;  
}  

@Override  
public Rumbler[] getRumblers() {  
return new Rumbler[0];  
}  

@Override  
public boolean poll() {  
return false;  
}  

@Override  
public void setEventQueueSize(int size) {  
}  

@Override  
public EventQueue getEventQueue() {  
return null;  
}  

@Override  
public PortType getPortType() {  
return Controller.PortType.UNKNOWN;  
}  

@Override  
public int getPortNumber() {  
return -1;  
}  

@Override  
public String getName() {  
return "NullController";  
}  
}
package ieexp3;  

public class robotController implements Runnable{  

private ControllerInput gamepadController;  

robotController(){  
this.gamepadController = new GamepadControllerInput();  
}  
public void run(){  
//ゲームパッド入力  
if(gamepadController.available()){  
while(true){  
gamepadController.getState();  
sleep(15L);  
}  
}  
}  
//コントローラ入力の状態を反映  
public void sleep(long millis){  
try{  
Thread.sleep(millis);  
}catch(InterruptedException e){  
throw new RuntimeException(e);  
}  
}  
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

おそらく参考にされているページは同じものを見ていると思いますので、そのページを見ながらもう一度以下の点を確認してみてください。

  • ネイティブライブラリーにパスを通す
  • ゲームパッドをONにしてからJavaプログラムを起動する
  • エラー(スタックトレース)が出ていたらそれをチェックする

それと、「ゲームパッドの信号が反映されない問題」について、もう少し調査をお願いします。
デバッグprintなどを活用して、どの時点で処理が動いていないのかを確認してみて下さい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/06 12:06

    ご質問については後半で返答します。
    先にコードの改善すべき箇所の説明から書きます。

    まず、ControllerInputの入力状態のチェックですが、
    これはループの中で行う必要があります。
    なので、operateRobot_with_GamepadControllerのhandleButtonRunメソッドに
    書いているif文を、robotControllerクラスのrunメソッドのwhile文の中に
    書くようにした方がよいです。

    あと、handleButtonRunメソッドのthreadはstartされていないので、
    処理が開始しないと思います。



    フリーズの件は、
    Windowsなら「応答なし」状態になるのがフリーズです。
    そうでなければ、単に処理が空振りしているだけの可能性があります。
    デバッグを行って、どこが動いていないのかを確認してみて下さい。


    staticフィールドの件は、
    ControllerInput.Stateというのは入力をチェックした
    その「時点」の「状態」を表すオブジェクトなので、
    staticにしてしまうと状態が次のチェックと混ざってしまう恐れがあります。
    ただ問題が発生する頻度がとても低いので、
    正しく動作しているように見えてしまうと思います。
    とにかく、クラスの使い方としては正しくないです。

    キャンセル

  • 2016/07/13 22:06

    修正したら正常に動作させることができました。
    いろいろとお答えしてくれてありがとうございました。
    最後にひとつだけお尋ねしたいのですが、
    ifPresent(this::changestate)
    これのthis::changestateはthis.changestateと同じ意味なのでしょうか?

    キャンセル

  • 2016/07/13 22:40

    this::changestateというのは「メソッド参照」を表します。
    this.changestateだとその場でメソッドを実行してしまいますが、
    メソッド参照は条件を満たした場合のみメソッドを後から実行するような場合に使用します。

    具体的には、
    gamepadInput.getState().ifPresent(this::changeState);
    はgetState()がOptionalを返しますが、値がemptyでない場合にだけ
    changeState()を実行するようにしています。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.95%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る