1cfd74d65d832137e20e193c960802afba73b5d38sm/*
23c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Copyright (C) 2010 The Android Open Source Project
3cfd74d65d832137e20e193c960802afba73b5d38sm *
4cfd74d65d832137e20e193c960802afba73b5d38sm * Licensed under the Apache License, Version 2.0 (the "License");
5cfd74d65d832137e20e193c960802afba73b5d38sm * you may not use this file except in compliance with the License.
6cfd74d65d832137e20e193c960802afba73b5d38sm * You may obtain a copy of the License at
7cfd74d65d832137e20e193c960802afba73b5d38sm *
8cfd74d65d832137e20e193c960802afba73b5d38sm *      http://www.apache.org/licenses/LICENSE-2.0
9cfd74d65d832137e20e193c960802afba73b5d38sm *
10cfd74d65d832137e20e193c960802afba73b5d38sm * Unless required by applicable law or agreed to in writing, software
11cfd74d65d832137e20e193c960802afba73b5d38sm * distributed under the License is distributed on an "AS IS" BASIS,
12cfd74d65d832137e20e193c960802afba73b5d38sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cfd74d65d832137e20e193c960802afba73b5d38sm * See the License for the specific language governing permissions and
14cfd74d65d832137e20e193c960802afba73b5d38sm * limitations under the License.
15cfd74d65d832137e20e193c960802afba73b5d38sm */
16cfd74d65d832137e20e193c960802afba73b5d38sm
17cfd74d65d832137e20e193c960802afba73b5d38smpackage com.replica.replicaisland;
18cfd74d65d832137e20e193c960802afba73b5d38sm
19cfd74d65d832137e20e193c960802afba73b5d38sm/**
20cfd74d65d832137e20e193c960802afba73b5d38sm * A general-purpose animation selection system for animating enemy characters.  Most enemy
21cfd74d65d832137e20e193c960802afba73b5d38sm * characters behave similarly, so this code tries to decide which animation bets fits their current
22cfd74d65d832137e20e193c960802afba73b5d38sm * state.  Other code (such as enemy AI) may move these characters around and change the current
23cfd74d65d832137e20e193c960802afba73b5d38sm * ActionType, which will result in this code figuring out which sequence of animations is best to
24cfd74d65d832137e20e193c960802afba73b5d38sm * play.
25cfd74d65d832137e20e193c960802afba73b5d38sm */
26cfd74d65d832137e20e193c960802afba73b5d38smpublic class EnemyAnimationComponent extends GameComponent {
27cfd74d65d832137e20e193c960802afba73b5d38sm
28cfd74d65d832137e20e193c960802afba73b5d38sm    public enum EnemyAnimations {
29cfd74d65d832137e20e193c960802afba73b5d38sm        IDLE,
30cfd74d65d832137e20e193c960802afba73b5d38sm        MOVE,
31cfd74d65d832137e20e193c960802afba73b5d38sm        ATTACK,
32cfd74d65d832137e20e193c960802afba73b5d38sm        HIDDEN,
33cfd74d65d832137e20e193c960802afba73b5d38sm        APPEAR,
34cfd74d65d832137e20e193c960802afba73b5d38sm    }
35cfd74d65d832137e20e193c960802afba73b5d38sm
36cfd74d65d832137e20e193c960802afba73b5d38sm    private enum AnimationState {
37cfd74d65d832137e20e193c960802afba73b5d38sm        IDLING,
38cfd74d65d832137e20e193c960802afba73b5d38sm        MOVING,
39cfd74d65d832137e20e193c960802afba73b5d38sm        HIDING,
40cfd74d65d832137e20e193c960802afba73b5d38sm        APPEARING,
41cfd74d65d832137e20e193c960802afba73b5d38sm        ATTACKING
42cfd74d65d832137e20e193c960802afba73b5d38sm    }
43cfd74d65d832137e20e193c960802afba73b5d38sm
44cfd74d65d832137e20e193c960802afba73b5d38sm    private SpriteComponent mSprite;
45cfd74d65d832137e20e193c960802afba73b5d38sm    private AnimationState mState;
46cfd74d65d832137e20e193c960802afba73b5d38sm    private boolean mFacePlayer;
47cfd74d65d832137e20e193c960802afba73b5d38sm
48cfd74d65d832137e20e193c960802afba73b5d38sm    public EnemyAnimationComponent() {
49cfd74d65d832137e20e193c960802afba73b5d38sm        super();
50cfd74d65d832137e20e193c960802afba73b5d38sm        setPhase(ComponentPhases.ANIMATION.ordinal());
51cfd74d65d832137e20e193c960802afba73b5d38sm        reset();
52cfd74d65d832137e20e193c960802afba73b5d38sm    }
53cfd74d65d832137e20e193c960802afba73b5d38sm
54cfd74d65d832137e20e193c960802afba73b5d38sm    @Override
55cfd74d65d832137e20e193c960802afba73b5d38sm    public void reset() {
56cfd74d65d832137e20e193c960802afba73b5d38sm        mState = AnimationState.IDLING;
57cfd74d65d832137e20e193c960802afba73b5d38sm        mFacePlayer = false;
58cfd74d65d832137e20e193c960802afba73b5d38sm        mSprite = null;
59cfd74d65d832137e20e193c960802afba73b5d38sm    }
60cfd74d65d832137e20e193c960802afba73b5d38sm
61cfd74d65d832137e20e193c960802afba73b5d38sm    @Override
62cfd74d65d832137e20e193c960802afba73b5d38sm    public void update(float timeDelta, BaseObject parent) {
63cfd74d65d832137e20e193c960802afba73b5d38sm        if (mSprite != null) {
64cfd74d65d832137e20e193c960802afba73b5d38sm            GameObject parentObject = (GameObject) parent;
65cfd74d65d832137e20e193c960802afba73b5d38sm            final float velocityX = parentObject.getVelocity().x;
66cfd74d65d832137e20e193c960802afba73b5d38sm
67cfd74d65d832137e20e193c960802afba73b5d38sm            GameObject.ActionType currentAction = parentObject.getCurrentAction();
68cfd74d65d832137e20e193c960802afba73b5d38sm
69cfd74d65d832137e20e193c960802afba73b5d38sm            switch(mState) {
70cfd74d65d832137e20e193c960802afba73b5d38sm                case IDLING:
71cfd74d65d832137e20e193c960802afba73b5d38sm                    mSprite.playAnimation(EnemyAnimations.IDLE.ordinal());
72cfd74d65d832137e20e193c960802afba73b5d38sm                    if (mFacePlayer) {
73cfd74d65d832137e20e193c960802afba73b5d38sm                        facePlayer(parentObject);
74cfd74d65d832137e20e193c960802afba73b5d38sm                    }
75cfd74d65d832137e20e193c960802afba73b5d38sm
76cfd74d65d832137e20e193c960802afba73b5d38sm                    if (currentAction == GameObject.ActionType.ATTACK) {
77cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.ATTACKING;
78cfd74d65d832137e20e193c960802afba73b5d38sm                    } else if (currentAction == GameObject.ActionType.HIDE) {
79cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.HIDING;
80cfd74d65d832137e20e193c960802afba73b5d38sm                    } else if (Math.abs(velocityX) > 0.0f) {
81cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.MOVING;
82cfd74d65d832137e20e193c960802afba73b5d38sm                    }
83cfd74d65d832137e20e193c960802afba73b5d38sm
84cfd74d65d832137e20e193c960802afba73b5d38sm                    break;
85cfd74d65d832137e20e193c960802afba73b5d38sm
86cfd74d65d832137e20e193c960802afba73b5d38sm                case MOVING:
87cfd74d65d832137e20e193c960802afba73b5d38sm                    mSprite.playAnimation(EnemyAnimations.MOVE.ordinal());
88cfd74d65d832137e20e193c960802afba73b5d38sm                    final float targetVelocityX = parentObject.getTargetVelocity().x;
89cfd74d65d832137e20e193c960802afba73b5d38sm
90cfd74d65d832137e20e193c960802afba73b5d38sm                    if (!Utils.close(velocityX, 0.0f)) {
91cfd74d65d832137e20e193c960802afba73b5d38sm                        if (velocityX < 0.0f && targetVelocityX < 0.0f) {
92cfd74d65d832137e20e193c960802afba73b5d38sm                            parentObject.facingDirection.x = -1.0f;
93cfd74d65d832137e20e193c960802afba73b5d38sm                        } else if (velocityX > 0.0f && targetVelocityX > 0.0f) {
94cfd74d65d832137e20e193c960802afba73b5d38sm                            parentObject.facingDirection.x = 1.0f;
95cfd74d65d832137e20e193c960802afba73b5d38sm                        }
96cfd74d65d832137e20e193c960802afba73b5d38sm                    }
97cfd74d65d832137e20e193c960802afba73b5d38sm                    if (currentAction == GameObject.ActionType.ATTACK) {
98cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.ATTACKING;
99cfd74d65d832137e20e193c960802afba73b5d38sm                    } else if (currentAction == GameObject.ActionType.HIDE) {
100cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.HIDING;
101cfd74d65d832137e20e193c960802afba73b5d38sm                    } else if (Math.abs(velocityX) == 0.0f) {
102cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.IDLING;
103cfd74d65d832137e20e193c960802afba73b5d38sm                    }
104cfd74d65d832137e20e193c960802afba73b5d38sm                    break;
105cfd74d65d832137e20e193c960802afba73b5d38sm                case ATTACKING:
106cfd74d65d832137e20e193c960802afba73b5d38sm                    mSprite.playAnimation(EnemyAnimations.ATTACK.ordinal());
107cfd74d65d832137e20e193c960802afba73b5d38sm                    if (currentAction != GameObject.ActionType.ATTACK
108cfd74d65d832137e20e193c960802afba73b5d38sm                            && mSprite.animationFinished()) {
109cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.IDLING;
110cfd74d65d832137e20e193c960802afba73b5d38sm                    }
111cfd74d65d832137e20e193c960802afba73b5d38sm                    break;
112cfd74d65d832137e20e193c960802afba73b5d38sm                case HIDING:
113cfd74d65d832137e20e193c960802afba73b5d38sm                    mSprite.playAnimation(EnemyAnimations.HIDDEN.ordinal());
114cfd74d65d832137e20e193c960802afba73b5d38sm                    if (currentAction != GameObject.ActionType.HIDE) {
115cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.APPEARING;
116cfd74d65d832137e20e193c960802afba73b5d38sm                    }
117cfd74d65d832137e20e193c960802afba73b5d38sm                    break;
118cfd74d65d832137e20e193c960802afba73b5d38sm                case APPEARING:
119cfd74d65d832137e20e193c960802afba73b5d38sm                    if (mFacePlayer) {
120cfd74d65d832137e20e193c960802afba73b5d38sm                        facePlayer(parentObject);
121cfd74d65d832137e20e193c960802afba73b5d38sm                    }
122cfd74d65d832137e20e193c960802afba73b5d38sm
123cfd74d65d832137e20e193c960802afba73b5d38sm                    mSprite.playAnimation(EnemyAnimations.APPEAR.ordinal());
124cfd74d65d832137e20e193c960802afba73b5d38sm                    if (mSprite.animationFinished()) {
125cfd74d65d832137e20e193c960802afba73b5d38sm                        mState = AnimationState.IDLING;
126cfd74d65d832137e20e193c960802afba73b5d38sm                    }
127cfd74d65d832137e20e193c960802afba73b5d38sm                    break;
128cfd74d65d832137e20e193c960802afba73b5d38sm
129cfd74d65d832137e20e193c960802afba73b5d38sm            }
130cfd74d65d832137e20e193c960802afba73b5d38sm
131cfd74d65d832137e20e193c960802afba73b5d38sm
132cfd74d65d832137e20e193c960802afba73b5d38sm        }
133cfd74d65d832137e20e193c960802afba73b5d38sm    }
134cfd74d65d832137e20e193c960802afba73b5d38sm
135cfd74d65d832137e20e193c960802afba73b5d38sm    private void facePlayer(GameObject parentObject) {
136cfd74d65d832137e20e193c960802afba73b5d38sm        GameObjectManager manager = sSystemRegistry.gameObjectManager;
137cfd74d65d832137e20e193c960802afba73b5d38sm        if (manager != null) {
138cfd74d65d832137e20e193c960802afba73b5d38sm            GameObject player = manager.getPlayer();
139cfd74d65d832137e20e193c960802afba73b5d38sm            if (player != null) {
140cfd74d65d832137e20e193c960802afba73b5d38sm                if (player.getPosition().x < parentObject.getPosition().x) {
141cfd74d65d832137e20e193c960802afba73b5d38sm                    parentObject.facingDirection.x = -1.0f;
142cfd74d65d832137e20e193c960802afba73b5d38sm                } else {
143cfd74d65d832137e20e193c960802afba73b5d38sm                    parentObject.facingDirection.x = 1.0f;
144cfd74d65d832137e20e193c960802afba73b5d38sm                }
145cfd74d65d832137e20e193c960802afba73b5d38sm            }
146cfd74d65d832137e20e193c960802afba73b5d38sm        }
147cfd74d65d832137e20e193c960802afba73b5d38sm    }
148cfd74d65d832137e20e193c960802afba73b5d38sm
149cfd74d65d832137e20e193c960802afba73b5d38sm    public void setSprite(SpriteComponent sprite) {
150cfd74d65d832137e20e193c960802afba73b5d38sm        mSprite = sprite;
151cfd74d65d832137e20e193c960802afba73b5d38sm    }
152cfd74d65d832137e20e193c960802afba73b5d38sm
153cfd74d65d832137e20e193c960802afba73b5d38sm    public void setFacePlayer(boolean facePlayer) {
154cfd74d65d832137e20e193c960802afba73b5d38sm        mFacePlayer = facePlayer;
155cfd74d65d832137e20e193c960802afba73b5d38sm    }
156cfd74d65d832137e20e193c960802afba73b5d38sm}
157