代码之家  ›  专栏  ›  技术社区  ›  Ivo Wetzel

Linux /X11下的JavaKePress/密钥发布问题

  •  1
  • Ivo Wetzel  · 技术社区  · 15 年前

    我正在开发一个小型的2D游戏引擎在Java,在玩我的演示游戏在虚拟箱VM托管Ubuntu,我发现一个奇怪的bug,有时会导致游戏忽略了一个事实,一个键被按下。所以你往左边跑,直到突然停下来。

    现在在一个真正的Ubuntu下,我找到了问题的原因。当我按住一个键时,按键/按键释放事件将一直发送。

    我的系统检查是否按了键,如下所示:
    -如果按下某个键,将其添加到“下载列表”
    -如果钥匙被释放,将其添加到上行链路
    -在游戏的每一帧上,将上行链路中的键从下行链路中删除。
    -如果某个键仍在下载列表中,则按下该键。

    现在,当您按下第二个键时,有时键释放是由另一个键触发的最后一个事件,该另一个键仍保持不变,但无法以这种方式识别。

    有什么解决办法吗?真的很烦人。

    编辑
    为了澄清这是我连续按住一个键时得到的结果:
    按下:87
    发布:87
    发布:87
    按下:87
    发布:87
    按下:87
    发布:87
    按下:87
    发布:87
    等。

    编辑2
    OK Google之后,我发现这是X11服务器的一个“特性”,但我仍然不知道如何检测Java中的“假”关键事件。

    3 回复  |  直到 15 年前
        1
  •  1
  •   bkritzer    15 年前

    您可能会遇到一些冲突,因为您解决每帧按键和在列表之间切换的方式。对于您计划按下的每一个键(如右箭头、左箭头等),使用布尔值可能会更干净一些。当按下某个键时,将相应的布尔值设置为“真”,然后释放后,将其设置为“假”。这是处理电子游戏中键盘控制的一种很常见的方法

        2
  •  1
  •   Ivo Wetzel    15 年前

    可以。。。我“修理”了它。

    由于X11不断地烧毁它的自动重复键事件,所以没有办法改变整个事情的方式,那些“假”事件被忽略,你不能区分“真实”和“假”事件在Java中。

    所以解决这个问题的方法如下。由于每个“假”keyup事件后面都有一个立即的keydown事件,因此如果收到keydown事件,只需从keyremovelist中删除keyup事件,如下所示:

    public final void keyPressed(final KeyEvent e) {
        int key = e.getKeyCode();
    
        // Fix AutoKeyRepeat under X11
        if (keysRemove.contains(key)) {
            keysRemove.remove(Integer.valueOf(key));
        }
    
        if (!keysDown.contains(key)) {
            keysDown.add(key);
            keysPressed.add(key);
            lastKeys.add(key);
            if (lastKeys.size() > 16) {
                lastKeys.remove(0);
            }
        }
        e.consume();
    }
    

    因为“真正的”keyup事件后面不是立即的keydown事件,所以它是正常处理的。理论上,游戏框架不可能出现在“假”键控和键控之间。

        3
  •  0
  •   Diego Torres Milano    15 年前

    当然,自动重复可以在x11中配置。看看就行了 xset 命令选项 R -R . 您可以使用禁用某些键码的自动重复

    $ xset -r keycode