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
17package com.replica.replicaisland;
18
19import com.replica.replicaisland.GameObject.ActionType;
20import com.replica.replicaisland.SoundSystem.Sound;
21
22public class LauncherComponent extends GameComponent {
23    private final static float DEFAULT_LAUNCH_DELAY = 2.0f;
24    private final static float DEFAULT_LAUNCH_MAGNITUDE = 2000.0f;
25    private final static float DEFAULT_POST_LAUNCH_DELAY = 1.0f;
26    private GameObject mShot;
27    private float mLaunchTime;
28    private float mAngle;
29    private float mLaunchDelay;
30    private Vector2 mLaunchDirection;
31    private float mLaunchMagnitude;
32    private float mPostLaunchDelay;
33    private boolean mDriveActions;
34    private GameObjectFactory.GameObjectType mLaunchEffect;
35    private float mLaunchEffectOffsetX;
36    private float mLaunchEffectOffsetY;
37    private Sound mLaunchSound;
38
39    public LauncherComponent() {
40        super();
41        mLaunchDirection = new Vector2();
42        reset();
43        setPhase(ComponentPhases.THINK.ordinal());
44    }
45
46    @Override
47    public void reset() {
48        mShot = null;
49        mLaunchTime = 0.0f;
50        mAngle = 0.0f;
51        mLaunchDelay = DEFAULT_LAUNCH_DELAY;
52        mLaunchMagnitude = DEFAULT_LAUNCH_MAGNITUDE;
53        mPostLaunchDelay = DEFAULT_POST_LAUNCH_DELAY;
54        mDriveActions = true;
55        mLaunchEffect = GameObjectFactory.GameObjectType.INVALID;
56        mLaunchEffectOffsetX = 0.0f;
57        mLaunchEffectOffsetY = 0.0f;
58        mLaunchSound = null;
59    }
60
61    @Override
62    public void update(float timeDelta, BaseObject parent) {
63        final TimeSystem time = sSystemRegistry.timeSystem;
64        final float gameTime = time.getGameTime();
65        GameObject parentObject = (GameObject)parent;
66
67        if (mShot != null) {
68            if (mShot.life <= 0) {
69                // Looks like the shot is dead.  Let's forget about it.
70                // TODO: this is unreliable.  We should have a "notify on death" event or something.
71                mShot = null;
72            } else {
73                if (gameTime > mLaunchTime) {
74                    fire(mShot, parentObject, mAngle);
75                    mShot = null;
76                    if (mDriveActions) {
77                    	parentObject.setCurrentAction(ActionType.ATTACK);
78                    }
79                } else {
80                    mShot.setPosition(parentObject.getPosition());
81                }
82            }
83        } else if (gameTime > mLaunchTime + mPostLaunchDelay) {
84        	if (mDriveActions) {
85        		parentObject.setCurrentAction(ActionType.IDLE);
86        	}
87        }
88    }
89
90    public void prepareToLaunch(GameObject object, GameObject parentObject) {
91        if (mShot != object) {
92            if (mShot != null) {
93                // We already have a shot loaded and we are asked to shoot something else.
94                // Shoot the current shot off and then load the new one.
95                fire(mShot, parentObject, mAngle);
96            }
97            final TimeSystem time = sSystemRegistry.timeSystem;
98            final float gameTime = time.getGameTime();
99            mShot = object;
100            mLaunchTime = gameTime + mLaunchDelay;
101        }
102    }
103
104    private void fire(GameObject object, GameObject parentObject, float mAngle) {
105        if (mDriveActions) {
106        	object.setCurrentAction(ActionType.MOVE);
107        }
108        mLaunchDirection.set((float)Math.sin(mAngle), (float)Math.cos(mAngle));
109        mLaunchDirection.multiply(parentObject.facingDirection);
110        mLaunchDirection.multiply(mLaunchMagnitude);
111        object.setVelocity(mLaunchDirection);
112
113        if (mLaunchSound != null) {
114        	SoundSystem sound = sSystemRegistry.soundSystem;
115        	if (sound != null) {
116        		sound.play(mLaunchSound, false, SoundSystem.PRIORITY_NORMAL);
117        	}
118        }
119
120        if (mLaunchEffect != GameObjectFactory.GameObjectType.INVALID) {
121        	GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
122        	GameObjectManager manager = sSystemRegistry.gameObjectManager;
123        	if (factory != null && manager != null) {
124        		final Vector2 position = parentObject.getPosition();
125
126        		GameObject effect = factory.spawn(mLaunchEffect,
127        				position.x + (mLaunchEffectOffsetX * parentObject.facingDirection.x),
128        				position.y + (mLaunchEffectOffsetY * parentObject.facingDirection.y),
129        				false);
130        		if (effect != null) {
131        			manager.add(effect);
132        		}
133        	}
134        }
135    }
136
137    public void setup(float angle, float magnitude, float launchDelay, float postLaunchDelay, boolean driveActions) {
138    	mAngle = angle;
139    	mLaunchMagnitude = magnitude;
140    	mLaunchDelay = launchDelay;
141    	mPostLaunchDelay = postLaunchDelay;
142    	mDriveActions = driveActions;
143    }
144
145    public void setLaunchEffect(GameObjectFactory.GameObjectType effectType, float offsetX, float offsetY) {
146    	mLaunchEffect = effectType;
147    	mLaunchEffectOffsetX = offsetX;
148    	mLaunchEffectOffsetY = offsetY;
149    }
150
151    public void setLaunchSound(Sound sound) {
152    	mLaunchSound = sound;
153    }
154
155}
156