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);

下面是两个 Action 类:

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());
    }

}

我的问题是,当您按住第一个和第二个“移动”之间的一个移动键时,比所需的 0.125 毫秒等待时间长得多。以下是一些示例数据:

设置 1:

6059 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):2.567790275

6620 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):0.560479937

6670 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.0504469 6710 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.09360516 6750 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):0.129943376

6791 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.04009505 6821 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.07098997 6851 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.102378686 6902 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):0.152006677

第 2 组:

9690 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):2.03802468

10272 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):0.582025645

10322 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.054749323 10342 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.069890042 10372 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.100790212 10412 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):0.141337411

10462 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.049483458 10462 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.049720381 10512 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(快速):0.098888524 10542 [AWT-EventQueue-0] 信息 com.jayavon.game.client.MyClient - 按键(有效):0.128729361

现在是时候提出这个问题了。显然,您第一次移动经过的时间取决于多长时间,所以这是有道理的。我不明白为什么第二个“运动”大约是 0.5 而不是更接近 0.125。正如您从数据中看到的那样,第三步和第四步在按住键时发射得非常快,以至于它们小于 0.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

分析您的代码后 - 我的快速回复

  • 当一个键被按下来快速时,它不会被你的 moveBitKeys 识别(无效)这可能是一个问题。当您快速按下按键时,例如“s”后跟“w”而不是“a”。

"s" 有效(向南移动) - 向南移动

(释放“s” - 什么都不做)s

"w" 无效(快速)

“a”有效(向东移动)->向东移动->这是错误的-应该是东北

我的另一个建议。目前您使用两个计时器。一个用于 elapsedTimeInSeconds 和一个 Timer 用于控制按下的键。

这可以在一个过程中完成

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

如果您按住一个键,那么在发送重复事件之前会有一个计时器等待。这听起来与此处发布的问题非常相似Elimination Initial keypress delayFixing delay issue in java keypress action

为什么不直接假设当您收到一个 keyPressed 事件时该键已关闭,直到您获得一个 keyReleased。因此,不要依赖系统为您生成事件。拥有自己的计时器,当您收到 keyPressed 事件并且没有 keyRelease 时,它​​会在您要求的时间间隔内请求角色沿按键方向移动。当您收到 keyRelease 时,只需停止计时器。

于 2012-10-24T05:04:08.550 回答