Last active
April 2, 2021 23:17
-
-
Save mcgivrer/34641df0df83c023e9983157b61be8b8 to your computer and use it in GitHub Desktop.
A Simple InputHandler with action vs. key mapping, mainly for gaming purpose
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The <code>InputHandler</code> is implementing the <code>KeyListener</code> to | |
* be the keyboard manager. It is mapping some <code>keyEvent</code> code to | |
* possible <code>ACTIONS</code>. | |
* <ul> | |
* <li>the <code>keyMapping</code> are the map containing the mapping between | |
* some KeyCode to <code>ACTIONS</code> values,</li> | |
* <li>the internal <code>keys</code> map contains all keys status as boolean | |
* values,</li> | |
* <li>the <code>actions</code> contains all Action events produced.</li> | |
* </ul> | |
* | |
* To use this <code>InputHandler</code>, you must implments the | |
* <code>GameActionListener</code> in your using class and the specific | |
* <code>action(ACTIONS)</code> method to use the action handling. you can also | |
* use the <code>getAction(ACTIONS)</code> as an asynchronous access to the | |
* actions map. | |
* | |
* | |
* | |
* @author Frédéric Delorme <[email protected]> | |
* @since 2020 | |
*/ | |
public static class InputHandler implements KeyListener { | |
public interface GameActionListener extends KeyListener { | |
public void action(ACTIONS action); | |
} | |
public enum ACTIONS { | |
UP, LEFT, RIGHT, DOWN, FIRE1, FIRE2, FIRE3, FIRE4, LT_FIRE, LB_FIRE, RT_FIRE, RB_FIRE, START, HOME, POWER | |
} | |
/* | |
* Internal key current status buffer | |
*/ | |
private final boolean[] keys = new boolean[65536]; | |
/* | |
* Internal key previous sttaus buffer | |
*/ | |
private final boolean[] previousKeys = new boolean[65536]; | |
private List<GameActionListener> listeners = new CopyOnWriteArrayList<>(); | |
private Map<Integer, ACTIONS> keyMapping = new HashMap<>(); | |
private Map<ACTIONS, Boolean> actions = new HashMap<>(); | |
private boolean ctrl; | |
private boolean shift; | |
private boolean alt; | |
private boolean altGr; | |
DemoGame game; | |
/** | |
* Initialization of the InputHandler. Define a default Action mapping with | |
* basic keys. The map can be adapted or changed. | |
* | |
* @param dg | |
*/ | |
public InputHandler(DemoGame dg) { | |
this.game = dg; | |
this.keyMapping.put(KeyEvent.VK_ENTER, ACTIONS.START); | |
this.keyMapping.put(KeyEvent.VK_HOME, ACTIONS.HOME); | |
this.keyMapping.put(KeyEvent.VK_SCROLL_LOCK, ACTIONS.POWER); | |
this.keyMapping.put(KeyEvent.VK_UP, ACTIONS.UP); | |
this.keyMapping.put(KeyEvent.VK_DOWN, ACTIONS.DOWN); | |
this.keyMapping.put(KeyEvent.VK_LEFT, ACTIONS.LEFT); | |
this.keyMapping.put(KeyEvent.VK_RIGHT, ACTIONS.RIGHT); | |
this.keyMapping.put(KeyEvent.VK_SPACE, ACTIONS.FIRE1); | |
this.keyMapping.put(KeyEvent.VK_Y, ACTIONS.FIRE2); | |
this.keyMapping.put(KeyEvent.VK_A, ACTIONS.FIRE3); | |
this.keyMapping.put(KeyEvent.VK_B, ACTIONS.FIRE4); | |
this.keyMapping.put(KeyEvent.VK_F1, ACTIONS.LT_FIRE); | |
this.keyMapping.put(KeyEvent.VK_F2, ACTIONS.LB_FIRE); | |
this.keyMapping.put(KeyEvent.VK_F3, ACTIONS.RT_FIRE); | |
this.keyMapping.put(KeyEvent.VK_F4, ACTIONS.RB_FIRE); | |
} | |
public void add(GameActionListener kl) { | |
listeners.add(kl); | |
} | |
public void remove(GameActionListener kl) { | |
listeners.remove(kl); | |
} | |
/** | |
* Define the new KeyMapping to map actions and keys. | |
* | |
* @param keyMapping | |
*/ | |
public void setActionMap(Map<Integer, ACTIONS> keyMapping) { | |
this.keyMapping = keyMapping; | |
} | |
public void keyTyped(final KeyEvent e) { | |
listeners.forEach(kl -> { | |
kl.keyTyped(e); | |
}); | |
} | |
public void keyPressed(final KeyEvent e) { | |
// capture current event | |
this.previousKeys[e.getKeyCode()] = this.keys[e.getKeyCode()]; | |
this.keys[e.getKeyCode()] = true; | |
// get modifier's key status | |
this.shift = e.getModifiers() == SHIFT_DOWN_MASK; | |
this.ctrl = e.getModifiers() == CTRL_DOWN_MASK; | |
this.alt = e.getModifiers() == ALT_DOWN_MASK; | |
this.altGr = e.getModifiers() == ALT_GRAPH_DOWN_MASK; | |
// Convert Key pressed to action | |
if (keyMapping.containsKey(e.getKeyCode())) { | |
actions.put(keyMapping.get(e.getKeyCode()), true); | |
// Delegate action's event to registred listeners | |
listeners.forEach(kl -> { | |
kl.action(keyMapping.get(e.getKeyCode())); | |
}); | |
} | |
// Delegate key's event to registred listeners | |
listeners.forEach(kl -> { | |
kl.keyPressed(e); | |
}); | |
} | |
public void keyReleased(final KeyEvent e) { | |
// capture current event | |
this.previousKeys[e.getKeyCode()] = this.keys[e.getKeyCode()]; | |
this.keys[e.getKeyCode()] = false; | |
// get modifier's key status | |
this.shift = e.getModifiers() == SHIFT_DOWN_MASK; | |
this.ctrl = e.getModifiers() == CTRL_DOWN_MASK; | |
this.alt = e.getModifiers() == ALT_DOWN_MASK; | |
this.altGr = e.getModifiers() == ALT_GRAPH_DOWN_MASK; | |
// Convert Key released to action | |
if (keyMapping.containsKey(e.getKeyCode())) { | |
actions.put(keyMapping.get(e.getKeyCode()), false); | |
} | |
// Delegate key's event to registred listeners | |
listeners.forEach(kl -> { | |
kl.keyReleased(e); | |
}); | |
// Special Key for Debug mode capturing changes | |
if (e.getKeyCode() == KeyEvent.VK_D) { | |
game.debug = (game.debug > 5 ? 0 : game.debug + 1); | |
} | |
} | |
public boolean get(int key) { | |
return keys[key]; | |
} | |
/** | |
* Return action status | |
* | |
* @return boolean value | |
*/ | |
public boolean getAction(ACTIONS actionCode) { | |
return this.actions.containsKey(actionCode) ? this.actions.get(actionCode) : false; | |
} | |
public boolean getShift() { | |
return shift; | |
} | |
public boolean getCtrl() { | |
return ctrl; | |
} | |
public boolean getAlt() { | |
return alt; | |
} | |
public boolean getAltGr() { | |
return altGr; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment