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