Hi guys,
I’m having a bit of difficulty right now working out how to capture arrow keys in my game…
Using Java 2d, I have a Canvas object in my JPanel that has the listeners attached to it:
canvas = new Canvas();
// add keyboard and mouse handlers
canvas.addKeyListener((KeyListener)engine.getEventHandler());
canvas.addMouseListener((MouseListener)engine.getEventHandler());
canvas.addMouseMotionListener((MouseMotionListener)engine.getEventHandler());
This all works lovely, in my EventHandler class I handle each event and do the actions required:
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case Constants.KEY_MAIN_MENU:
// show the main menu
break;
case Constants.KEY_TOGGLE_GRID:
case Constants.KEY_TOGGLE_HITBOXES:
// pass to Renderer to process
renderer.processKeyDownInput(e.getKeyCode());
break;
case Constants.KEY_PLAYER_ATTACK:
// pass to Controller
controller.doPlayerMeleeAttack();
break;
case Constants.KEY_PLAYER_MOVE_UP:
controller.addMovementKeyFlag(Constants.DIRECTION_UP);
break;
case Constants.KEY_PLAYER_MOVE_RIGHT:
controller.addMovementKeyFlag(Constants.DIRECTION_RIGHT);
break;
case Constants.KEY_PLAYER_MOVE_DOWN:
controller.addMovementKeyFlag(Constants.DIRECTION_DOWN);
break;
case Constants.KEY_PLAYER_MOVE_LEFT:
controller.addMovementKeyFlag(Constants.DIRECTION_LEFT);
break;
}
}
The addMovementKey method in my Controller maintains a stack of keys held down (so if the user is holding the “down” movement key and presses the “right” movement key for a second the player will move right for as long as that key is held then revert to downward movement afterwards:
public void addMovementKeyFlag(byte direction) {
// first, check if key is already being held down
// this should never happen but good to check anyway
int i;
for (i=0; i<this.movementKeys.size(); i++) {
if (this.movementKeys.get(i) == direction) {
// check that we aren't trying to trigger the same key twice
System.out.println("Duplicate direction key found! :: "+direction);
return;
}
}
this.movementKeys.add((int)direction);
this.playerEntity.setFacingDirection(direction);
this.playerEntity.setState(EntityState.MOVING);
}
My problem has now started because someone else tried to play my game and immediately asked “why can’t I use the arrow keys?”. So now I’m on a journey to get the arrow keys working.
The problem specifically is that when holding down a character on the keyboard (e.g. W, A, S, or D), the keyPressed event fires exactly once (meaning that to continually travel in a direction we have to flag the key as being held down then un-flag it when the key is released). However, when an arrow key is pressed (VK_UP, VK_DOWN, as the keyCode returns) the event fires continuously.
Is there a way to get around that? Or can anyone suggest how I can maintain my clever little stack to track the other buttons being held down at the same time?
Sorry if this is a massive ramble and doesn’t make any sense!
P.S. it does kind of work but it means the game is constantly looping over a list of up to 4 items checking if an item is already in the list (which doesn’t sound like a good thing to me).