[solved] Capturing - arrow keys and letters

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