• 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 
20 import com.replica.replicaisland.CollisionParameters.HitType;
21 import com.replica.replicaisland.GameObject.ActionType;
22 import com.replica.replicaisland.SoundSystem.Sound;
23 
24 /**
25  * Player Animation game object component.  Responsible for selecting an animation to describe the
26  * player's current state.  Requires the object to contain a SpriteComponent to play animations.
27  */
28 public class AnimationComponent extends GameComponent {
29 
30     public enum PlayerAnimations {
31         IDLE,
32         MOVE,
33         MOVE_FAST,
34         BOOST_UP,
35         BOOST_MOVE,
36         BOOST_MOVE_FAST,
37         STOMP,
38         HIT_REACT,
39         DEATH,
40         FROZEN
41     }
42 
43     private static final float MIN_ROCKET_TIME = 0.0f;
44     private static final float FLICKER_INTERVAL = 0.15f;
45     private static final float FLICKER_DURATION = 3.0f;
46     private static final float LAND_THUMP_DELAY = 0.5f;
47 
48     private SpriteComponent mSprite;
49     private SpriteComponent mJetSprite;
50     private SpriteComponent mSparksSprite;
51 
52     private PlayerComponent mPlayer;
53     private float mLastFlickerTime;
54     private boolean mFlickerOn;
55     private float mFlickerTimeRemaining;
56 
57     private GameObject.ActionType mPreviousAction;
58 
59     private float mLastRocketsOnTime;
60     private boolean mExplodingDeath;
61 
62     private ChangeComponentsComponent mDamageSwap;
63     private Sound mLandThump;
64     private Sound mRocketSound;
65     private Sound mExplosionSound;
66     private float mLandThumpDelay;
67     private int mRocketSoundStream;
68     private boolean mRocketSoundPaused;
69 
70     private int mLastRubyCount;
71     private Sound mRubySound1;
72     private Sound mRubySound2;
73     private Sound mRubySound3;
74     private InventoryComponent mInventory;
75 
76 
AnimationComponent()77     public AnimationComponent() {
78         super();
79         reset();
80         setPhase(ComponentPhases.ANIMATION.ordinal());
81     }
82 
83     @Override
reset()84     public void reset() {
85         mPreviousAction = ActionType.INVALID;
86         mSprite = null;
87         mJetSprite = null;
88         mSparksSprite = null;
89         mPlayer = null;
90         mLastFlickerTime = 0.0f;
91         mFlickerOn = false;
92         mFlickerTimeRemaining = 0.0f;
93         mLastRocketsOnTime = 0.0f;
94         mExplodingDeath = false;
95         mDamageSwap = null;
96         mLandThump = null;
97         mLandThumpDelay = 0.0f;
98         mRocketSound = null;
99         mRocketSoundStream = -1;
100         mLastRubyCount = 0;
101         mInventory = null;
102         mExplosionSound = null;
103     }
104 
105     @Override
update(float timeDelta, BaseObject parent)106     public void update(float timeDelta, BaseObject parent) {
107         if (mSprite != null) {
108 
109             GameObject parentObject = (GameObject) parent;
110 
111             final float velocityX = parentObject.getVelocity().x;
112             final float velocityY = parentObject.getVelocity().y;
113 
114 
115             GameObject.ActionType currentAction = parentObject.getCurrentAction();
116 
117             if (mJetSprite != null) {
118                 mJetSprite.setVisible(false);
119             }
120 
121             if (mSparksSprite != null) {
122                 mSparksSprite.setVisible(false);
123             }
124 
125 
126             final TimeSystem time = sSystemRegistry.timeSystem;
127             final float gameTime = time.getGameTime();
128 
129             if (currentAction != ActionType.HIT_REACT && mPreviousAction == ActionType.HIT_REACT) {
130                 mFlickerTimeRemaining = FLICKER_DURATION;
131             }
132 
133 
134             final boolean touchingGround = parentObject.touchingGround();
135 
136             boolean boosting = mPlayer != null ? mPlayer.getRocketsOn() : false;
137 
138             boolean visible = true;
139 
140             SoundSystem sound = sSystemRegistry.soundSystem;
141 
142             // It's usually not necessary to test to see if sound is enabled or not (when it's disabled,
143             // play() is just a nop), but in this case I have a stream that is maintained for the rocket
144             // sounds.  So it's simpler to just avoid that code if sound is off.
145             if (sound.getSoundEnabled()) {
146 	            if (boosting) {
147 	                mLastRocketsOnTime = gameTime;
148 	            } else {
149 	                if (gameTime - mLastRocketsOnTime < MIN_ROCKET_TIME
150 	                        && velocityY >= 0.0f) {
151 	                    boosting = true;
152 	                }
153 	            }
154 
155 	            if (mRocketSound != null) {
156 		            if (boosting) {
157 		            	if (mRocketSoundStream == -1) {
158 		            		mRocketSoundStream = sound.play(mRocketSound, true, SoundSystem.PRIORITY_HIGH);
159 		            		mRocketSoundPaused = false;
160 		            	} else if (mRocketSoundPaused) {
161 		            		sound.resume(mRocketSoundStream);
162 		            		mRocketSoundPaused = false;
163 		            	}
164 		            } else {
165 		            	sound.pause(mRocketSoundStream);
166 		            	mRocketSoundPaused = true;
167 		            }
168 	            }
169             }
170 
171             // Normally, for collectables like the coin, we could just tell the object to play
172             // a sound when it is collected.  The gems are a special case, though, as we
173             // want to pick a different sound depending on how many have been collected.
174             if (mInventory != null && mRubySound1 != null && mRubySound2 != null && mRubySound3 != null) {
175             	InventoryComponent.UpdateRecord inventory = mInventory.getRecord();
176             	final int rubyCount = inventory.rubyCount;
177             	if (rubyCount != mLastRubyCount) {
178             		mLastRubyCount = rubyCount;
179             		switch (rubyCount) {
180             		case 1:
181             			sound.play(mRubySound1, false, SoundSystem.PRIORITY_NORMAL);
182             			break;
183             		case 2:
184             			sound.play(mRubySound2, false, SoundSystem.PRIORITY_NORMAL);
185             			break;
186             		case 3:
187             			sound.play(mRubySound3, false, SoundSystem.PRIORITY_NORMAL);
188             			break;
189             		}
190 
191             	}
192             }
193 
194             // Turn on visual effects (smoke, etc) when the player's life reaches 1.
195             if (mDamageSwap != null) {
196                 if (parentObject.life == 1 && !mDamageSwap.getCurrentlySwapped()) {
197                     mDamageSwap.activate(parentObject);
198                 } else if (parentObject.life != 1 && mDamageSwap.getCurrentlySwapped()) {
199                     mDamageSwap.activate(parentObject);
200                 }
201             }
202 
203             float opacity = 1.0f;
204 
205             if (currentAction == ActionType.MOVE) {
206                 InputGameInterface input = sSystemRegistry.inputGameInterface;
207                 final InputXY dpad = input.getDirectionalPad();
208                 if (dpad.getX() < 0.0f) {
209                     parentObject.facingDirection.x = -1.0f;
210                 } else if (dpad.getX() > 0.0f) {
211                     parentObject.facingDirection.x = 1.0f;
212                 }
213 
214                 // TODO: get rid of these magic numbers!
215                 if (touchingGround) {
216 
217                     if (Utils.close(velocityX, 0.0f, 30.0f)) {
218                         mSprite.playAnimation(PlayerAnimations.IDLE.ordinal());
219                     } else if (Math.abs(velocityX) > 300.0f) {
220                         mSprite.playAnimation(PlayerAnimations.MOVE_FAST.ordinal());
221                     } else {
222                         mSprite.playAnimation(PlayerAnimations.MOVE.ordinal());
223                     }
224 
225                     final InputButton attackButton = input.getAttackButton();
226 
227                     if (attackButton.getPressed()) {
228                         // charge
229                         final float pressedTime = gameTime - attackButton.getLastPressedTime();
230                         final float wave = (float)Math.cos(pressedTime * (float)Math.PI * 2.0f);
231                         opacity = (wave * 0.25f) + 0.75f;
232                     }
233 
234                 } else {
235                     if (boosting) {
236                         if (mJetSprite != null) {
237                             mJetSprite.setVisible(true);
238                         }
239 
240                         if (Math.abs(velocityX) < 100.0f && velocityY > 10.0f) {
241                             mSprite.playAnimation(PlayerAnimations.BOOST_UP.ordinal());
242                         } else if (Math.abs(velocityX) > 300.0f) {
243                             mSprite.playAnimation(PlayerAnimations.BOOST_MOVE_FAST.ordinal());
244                         } else {
245                             mSprite.playAnimation(PlayerAnimations.BOOST_MOVE.ordinal());
246                         }
247                     } else {
248 
249                         if (Utils.close(velocityX, 0.0f, 1.0f)) {
250                             mSprite.playAnimation(PlayerAnimations.IDLE.ordinal());
251                         } else if (Math.abs(velocityX) > 300.0f) {
252                             mSprite.playAnimation(PlayerAnimations.MOVE_FAST.ordinal());
253                         } else {
254                             mSprite.playAnimation(PlayerAnimations.MOVE.ordinal());
255                         }
256                     }
257 
258                 }
259             } else if (currentAction == ActionType.ATTACK) {
260                 mSprite.playAnimation(PlayerAnimations.STOMP.ordinal());
261                 if (touchingGround && gameTime > mLandThumpDelay) {
262                     if (mLandThump != null && sound != null) {
263                         // modulate the sound slightly to avoid sounding too similar
264                         sound.play(mLandThump, false, SoundSystem.PRIORITY_HIGH, 1.0f,
265                                 (float)(Math.random() * 0.5f) + 0.75f);
266                         mLandThumpDelay = gameTime + LAND_THUMP_DELAY;
267                     }
268                 }
269             } else if (currentAction == ActionType.HIT_REACT) {
270                 mSprite.playAnimation(PlayerAnimations.HIT_REACT.ordinal());
271 
272                 if (velocityX > 0.0f) {
273                     parentObject.facingDirection.x = -1.0f;
274                 } else if (velocityX < 0.0f) {
275                     parentObject.facingDirection.x = 1.0f;
276                 }
277 
278                 if (mSparksSprite != null) {
279                     mSparksSprite.setVisible(true);
280                 }
281             } else if (currentAction == ActionType.DEATH) {
282                 if (mPreviousAction != currentAction) {
283                 	if (mExplosionSound != null) {
284                 		sound.play(mExplosionSound, false, SoundSystem.PRIORITY_NORMAL);
285                 	}
286                 	// by default, explode when hit with the DEATH hit type.
287                     boolean explodingDeath = parentObject.lastReceivedHitType == HitType.DEATH;
288                     // or if touching a death tile.
289                     HotSpotSystem hotSpot = sSystemRegistry.hotSpotSystem;
290                     if (hotSpot != null) {
291                         // TODO: HACK!  Unify all this code.
292                         if (hotSpot.getHotSpot(parentObject.getCenteredPositionX(),
293                                 parentObject.getPosition().y + 10.0f) == HotSpotSystem.HotSpotType.DIE) {
294                             explodingDeath = true;
295                         }
296                     }
297                     if (explodingDeath) {
298                         mExplodingDeath = true;
299                         GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
300                         GameObjectManager manager = sSystemRegistry.gameObjectManager;
301                         if (factory != null && manager != null) {
302                             GameObject explosion = factory.spawnEffectExplosionGiant(parentObject.getPosition().x, parentObject.getPosition().y);
303                             if (explosion != null) {
304                                 manager.add(explosion);
305                             }
306                         }
307                     } else {
308                         mSprite.playAnimation(PlayerAnimations.DEATH.ordinal());
309                         mExplodingDeath = false;
310                     }
311 
312                     mFlickerTimeRemaining = 0.0f;
313                     if (mSparksSprite != null) {
314                         if (!mSprite.animationFinished()) {
315                             mSparksSprite.setVisible(true);
316                         }
317                     }
318                 }
319                 if (mExplodingDeath) {
320                     visible = false;
321                 }
322             } else if (currentAction == ActionType.FROZEN) {
323                 mSprite.playAnimation(PlayerAnimations.FROZEN.ordinal());
324             }
325 
326             if (mFlickerTimeRemaining > 0.0f) {
327                 mFlickerTimeRemaining -= timeDelta;
328                 if (gameTime > mLastFlickerTime + FLICKER_INTERVAL) {
329                     mLastFlickerTime = gameTime;
330                     mFlickerOn = !mFlickerOn;
331                 }
332                 mSprite.setVisible(mFlickerOn);
333                 if (mJetSprite != null && mJetSprite.getVisible()) {
334                     mJetSprite.setVisible(mFlickerOn);
335                 }
336             } else {
337                 mSprite.setVisible(visible);
338                 mSprite.setOpacity(opacity);
339             }
340 
341             mPreviousAction = currentAction;
342         }
343     }
344 
setSprite(SpriteComponent sprite)345     public void setSprite(SpriteComponent sprite) {
346         mSprite = sprite;
347     }
348 
setJetSprite(SpriteComponent sprite)349     public void setJetSprite(SpriteComponent sprite) {
350         mJetSprite = sprite;
351     }
352 
setSparksSprite(SpriteComponent sprite)353     public void setSparksSprite(SpriteComponent sprite) {
354         mSparksSprite = sprite;
355     }
356 
setPlayer(PlayerComponent player)357     public void setPlayer(PlayerComponent player) {
358         mPlayer = player;
359     }
360 
setDamageSwap(ChangeComponentsComponent damageSwap)361     public final void setDamageSwap(ChangeComponentsComponent damageSwap) {
362         mDamageSwap = damageSwap;
363     }
364 
setLandThump(Sound land)365     public void setLandThump(Sound land) {
366         mLandThump = land;
367     }
368 
setRocketSound(Sound sound)369 	public void setRocketSound(Sound sound) {
370 		mRocketSound = sound;
371 	}
372 
setRubySounds(Sound one, Sound two, Sound three)373 	public void setRubySounds(Sound one, Sound two, Sound three) {
374 		mRubySound1 = one;
375 		mRubySound2 = two;
376 		mRubySound3 = three;
377 	}
378 
setInventory(InventoryComponent inventory)379 	public void setInventory(InventoryComponent inventory) {
380 		mInventory = inventory;
381 	}
382 
setExplosionSound(Sound sound)383 	public void setExplosionSound(Sound sound) {
384 		mExplosionSound = sound;
385 	}
386 }
387