Java 第一次重复时按下事件慢

Java 第一次重复时按下事件慢,java,events,keypress,bitset,Java,Events,Keypress,Bitset,好吧,我很抱歉这是一个非常奇怪的问题,但它让我发疯 我通过以下方式处理游戏中WASD的移动: Action ClassWASDKeyPressed = new ClassWASDKeyPressed(); Action ClassWASDKeyReleased = new ClassWASDKeyReleased(); BitKeys movementBitKeys = new BitKeys(); //for WASD movement key pressed/releases //pres

好吧,我很抱歉这是一个非常奇怪的问题,但它让我发疯

我通过以下方式处理游戏中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);
以下是两个动作类:

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
}
我的问题是,当你在第一个和第二个“移动”之间按住一个移动键时,它比所需的.125毫秒等待时间长得多。以下是一些示例数据:

第1组:

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

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

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

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

第2组:

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

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

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

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

现在是提问的时候了。很明显,第一次移动时,所用的时间非常长,这取决于移动时间的长短,所以这是有意义的。我不明白的是,为什么第二个“运动”在.5左右,而不是接近.125。从数据中可以看出,第三和第四步在按住键的同时启动得非常快,它们小于.125


有谁能帮我解决这个问题吗?任何以任何方式改进我的代码的建议都将是巨大的帮助。毫秒计数。

如果您按住一个键,则会有一个计时器在发送重复事件之前等待。这听起来和这里贴的问题非常相似


为什么不采取这样的方法,假设当你收到一个按键事件时,在你得到一个按键释放之前,按键是向下的呢。因此,不要依赖系统为您生成事件。拥有自己的计时器,当您收到按键事件且没有按键释放时,计时器会在您要求的时间间隔内请求角色沿按键方向移动。当您收到按键释放时,只需停止计时器。

由于@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);
    }
}

希望这能对其他人有所帮助

在分析您的代码之后-我的快速响应

  • 当按下某个键以快速移动时,它不会被您的movementBitKeys重新设置(无效) 这可能是个问题。当您快速按下按键时,例如“s”后跟“w”而不是“a”
“s”有效(向南移动)-向南移动

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

“w”无效(要快速)

“a”有效(向东移动)->向东移动->这是错误的-应该是东北方向 我的另一个建议。 目前您使用两个计时器。一个用于延时键,另一个用于控制按下的键

这可以在一个过程中完成

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

还有时间任务的改变

Timer timer = new Timer();
timer.schedule(new TimerTask() {
  public void run() {
    move(movementBitKeys); // instead of keypressed - without elapsedTimeSeconds  
  }
}, 0, 0125);

试着改用。这允许您指定要在按下或按下时触发事件release@aioobe我在网上看到你的一篇帖子回答了一个非常类似的问题。你的解决方案让我有点困惑。我不想惹人烦,但如果你有时间,你有没有可能看一下这篇文章,帮帮忙?谢谢。@Ragnagord你能再详细阐述一下你的想法吗?谢谢你。前几天我自己发现了它,当时它工作不太正常,我就是这样修复的。我想回到这里并添加它:)很好的提醒:如果(elapsedtimesons<.125){//让他们每秒移动8次logger.info(“按键(快速):“+elapsedtimesons”);移动bitkeys.KeyPressed(e);}我直到现在才真正理解你的意思,你的想法实际上帮助简化了很多事情。非常感谢。。。我会给你赏金:)
Timer timer = new Timer();
timer.schedule(new TimerTask() {
  public void run() {
    move(movementBitKeys); // instead of keypressed - without elapsedTimeSeconds  
  }
}, 0, 0125);