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 com.replica.replicaisland.SoundSystem.Sound; 20 21 public class DoorAnimationComponent extends GameComponent { 22 23 public static final class Animation { 24 // Animations 25 public static final int CLOSED = 0; 26 public static final int OPEN = 1; 27 public static final int CLOSING = 2; 28 public static final int OPENING = 3; 29 } 30 31 // State 32 protected static final int STATE_CLOSED = 0; 33 protected static final int STATE_OPEN = 1; 34 protected static final int STATE_CLOSING = 2; 35 protected static final int STATE_OPENING = 3; 36 37 protected final static float DEFAULT_STAY_OPEN_TIME = 5.0f; 38 39 private SpriteComponent mSprite; 40 private int mState; 41 private ChannelSystem.Channel mChannel; 42 private SolidSurfaceComponent mSolidSurface; 43 private float mStayOpenTime; 44 private Sound mCloseSound; 45 private Sound mOpenSound; 46 47 public DoorAnimationComponent() { 48 super(); 49 setPhase(ComponentPhases.ANIMATION.ordinal()); 50 reset(); 51 } 52 53 @Override 54 public void reset() { 55 mSprite = null; 56 mState = STATE_CLOSED; 57 mChannel = null; 58 mSolidSurface = null; 59 mStayOpenTime = DEFAULT_STAY_OPEN_TIME; 60 mCloseSound = null; 61 mOpenSound = null; 62 } 63 64 private void open(float timeSinceTriggered, GameObject parentObject) { 65 if (mSprite != null) { 66 final float openAnimationLength = mSprite.findAnimation(Animation.OPENING).getLength(); 67 68 69 70 if (timeSinceTriggered > openAnimationLength) { 71 // snap open. 72 mSprite.playAnimation(Animation.OPEN); 73 mState = STATE_OPEN; 74 if (mSolidSurface != null) { 75 parentObject.remove(mSolidSurface); 76 } 77 } else { 78 float timeOffset = timeSinceTriggered; 79 if (mState == STATE_CLOSING) { 80 // opening and closing animations are the same length. 81 // if we're in the middle of one and need to go to the other, 82 // we can start the new one mid-way through so that the door appears to 83 // simply reverse direction. 84 timeOffset = openAnimationLength - mSprite.getCurrentAnimationTime(); 85 } else { 86 if (mSolidSurface != null) { 87 parentObject.remove(mSolidSurface); 88 } 89 } 90 91 mState = STATE_OPENING; 92 mSprite.playAnimation(Animation.OPENING); 93 mSprite.setCurrentAnimationTime(timeOffset); 94 95 if (mOpenSound != null) { 96 SoundSystem sound = sSystemRegistry.soundSystem; 97 if (sound != null) { 98 sound.play(mOpenSound, false, SoundSystem.PRIORITY_NORMAL); 99 } 100 } 101 } 102 } 103 } 104 105 private void close(float timeSinceTriggered, GameObject parentObject) { 106 if (mSprite != null) { 107 final float closeAnimationLength = mSprite.findAnimation(Animation.CLOSING).getLength(); 108 109 if (timeSinceTriggered > mStayOpenTime + closeAnimationLength) { 110 // snap open. 111 mSprite.playAnimation(Animation.CLOSED); 112 mState = STATE_CLOSED; 113 if (mSolidSurface != null) { 114 parentObject.add(mSolidSurface); 115 } 116 } else { 117 float timeOffset = timeSinceTriggered - mStayOpenTime; 118 if (mState == STATE_OPENING) { 119 timeOffset = closeAnimationLength - mSprite.getCurrentAnimationTime(); 120 } 121 122 mState = STATE_CLOSING; 123 mSprite.playAnimation(Animation.CLOSING); 124 mSprite.setCurrentAnimationTime(timeOffset); 125 if (mCloseSound != null) { 126 SoundSystem sound = sSystemRegistry.soundSystem; 127 if (sound != null) { 128 sound.play(mCloseSound, false, SoundSystem.PRIORITY_NORMAL); 129 } 130 } 131 } 132 } 133 } 134 135 136 @Override 137 public void update(float timeDelta, BaseObject parent) { 138 if (mChannel != null) { 139 if (mChannel.value != null && mChannel.value instanceof ChannelSystem.ChannelFloatValue) { 140 final float lastPressedTime = ((ChannelSystem.ChannelFloatValue)mChannel.value).value; 141 TimeSystem time = sSystemRegistry.timeSystem; 142 final float gameTime = time.getGameTime(); 143 final float delta = gameTime - lastPressedTime; 144 if (delta < mStayOpenTime 145 && (mState == STATE_CLOSED || mState == STATE_CLOSING)) { 146 open(delta, (GameObject)parent); 147 148 } else if (delta > mStayOpenTime 149 && (mState == STATE_OPEN || mState == STATE_OPENING)) { 150 close(delta, (GameObject)parent); 151 } 152 } 153 } 154 if (mSprite != null) { 155 156 157 if (mState == STATE_OPENING && mSprite.animationFinished()) { 158 mSprite.playAnimation(Animation.OPEN); 159 mState = STATE_OPEN; 160 } else if (mState == STATE_CLOSING && mSprite.animationFinished()) { 161 mSprite.playAnimation(Animation.CLOSED); 162 mState = STATE_CLOSED; 163 if (mSolidSurface != null) { 164 ((GameObject)parent).add(mSolidSurface); 165 } 166 } 167 168 // Deal with the case where the animation and state are out of sync 169 // (side-effect of possession). 170 // TODO: figure out a better way to do this. 171 if (mSprite.getCurrentAnimation() == Animation.OPENING && mState == STATE_CLOSED) { 172 mSprite.playAnimation(Animation.CLOSING); 173 mState = STATE_CLOSING; 174 } 175 176 } 177 } 178 179 public void setSprite(SpriteComponent sprite) { 180 mSprite = sprite; 181 } 182 183 public void setChannel(ChannelSystem.Channel channel) { 184 mChannel = channel; 185 } 186 187 public void setSolidSurface(SolidSurfaceComponent surface) { 188 mSolidSurface = surface; 189 } 190 191 public void setStayOpenTime(float time) { 192 mStayOpenTime = time; 193 } 194 195 public void setSounds(Sound openSound, Sound closeSound) { 196 mOpenSound = openSound; 197 mCloseSound = closeSound; 198 } 199 } 200