blob: f1fa36928cf54986a1329a7428e93b72bd6388ec [file] [log] [blame]
sm0a9f4cfd74d62010-03-18 09:32:06 +00001/*
sm0a9f43c1e67e2010-04-02 17:29:14 +00002 * Copyright (C) 2010 The Android Open Source Project
sm0a9f4cfd74d62010-03-18 09:32:06 +00003 *
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
17package com.replica.replicaisland;
18
19import com.replica.replicaisland.ChannelSystem.Channel;
20import com.replica.replicaisland.GameObject.ActionType;
21
22public class NPCAnimationComponent extends GameComponent {
23
24 // Animations
25 public static final int IDLE = 0;
26 public static final int WALK = 1;
27 public static final int RUN_START = 2;
28 public static final int RUN = 3;
29 public static final int SHOOT = 4;
30 public static final int JUMP_START = 5;
31 public static final int JUMP_AIR = 6;
32 public static final int TAKE_HIT = 7;
33 public static final int SURPRISED = 8;
34 public static final int DEATH = 9;
35
36
37 protected static final float RUN_SPEED_THRESHOLD = 100.0f;
38 protected static final float JUMP_SPEED_THRESHOLD = 25.0f;
39 protected static final float FALL_SPEED_THRESHOLD = -25.0f;
40 protected static final float FALL_TIME_THRESHOLD = 0.2f;
41
42 private int mCurrentAnimation;
43 private SpriteComponent mSprite;
44 private ChannelSystem.Channel mChannel;
45 private int mChannelTrigger;
46 private boolean mFlying;
47 private boolean mStopAtWalls; // Controls whether or not the character will go back
48 // to idle when running into a wall
49
50
51 public NPCAnimationComponent() {
52 super();
53 reset();
54 setPhase(GameComponent.ComponentPhases.ANIMATION.ordinal());
55 }
56
57 @Override
58 public void reset() {
59 mCurrentAnimation = IDLE;
60 mChannel = null;
61 mSprite = null;
62 mFlying = false;
63 mStopAtWalls = true;
64 }
65
66 @Override
67 public void update(float timeDelta, BaseObject parent) {
68 if (mSprite != null) {
69 GameObject parentObject = (GameObject)parent;
70
71 final int oldAnimation = mCurrentAnimation;
72 switch(mCurrentAnimation) {
73 case IDLE:
74 idle(parentObject);
75 break;
76 case WALK:
77 walk(parentObject);
78 break;
79 case RUN_START:
80 runStart(parentObject);
81 break;
82 case RUN:
83 run(parentObject);
84 break;
85 case SHOOT:
86 shoot(parentObject);
87 break;
88 case JUMP_START:
89 jumpStart(parentObject);
90 break;
91 case JUMP_AIR:
92 jumpAir(parentObject);
93 break;
94 case TAKE_HIT:
95 takeHit(parentObject);
96 break;
97 case SURPRISED:
98 surprised(parentObject);
99 break;
100 case DEATH:
101 death(parentObject);
102 break;
103 default:
104 assert(false);
105 }
106
107 if (mChannel != null) {
108 if (mChannel.value != null
109 && ((ChannelSystem.ChannelBooleanValue)mChannel.value).value) {
110 mCurrentAnimation = mChannelTrigger;
111 }
112 }
113
114 if (oldAnimation != mCurrentAnimation) {
115 mSprite.playAnimation(mCurrentAnimation);
116 }
117 }
118 }
119
120 protected boolean shouldFall(GameObject parentObject) {
121 boolean result = false;
122 TimeSystem time = sSystemRegistry.timeSystem;
123 final float airTime = time.getGameTime() - parentObject.getLastTouchedFloorTime();
124 if (!mFlying && !parentObject.touchingGround() && airTime > FALL_TIME_THRESHOLD) {
125 final Vector2 velocity = parentObject.getVelocity();
126 if (velocity.y < FALL_SPEED_THRESHOLD) {
127 result = true;
128 }
129 }
130 return result;
131 }
132
133 protected boolean shouldJump(GameObject parentObject) {
134 boolean result = false;
135
136 if (!mFlying) {
137 final Vector2 velocity = parentObject.getVelocity();
138 if (velocity.y > JUMP_SPEED_THRESHOLD) {
139 result = true;
140 }
141 }
142 return result;
143 }
144
145 protected boolean shouldRun(GameObject parentObject) {
146 boolean result = false;
147 if (!mFlying && parentObject.touchingGround()) {
148 final Vector2 velocity = parentObject.getVelocity();
149 if (Math.abs(velocity.x) >= RUN_SPEED_THRESHOLD) {
150 result = true;
151 }
152 }
153 return result;
154 }
155
156 protected boolean shouldMove(GameObject parentObject) {
157 boolean result = true;
158 final Vector2 velocity = parentObject.getVelocity();
159
160 if (mStopAtWalls) {
161 if ((velocity.x < 0.0f && parentObject.touchingLeftWall())
162 || (velocity.x > 0.0f && parentObject.touchingRightWall())) {
163 result = false;
164 }
165 }
166 return result;
167 }
168
169 protected boolean shouldTakeHit(GameObject parentObject) {
170 boolean result = false;
171 if (parentObject.getCurrentAction() == ActionType.HIT_REACT
172 && mSprite.findAnimation(TAKE_HIT) != null) {
173 result = true;
174 }
175 return result;
176 }
177
178 protected void gotoRunStart() {
179 if (mSprite.findAnimation(RUN_START) != null) {
180 mCurrentAnimation = RUN_START;
181 } else {
182 mCurrentAnimation = RUN;
183 }
184 }
185
186 protected void gotoRun() {
187 mCurrentAnimation = RUN;
188 }
189
190 protected void idle(GameObject parentObject) {
191 final GameObject.ActionType currentAction = parentObject.getCurrentAction();
192 if (currentAction == ActionType.MOVE) {
193 final Vector2 velocity = parentObject.getVelocity();
194 if (shouldFall(parentObject)) {
195 mCurrentAnimation = JUMP_AIR;
196 } else if (shouldJump(parentObject)) {
197 mCurrentAnimation = JUMP_START;
198 parentObject.positionLocked = true;
199 } else if (Math.abs(velocity.x) > 0.0f && shouldMove(parentObject)) {
200 if (shouldRun(parentObject)) {
201 gotoRunStart();
202 parentObject.positionLocked = true;
203 } else {
204 mCurrentAnimation = WALK;
205 }
206 }
207 } else if (currentAction == ActionType.ATTACK) {
208 mCurrentAnimation = SHOOT;
209 } else if (shouldTakeHit(parentObject)) {
210 mCurrentAnimation = TAKE_HIT;
211 } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
212 mCurrentAnimation = DEATH;
213 }
214 }
215
216 protected void walk(GameObject parentObject) {
217 final GameObject.ActionType currentAction = parentObject.getCurrentAction();
218 if (currentAction == ActionType.MOVE) {
219 final Vector2 velocity = parentObject.getVelocity();
220 if (shouldFall(parentObject)) {
221 mCurrentAnimation = JUMP_AIR;
222 } else if (shouldJump(parentObject)) {
223 mCurrentAnimation = JUMP_START;
224 parentObject.positionLocked = true;
225 } else if (Math.abs(velocity.x) > 0.0f) {
226 if (shouldRun(parentObject)) {
227 gotoRun();
228 }
229 if (velocity.x > 0.0f) {
230 parentObject.facingDirection.x = 1;
231 } else {
232 parentObject.facingDirection.x = -1;
233 }
234 } else {
235 mCurrentAnimation = IDLE;
236 }
237 } else if (currentAction == ActionType.ATTACK) {
238 mCurrentAnimation = SHOOT;
239 } else if (shouldTakeHit(parentObject)) {
240 mCurrentAnimation = TAKE_HIT;
241 } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
242 mCurrentAnimation = DEATH;
243 }
244 }
245
246 protected void runStart(GameObject parentObject) {
247 parentObject.positionLocked = true;
248 if (mSprite.animationFinished()) {
249 mCurrentAnimation = RUN;
250 parentObject.positionLocked = false;
251 }
252 }
253 protected void run(GameObject parentObject) {
254 final GameObject.ActionType currentAction = parentObject.getCurrentAction();
255 if (currentAction == ActionType.MOVE) {
256 final Vector2 velocity = parentObject.getVelocity();
257 if (shouldFall(parentObject)) {
258 mCurrentAnimation = JUMP_AIR;
259 } else if (shouldJump(parentObject)) {
260 parentObject.positionLocked = true;
261 mCurrentAnimation = JUMP_START;
262 } else if (Math.abs(velocity.x) > 0.0f) {
263 if (!shouldRun(parentObject)) {
264 mCurrentAnimation = WALK;
265 }
266
267 if (velocity.x > 0.0f) {
268 parentObject.facingDirection.x = 1;
269 } else {
270 parentObject.facingDirection.x = -1;
271 }
272 } else {
273 mCurrentAnimation = IDLE;
274 }
275 } else if (currentAction == ActionType.ATTACK) {
276 mCurrentAnimation = SHOOT;
277 } else if (shouldTakeHit(parentObject)) {
278 mCurrentAnimation = TAKE_HIT;
279 } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
280 mCurrentAnimation = DEATH;
281 }
282 }
283
284 protected void shoot(GameObject parentObject) {
285 if (mSprite.animationFinished() || parentObject.getCurrentAction() != ActionType.ATTACK) {
286 mCurrentAnimation = IDLE;
287 } else if (shouldTakeHit(parentObject)) {
288 mCurrentAnimation = TAKE_HIT;
289 } else if (parentObject.getCurrentAction() == ActionType.DEATH) {
290 mCurrentAnimation = DEATH;
291 } else {
292 final Vector2 velocity = parentObject.getVelocity();
293
294 if (velocity.x > 0.0f) {
295 parentObject.facingDirection.x = 1;
296 } else if (velocity.x < 0.0f) {
297 parentObject.facingDirection.x = -1;
298 }
299 }
300 }
301
302 protected void jumpStart(GameObject parentObject) {
303 final Vector2 velocity = parentObject.getVelocity();
304
305 if (velocity.x > 0.0f) {
306 parentObject.facingDirection.x = 1;
307 } else if (velocity.x < 0.0f) {
308 parentObject.facingDirection.x = -1;
309 }
310 parentObject.positionLocked = true;
311
312 if (mSprite.animationFinished()) {
313 mCurrentAnimation = JUMP_AIR;
314 parentObject.positionLocked = false;
315 }
316 }
317
318 protected void jumpAir(GameObject parentObject) {
319 final GameObject.ActionType currentAction = parentObject.getCurrentAction();
320 if (currentAction == ActionType.MOVE) {
321 final Vector2 velocity = parentObject.getVelocity();
322
323 if (parentObject.touchingGround()) {
324 if (Math.abs(velocity.x) > 0.0f) {
325 if (shouldRun(parentObject)) {
326 mCurrentAnimation = RUN;
327 } else {
328 mCurrentAnimation = WALK;
329 }
330 } else {
331 mCurrentAnimation = IDLE;
332 }
333 } else {
334
335 if (velocity.x > 0.0f) {
336 parentObject.facingDirection.x = 1;
337 } else if (velocity.x < 0.0f) {
338 parentObject.facingDirection.x = -1;
339 }
340
341 }
342 } else {
343 mCurrentAnimation = IDLE;
344 }
345 }
346
347 protected void takeHit(GameObject parentObject) {
348 if (mSprite.animationFinished()) {
349 if (parentObject.life > 0 && parentObject.getCurrentAction() != ActionType.DEATH) {
350 if (parentObject.getCurrentAction() != ActionType.HIT_REACT) {
351 mCurrentAnimation = IDLE;
352 }
353 } else {
354 mCurrentAnimation = DEATH;
355 }
356 }
357 }
358
359 protected void surprised(GameObject parentObject) {
360 if (mSprite.animationFinished()) {
361 mCurrentAnimation = IDLE;
362 }
363 }
364
365 protected void death(GameObject parentObject) {
366 }
367
368 public void setSprite(SpriteComponent sprite) {
369 mSprite = sprite;
370 }
371
372 public void setChannel(Channel channel) {
373 mChannel = channel;
374 }
375
376 public void setChannelTrigger(int animation) {
377 mChannelTrigger = animation;
378 }
379
380 public void setFlying(boolean flying) {
381 mFlying = flying;
382 }
383
384 public void setStopAtWalls(boolean stop) {
385 mStopAtWalls = stop;
386 }
387}