From a4e95b1c9848b2ce8aa7b88fa7985d74434e5433 Mon Sep 17 00:00:00 2001 From: guru_meditation_no42 Date: Tue, 13 Apr 2021 22:50:59 -0700 Subject: [PATCH] Move keycode mapping to keyMap array instead of switch case entries. --- .../controller/InputController.java | 180 +++++++++++++----- .../gpl/rpg/AndorsTrail/view/MainView.java | 19 +- 2 files changed, 137 insertions(+), 62 deletions(-) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java index def9fc11c..9522d693b 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java @@ -28,12 +28,30 @@ public final class InputController implements OnClickListener, OnLongClickListen private boolean keyState_attack = false; private boolean keyState_flee = false; private boolean keyState_endturn = false; + + final private int KEY_UNHANDLED = 0; // Default, for unhandled keycodes + final private int KEY_UP = 1; + final private int KEY_DOWN = 2; + final private int KEY_LEFT = 3; + final private int KEY_RIGHT = 4; + final private int KEY_UP_LEFT = 5; + final private int KEY_UP_RIGHT = 6; + final private int KEY_DOWN_LEFT = 7; + final private int KEY_DOWN_RIGHT = 8; + final private int KEY_ATTACK = 9; + final private int KEY_FLEE = 10; + final private int KEY_END_TURN = 11; + final private int KEY_HERO_INFO = 12; + + private char keyMap[]; // Android keycode to internal key event mapping. TODO: Configure via preferences public InputController(ControllerContext controllers, WorldContext world) { this.controllers = controllers; this.world = world; + initializeKeyMap(); + } - + /* New keyboard handler. Both Key Down and Key Up events handled to allow conditional behaviours. On 4-way dpad controllers, cursor keys, and WASD, diagonals are generated by chording two keys. Single-key diagonals are supported on numeric keypad and 8-way dpads (not seen/tested in the wild). @@ -42,78 +60,148 @@ public final class InputController implements OnClickListener, OnLongClickListen be dangerous in tight spaces, modifiers are provided to "lock" the input until both keys are down. TODO: Use delay timer to enable chorded diagonals on first move? */ + + // Map key codes to spectic internal actions + // TODO: Move mapping out of code, to JSON or XML file, or maybe eventually user preferences + private void initializeKeyMap() { + char key; + + keyMap = new char[1024]; // Should be a long time before android exceeds 1024 keycodes + + // Keys mapping to UP + key = KEY_UP; + keyMap[KeyEvent.KEYCODE_DPAD_UP] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_8] = key; + keyMap[KeyEvent.KEYCODE_8] = key; + keyMap[KeyEvent.KEYCODE_W] = key; + + // Keys mapping to DOWN + key = KEY_DOWN; + keyMap[KeyEvent.KEYCODE_DPAD_DOWN] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_2] = key; + keyMap[KeyEvent.KEYCODE_2] = key; + keyMap[KeyEvent.KEYCODE_S] = key; + + // Keys mapping to LEFT + key = KEY_LEFT; + keyMap[KeyEvent.KEYCODE_DPAD_LEFT] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_4] = key; + keyMap[KeyEvent.KEYCODE_4] = key; + keyMap[KeyEvent.KEYCODE_A] = key; + + // Keys mapping to RIGHT + key = KEY_RIGHT; + keyMap[KeyEvent.KEYCODE_DPAD_RIGHT] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_6] = key; + keyMap[KeyEvent.KEYCODE_6] = key; + keyMap[KeyEvent.KEYCODE_D] = key; + + // Keys mapping to UP_LEFT + key = KEY_UP_LEFT; + keyMap[KeyEvent.KEYCODE_DPAD_UP_LEFT] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_7] = key; + keyMap[KeyEvent.KEYCODE_7] = key; + keyMap[KeyEvent.KEYCODE_MOVE_HOME] = key; + + // Keys mapping to UP_RIGHT + key = KEY_UP_RIGHT; + keyMap[KeyEvent.KEYCODE_DPAD_UP_RIGHT] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_9] = key; + keyMap[KeyEvent.KEYCODE_9] = key; + keyMap[KeyEvent.KEYCODE_PAGE_UP] = key; + + // Keys mapping to DOWN_LEFT + key = KEY_DOWN_LEFT; + keyMap[KeyEvent.KEYCODE_DPAD_DOWN_LEFT] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_1] = key; + keyMap[KeyEvent.KEYCODE_1] = key; + keyMap[KeyEvent.KEYCODE_MOVE_END] = key; + + // Keys mapping to DOWN_RIGHT + key = KEY_UP_LEFT; + keyMap[KeyEvent.KEYCODE_DPAD_DOWN_RIGHT] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_3] = key; + keyMap[KeyEvent.KEYCODE_3] = key; + keyMap[KeyEvent.KEYCODE_PAGE_DOWN] = key; + + // Keys mapping to ATTACK + key = KEY_ATTACK; + keyMap[KeyEvent.KEYCODE_DPAD_CENTER] = key; + keyMap[KeyEvent.KEYCODE_BUTTON_A] = key; + keyMap[KeyEvent.KEYCODE_SPACE] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_5] = key; + + // Keys mapping to FLEE + key = KEY_FLEE; + keyMap[KeyEvent.KEYCODE_BUTTON_X] = key; + keyMap[KeyEvent.KEYCODE_F] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_ENTER] = key; + keyMap[KeyEvent.KEYCODE_ENTER] = key; + + // Keys mapping to END_TURN + key = KEY_END_TURN; + keyMap[KeyEvent.KEYCODE_BUTTON_Y] = key; + keyMap[KeyEvent.KEYCODE_E] = key; + keyMap[KeyEvent.KEYCODE_FORWARD_DEL] = key; + keyMap[KeyEvent.KEYCODE_NUMPAD_DOT] = key; + + // Keys mapping to HERO_INFO + key = KEY_HERO_INFO; + keyMap[KeyEvent.KEYCODE_BUTTON_SELECT] = key; + keyMap[KeyEvent.KEYCODE_C] = key; + } + + // Generate game actions based on mapped keys public boolean onKeyboardAction(Context context, KeyEvent event) { -// L.log("onKeyboardAction(): Processing action " + event.getAction() + " for keyCode " + event.getKeyCode()); + L.log("onKeyboardAction(): Processing action " + event.getAction() + " for keyCode " + event.getKeyCode()); if (event.getAction() != KeyEvent.ACTION_DOWN && event.getAction() != KeyEvent.ACTION_UP) return false; // don't handle other actions boolean keydown = (event.getAction() == KeyEvent.ACTION_DOWN); boolean inihbit = (keyState_attack || keyState_endturn || keyState_flee); // used to inhibit movement if an action key is held down - switch (event.getKeyCode()) { + if (event.getKeyCode() >= keyMap.length) return false; // just in case we get an oddball keycode + + switch (keyMap[event.getKeyCode()]) { // Basic movement handled first // Ordinal directional keys - only modify one direction register, can be combined when // used simultaneously to create synthetic diagonals - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_NUMPAD_8: - case KeyEvent.KEYCODE_8: - case KeyEvent.KEYCODE_W: + case KEY_UP: keyState_dy = keydown ? -1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); break; - case KeyEvent.KEYCODE_DPAD_DOWN: - case KeyEvent.KEYCODE_NUMPAD_2: - case KeyEvent.KEYCODE_2: - case KeyEvent.KEYCODE_S: + case KEY_DOWN: keyState_dy = keydown ? 1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); break; - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_NUMPAD_4: - case KeyEvent.KEYCODE_4: - case KeyEvent.KEYCODE_A: + case KEY_LEFT: keyState_dx = keydown ? -1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - case KeyEvent.KEYCODE_NUMPAD_6: - case KeyEvent.KEYCODE_6: - case KeyEvent.KEYCODE_D: + case KEY_RIGHT: keyState_dx = keydown ? 1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); break; // Diagonal directional keys. Modify both direction registers, can't be combined // TODO: store individual key position to allow combinations. May not be worth the trouble. - case KeyEvent.KEYCODE_DPAD_UP_LEFT: - case KeyEvent.KEYCODE_NUMPAD_7: - case KeyEvent.KEYCODE_7: - case KeyEvent.KEYCODE_MOVE_HOME: + case KEY_UP_LEFT: keyState_dx = keydown ? -1 : 0; keyState_dy = keydown ? -1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); break; - case KeyEvent.KEYCODE_DPAD_UP_RIGHT: - case KeyEvent.KEYCODE_NUMPAD_9: - case KeyEvent.KEYCODE_9: - case KeyEvent.KEYCODE_PAGE_UP: + case KEY_UP_RIGHT: keyState_dx = keydown ? 1 : 0; keyState_dy = keydown ? -1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); break; - case KeyEvent.KEYCODE_DPAD_DOWN_LEFT: - case KeyEvent.KEYCODE_NUMPAD_1: - case KeyEvent.KEYCODE_1: - case KeyEvent.KEYCODE_MOVE_END: + case KEY_DOWN_LEFT: keyState_dx = keydown ? -1 : 0; keyState_dy = keydown ? 1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); break; - case KeyEvent.KEYCODE_DPAD_DOWN_RIGHT: - case KeyEvent.KEYCODE_NUMPAD_3: - case KeyEvent.KEYCODE_3: - case KeyEvent.KEYCODE_PAGE_DOWN: + case KEY_DOWN_RIGHT: keyState_dx = keydown ? 1 : 0; keyState_dy = keydown ? 1 : 0; if (!inihbit) onRelativeMovement(keyState_dx, keyState_dy); @@ -124,10 +212,7 @@ public final class InputController implements OnClickListener, OnLongClickListen // "Attack" shortcut - freeze movement to allow chorded direction when key is released. // if in combat, executes an attack on key release - case KeyEvent.KEYCODE_DPAD_CENTER: // Not sure if this is needed - case KeyEvent.KEYCODE_BUTTON_A: // lock movement until released for precise directional move/attack - case KeyEvent.KEYCODE_SPACE: - case KeyEvent.KEYCODE_NUMPAD_5: + case KEY_ATTACK: if (keydown && !keyState_attack) { // key pressed - pause movement if(!world.model.uiSelections.isInCombat) controllers.movementController.stopMovement(); } else if (!keydown && keyState_attack) { // key released - execute attack / move in direction @@ -137,10 +222,7 @@ public final class InputController implements OnClickListener, OnLongClickListen break; // "Flee" shortcut. Intitiates flee when pressed. If a direction is held, moves in chosen direction when released - case KeyEvent.KEYCODE_BUTTON_X: - case KeyEvent.KEYCODE_F: - case KeyEvent.KEYCODE_NUMPAD_ENTER: - case KeyEvent.KEYCODE_ENTER: + case KEY_FLEE: if (world.model.uiSelections.isInCombat) { if (keydown && !keyState_flee) { // button pressed - set flee; movement locked while pressed controllers.combatController.startFlee(); @@ -155,10 +237,7 @@ public final class InputController implements OnClickListener, OnLongClickListen break; // "End Turn" shortcut. Flag prevents repeated end turn if key is held down. - case KeyEvent.KEYCODE_BUTTON_Y: - case KeyEvent.KEYCODE_E: - case KeyEvent.KEYCODE_FORWARD_DEL: - case KeyEvent.KEYCODE_NUMPAD_DOT: + case KEY_END_TURN: if (keydown && !keyState_endturn) { if (world.model.uiSelections.isInCombat) controllers.combatController.endPlayerTurn(); } @@ -166,11 +245,12 @@ public final class InputController implements OnClickListener, OnLongClickListen break; // "Hero Info" screen shortcut. New activity takes focus, so we don't need to worry about repeats. - case KeyEvent.KEYCODE_BUTTON_SELECT: - case KeyEvent.KEYCODE_C: + case KEY_HERO_INFO: if (keydown) context.startActivity(new Intent(context, HeroinfoActivity.class)); break; - default: // unhandled key + + case KEY_UNHANDLED: // Unhandled keycode + default: // unhandled keymap code entry (should not happen) return false; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java index e214898e0..2c5c0e523 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java @@ -4,8 +4,6 @@ import java.lang.ref.WeakReference; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; -import com.gpl.rpg.AndorsTrail.R; -import com.gpl.rpg.AndorsTrail.activity.HeroinfoActivity; import com.gpl.rpg.AndorsTrail.context.ControllerContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.controller.Constants; @@ -34,20 +32,17 @@ import com.gpl.rpg.AndorsTrail.util.CoordRect; import com.gpl.rpg.AndorsTrail.util.Size; import android.content.Context; -import android.content.Intent; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Rect; -import android.os.Build; import android.os.Handler; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; -import android.widget.ImageButton; public final class MainView extends SurfaceView implements SurfaceHolder.Callback, @@ -660,14 +655,14 @@ public final class MainView extends SurfaceView if (v.controllers.preferences.enableUiAnimations) postDelayed(this, 0); } } - + public void stop() { stop = true; } } - - - + + + @Override public void onPlayerMoved(PredefinedMap map, Coord newPosition, Coord previousPosition) { if (map != currentMap) return; @@ -798,19 +793,19 @@ public final class MainView extends SurfaceView movingSpritesRedrawTick.start(); } } - + @Override public void onNewSpriteMoveFrame(SpriteMoveAnimation animation) { //redrawMoveArea_(CoordRect.getBoundingRect(animation.origin, animation.destination, animation.actor.tileSize), animation); } - + @Override public void onSpriteMoveCompleted(SpriteMoveAnimation animation) { if (animation.map != currentMap) return; movingSprites--; redrawArea(CoordRect.getBoundingRect(animation.origin, animation.destination, animation.actor.tileSize), RedrawAreaDebugReason.EffectCompleted); } - + @Override public void onAsyncAreaUpdate(CoordRect area) { redrawArea(area, RedrawAreaDebugReason.AsyncRequest);