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
19cfd74d65d832137e20e193c960802afba73b5d38smimport com.replica.replicaisland.SoundSystem.Sound;
20cfd74d65d832137e20e193c960802afba73b5d38sm
21cfd74d65d832137e20e193c960802afba73b5d38sm/**
22cfd74d65d832137e20e193c960802afba73b5d38sm * This component allows objects to die and be deleted when their life is reduced to zero or they
23cfd74d65d832137e20e193c960802afba73b5d38sm * meet other configurable criteria.
24cfd74d65d832137e20e193c960802afba73b5d38sm */
25cfd74d65d832137e20e193c960802afba73b5d38smpublic class LifetimeComponent extends GameComponent {
26cfd74d65d832137e20e193c960802afba73b5d38sm    private boolean mDieWhenInvisible;
27cfd74d65d832137e20e193c960802afba73b5d38sm    private float mTimeUntilDeath;
28cfd74d65d832137e20e193c960802afba73b5d38sm    private GameObjectFactory.GameObjectType mSpawnOnDeathType;
29cfd74d65d832137e20e193c960802afba73b5d38sm    private LaunchProjectileComponent mTrackingSpawner;
30cfd74d65d832137e20e193c960802afba73b5d38sm    private Vector2 mHotSpotTestPoint;
31cfd74d65d832137e20e193c960802afba73b5d38sm    private boolean mReleaseGhostOnDeath;
32cfd74d65d832137e20e193c960802afba73b5d38sm    private boolean mVulnerableToDeathTiles;
33cfd74d65d832137e20e193c960802afba73b5d38sm    private boolean mDieOnHitBackground;
34cfd74d65d832137e20e193c960802afba73b5d38sm    private Sound mDeathSound;
352b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm    private boolean mIncrementEventCounter;
362b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm    private int mEventCounter;
37cfd74d65d832137e20e193c960802afba73b5d38sm
38cfd74d65d832137e20e193c960802afba73b5d38sm    public LifetimeComponent() {
39cfd74d65d832137e20e193c960802afba73b5d38sm        super();
40cfd74d65d832137e20e193c960802afba73b5d38sm        mHotSpotTestPoint = new Vector2();
41cfd74d65d832137e20e193c960802afba73b5d38sm        reset();
42cfd74d65d832137e20e193c960802afba73b5d38sm        setPhase(ComponentPhases.THINK.ordinal());
43cfd74d65d832137e20e193c960802afba73b5d38sm    }
44cfd74d65d832137e20e193c960802afba73b5d38sm
45cfd74d65d832137e20e193c960802afba73b5d38sm    @Override
46cfd74d65d832137e20e193c960802afba73b5d38sm    public void reset() {
47cfd74d65d832137e20e193c960802afba73b5d38sm        mDieWhenInvisible = false;
48cfd74d65d832137e20e193c960802afba73b5d38sm        mTimeUntilDeath = -1;
49cfd74d65d832137e20e193c960802afba73b5d38sm        mSpawnOnDeathType = GameObjectFactory.GameObjectType.INVALID;
50cfd74d65d832137e20e193c960802afba73b5d38sm        mTrackingSpawner = null;
51cfd74d65d832137e20e193c960802afba73b5d38sm        mHotSpotTestPoint.zero();
52cfd74d65d832137e20e193c960802afba73b5d38sm        mReleaseGhostOnDeath = true;
53cfd74d65d832137e20e193c960802afba73b5d38sm        mVulnerableToDeathTiles = false;
54cfd74d65d832137e20e193c960802afba73b5d38sm        mDieOnHitBackground = false;
55cfd74d65d832137e20e193c960802afba73b5d38sm        mDeathSound = null;
562b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        mIncrementEventCounter = false;
572b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        mEventCounter = -1;
58cfd74d65d832137e20e193c960802afba73b5d38sm    }
59cfd74d65d832137e20e193c960802afba73b5d38sm
60cfd74d65d832137e20e193c960802afba73b5d38sm    public void setDieWhenInvisible(boolean die) {
61cfd74d65d832137e20e193c960802afba73b5d38sm        mDieWhenInvisible = die;
62cfd74d65d832137e20e193c960802afba73b5d38sm    }
63cfd74d65d832137e20e193c960802afba73b5d38sm
64cfd74d65d832137e20e193c960802afba73b5d38sm    public void setTimeUntilDeath(float time) {
65cfd74d65d832137e20e193c960802afba73b5d38sm        mTimeUntilDeath = time;
66cfd74d65d832137e20e193c960802afba73b5d38sm    }
67cfd74d65d832137e20e193c960802afba73b5d38sm
68cfd74d65d832137e20e193c960802afba73b5d38sm    public void setObjectToSpawnOnDeath(GameObjectFactory.GameObjectType type) {
69cfd74d65d832137e20e193c960802afba73b5d38sm        mSpawnOnDeathType = type;
70cfd74d65d832137e20e193c960802afba73b5d38sm    }
71cfd74d65d832137e20e193c960802afba73b5d38sm
722b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm    public void setIncrementEventCounter(int event) {
732b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm    	mIncrementEventCounter = true;
742b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm    	mEventCounter = event;
752b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm    }
762b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
77cfd74d65d832137e20e193c960802afba73b5d38sm    @Override
78cfd74d65d832137e20e193c960802afba73b5d38sm    public void update(float timeDelta, BaseObject parent) {
79cfd74d65d832137e20e193c960802afba73b5d38sm        GameObject parentObject = (GameObject)parent;
80cfd74d65d832137e20e193c960802afba73b5d38sm        if (mTimeUntilDeath > 0) {
81cfd74d65d832137e20e193c960802afba73b5d38sm            mTimeUntilDeath -= timeDelta;
82cfd74d65d832137e20e193c960802afba73b5d38sm            if (mTimeUntilDeath <= 0) {
83cfd74d65d832137e20e193c960802afba73b5d38sm                die(parentObject);
84cfd74d65d832137e20e193c960802afba73b5d38sm                return;
85cfd74d65d832137e20e193c960802afba73b5d38sm            }
86cfd74d65d832137e20e193c960802afba73b5d38sm        }
87cfd74d65d832137e20e193c960802afba73b5d38sm
88cfd74d65d832137e20e193c960802afba73b5d38sm        if (mDieWhenInvisible) {
89cfd74d65d832137e20e193c960802afba73b5d38sm            CameraSystem camera = sSystemRegistry.cameraSystem;
90cfd74d65d832137e20e193c960802afba73b5d38sm            ContextParameters context = sSystemRegistry.contextParameters;
91cfd74d65d832137e20e193c960802afba73b5d38sm            final float dx =
92cfd74d65d832137e20e193c960802afba73b5d38sm                Math.abs(parentObject.getPosition().x - camera.getFocusPositionX());
93cfd74d65d832137e20e193c960802afba73b5d38sm            final float dy =
94cfd74d65d832137e20e193c960802afba73b5d38sm                Math.abs(parentObject.getPosition().y - camera.getFocusPositionY());
95cfd74d65d832137e20e193c960802afba73b5d38sm            if (dx > context.gameWidth || dy > context.gameHeight) {
96cfd74d65d832137e20e193c960802afba73b5d38sm                // the position of this object is off the screen, destroy!
97cfd74d65d832137e20e193c960802afba73b5d38sm                // TODO: this is a pretty dumb test.  We should have a bounding volume instead.
98cfd74d65d832137e20e193c960802afba73b5d38sm                die(parentObject);
99cfd74d65d832137e20e193c960802afba73b5d38sm                return;
100cfd74d65d832137e20e193c960802afba73b5d38sm            }
101cfd74d65d832137e20e193c960802afba73b5d38sm        }
102cfd74d65d832137e20e193c960802afba73b5d38sm
103cfd74d65d832137e20e193c960802afba73b5d38sm        if (parentObject.life > 0 && mVulnerableToDeathTiles) {
104cfd74d65d832137e20e193c960802afba73b5d38sm            HotSpotSystem hotSpot = sSystemRegistry.hotSpotSystem;
105cfd74d65d832137e20e193c960802afba73b5d38sm            if (hotSpot != null) {
106cfd74d65d832137e20e193c960802afba73b5d38sm                // TODO: HACK!  Unify all this code.
107cfd74d65d832137e20e193c960802afba73b5d38sm                if (hotSpot.getHotSpot(parentObject.getCenteredPositionX(),
108cfd74d65d832137e20e193c960802afba73b5d38sm                        parentObject.getPosition().y + 10.0f) == HotSpotSystem.HotSpotType.DIE) {
109cfd74d65d832137e20e193c960802afba73b5d38sm                    parentObject.life = 0;
110cfd74d65d832137e20e193c960802afba73b5d38sm                }
111cfd74d65d832137e20e193c960802afba73b5d38sm            }
112cfd74d65d832137e20e193c960802afba73b5d38sm        }
113cfd74d65d832137e20e193c960802afba73b5d38sm
114cfd74d65d832137e20e193c960802afba73b5d38sm        if (parentObject.life > 0 && mDieOnHitBackground) {
115cfd74d65d832137e20e193c960802afba73b5d38sm        	if (parentObject.getBackgroundCollisionNormal().length2() > 0.0f) {
116cfd74d65d832137e20e193c960802afba73b5d38sm        		parentObject.life = 0;
117cfd74d65d832137e20e193c960802afba73b5d38sm        	}
118cfd74d65d832137e20e193c960802afba73b5d38sm        }
119cfd74d65d832137e20e193c960802afba73b5d38sm
120cfd74d65d832137e20e193c960802afba73b5d38sm        if (parentObject.life <= 0) {
121cfd74d65d832137e20e193c960802afba73b5d38sm            die(parentObject);
122cfd74d65d832137e20e193c960802afba73b5d38sm            return;
123cfd74d65d832137e20e193c960802afba73b5d38sm        }
124cfd74d65d832137e20e193c960802afba73b5d38sm    }
125cfd74d65d832137e20e193c960802afba73b5d38sm
126cfd74d65d832137e20e193c960802afba73b5d38sm    private void die(GameObject parentObject) {
127cfd74d65d832137e20e193c960802afba73b5d38sm        GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
128cfd74d65d832137e20e193c960802afba73b5d38sm        GameObjectManager manager = sSystemRegistry.gameObjectManager;
129cfd74d65d832137e20e193c960802afba73b5d38sm
130cfd74d65d832137e20e193c960802afba73b5d38sm        if (mReleaseGhostOnDeath) {
131cfd74d65d832137e20e193c960802afba73b5d38sm            // TODO: This is sort of a hack.  Find a better way to do this without introducing a
132cfd74d65d832137e20e193c960802afba73b5d38sm            // dependency between these two.  Generic on-death event or something.
133cfd74d65d832137e20e193c960802afba73b5d38sm            GhostComponent ghost = parentObject.findByClass(GhostComponent.class);
134cfd74d65d832137e20e193c960802afba73b5d38sm            if (ghost != null) {
135cfd74d65d832137e20e193c960802afba73b5d38sm                ghost.releaseControl(parentObject);
136cfd74d65d832137e20e193c960802afba73b5d38sm            }
137cfd74d65d832137e20e193c960802afba73b5d38sm        }
1382b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
1392b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        if (mIncrementEventCounter) {
1402b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        	EventRecorder recorder = sSystemRegistry.eventRecorder;
1412b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        	recorder.incrementEventCounter(mEventCounter);
1422b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm        }
143cfd74d65d832137e20e193c960802afba73b5d38sm
144cfd74d65d832137e20e193c960802afba73b5d38sm        if (mSpawnOnDeathType != GameObjectFactory.GameObjectType.INVALID) {
145cfd74d65d832137e20e193c960802afba73b5d38sm            GameObject object = factory.spawn(mSpawnOnDeathType, parentObject.getPosition().x,
146cfd74d65d832137e20e193c960802afba73b5d38sm                    parentObject.getPosition().y, parentObject.facingDirection.x < 0.0f);
147cfd74d65d832137e20e193c960802afba73b5d38sm
148cfd74d65d832137e20e193c960802afba73b5d38sm            if (object != null && manager != null) {
149cfd74d65d832137e20e193c960802afba73b5d38sm                manager.add(object);
150cfd74d65d832137e20e193c960802afba73b5d38sm            }
151cfd74d65d832137e20e193c960802afba73b5d38sm
152cfd74d65d832137e20e193c960802afba73b5d38sm        }
153cfd74d65d832137e20e193c960802afba73b5d38sm
154cfd74d65d832137e20e193c960802afba73b5d38sm        if (mTrackingSpawner != null) {
155cfd74d65d832137e20e193c960802afba73b5d38sm            mTrackingSpawner.trackedProjectileDestroyed();
156cfd74d65d832137e20e193c960802afba73b5d38sm        }
157cfd74d65d832137e20e193c960802afba73b5d38sm
1582b1168acefb6a4104bb7f008df6ac51fcd1de7ecsm
159cfd74d65d832137e20e193c960802afba73b5d38sm        if (manager != null) {
160cfd74d65d832137e20e193c960802afba73b5d38sm            manager.destroy(parentObject);
161cfd74d65d832137e20e193c960802afba73b5d38sm        }
162cfd74d65d832137e20e193c960802afba73b5d38sm
163cfd74d65d832137e20e193c960802afba73b5d38sm        if (mDeathSound != null) {
164cfd74d65d832137e20e193c960802afba73b5d38sm        	SoundSystem sound = sSystemRegistry.soundSystem;
165cfd74d65d832137e20e193c960802afba73b5d38sm        	if (sound != null) {
166cfd74d65d832137e20e193c960802afba73b5d38sm        		sound.play(mDeathSound, false, SoundSystem.PRIORITY_NORMAL);
167cfd74d65d832137e20e193c960802afba73b5d38sm        	}
168cfd74d65d832137e20e193c960802afba73b5d38sm        }
169cfd74d65d832137e20e193c960802afba73b5d38sm
170cfd74d65d832137e20e193c960802afba73b5d38sm    }
171cfd74d65d832137e20e193c960802afba73b5d38sm
172cfd74d65d832137e20e193c960802afba73b5d38sm    public final void setTrackingSpawner(LaunchProjectileComponent spawner) {
173cfd74d65d832137e20e193c960802afba73b5d38sm        mTrackingSpawner = spawner;
174cfd74d65d832137e20e193c960802afba73b5d38sm    }
175cfd74d65d832137e20e193c960802afba73b5d38sm
176cfd74d65d832137e20e193c960802afba73b5d38sm    public final void setReleaseGhostOnDeath(boolean release) {
177cfd74d65d832137e20e193c960802afba73b5d38sm        mReleaseGhostOnDeath = release;
178cfd74d65d832137e20e193c960802afba73b5d38sm    }
179cfd74d65d832137e20e193c960802afba73b5d38sm
180cfd74d65d832137e20e193c960802afba73b5d38sm    public final void setVulnerableToDeathTiles(boolean vulnerable) {
181cfd74d65d832137e20e193c960802afba73b5d38sm        mVulnerableToDeathTiles = vulnerable;
182cfd74d65d832137e20e193c960802afba73b5d38sm    }
183cfd74d65d832137e20e193c960802afba73b5d38sm
184cfd74d65d832137e20e193c960802afba73b5d38sm    public final void setDieOnHitBackground(boolean die) {
185cfd74d65d832137e20e193c960802afba73b5d38sm    	mDieOnHitBackground = die;
186cfd74d65d832137e20e193c960802afba73b5d38sm    }
187cfd74d65d832137e20e193c960802afba73b5d38sm
188cfd74d65d832137e20e193c960802afba73b5d38sm    public final void setDeathSound(Sound deathSound) {
189cfd74d65d832137e20e193c960802afba73b5d38sm    	mDeathSound = deathSound;
190cfd74d65d832137e20e193c960802afba73b5d38sm    }
191cfd74d65d832137e20e193c960802afba73b5d38sm}
192