Медленная реакция AWT KeyListener

Я создаю простую игру с Java Swing. У меня проблема - KeyListener кажется немного прерывистым/медленным. Персонаж перемещается с помощью этого кода:

// player control
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        switch(key){
        case(KeyEvent.VK_LEFT): dx = -speed; break;
        case(KeyEvent.VK_RIGHT): dx = speed; break;
        case(KeyEvent.VK_UP): dy = -speed; break;
        case(KeyEvent.VK_DOWN): dy = speed; break;
        }
    }

public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();
    switch(key){
    case(KeyEvent.VK_LEFT): dx = 0; break;
    case(KeyEvent.VK_RIGHT): dx = 0; break;
    case(KeyEvent.VK_UP): dy = 0; break;
    case(KeyEvent.VK_DOWN): dy = 0; break;
    }
}

// this method is performed each time before redrawing the screen
public void step() {
    x += dx;
    y += dy;
}

Большую часть времени все нормально, но иногда персонаж ненадолго останавливается, прежде чем реагировать на клавиатуру. Как сделать ввод с клавиатуры более плавным?


person YemSalat    schedule 05.06.2012    source источник
comment
Может быть «ключевая скорость повторения». Рассматривали ли вы возможность использования привязки клавиш?   -  person Andrew Thompson    schedule 05.06.2012
comment
это совсем не так, медленные реакции ???, конечно, есть одна проблема == зависит от вашего кода, который .... (то же самое будет с использованием KeyBinding), для лучшей помощи скорее отредактируйте свой вопрос с помощью SSCCE   -  person mKorbel    schedule 05.06.2012
comment
на самом деле после прочтения о привязках клавиш кажется, что они работают так же, как KeyListener. Мне также было интересно, можно ли «выйти» из события KeyPressed после его запуска, чтобы оно не повторялось   -  person YemSalat    schedule 05.06.2012
comment
Я думаю, что проблема в «скорости повторения клавиш». В основном происходит следующее: например, нажимается правая клавиша, персонаж движется вправо. Затем нажимается левая клавиша - персонаж начинает двигаться влево. Если вы сейчас отпустите правую клавишу, сработает keyReleased и сбросит xSpeed ​​до 0. Теперь слушатель ждет срабатывания следующей keyPressed, так как мы все еще удерживаем левую клавишу.   -  person YemSalat    schedule 05.06.2012
comment
правый вывод с клавиатуры на KeyListener такой же как и KeyBindings, но тут сходство уже заканчивается, все дальше про Focus и FocusSubsystem, с KeyBindings не важно есть или нет, этот вопрос не решить никогда, с KeyListener является наиболее важным, серьезной проблемой и зависит от..., вплоть до того, что вы в том числе отредактируете свой пост с помощью SSCCE, чтобы лучше проверить сообщение с помощью мыши на keylistener   -  person mKorbel    schedule 05.06.2012
comment
вы правы, получается никак не решить это с помощью самого KeyListener, однако я нашел другое решение - просто отслеживать какие клавиши нажаты в данный момент и проверять их на каждом keyReleased() Так что нам не нужно сбрасывать скорость персонажа до нуля, когда, например, правая клавиша отпущена, но пользователь все еще держит левую клавишу. Я обновлю свой пост, чтобы показать решение.   -  person YemSalat    schedule 05.06.2012
comment
нет проблем с задержкой событий от любого из Listener с помощью Swing Timer,   -  person mKorbel    schedule 05.06.2012
comment
На самом деле я не пытаюсь отсрочить событие - я искал решение для «ускорения» KeyListener, но, как я уже сказал, проверка того, какие клавиши нажаты, решает проблему.   -  person YemSalat    schedule 05.06.2012


Ответы (2)


Спасибо всем за ваши ответы! Они помогли мне встать на правильный путь.

Происходит здесь, как я сказал в своем комментарии, следующее: если, например, мы держим правую клавишу - персонаж движется вправо, то мы нажимаем левую клавишу, и он начинает двигаться влево. Теперь, если мы отпустим правую клавишу, скорость xSpeed ​​будет сброшена до нуля, и KeyListener придется ждать, пока снова не сработает keyPressed(), так как мы все еще удерживаем левую клавишу. 'Скорость повторения клавиш' установлена ​​по умолчанию и насколько я понимаю не регулируется.

Таким образом, решение состоит в том, чтобы отслеживать, какие клавиши нажаты в данный момент, поэтому нам не нужно сбрасывать скорость персонажа до нуля, когда правая клавиша отпущена, если мы все еще удерживаем левую клавишу.

Извините за немного загадочный пример, просто пытаюсь сделать код небольшим:

// Define keys: up, right, down, left
// 0 - not pressed, 1 - pressed
private int[] keys = {0, 0, 0, 0};

// player control
public void keyPressed(KeyEvent e) {
    int key = e.getKeyCode();
    // we set the corresponding 'key indicator' to 1 when it is pressed
    switch(key){
        case(KeyEvent.VK_LEFT): dx = -speed; keys[3] = 1; break; 
        case(KeyEvent.VK_RIGHT): dx = speed; keys[1] = 1; break;
        case(KeyEvent.VK_UP): dy = -speed; keys[0] = 1; break;
        case(KeyEvent.VK_DOWN): dy = speed; keys[2] = 1; break;
        case(KeyEvent.VK_SPACE): fireOn = true; break;
    }
}

public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();
    // now before resetting the speed we check if the opposite key
    // is still pressed
    switch(key){
        case(KeyEvent.VK_LEFT): if(keys[1]==0){dx = 0;} keys[3] = 0; break;
        case(KeyEvent.VK_RIGHT): if(keys[3]==0){dx = 0;} keys[1] = 0; break;
        case(KeyEvent.VK_UP): if(keys[2]==0){dy = 0;} keys[0] = 0; break;
        case(KeyEvent.VK_DOWN): if(keys[0]==0){dy = 0;} keys[2] = 0; break;
        case(KeyEvent.VK_SPACE): fireOn = false; break;
    }
}
person YemSalat    schedule 05.06.2012
comment
затем, чтобы проверить альтернативу, теперь вы видите различия??? - person mKorbel; 06.06.2012

Другой способ может помочь:

object.addKeyListener(new KeyAdapter() {
    @Override
    public void keyTyped(KeyEvent e) {
        updateOpreation();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        updateOpreation();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        updateOpreation();
    }

}
person user1530608    schedule 08.05.2013
comment
почему это должно помочь? - person subsub; 25.02.2014