处理多个按键忽略重复键(handle multiple key presses ignoring r

2019-06-26 20:36发布

我曾问这在另外一个问题的评论部分(> 如何处理Java中同时按键? ),并要求做一个新的问题完全。

我的问题是,当我创建按键的ArrayList不会被删除它们不够快通过的keyReleased事件,如果用户按住键。 我想运动与“ASDF”和北,东,南,西,东北等...

这里是我的两个事件代码:

@Override
public void keyPressed(KeyEvent e) {
    if(chatTextField.isFocusOwner() == true){
        //do nothing - don't walk
    } else {
        logger.debug("Key Pressed: " + e.getKeyChar());
        lastKey = keysPressed.get(keysPressed.size()-1);

        for (String key : keysPressed){
            if (!key.contains(String.valueOf(e.getKeyChar())) && !lastKey.contains(String.valueOf(e.getKeyChar()))){
                keysPressed.add(String.valueOf(e.getKeyChar()));
                System.out.println("ADDED: " + keysPressed);
            }
        }

        String keysList = keysPressed.toString();
        if (keysList.contains("w")){
            if (keysList.contains("d")){
                requestCharacterMove("NorthEast");
            } else if(keysList.contains("a")){
                requestCharacterMove("NorthWest");
            } else{
                requestCharacterMove("North");
            }
        } else if (keysList.contains("s")){
            if (keysList.contains("d")){
                requestCharacterMove("SouthEast");
            } else if(keysList.contains("a")){
                requestCharacterMove("SouthWest");
            } else{
                requestCharacterMove("South");
            }
        } else if (keysList.contains("d")){
            requestCharacterMove("East");
        } else if (keysList.contains("a")){
            requestCharacterMove("West");
        }
    }
}

@Override
public void keyReleased(KeyEvent e) {
    if(chatTextField.isFocusOwner() == true){
        //do nothing - don't walk
    } else {
        logger.debug("Key Released: " + e.getKeyChar());
        for (String key : keysPressed){
            if (key.contains(String.valueOf(e.getKeyChar()))){
                keysPressed.remove(String.valueOf(e.getKeyChar()));
                System.out.println("REMOVED: " + keysPressed);
            }
        }
    }
}

@Override
public void keyTyped(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

直到我在那里通过的lastKey(字符串)变量加入第二检查所创建的金字塔是巨大的。 即使与第二次检查的名单不断增加,而且几乎总是有两三个重复。 因为我的性格是笨拙地移动任何帮助将是巨大的。 :(

也没有办法删除重复的转换为char,字符串,因为我很紧张我用了太多种类的东西“简单”的ArrayList将是巨大的。

Answer 1:

你obseravtion事情最有可能慢慢地处理引起是众多的System.out.println()语句。

您的问题,你没有得到斜向运动从某种程度上故障检查逻辑茎-而是明确检查,如果(例如)键A B压制,只是检查它们独立的-关键的一个在另一个在一个方向上移动人物,B 。 在总(EG),通过移动西部北部,你将有有效的移动西北部。

相反按下键的列表,你可以使用一个java.util.BitSet中,只是定了位的每个当前按键。 这也应该大大减少你需要编写的代码量(只的keyPressed通过设置键代码指示的比特,调用keyReleased清除它)。 要检查是否有键按下你问的BitSet那么如果对码位的当前设置。

编辑:使用的替代列表位集合的实施例

public class BitKeys implements KeyListener {

    private BitSet keyBits = new BitSet(256);

    @Override
    public void keyPressed(final KeyEvent event) {
        int keyCode = event.getKeyCode();
        keyBits.set(keyCode);
    }

    @Override
    public void keyReleased(final KeyEvent event) {
        int keyCode = event.getKeyCode();
        keyBits.clear(keyCode);
    }

    @Override
    public void keyTyped(final KeyEvent event) {
        // don't care
    }

    public boolean isKeyPressed(final int keyCode) {
        return keyBits.get(keyCode);
    }

}

我做了例子实施KeyListener的,所以你甚至可以把它当作是。 当你需要知道,如果一个键被按下只使用isKeyPressed()。 你需要决定是否与原始键代码更喜欢(像我一样),或者与关键角色去(像您目前)。 在任何情况下,你看到使用的BitSet类的代码量记录的关键是如何减少到几行:)



Answer 2:

作为替代方案,这个游戏使用数字键盘来实现与一个按键的每个(半)基本方向。 默认排列方式显示在设计部分。 该键可以单独重新分配给键盘上的任意位置绘制了类似的花环。



Answer 3:

看起来你是不是在Java中正确处理线程。 有三个线程(最低)到任何Java程序。 它们的主要程序线程,事件调度线程,还有一个,我不记得现在。

当你得到它是通过一个特殊的线程提供给您一个事件(我相信这是事件调度线程,但是这是除了点)。 你不允许做任何事情在这个线程(这需要时间),这将冻结你的输入,使你错过的事件,使得Java看起来反应迟钝。 所以,发生了什么事是你在Java爆发事件系统。 你应该做的是把结果保存在某种缓冲的,这是你可以预期与事件做禁食的事情,那么它以后的处理,我将描述。

[旁白:一个有趣的应用是做一个简单的图形用户界面,并在该线程上的按钮呼叫等待的记者像5秒。 整个图形用户界面将冻结,直到延迟完成!]

你应该就在身边(可能你的主线程)运行在不同的线程。 它将运行某种循环,它控制在你的程序的框架,每场比赛周期完成一次。 一旦每个周期这个线程读出存储在输入缓存器中的结果并处理它们。 这背后的理论很简单,但执行可能有点乱,因为你需要确保没有输入事件将被删除或读取更多然后一次。 无论哪种方式,祝你游戏!



文章来源: handle multiple key presses ignoring repeated key