处理多次按键忽略重复键 [英] handle multiple key presses ignoring repeated key

查看:182
本文介绍了处理多次按键忽略重复键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I had asked this in the comments section of another question (> How do I handle simultaneous key presses in Java?), and was asked to make a new question altogether.

我的问题是当我创建一个按键的ArrayList时,如果用户按下键,则不会通过keyReleased事件足够快地删除它们。我希望运动与asdf以及北,东,南,西,东北等等。

My problem is that when I create an ArrayList of keypresses they are not removed fast enough via the keyReleased event if the user holds down the keys. I want movement to be with "asdf" and North, East, South, West, NorthEast... etc.

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

Here is my code for both events:

@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(String)变量创建的金字塔是巨大的。即使进行第二次检查,列表也会增长,并且几乎总是有两到三个重复。任何有关这方面的帮助都会很棒,因为我的角色笨拙地移动着。 :(

Until I added the second check in there via the lastKey(String) variable the pyramid created was enormous. Even with that second check the list grows and almost always has two-three duplicates. Any help on this would be great as my character is moving awkwardly. :(

此外,任何删除重复转换为char,string,arrayList的方法都会很棒,因为我很紧张我使用了太多类型的简单。

Also any way to remove duplicate conversions to char, string, arrayList would be great as I'm nervous I used too many types for something "simple".

推荐答案

你的观点认为,事情处理得很慢很可能是因为完全是许多System.out。 println()语句。

Your obseravtion that things are handled slowly most likely is caused solely be the many System.out.println() statements.

你没有得到对角线移动的问题源于你有点错误的检查逻辑 - 而不是明确地检查是否(例如)键A B被按下,只需单独检查它们 - 键A将角色向一个方向移动,B向另一个方向移动。总计(例如),通过移动WEST NORTH,您将有效移动了NORTHWEST。

Your problem that you do not get diagonal movement stems from your somewhat faulty checking logic - instead of explicitly checking if (for example) keys A and B are pressed, just check them independently - key A moves the character in one direction, B in another. In total (e.g.), by moving WEST and NORTH you will have effectively moved NORTHWEST.

您可以使用java.util.BitSet代替按下的键列表,只需为当前按下的每个键设置该位。也大大减少了你需要编写的代码量(keyPressed只是设置了b所示的位) y密钥代码,keyReleased清除它)。要检查是否按下某个键,请询问BitSet然后是否当前设置了代码位。

Instead of a list of pressed keys, you could use a java.util.BitSet and just set the bit for each key that is currently pressed. That should also drastically reduce the amount of code you need to write (keyPressed just sets the bit indicated by key code, keyReleased clears it). To check if a key is pressed you ask the BitSet then if the bit for the code is currently set.

编辑:使用BitSet而不是列表的示例

Example of using BitSet instead of a list

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类来记录键的代码量减少到几行:)

I made the example implement KeyListener, so you could even use it as is. When you need to know if a key is pressed just use isKeyPressed(). You need to decide if you prefer with raw key code (like I did) or go with key character (like you currently do). In any case, you see how using the BitSet class the amount of code for recording the keys reduces to a few lines :)

这篇关于处理多次按键忽略重复键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆