3

さて、これが本当に奇妙な質問であることをお詫びしますが、それは私を狂わせています。

私は自分のゲームのWASDの動きを次の方法で処理します。

Action ClassWASDKeyPressed = new ClassWASDKeyPressed();
Action ClassWASDKeyReleased = new ClassWASDKeyReleased();
BitKeys movementBitKeys = new BitKeys(); //for WASD movement key pressed/releases

//pressed
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("W"), "wButtonPress");
theDesktop.getActionMap().put("wButtonPress", ClassWASDKeyPressed);
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), "aButtonPress");
theDesktop.getActionMap().put("aButtonPress", ClassWASDKeyPressed);
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("S"), "sButtonPress");
theDesktop.getActionMap().put("sButtonPress", ClassWASDKeyPressed);
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("D"), "dButtonPress");
theDesktop.getActionMap().put("dButtonPress", ClassWASDKeyPressed);
//released
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released W"), "wButtonRelease");
theDesktop.getActionMap().put("wButtonRelease", ClassWASDKeyReleased);
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released A"), "aButtonRelease");
theDesktop.getActionMap().put("aButtonRelease", ClassWASDKeyReleased);
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released S"), "sButtonRelease");
theDesktop.getActionMap().put("sButtonRelease", ClassWASDKeyReleased);
theDesktop.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released D"), "dButtonRelease");
theDesktop.getActionMap().put("dButtonRelease", ClassWASDKeyReleased);

2つのアクションクラスは次のとおりです。

class ClassWASDKeyPressed extends AbstractAction {
    private static final long serialVersionUID = 1L;

    public void actionPerformed(ActionEvent e) {
        if (chatTextField.isFocusOwner() == false){
            if (e.getActionCommand().equals("w")){
                keyPressed(87);
            } else if(e.getActionCommand().equals("a")){
                keyPressed(65);
            } else if(e.getActionCommand().equals("s")){
                keyPressed(83);
            } else if(e.getActionCommand().equals("d")){
                keyPressed(68);
            }
        }
    }
}

class ClassWASDKeyReleased extends AbstractAction {
    private static final long serialVersionUID = 1L;

    public void actionPerformed(ActionEvent e) {
        if (chatTextField.isFocusOwner() == false){
            if (e.getActionCommand().equals("w")){
                keyReleased(87);
            } else if(e.getActionCommand().equals("a")){
                keyReleased(65);
            } else if(e.getActionCommand().equals("s")){
                keyReleased(83);
            } else if(e.getActionCommand().equals("d")){
                keyReleased(68);
            }
        }
    }
}

そして、これのロジックは次のとおりです。

public void keyPressed(int e) {
    long endTime = System.nanoTime();
    long elapsedTime = endTime - startTime;
    double elapsedTimeSeconds = (double)elapsedTime / 1000000000.0;

    if (elapsedTimeSeconds < .125){ //let them move 8 times a second
        logger.info("KeyPressed (QUICK): " + elapsedTimeSeconds);
    } else {
        logger.info("KeyPressed (VALID): " + elapsedTimeSeconds);
        //logger.debug("Key Pressed: " + e.getKeyChar());  //FOR TROUBLESHOOTING
        movementBitKeys.keyPressed(e);
        //movementBitKeys.showKeyList();  //FOR TROUBLESHOOTING

        if (movementBitKeys.isKeyPressed(87) && !movementBitKeys.isKeyPressed(68) && !movementBitKeys.isKeyPressed(83) && !movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("North");
        }
        if (movementBitKeys.isKeyPressed(87) && movementBitKeys.isKeyPressed(68) && !movementBitKeys.isKeyPressed(83) && !movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("NorthEast");
        }
        if (movementBitKeys.isKeyPressed(87) && !movementBitKeys.isKeyPressed(68) && !movementBitKeys.isKeyPressed(83) && movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("NorthWest");
        }
        if (!movementBitKeys.isKeyPressed(87) && movementBitKeys.isKeyPressed(68) && !movementBitKeys.isKeyPressed(83) && !movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("East");
        }
        if (!movementBitKeys.isKeyPressed(87) && !movementBitKeys.isKeyPressed(68) && movementBitKeys.isKeyPressed(83) && !movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("South");
        }
        if (!movementBitKeys.isKeyPressed(87) && movementBitKeys.isKeyPressed(68) && movementBitKeys.isKeyPressed(83) && !movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("SouthEast");
        }
        if (!movementBitKeys.isKeyPressed(87) && !movementBitKeys.isKeyPressed(68) && movementBitKeys.isKeyPressed(83) && movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("SouthWest");
        }
        if (!movementBitKeys.isKeyPressed(87) && !movementBitKeys.isKeyPressed(68) && !movementBitKeys.isKeyPressed(83) && movementBitKeys.isKeyPressed(65)){
            requestCharacterMove("West");
        }
        startTime = endTime;
    }
}

public void keyReleased(int e) {
    //logger.debug("Key Released: " + e.getKeyChar());  //FOR TROUBLESHOOTING
    movementBitKeys.keyReleased(e);
    //movementBitKeys.showKeyList();  //FOR TROUBLESHOOTING
}

public void keyTyped(int e) {
    // not used - but in case I ever want it
}

また、BitSetクラス:

package com.jayavon.game.helper;

import java.util.BitSet;

public class BitKeys{

    private BitSet keyBits = new BitSet(256);

    public void keyPressed(final int keyCode) {
        keyBits.set(keyCode);
    }

    public void keyReleased(final int keyCode) {
        keyBits.clear(keyCode);
    }

    public void keyTyped(final int keyCode) {
        // don't care
    }

    public boolean isKeyPressed(final int keyCode) {
        return keyBits.get(keyCode);
    }

    public void showKeyList(){
        System.out.println(keyBits.toString());
    }

}

私の問題は、最初と2番目の「移動」の間に移動キーの1つを押したままにすると、必要な.125ミリ秒の待機時間よりもはるかに長くなることです。サンプルデータは次のとおりです。

セット1:

6059 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):2.567790275

6620 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):0.560479937

6670 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.0504469 6710 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.09360516 6750 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):0.129943376

6791 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.04009505 6821 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.07098997 6851 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.102378686 6902 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):0.152006677

セット2:

9690 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):2.03802468

10272 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):0.582025645

10322 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.054749323 10342 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.069890042 10372 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.100790212 10412 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):0.141337411

10462 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.049483458 10462 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.049720381 10512 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(QUICK):0.098888524 10542 [AWT-EventQueue-0] INFO com.jayavon.game.client.MyClient-KeyPressed(VALID):0.128729361

そして今、質問の時間です。明らかに、最初に移動するときの経過時間は、長さによっては膨大な時間になるので、それは理にかなっています。私が得られないのは、2番目の「動き」が.125に近いのではなく、約.5である理由です。データからわかるように、3番目と4番目のステップは、キーを押している間、非常に速く起動しているため、.125未満です。

誰かがこれをなんらかの方法で手伝ってくれる?何らかの方法で私のコードを改善するための提案は、確かに非常に役立ちます。ミリ秒がカウントされます。

4

3 に答える 3

3

@aioobeの多大な助けにより、これをどのように解決したかを説明します。

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    public void run() {
        checkKeyStrokes();
    }
}, 0, 0135);

public void checkKeyStrokes(){
    if (movementBitKeys.isKeyPressed(87)){ //w
        keyPressed(87);
    }
    if (movementBitKeys.isKeyPressed(65)){ //a
        keyPressed(65);
    }
    if (movementBitKeys.isKeyPressed(83)){ //s
        keyPressed(83);
    }
    if (movementBitKeys.isKeyPressed(68)){ //d
        keyPressed(68);
    }
}

これが他の人の助けになることを願っています!!!

于 2012-11-15T06:47:29.577 に答える
3

あなたのコードを分析した後-私からの迅速な応答

  • キーを押してクイックすると、movementBitKeysによって認識されません(無効)これは問題になる可能性があります。キーをすばやく押すと、たとえば「s」の後に「a」ではなく「w」が続きます。

「s」は有効です(南に移動)-南に移動

(「s」を解放します-何もしません)s

「w」は無効です(すばやく)

「a」は有効です(東に移動)->東に移動->これは間違っています-北東である必要があります

私の別の提案。現在、2つのタイマーを使用しています。1つは経過時間InSeconds用で、もう1つは押されたキーを制御するためのタイマーです。

これは1つのプロセスで実行できます

class ClassWASDKeyPressed extends AbstractAction {
  private static final long serialVersionUID = 1L;

  public void actionPerformed(ActionEvent e) {
    if (chatTextField.isFocusOwner() == false){
        if (e.getActionCommand().equals("w")){
            movementBitKeys.keyPressed(87);
        } else if(e.getActionCommand().equals("a")){
            movementBitKeys.keyPressed(65);
        } else if(e.getActionCommand().equals("s")){
            movementBitKeys.keyPressed(83);
        } else if(e.getActionCommand().equals("d")){
            movementBitKeys.keyPressed(68);
        }
    }
  }

}

そしてTimerTaskの変更

Timer timer = new Timer();
timer.schedule(new TimerTask() {
  public void run() {
    move(movementBitKeys); // instead of keypressed - without elapsedTimeSeconds  
  }
}, 0, 0125);
于 2012-11-16T07:22:51.467 に答える
2

キーを押したままにしている場合は、繰り返しイベントを送信する前に待機するタイマーがあります。これは、ここに投稿された質問と非常によく似ています。Javaキー押下アクションでの初期キー押下遅延の排除遅延問題の修正

keyPressedイベントを受信したときに、keyReleasedを取得するまでキーがダウンしていると想定するというアプローチをとってみませんか。したがって、イベントを生成するシステムに依存しないでください。keyPressedイベントを受信し、keyReleaseがない場合に、必要な間隔でキャラクターがキーを押した方向に移動するように要求する独自のタイマーを用意します。keyReleaseを受け取ったら、タイマーを停止するだけです。

于 2012-10-24T05:04:08.550 に答える