Java 第一次重复时按下事件慢
好吧,我很抱歉这是一个非常奇怪的问题,但它让我发疯 我通过以下方式处理游戏中WASD的移动: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
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”
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);