19d4cc2572d37983607df38b0f4216ed76ac51814sm/*
29d4cc2572d37983607df38b0f4216ed76ac51814sm * Copyright (C) 2010 The Android Open Source Project
39d4cc2572d37983607df38b0f4216ed76ac51814sm *
49d4cc2572d37983607df38b0f4216ed76ac51814sm * Licensed under the Apache License, Version 2.0 (the "License");
59d4cc2572d37983607df38b0f4216ed76ac51814sm * you may not use this file except in compliance with the License.
69d4cc2572d37983607df38b0f4216ed76ac51814sm * You may obtain a copy of the License at
79d4cc2572d37983607df38b0f4216ed76ac51814sm *
89d4cc2572d37983607df38b0f4216ed76ac51814sm *      http://www.apache.org/licenses/LICENSE-2.0
99d4cc2572d37983607df38b0f4216ed76ac51814sm *
109d4cc2572d37983607df38b0f4216ed76ac51814sm * Unless required by applicable law or agreed to in writing, software
119d4cc2572d37983607df38b0f4216ed76ac51814sm * distributed under the License is distributed on an "AS IS" BASIS,
129d4cc2572d37983607df38b0f4216ed76ac51814sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139d4cc2572d37983607df38b0f4216ed76ac51814sm * See the License for the specific language governing permissions and
149d4cc2572d37983607df38b0f4216ed76ac51814sm * limitations under the License.
159d4cc2572d37983607df38b0f4216ed76ac51814sm */
169d4cc2572d37983607df38b0f4216ed76ac51814sm
179d4cc2572d37983607df38b0f4216ed76ac51814smpackage com.replica.replicaisland;
189d4cc2572d37983607df38b0f4216ed76ac51814sm
199d4cc2572d37983607df38b0f4216ed76ac51814smimport android.view.KeyEvent;
209d4cc2572d37983607df38b0f4216ed76ac51814sm
219d4cc2572d37983607df38b0f4216ed76ac51814smpublic class InputGameInterface extends BaseObject {
229d4cc2572d37983607df38b0f4216ed76ac51814sm	private static final float ORIENTATION_DEAD_ZONE_MIN = 0.03f;
239d4cc2572d37983607df38b0f4216ed76ac51814sm	private static final float ORIENTATION_DEAD_ZONE_MAX = 0.1f;
249d4cc2572d37983607df38b0f4216ed76ac51814sm	private static final float ORIENTATION_DEAD_ZONE_SCALE = 0.75f;
259d4cc2572d37983607df38b0f4216ed76ac51814sm
269d4cc2572d37983607df38b0f4216ed76ac51814sm	private final static float ROLL_TIMEOUT = 0.1f;
279d4cc2572d37983607df38b0f4216ed76ac51814sm	private final static float ROLL_RESET_DELAY = 0.075f;
289d4cc2572d37983607df38b0f4216ed76ac51814sm
299d4cc2572d37983607df38b0f4216ed76ac51814sm    // Raw trackball input is filtered by this value. Increasing it will
309d4cc2572d37983607df38b0f4216ed76ac51814sm    // make the control more twitchy, while decreasing it will make the control more precise.
319d4cc2572d37983607df38b0f4216ed76ac51814sm    private final static float ROLL_FILTER = 0.4f;
329d4cc2572d37983607df38b0f4216ed76ac51814sm    private final static float ROLL_DECAY = 8.0f;
339d4cc2572d37983607df38b0f4216ed76ac51814sm
349d4cc2572d37983607df38b0f4216ed76ac51814sm    private final static float KEY_FILTER = 0.25f;
352b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm    private final static float SLIDER_FILTER = 0.25f;
362b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
379d4cc2572d37983607df38b0f4216ed76ac51814sm
389d4cc2572d37983607df38b0f4216ed76ac51814sm	private InputButton mJumpButton = new InputButton();
399d4cc2572d37983607df38b0f4216ed76ac51814sm	private InputButton mAttackButton = new InputButton();
409d4cc2572d37983607df38b0f4216ed76ac51814sm	private InputXY mDirectionalPad = new InputXY();
419d4cc2572d37983607df38b0f4216ed76ac51814sm	private InputXY mTilt = new InputXY();
429d4cc2572d37983607df38b0f4216ed76ac51814sm
439d4cc2572d37983607df38b0f4216ed76ac51814sm	private int mLeftKeyCode = KeyEvent.KEYCODE_DPAD_LEFT;
449d4cc2572d37983607df38b0f4216ed76ac51814sm	private int mRightKeyCode = KeyEvent.KEYCODE_DPAD_RIGHT;
459d4cc2572d37983607df38b0f4216ed76ac51814sm	private int mJumpKeyCode = KeyEvent.KEYCODE_SPACE;
469d4cc2572d37983607df38b0f4216ed76ac51814sm	private int mAttackKeyCode = KeyEvent.KEYCODE_SHIFT_LEFT;
479d4cc2572d37983607df38b0f4216ed76ac51814sm
489d4cc2572d37983607df38b0f4216ed76ac51814sm	private float mOrientationDeadZoneMin = ORIENTATION_DEAD_ZONE_MIN;
499d4cc2572d37983607df38b0f4216ed76ac51814sm	private float mOrientationDeadZoneMax = ORIENTATION_DEAD_ZONE_MAX;
509d4cc2572d37983607df38b0f4216ed76ac51814sm	private float mOrientationDeadZoneScale = ORIENTATION_DEAD_ZONE_SCALE;
519d4cc2572d37983607df38b0f4216ed76ac51814sm	private float mOrientationSensitivity = 1.0f;
529d4cc2572d37983607df38b0f4216ed76ac51814sm	private float mOrientationSensitivityFactor = 1.0f;
539d4cc2572d37983607df38b0f4216ed76ac51814sm	private float mMovementSensitivity = 1.0f;
542b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
559d4cc2572d37983607df38b0f4216ed76ac51814sm	private boolean mUseClickButtonForAttack = true;
569d4cc2572d37983607df38b0f4216ed76ac51814sm	private boolean mUseOrientationForMovement = false;
572b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm	private boolean mUseOnScreenControls = false;
589d4cc2572d37983607df38b0f4216ed76ac51814sm
599d4cc2572d37983607df38b0f4216ed76ac51814sm	private float mLastRollTime;
609d4cc2572d37983607df38b0f4216ed76ac51814sm
619d4cc2572d37983607df38b0f4216ed76ac51814sm	public InputGameInterface() {
629d4cc2572d37983607df38b0f4216ed76ac51814sm		super();
639d4cc2572d37983607df38b0f4216ed76ac51814sm		reset();
649d4cc2572d37983607df38b0f4216ed76ac51814sm	}
659d4cc2572d37983607df38b0f4216ed76ac51814sm
669d4cc2572d37983607df38b0f4216ed76ac51814sm	@Override
679d4cc2572d37983607df38b0f4216ed76ac51814sm	public void reset() {
689d4cc2572d37983607df38b0f4216ed76ac51814sm		mJumpButton.release();
699d4cc2572d37983607df38b0f4216ed76ac51814sm		mAttackButton.release();
709d4cc2572d37983607df38b0f4216ed76ac51814sm		mDirectionalPad.release();
719d4cc2572d37983607df38b0f4216ed76ac51814sm		mTilt.release();
729d4cc2572d37983607df38b0f4216ed76ac51814sm	}
739d4cc2572d37983607df38b0f4216ed76ac51814sm
749d4cc2572d37983607df38b0f4216ed76ac51814sm
759d4cc2572d37983607df38b0f4216ed76ac51814sm
769d4cc2572d37983607df38b0f4216ed76ac51814sm	@Override
779d4cc2572d37983607df38b0f4216ed76ac51814sm    public void update(float timeDelta, BaseObject parent) {
789d4cc2572d37983607df38b0f4216ed76ac51814sm		InputSystem input = sSystemRegistry.inputSystem;
799d4cc2572d37983607df38b0f4216ed76ac51814sm		final InputButton[] keys = input.getKeyboard().getKeys();
809d4cc2572d37983607df38b0f4216ed76ac51814sm		final InputXY orientation = input.getOrientationSensor();
819d4cc2572d37983607df38b0f4216ed76ac51814sm
829d4cc2572d37983607df38b0f4216ed76ac51814sm		// tilt is easy
839d4cc2572d37983607df38b0f4216ed76ac51814sm		mTilt.clone(orientation);
849d4cc2572d37983607df38b0f4216ed76ac51814sm
852b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		final InputTouchScreen touch = input.getTouchScreen();
862b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		final float gameTime = sSystemRegistry.timeSystem.getGameTime();
872b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
882b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		float sliderOffset = 0;
892b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
909d4cc2572d37983607df38b0f4216ed76ac51814sm		// update movement inputs
912b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		if (mUseOnScreenControls) {
922b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm			final InputXY sliderTouch = touch.findPointerInRegion(
932b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm					ButtonConstants.MOVEMENT_SLIDER_REGION_X,
942b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                    ButtonConstants.MOVEMENT_SLIDER_REGION_Y,
952b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                    ButtonConstants.MOVEMENT_SLIDER_REGION_WIDTH,
962b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                    ButtonConstants.MOVEMENT_SLIDER_REGION_HEIGHT);
972b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
982b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm			if (sliderTouch != null) {
992b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				final float halfWidth = ButtonConstants.MOVEMENT_SLIDER_BAR_WIDTH / 2.0f;
1002b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				final float center = ButtonConstants.MOVEMENT_SLIDER_X + halfWidth;
1012b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				final float offset = sliderTouch.getX() - center;
1022b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				float magnitudeRamp = Math.abs(offset) > halfWidth ? 1.0f : (Math.abs(offset) / halfWidth);
1032b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
1042b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				final float magnitude = magnitudeRamp * Utils.sign(offset) * SLIDER_FILTER * mMovementSensitivity;
1052b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				sliderOffset = magnitudeRamp * Utils.sign(offset);
1062b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				mDirectionalPad.press(gameTime, magnitude, 0.0f);
1072b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm			} else {
1082b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				mDirectionalPad.release();
1092b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm			}
1102b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		} else if (mUseOrientationForMovement) {
1119d4cc2572d37983607df38b0f4216ed76ac51814sm			mDirectionalPad.clone(orientation);
1129d4cc2572d37983607df38b0f4216ed76ac51814sm			mDirectionalPad.setMagnitude(
1139d4cc2572d37983607df38b0f4216ed76ac51814sm					filterOrientationForMovement(orientation.getX()),
1149d4cc2572d37983607df38b0f4216ed76ac51814sm					filterOrientationForMovement(orientation.getY()));
1159d4cc2572d37983607df38b0f4216ed76ac51814sm		} else {
1169d4cc2572d37983607df38b0f4216ed76ac51814sm			// keys or trackball
1179d4cc2572d37983607df38b0f4216ed76ac51814sm			final InputXY trackball = input.getTrackball();
1189d4cc2572d37983607df38b0f4216ed76ac51814sm			final InputButton left = keys[mLeftKeyCode];
1199d4cc2572d37983607df38b0f4216ed76ac51814sm			final InputButton right = keys[mRightKeyCode];
1209d4cc2572d37983607df38b0f4216ed76ac51814sm			final float leftPressedTime = left.getLastPressedTime();
1219d4cc2572d37983607df38b0f4216ed76ac51814sm			final float rightPressedTime = right.getLastPressedTime();
1229d4cc2572d37983607df38b0f4216ed76ac51814sm
1239d4cc2572d37983607df38b0f4216ed76ac51814sm
1249d4cc2572d37983607df38b0f4216ed76ac51814sm			if (trackball.getLastPressedTime() > Math.max(leftPressedTime, rightPressedTime)) {
1259d4cc2572d37983607df38b0f4216ed76ac51814sm				// The trackball never goes "up", so force it to turn off if it wasn't triggered in the last frame.
1269d4cc2572d37983607df38b0f4216ed76ac51814sm				// What follows is a bunch of code to filter trackball events into something like a dpad event.
1279d4cc2572d37983607df38b0f4216ed76ac51814sm				// The goals here are:
1289d4cc2572d37983607df38b0f4216ed76ac51814sm				// 	- For roll events that occur in quick succession to accumulate.
1299d4cc2572d37983607df38b0f4216ed76ac51814sm				//	- For roll events that occur with more time between them, lessen the impact of older events
1309d4cc2572d37983607df38b0f4216ed76ac51814sm				//	- In the absence of roll events, fade the roll out over time.
1319d4cc2572d37983607df38b0f4216ed76ac51814sm				if (gameTime - trackball.getLastPressedTime() < ROLL_TIMEOUT) {
1329d4cc2572d37983607df38b0f4216ed76ac51814sm					float newX;
1339d4cc2572d37983607df38b0f4216ed76ac51814sm					float newY;
1349d4cc2572d37983607df38b0f4216ed76ac51814sm					final float delay = Math.max(ROLL_RESET_DELAY, timeDelta);
1359d4cc2572d37983607df38b0f4216ed76ac51814sm					if (gameTime - mLastRollTime <= delay) {
1369d4cc2572d37983607df38b0f4216ed76ac51814sm						newX = mDirectionalPad.getX() + (trackball.getX() * ROLL_FILTER * mMovementSensitivity);
1379d4cc2572d37983607df38b0f4216ed76ac51814sm						newY = mDirectionalPad.getY() + (trackball.getY() * ROLL_FILTER * mMovementSensitivity);
1389d4cc2572d37983607df38b0f4216ed76ac51814sm					} else {
1399d4cc2572d37983607df38b0f4216ed76ac51814sm						float oldX = mDirectionalPad.getX() != 0.0f ? mDirectionalPad.getX() / 2.0f : 0.0f;
1409d4cc2572d37983607df38b0f4216ed76ac51814sm						float oldY = mDirectionalPad.getX() != 0.0f ? mDirectionalPad.getX() / 2.0f : 0.0f;
1419d4cc2572d37983607df38b0f4216ed76ac51814sm						newX = oldX + (trackball.getX() * ROLL_FILTER * mMovementSensitivity);
1429d4cc2572d37983607df38b0f4216ed76ac51814sm						newY = oldY + (trackball.getX() * ROLL_FILTER * mMovementSensitivity);
1439d4cc2572d37983607df38b0f4216ed76ac51814sm					}
1449d4cc2572d37983607df38b0f4216ed76ac51814sm
1459d4cc2572d37983607df38b0f4216ed76ac51814sm					mDirectionalPad.press(gameTime, newX, newY);
1469d4cc2572d37983607df38b0f4216ed76ac51814sm					mLastRollTime = gameTime;
1479d4cc2572d37983607df38b0f4216ed76ac51814sm					trackball.release();
1489d4cc2572d37983607df38b0f4216ed76ac51814sm				} else {
1499d4cc2572d37983607df38b0f4216ed76ac51814sm					float x = mDirectionalPad.getX();
1509d4cc2572d37983607df38b0f4216ed76ac51814sm					float y = mDirectionalPad.getY();
1519d4cc2572d37983607df38b0f4216ed76ac51814sm					if (x != 0.0f) {
1529d4cc2572d37983607df38b0f4216ed76ac51814sm						int sign = Utils.sign(x);
1539d4cc2572d37983607df38b0f4216ed76ac51814sm						x = x - (sign * ROLL_DECAY * timeDelta);
1549d4cc2572d37983607df38b0f4216ed76ac51814sm						if (Utils.sign(x) != sign) {
1559d4cc2572d37983607df38b0f4216ed76ac51814sm							x = 0.0f;
1569d4cc2572d37983607df38b0f4216ed76ac51814sm						}
1579d4cc2572d37983607df38b0f4216ed76ac51814sm					}
1589d4cc2572d37983607df38b0f4216ed76ac51814sm
1599d4cc2572d37983607df38b0f4216ed76ac51814sm					if (y != 0.0f) {
1609d4cc2572d37983607df38b0f4216ed76ac51814sm						int sign = Utils.sign(y);
1619d4cc2572d37983607df38b0f4216ed76ac51814sm						y = y - (sign * ROLL_DECAY * timeDelta);
1629d4cc2572d37983607df38b0f4216ed76ac51814sm						if (Utils.sign(x) != sign) {
1639d4cc2572d37983607df38b0f4216ed76ac51814sm							y = 0.0f;
1649d4cc2572d37983607df38b0f4216ed76ac51814sm						}
1659d4cc2572d37983607df38b0f4216ed76ac51814sm					}
1669d4cc2572d37983607df38b0f4216ed76ac51814sm
1679d4cc2572d37983607df38b0f4216ed76ac51814sm
1689d4cc2572d37983607df38b0f4216ed76ac51814sm					if (x == 0 && y == 0) {
1699d4cc2572d37983607df38b0f4216ed76ac51814sm						mDirectionalPad.release();
1709d4cc2572d37983607df38b0f4216ed76ac51814sm					} else {
1719d4cc2572d37983607df38b0f4216ed76ac51814sm						mDirectionalPad.setMagnitude(x, y);
1729d4cc2572d37983607df38b0f4216ed76ac51814sm					}
1739d4cc2572d37983607df38b0f4216ed76ac51814sm				}
1749d4cc2572d37983607df38b0f4216ed76ac51814sm
1759d4cc2572d37983607df38b0f4216ed76ac51814sm			} else {
1769d4cc2572d37983607df38b0f4216ed76ac51814sm				float xMagnitude = 0.0f;
1779d4cc2572d37983607df38b0f4216ed76ac51814sm				float yMagnitude = 0.0f;
1789d4cc2572d37983607df38b0f4216ed76ac51814sm				float pressTime = 0.0f;
1799d4cc2572d37983607df38b0f4216ed76ac51814sm				// left and right are mutually exclusive
1809d4cc2572d37983607df38b0f4216ed76ac51814sm				if (leftPressedTime > rightPressedTime) {
1819d4cc2572d37983607df38b0f4216ed76ac51814sm					xMagnitude = -left.getMagnitude() * KEY_FILTER * mMovementSensitivity;
1829d4cc2572d37983607df38b0f4216ed76ac51814sm					pressTime = leftPressedTime;
1839d4cc2572d37983607df38b0f4216ed76ac51814sm				} else {
1849d4cc2572d37983607df38b0f4216ed76ac51814sm					xMagnitude = right.getMagnitude() * KEY_FILTER * mMovementSensitivity;
1859d4cc2572d37983607df38b0f4216ed76ac51814sm					pressTime = rightPressedTime;
1869d4cc2572d37983607df38b0f4216ed76ac51814sm				}
1879d4cc2572d37983607df38b0f4216ed76ac51814sm
1889d4cc2572d37983607df38b0f4216ed76ac51814sm				if (xMagnitude != 0.0f) {
1899d4cc2572d37983607df38b0f4216ed76ac51814sm					mDirectionalPad.press(pressTime, xMagnitude, yMagnitude);
1909d4cc2572d37983607df38b0f4216ed76ac51814sm				} else {
1919d4cc2572d37983607df38b0f4216ed76ac51814sm					mDirectionalPad.release();
1929d4cc2572d37983607df38b0f4216ed76ac51814sm				}
1939d4cc2572d37983607df38b0f4216ed76ac51814sm			}
1949d4cc2572d37983607df38b0f4216ed76ac51814sm		}
1959d4cc2572d37983607df38b0f4216ed76ac51814sm
1969d4cc2572d37983607df38b0f4216ed76ac51814sm		// update other buttons
1979d4cc2572d37983607df38b0f4216ed76ac51814sm		final InputButton jumpKey = keys[mJumpKeyCode];
1982b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
1992b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		// when on-screen movement controls are on, the fly and attack buttons are flipped.
2002b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		float flyButtonRegionX = ButtonConstants.FLY_BUTTON_REGION_X;
2012b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		float stompButtonRegionX = ButtonConstants.STOMP_BUTTON_REGION_X;
2022b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
2032b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		if (mUseOnScreenControls) {
2042b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm			ContextParameters params = sSystemRegistry.contextParameters;
2052b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm			flyButtonRegionX = params.gameWidth - ButtonConstants.FLY_BUTTON_REGION_WIDTH - ButtonConstants.FLY_BUTTON_REGION_X;
2062b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm			stompButtonRegionX = params.gameWidth - ButtonConstants.STOMP_BUTTON_REGION_WIDTH - ButtonConstants.STOMP_BUTTON_REGION_X;
2072b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		}
2082b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
2092b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		final InputXY jumpTouch = touch.findPointerInRegion(
2102b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				flyButtonRegionX,
2112b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                ButtonConstants.FLY_BUTTON_REGION_Y,
2122b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                ButtonConstants.FLY_BUTTON_REGION_WIDTH,
2132b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                ButtonConstants.FLY_BUTTON_REGION_HEIGHT);
2149d4cc2572d37983607df38b0f4216ed76ac51814sm
2159d4cc2572d37983607df38b0f4216ed76ac51814sm		if (jumpKey.getPressed()) {
2169d4cc2572d37983607df38b0f4216ed76ac51814sm			mJumpButton.press(jumpKey.getLastPressedTime(), jumpKey.getMagnitude());
2172b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		} else if (jumpTouch != null) {
2189d4cc2572d37983607df38b0f4216ed76ac51814sm			if (!mJumpButton.getPressed()) {
2192b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				mJumpButton.press(jumpTouch.getLastPressedTime(), 1.0f);
2209d4cc2572d37983607df38b0f4216ed76ac51814sm			}
2219d4cc2572d37983607df38b0f4216ed76ac51814sm		} else {
2229d4cc2572d37983607df38b0f4216ed76ac51814sm			mJumpButton.release();
2239d4cc2572d37983607df38b0f4216ed76ac51814sm		}
2249d4cc2572d37983607df38b0f4216ed76ac51814sm
2259d4cc2572d37983607df38b0f4216ed76ac51814sm		final InputButton attackKey = keys[mAttackKeyCode];
2269d4cc2572d37983607df38b0f4216ed76ac51814sm		final InputButton clickButton = keys[KeyEvent.KEYCODE_DPAD_CENTER]; // special case
2279d4cc2572d37983607df38b0f4216ed76ac51814sm
2282b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		final InputXY stompTouch = touch.findPointerInRegion(
2292b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				stompButtonRegionX,
2302b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                ButtonConstants.STOMP_BUTTON_REGION_Y,
2312b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                ButtonConstants.STOMP_BUTTON_REGION_WIDTH,
2322b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm                ButtonConstants.STOMP_BUTTON_REGION_HEIGHT);
2332b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
2349d4cc2572d37983607df38b0f4216ed76ac51814sm		if (mUseClickButtonForAttack && clickButton.getPressed()) {
2359d4cc2572d37983607df38b0f4216ed76ac51814sm			mAttackButton.press(clickButton.getLastPressedTime(), clickButton.getMagnitude());
2369d4cc2572d37983607df38b0f4216ed76ac51814sm		} else if (attackKey.getPressed()) {
2379d4cc2572d37983607df38b0f4216ed76ac51814sm			mAttackButton.press(attackKey.getLastPressedTime(), attackKey.getMagnitude());
2382b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		} else if (stompTouch != null) {
2399d4cc2572d37983607df38b0f4216ed76ac51814sm			// Since touch events come in constantly, we only want to press the attack button
2409d4cc2572d37983607df38b0f4216ed76ac51814sm			// here if it's not already down.  That makes it act like the other buttons (down once then up).
2419d4cc2572d37983607df38b0f4216ed76ac51814sm			if (!mAttackButton.getPressed()) {
2422b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm				mAttackButton.press(stompTouch.getLastPressedTime(), 1.0f);
2439d4cc2572d37983607df38b0f4216ed76ac51814sm			}
2449d4cc2572d37983607df38b0f4216ed76ac51814sm		} else {
2459d4cc2572d37983607df38b0f4216ed76ac51814sm			mAttackButton.release();
2469d4cc2572d37983607df38b0f4216ed76ac51814sm		}
2472b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
2482b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		// This doesn't seem like exactly the right place to write to the HUD, but on the other hand,
2492b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		// putting this code elsewhere causes dependencies between exact HUD content and physics, which
2502b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		// we sometimes wish to avoid.
2512b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		final HudSystem hud = sSystemRegistry.hudSystem;
2522b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        if (hud != null) {
2532b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm            hud.setButtonState(mJumpButton.getPressed(), mAttackButton.getPressed(), mDirectionalPad.getPressed());
2542b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm            hud.setMovementSliderOffset(sliderOffset);
2552b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        }
2569d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2579d4cc2572d37983607df38b0f4216ed76ac51814sm
2589d4cc2572d37983607df38b0f4216ed76ac51814sm
2599d4cc2572d37983607df38b0f4216ed76ac51814sm	private float filterOrientationForMovement(float magnitude) {
2609d4cc2572d37983607df38b0f4216ed76ac51814sm		float scaledMagnitude = magnitude * mOrientationSensitivityFactor;
2619d4cc2572d37983607df38b0f4216ed76ac51814sm
2629d4cc2572d37983607df38b0f4216ed76ac51814sm		return deadZoneFilter(scaledMagnitude, mOrientationDeadZoneMin, mOrientationDeadZoneMax, mOrientationDeadZoneScale);
2639d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2649d4cc2572d37983607df38b0f4216ed76ac51814sm
2659d4cc2572d37983607df38b0f4216ed76ac51814sm	private float deadZoneFilter(float magnitude, float min, float max, float scale) {
2669d4cc2572d37983607df38b0f4216ed76ac51814sm		float smoothedMagnatude = magnitude;
2679d4cc2572d37983607df38b0f4216ed76ac51814sm    	if (Math.abs(magnitude) < min) {
2689d4cc2572d37983607df38b0f4216ed76ac51814sm    		smoothedMagnatude = 0.0f;	// dead zone
2699d4cc2572d37983607df38b0f4216ed76ac51814sm    	} else if (Math.abs(magnitude) < max) {
2709d4cc2572d37983607df38b0f4216ed76ac51814sm    		smoothedMagnatude *= scale;
2719d4cc2572d37983607df38b0f4216ed76ac51814sm    	}
2729d4cc2572d37983607df38b0f4216ed76ac51814sm
2739d4cc2572d37983607df38b0f4216ed76ac51814sm    	return smoothedMagnatude;
2749d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2759d4cc2572d37983607df38b0f4216ed76ac51814sm
2769d4cc2572d37983607df38b0f4216ed76ac51814sm
2779d4cc2572d37983607df38b0f4216ed76ac51814sm	public final InputXY getDirectionalPad() {
2789d4cc2572d37983607df38b0f4216ed76ac51814sm		return mDirectionalPad;
2799d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2809d4cc2572d37983607df38b0f4216ed76ac51814sm
2819d4cc2572d37983607df38b0f4216ed76ac51814sm	public final InputXY getTilt() {
2829d4cc2572d37983607df38b0f4216ed76ac51814sm		return mTilt;
2839d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2849d4cc2572d37983607df38b0f4216ed76ac51814sm
2859d4cc2572d37983607df38b0f4216ed76ac51814sm	public final InputButton getJumpButton() {
2869d4cc2572d37983607df38b0f4216ed76ac51814sm		return mJumpButton;
2879d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2889d4cc2572d37983607df38b0f4216ed76ac51814sm
2899d4cc2572d37983607df38b0f4216ed76ac51814sm	public final InputButton getAttackButton() {
2909d4cc2572d37983607df38b0f4216ed76ac51814sm		return mAttackButton;
2919d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2929d4cc2572d37983607df38b0f4216ed76ac51814sm
2939d4cc2572d37983607df38b0f4216ed76ac51814sm	public void setKeys(int left, int right, int jump, int attack) {
2949d4cc2572d37983607df38b0f4216ed76ac51814sm		mLeftKeyCode = left;
2959d4cc2572d37983607df38b0f4216ed76ac51814sm		mRightKeyCode = right;
2969d4cc2572d37983607df38b0f4216ed76ac51814sm		mJumpKeyCode = jump;
2979d4cc2572d37983607df38b0f4216ed76ac51814sm		mAttackKeyCode = attack;
2989d4cc2572d37983607df38b0f4216ed76ac51814sm	}
2999d4cc2572d37983607df38b0f4216ed76ac51814sm
3009d4cc2572d37983607df38b0f4216ed76ac51814sm	public void setUseClickForAttack(boolean click) {
3019d4cc2572d37983607df38b0f4216ed76ac51814sm		mUseClickButtonForAttack = click;
3029d4cc2572d37983607df38b0f4216ed76ac51814sm	}
3039d4cc2572d37983607df38b0f4216ed76ac51814sm
3049d4cc2572d37983607df38b0f4216ed76ac51814sm	public void setUseOrientationForMovement(boolean orientation) {
3059d4cc2572d37983607df38b0f4216ed76ac51814sm		mUseOrientationForMovement = orientation;
3069d4cc2572d37983607df38b0f4216ed76ac51814sm	}
3079d4cc2572d37983607df38b0f4216ed76ac51814sm
3089d4cc2572d37983607df38b0f4216ed76ac51814sm	public void setOrientationMovementSensitivity(float sensitivity) {
3099d4cc2572d37983607df38b0f4216ed76ac51814sm		mOrientationSensitivity = sensitivity;
3109d4cc2572d37983607df38b0f4216ed76ac51814sm		mOrientationSensitivityFactor = 2.9f * sensitivity + 0.1f;
3119d4cc2572d37983607df38b0f4216ed76ac51814sm	}
3129d4cc2572d37983607df38b0f4216ed76ac51814sm
3139d4cc2572d37983607df38b0f4216ed76ac51814sm	public void setMovementSensitivity(float sensitivity) {
3149d4cc2572d37983607df38b0f4216ed76ac51814sm		mMovementSensitivity  = sensitivity;
3159d4cc2572d37983607df38b0f4216ed76ac51814sm	}
3169d4cc2572d37983607df38b0f4216ed76ac51814sm
3172b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm	public void setUseOnScreenControls(boolean onscreen) {
3182b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm		mUseOnScreenControls = onscreen;
3192b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm	}
3202b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
3219d4cc2572d37983607df38b0f4216ed76ac51814sm}
322