Erm. It's 6 am in my TZ, so I might be wrong, but - threading. Store the keyboard state in a thread-safe set/map, update the set/map on press event, use the state every game tick to execute the results.
Or just use a bool array. Will work as well in most cases. For example:
static public enum camera_action {
ESCAPE, // e.g. exit to main menu, terminate mouse capture etc
MV_FORWARD, MV_BACKWARD, MV_STRAFE_LEFT, MV_STRAFE_RIGHT, MV_JUMP, MV_CROUCH, // etc
}
final protected SC_HashMap<Integer, camera_action> keymap = new SC_HashMap.linked<>();
protected boolean[] action_state = new boolean[camera_action.values().length];
final protected void set_default_keymap() {
keymap.put( KeyEvent.VK_SHIFT, camera_action.MV_JUMP );
keymap.put( KeyEvent.VK_CONTROL, camera_action.MV_CROUCH );
keymap.put( KeyEvent.VK_W, camera_action.MV_FORWARD );
keymap.put( KeyEvent.VK_S, camera_action.MV_BACKWARD );
keymap.put( KeyEvent.VK_A, camera_action.MV_STRAFE_LEFT );
keymap.put( KeyEvent.VK_D, camera_action.MV_STRAFE_RIGHT );
keymap.put( KeyEvent.VK_ESCAPE, camera_action.ESCAPE );
}
protected void set_action_state( camera_action a, boolean new_state ) {
action_state[a.ordinal()] = new_state;
}
protected boolean get_action_state( camera_action a ) {
return action_state[a.ordinal()];
}
public void reset_action_state() {
action_state = new boolean[camera_action.values().length];
}
@Override
public void keyPressed( KeyEvent e ) {
camera_action a = keymap.get( e.getKeyCode() );
if ( a != null )
set_action_state( a, true );
}
@Override
public void keyReleased( KeyEvent e ) {
camera_action a = keymap.get( e.getKeyCode() );
if ( a != null )
set_action_state( a, false );
}
I know the Oracle's policy on Enum.ordinal() - I don't give a heck about it. If EnumSet can use it, so can I. The contract of ordinal() is solid enough.
And - yeah. possible dupe of Swing's KeyListener and multiple keys pressed at the same time.