• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.replica.replicaisland;
18 
19 import android.view.KeyEvent;
20 
21 public class InputGameInterface extends BaseObject {
22 	private static final float ORIENTATION_DEAD_ZONE_MIN = 0.03f;
23 	private static final float ORIENTATION_DEAD_ZONE_MAX = 0.1f;
24 	private static final float ORIENTATION_DEAD_ZONE_SCALE = 0.75f;
25 
26 	private final static float ROLL_TIMEOUT = 0.1f;
27 	private final static float ROLL_RESET_DELAY = 0.075f;
28 
29     // Raw trackball input is filtered by this value. Increasing it will
30     // make the control more twitchy, while decreasing it will make the control more precise.
31     private final static float ROLL_FILTER = 0.4f;
32     private final static float ROLL_DECAY = 8.0f;
33 
34     private final static float KEY_FILTER = 0.25f;
35     private final static float SLIDER_FILTER = 0.25f;
36 
37 
38 	private InputButton mJumpButton = new InputButton();
39 	private InputButton mAttackButton = new InputButton();
40 	private InputXY mDirectionalPad = new InputXY();
41 	private InputXY mTilt = new InputXY();
42 
43 	private int mLeftKeyCode = KeyEvent.KEYCODE_DPAD_LEFT;
44 	private int mRightKeyCode = KeyEvent.KEYCODE_DPAD_RIGHT;
45 	private int mJumpKeyCode = KeyEvent.KEYCODE_SPACE;
46 	private int mAttackKeyCode = KeyEvent.KEYCODE_SHIFT_LEFT;
47 
48 	private float mOrientationDeadZoneMin = ORIENTATION_DEAD_ZONE_MIN;
49 	private float mOrientationDeadZoneMax = ORIENTATION_DEAD_ZONE_MAX;
50 	private float mOrientationDeadZoneScale = ORIENTATION_DEAD_ZONE_SCALE;
51 	private float mOrientationSensitivity = 1.0f;
52 	private float mOrientationSensitivityFactor = 1.0f;
53 	private float mMovementSensitivity = 1.0f;
54 
55 	private boolean mUseClickButtonForAttack = true;
56 	private boolean mUseOrientationForMovement = false;
57 	private boolean mUseOnScreenControls = false;
58 
59 	private float mLastRollTime;
60 
InputGameInterface()61 	public InputGameInterface() {
62 		super();
63 		reset();
64 	}
65 
66 	@Override
reset()67 	public void reset() {
68 		mJumpButton.release();
69 		mAttackButton.release();
70 		mDirectionalPad.release();
71 		mTilt.release();
72 	}
73 
74 
75 
76 	@Override
update(float timeDelta, BaseObject parent)77     public void update(float timeDelta, BaseObject parent) {
78 		InputSystem input = sSystemRegistry.inputSystem;
79 		final InputButton[] keys = input.getKeyboard().getKeys();
80 		final InputXY orientation = input.getOrientationSensor();
81 
82 		// tilt is easy
83 		mTilt.clone(orientation);
84 
85 		final InputTouchScreen touch = input.getTouchScreen();
86 		final float gameTime = sSystemRegistry.timeSystem.getGameTime();
87 
88 		float sliderOffset = 0;
89 
90 		// update movement inputs
91 		if (mUseOnScreenControls) {
92 			final InputXY sliderTouch = touch.findPointerInRegion(
93 					ButtonConstants.MOVEMENT_SLIDER_REGION_X,
94                     ButtonConstants.MOVEMENT_SLIDER_REGION_Y,
95                     ButtonConstants.MOVEMENT_SLIDER_REGION_WIDTH,
96                     ButtonConstants.MOVEMENT_SLIDER_REGION_HEIGHT);
97 
98 			if (sliderTouch != null) {
99 				final float halfWidth = ButtonConstants.MOVEMENT_SLIDER_BAR_WIDTH / 2.0f;
100 				final float center = ButtonConstants.MOVEMENT_SLIDER_X + halfWidth;
101 				final float offset = sliderTouch.getX() - center;
102 				float magnitudeRamp = Math.abs(offset) > halfWidth ? 1.0f : (Math.abs(offset) / halfWidth);
103 
104 				final float magnitude = magnitudeRamp * Utils.sign(offset) * SLIDER_FILTER * mMovementSensitivity;
105 				sliderOffset = magnitudeRamp * Utils.sign(offset);
106 				mDirectionalPad.press(gameTime, magnitude, 0.0f);
107 			} else {
108 				mDirectionalPad.release();
109 			}
110 		} else if (mUseOrientationForMovement) {
111 			mDirectionalPad.clone(orientation);
112 			mDirectionalPad.setMagnitude(
113 					filterOrientationForMovement(orientation.getX()),
114 					filterOrientationForMovement(orientation.getY()));
115 		} else {
116 			// keys or trackball
117 			final InputXY trackball = input.getTrackball();
118 			final InputButton left = keys[mLeftKeyCode];
119 			final InputButton right = keys[mRightKeyCode];
120 			final float leftPressedTime = left.getLastPressedTime();
121 			final float rightPressedTime = right.getLastPressedTime();
122 
123 
124 			if (trackball.getLastPressedTime() > Math.max(leftPressedTime, rightPressedTime)) {
125 				// The trackball never goes "up", so force it to turn off if it wasn't triggered in the last frame.
126 				// What follows is a bunch of code to filter trackball events into something like a dpad event.
127 				// The goals here are:
128 				// 	- For roll events that occur in quick succession to accumulate.
129 				//	- For roll events that occur with more time between them, lessen the impact of older events
130 				//	- In the absence of roll events, fade the roll out over time.
131 				if (gameTime - trackball.getLastPressedTime() < ROLL_TIMEOUT) {
132 					float newX;
133 					float newY;
134 					final float delay = Math.max(ROLL_RESET_DELAY, timeDelta);
135 					if (gameTime - mLastRollTime <= delay) {
136 						newX = mDirectionalPad.getX() + (trackball.getX() * ROLL_FILTER * mMovementSensitivity);
137 						newY = mDirectionalPad.getY() + (trackball.getY() * ROLL_FILTER * mMovementSensitivity);
138 					} else {
139 						float oldX = mDirectionalPad.getX() != 0.0f ? mDirectionalPad.getX() / 2.0f : 0.0f;
140 						float oldY = mDirectionalPad.getX() != 0.0f ? mDirectionalPad.getX() / 2.0f : 0.0f;
141 						newX = oldX + (trackball.getX() * ROLL_FILTER * mMovementSensitivity);
142 						newY = oldY + (trackball.getX() * ROLL_FILTER * mMovementSensitivity);
143 					}
144 
145 					mDirectionalPad.press(gameTime, newX, newY);
146 					mLastRollTime = gameTime;
147 					trackball.release();
148 				} else {
149 					float x = mDirectionalPad.getX();
150 					float y = mDirectionalPad.getY();
151 					if (x != 0.0f) {
152 						int sign = Utils.sign(x);
153 						x = x - (sign * ROLL_DECAY * timeDelta);
154 						if (Utils.sign(x) != sign) {
155 							x = 0.0f;
156 						}
157 					}
158 
159 					if (y != 0.0f) {
160 						int sign = Utils.sign(y);
161 						y = y - (sign * ROLL_DECAY * timeDelta);
162 						if (Utils.sign(x) != sign) {
163 							y = 0.0f;
164 						}
165 					}
166 
167 
168 					if (x == 0 && y == 0) {
169 						mDirectionalPad.release();
170 					} else {
171 						mDirectionalPad.setMagnitude(x, y);
172 					}
173 				}
174 
175 			} else {
176 				float xMagnitude = 0.0f;
177 				float yMagnitude = 0.0f;
178 				float pressTime = 0.0f;
179 				// left and right are mutually exclusive
180 				if (leftPressedTime > rightPressedTime) {
181 					xMagnitude = -left.getMagnitude() * KEY_FILTER * mMovementSensitivity;
182 					pressTime = leftPressedTime;
183 				} else {
184 					xMagnitude = right.getMagnitude() * KEY_FILTER * mMovementSensitivity;
185 					pressTime = rightPressedTime;
186 				}
187 
188 				if (xMagnitude != 0.0f) {
189 					mDirectionalPad.press(pressTime, xMagnitude, yMagnitude);
190 				} else {
191 					mDirectionalPad.release();
192 				}
193 			}
194 		}
195 
196 		// update other buttons
197 		final InputButton jumpKey = keys[mJumpKeyCode];
198 
199 		// when on-screen movement controls are on, the fly and attack buttons are flipped.
200 		float flyButtonRegionX = ButtonConstants.FLY_BUTTON_REGION_X;
201 		float stompButtonRegionX = ButtonConstants.STOMP_BUTTON_REGION_X;
202 
203 		if (mUseOnScreenControls) {
204 			ContextParameters params = sSystemRegistry.contextParameters;
205 			flyButtonRegionX = params.gameWidth - ButtonConstants.FLY_BUTTON_REGION_WIDTH - ButtonConstants.FLY_BUTTON_REGION_X;
206 			stompButtonRegionX = params.gameWidth - ButtonConstants.STOMP_BUTTON_REGION_WIDTH - ButtonConstants.STOMP_BUTTON_REGION_X;
207 		}
208 
209 		final InputXY jumpTouch = touch.findPointerInRegion(
210 				flyButtonRegionX,
211                 ButtonConstants.FLY_BUTTON_REGION_Y,
212                 ButtonConstants.FLY_BUTTON_REGION_WIDTH,
213                 ButtonConstants.FLY_BUTTON_REGION_HEIGHT);
214 
215 		if (jumpKey.getPressed()) {
216 			mJumpButton.press(jumpKey.getLastPressedTime(), jumpKey.getMagnitude());
217 		} else if (jumpTouch != null) {
218 			if (!mJumpButton.getPressed()) {
219 				mJumpButton.press(jumpTouch.getLastPressedTime(), 1.0f);
220 			}
221 		} else {
222 			mJumpButton.release();
223 		}
224 
225 		final InputButton attackKey = keys[mAttackKeyCode];
226 		final InputButton clickButton = keys[KeyEvent.KEYCODE_DPAD_CENTER]; // special case
227 
228 		final InputXY stompTouch = touch.findPointerInRegion(
229 				stompButtonRegionX,
230                 ButtonConstants.STOMP_BUTTON_REGION_Y,
231                 ButtonConstants.STOMP_BUTTON_REGION_WIDTH,
232                 ButtonConstants.STOMP_BUTTON_REGION_HEIGHT);
233 
234 		if (mUseClickButtonForAttack && clickButton.getPressed()) {
235 			mAttackButton.press(clickButton.getLastPressedTime(), clickButton.getMagnitude());
236 		} else if (attackKey.getPressed()) {
237 			mAttackButton.press(attackKey.getLastPressedTime(), attackKey.getMagnitude());
238 		} else if (stompTouch != null) {
239 			// Since touch events come in constantly, we only want to press the attack button
240 			// here if it's not already down.  That makes it act like the other buttons (down once then up).
241 			if (!mAttackButton.getPressed()) {
242 				mAttackButton.press(stompTouch.getLastPressedTime(), 1.0f);
243 			}
244 		} else {
245 			mAttackButton.release();
246 		}
247 
248 		// This doesn't seem like exactly the right place to write to the HUD, but on the other hand,
249 		// putting this code elsewhere causes dependencies between exact HUD content and physics, which
250 		// we sometimes wish to avoid.
251 		final HudSystem hud = sSystemRegistry.hudSystem;
252         if (hud != null) {
253             hud.setButtonState(mJumpButton.getPressed(), mAttackButton.getPressed(), mDirectionalPad.getPressed());
254             hud.setMovementSliderOffset(sliderOffset);
255         }
256 	}
257 
258 
filterOrientationForMovement(float magnitude)259 	private float filterOrientationForMovement(float magnitude) {
260 		float scaledMagnitude = magnitude * mOrientationSensitivityFactor;
261 
262 		return deadZoneFilter(scaledMagnitude, mOrientationDeadZoneMin, mOrientationDeadZoneMax, mOrientationDeadZoneScale);
263 	}
264 
deadZoneFilter(float magnitude, float min, float max, float scale)265 	private float deadZoneFilter(float magnitude, float min, float max, float scale) {
266 		float smoothedMagnatude = magnitude;
267     	if (Math.abs(magnitude) < min) {
268     		smoothedMagnatude = 0.0f;	// dead zone
269     	} else if (Math.abs(magnitude) < max) {
270     		smoothedMagnatude *= scale;
271     	}
272 
273     	return smoothedMagnatude;
274 	}
275 
276 
getDirectionalPad()277 	public final InputXY getDirectionalPad() {
278 		return mDirectionalPad;
279 	}
280 
getTilt()281 	public final InputXY getTilt() {
282 		return mTilt;
283 	}
284 
getJumpButton()285 	public final InputButton getJumpButton() {
286 		return mJumpButton;
287 	}
288 
getAttackButton()289 	public final InputButton getAttackButton() {
290 		return mAttackButton;
291 	}
292 
setKeys(int left, int right, int jump, int attack)293 	public void setKeys(int left, int right, int jump, int attack) {
294 		mLeftKeyCode = left;
295 		mRightKeyCode = right;
296 		mJumpKeyCode = jump;
297 		mAttackKeyCode = attack;
298 	}
299 
setUseClickForAttack(boolean click)300 	public void setUseClickForAttack(boolean click) {
301 		mUseClickButtonForAttack = click;
302 	}
303 
setUseOrientationForMovement(boolean orientation)304 	public void setUseOrientationForMovement(boolean orientation) {
305 		mUseOrientationForMovement = orientation;
306 	}
307 
setOrientationMovementSensitivity(float sensitivity)308 	public void setOrientationMovementSensitivity(float sensitivity) {
309 		mOrientationSensitivity = sensitivity;
310 		mOrientationSensitivityFactor = 2.9f * sensitivity + 0.1f;
311 	}
312 
setMovementSensitivity(float sensitivity)313 	public void setMovementSensitivity(float sensitivity) {
314 		mMovementSensitivity  = sensitivity;
315 	}
316 
setUseOnScreenControls(boolean onscreen)317 	public void setUseOnScreenControls(boolean onscreen) {
318 		mUseOnScreenControls = onscreen;
319 	}
320 
321 }
322