好的,我很抱歉这是一个非常奇怪的问题,但它让我疯了。
我通过以下方式为我的游戏处理我的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());
}
}
我的问题是当你按住第一个和第二个'运动'之间的一个运动键时,比所需的.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
现在是问题的时候了。显然,第一次移动经过的时间很长,取决于多长时间,所以这是有道理的。我没有得到的是为什么第二个'运动'在.5左右而不是接近.125。正如你从数据中看到的那样,第三步和第四步的触发速度非常快,同时按下它们小于.125的键。
任何人都可以帮助我解决这个问题吗?任何以任何方式改进我的代码的建议都将是巨大的帮助。毫秒数。
答案 0 :(得分: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);
}
}
希望这对别人有帮助!!!
答案 1 :(得分:3)
在分析您的代码后 - 我的快速回复
“s”有效(向南移动) - 向南移动
(释放“s” - 什么都不做)s
“w”无效(快速)
我的另一个建议。 目前您使用两个计时器。一个用于elapsedTimeInSeconds,一个用于控制按下的键。
这可以在一个过程中完成
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);
答案 2 :(得分:2)
如果您按住某个键,则会有一个计时器在发送重复事件之前等待。这听起来与此处发布的问题Eliminating Initial keypress delay和Fixing delay issue in java keypress action
非常相似为什么不采取假设当你收到keyPressed事件时密钥关闭直到你获得keyReleased的方法。所以根本不要依赖为您生成事件的系统。拥有自己的计时器,当你收到一个keyPressed事件并且没有keyRelease时它会按照你所需的间隔请求角色按下按键方向。当你收到钥匙时,请简单地停止计时器。