How to Handle Simultaneous Key Presses in Java

How do I handle simultaneous key presses in Java?

One way would be to keep track yourself of what keys are currently down.

When you get a keyPressed event, add the new key to the list; when you get a keyReleased event, remove the key from the list.

Then in your game loop, you can do actions based on what's in the list of keys.

handle multiple key presses ignoring repeated key

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

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.

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.

EDIT: 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);
}

}

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 :)

Multiple keys pressed in Java

How about:

class MultiKeyPressListener implements KeyListener {

// Set of currently pressed keys
private final Set<Integer> pressed = new HashSet<Integer>();

@Override
public synchronized void keyPressed(KeyEvent e) {
pressed.add(e.getKeyCode());

if (pressed.contains(KeyEvent.VK_UP)) {
if (pressed.contains(KeyEvent.VK_LEFT)) {
starfighter.moveUpLeft();
}
if (pressed.contains(KeyEvent.VK_RIGHT)) {
starfighter.moveUpRight();
}
}
}

@Override
public synchronized void keyReleased(KeyEvent e) {
pressed.remove(e.getKeyCode());
}

@Override
public void keyTyped(KeyEvent e) {/* Not used */ }
}
}

Note how you have a set of Integers instead of Characters and store key codes instead of key characters.

Java swing - Processing simultaneous key presses with key bindings

I personally would use the KeyListener interface to keep track of what the user has typed and then just register within a List the keys that have been pressed (without releasing) and then collect them once any key has been released.

Make sure though to add to the list only the keys that are not present yet because the keyPressed event is fired multiple times while the user is holding down a key.

I've also created a little sample to give you the idea.

public class MyClass extends JFrame implements KeyListener {

private JTextArea textArea;
private List<Character> listKeys;

public MyClass() {
setTitle("test");

listKeys = new ArrayList<>();
textArea = new JTextArea();
textArea.addKeyListener(this);

setLayout(new BorderLayout());
add(textArea, BorderLayout.CENTER);

setLocation(50, 50);
setSize(500, 500);
setVisible(true);
}

@Override
public void keyTyped(KeyEvent e) {
}

@Override
public void keyPressed(KeyEvent e) {
if (!listKeys.contains(e.getKeyChar())) {
listKeys.add(e.getKeyChar());
}
}

@Override
public void keyReleased(KeyEvent e) {
if (listKeys.isEmpty()) {
return;
}

if (listKeys.size() > 1) {
System.out.print("The key combination ");
} else {
System.out.print("The key ");
}
for (Character c : listKeys) {
System.out.print(c + " ");
}
System.out.println("has been entered");
listKeys.clear();
}

public static void main(String[] args) {
new MyClass();
}
}

Swing's KeyListener and multiple keys pressed at the same time

Use a collection to remember which keys are currently pressed and check to see if more than one key is pressed every time a key is pressed.

class MultiKeyPressListener implements KeyListener {
// Set of currently pressed keys
private final Set<Integer> pressedKeys = new HashSet<>();

@Override
public synchronized void keyPressed(KeyEvent e) {
pressedKeys.add(e.getKeyCode());
Point offset = new Point();
if (!pressedKeys.isEmpty()) {
for (Iterator<Integer> it = pressedKeys.iterator(); it.hasNext();) {
switch (it.next()) {
case KeyEvent.VK_W:
case KeyEvent.VK_UP:
offset.y = -1;
break;
case KeyEvent.VK_A:
case KeyEvent.VK_LEFT:
offset.x = -1;
break;
case KeyEvent.VK_S:
case KeyEvent.VK_DOWN:
offset.y = 1;
break;
case KeyEvent.VK_D:
case KeyEvent.VK_RIGHT:
offset.x = 1;
break;
}
}
}
System.out.println(offset); // Do something with the offset.
}

@Override
public synchronized void keyReleased(KeyEvent e) {
pressedKeys.remove(e.getKeyCode());
}

@Override
public void keyTyped(KeyEvent e) { /* Event not used */ }
}

Java - KeyListener Multiple Keys

A lot of people have that problem. It is called Keyboard Ghosting and means that some combinations simply don't work on cheap keyboards. Thats why high class gaming keyboards exists. So nothing wrong with your code. No optimization possible. You need to use key combination that work.
To proof my answer here are some links for you.

  • http://board.flashkit.com/board/showthread.php?789015-wont-respond-to-keyboard-up-left-and-space-at-the-same-time

  • http://forums.steampowered.com/forums/showthread.php?t=1928521

  • http://www.tomshardware.co.uk/answers/id-2159074/alt-space-bar-work-holding-left-arrow.html

  • https://unix.stackexchange.com/questions/268850/leftupspace-keys-not-working-on-thinkpad-x201

How do I handle multiple key presses in a Java Applet?

What you usually do is to remember the state of every keypress.

You keep an array of your actions(or an array of all the keys if you want too). A keyDown event results in e.g.

boolean actions[12];...
...

public boolean keyDown( Event e, int key ) {
if (key == 'a') {
actions[ACTION_LEFT] = true;
}
..
}

And you'll need to catch the keyup event and set the actions to false when the keys are released.

In the movement logic you can just check the states of the keypresses

if(actions[ACTION_LEFT] == true)
moveLeft();
if(actions[ACTION_RIGTH] == true)
moveRight();


Related Topics



Leave a reply



Submit