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
19import com.replica.replicaisland.SoundSystem.Sound;
20
21public 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