密钥侦听器事件的短暂延迟



我正在编写一个小游戏。到目前为止,我有一个玩家,他可以跟随玩家在2D打印的瓷砖世界中移动。这里有一个小预览。

现在我的播放器移动代码如下所示:

键侦听器类

public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(5);
if(key == KeyEvent.VK_A) tempObject.setVelX(-5);
if(key == KeyEvent.VK_SPACE && Var.jump == true) {
tempObject.setVelY(-10);
Var.jump = false;
}
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(0);
if(key == KeyEvent.VK_A) tempObject.setVelX(0);
}
}

玩家类

public void tick() {
if (Var.falling == true) {
velY += Var.gravity;
if (velY > 10) {
velY = 10;
}
}
x += velX;
y += velY;

这些代码只是类的一部分。

问题

当我使用 A 或 D 向右或向左移动,然后以某种方式点击另一个键(从 a 到 d/从 d 到 a)时,我的角色会静止一小段时间,然后在短暂的延迟后移动。看这里。

  1. 用户按D,触发对keyPressed的调用,tempObject.setVelX(5)调用 。
  2. 用户释放A,这会触发对keyReleased的调用,tempObject.setVelX(0)调用 。 这会停止角色的运动。
  3. 用户仍然按住D,因此在短暂延迟后,该键的自动重复会触发对keyPressed的另一个调用,这会导致再次调用tempObject.setVelX(5),导致字符再次开始移动。

除非未按下移动键,否则不应调用tempObject.setVelX(0)

你如何确定这一点? 您需要定义跟踪它们的实例字段。 例如:

private boolean leftPressed;
private boolean rightPressed;
// ...
public void keyPressed(KeyEvent e) {
//...
if (key == KeyEvent.VK_D) {
rightPressed = true;
tempObject.setVelX(5);
}
if (key == KeyEvent.VK_A) {
leftPressed = true;
tempObject.setVelX(-5);
}
//...
}
public void keyReleased(KeyEvent e) {
//...
if (key == KeyEvent.VK_D) {
rightPressed = false;
if (!leftPressed) {
tempObject.setVelX(0);
}
}
if (key == KeyEvent.VK_A) {
leftPressed = false;
if (!rightPressed) {
tempObject.setVelX(0);
}
}
//...
}

一些旁注:

  • gameObject将是一个比tempObject更好的变量名称。
  • 你永远不应该写">booleanVariable== true"。 相反,只需编写布尔变量。 这避免了通过编写一个"="而不是两个来意外分配的任何可能性。 例如:
if (Var.falling) {

更简单地说:从代码中删除每个出现的== true

在不知道键控和键降的确切顺序的情况下,很难说出确切的问题是什么,但看起来您的程序容易受到重叠的键控/键下序列的影响 - 例如:

A down -> velocity = -5
D down -> velocity = +5
A up   -> velocity = 0 // but you want it to still be +5

将日志记录添加到游戏代码以帮助调试这些情况。

有许多方法可以处理此问题,但一种方法是保持当前关闭键的运行计数:

public void keyPressed(KeyEvent e) {
heldKeys++;
... other code ...
}
public void keyReleased(KeyEvent e) {
heldKeys--;
... other code ...
if(heldKeys == 0) {
velocity = 0;
}
}

这是轻巧但生硬的。更精细的方法可能是记录每个键的状态:

public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
heldKeys.set(key, true);
}

。根据keyStates中的内容更新游戏状态。

根据你想对效率的狂热程度,keyStates可能是你自己创造的HashSet(Integer, Boolean)或更专业的东西。


但!请参阅如何知道用户何时真正在 Java 中释放了密钥?讨论从键盘自动重复。

相关内容

  • 没有找到相关文章

最新更新