Home | History | Annotate | Download | only in replicaisland
      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.GameObject.ActionType;
     20 
     21 /**
     22  * A component that allows an object to spawn other objects and apply velocity to them at
     23  * specific intervals.  Can be used to launch projectiles, particle effects, or any other type
     24  * of game object.
     25  */
     26 public class LaunchProjectileComponent extends GameComponent {
     27     private GameObjectFactory.GameObjectType mObjectTypeToSpawn;
     28     private float mOffsetX;
     29     private float mOffsetY;
     30     private float mVelocityX;
     31     private float mVelocityY;
     32     private float mThetaError;
     33     private GameObject.ActionType mRequiredAction;
     34     private float mDelayBetweenShots;
     35     private int mProjectilesInSet;
     36     private float mDelayBetweenSets;
     37     private int mSetsPerActivation;
     38     private float mDelayBeforeFirstSet;
     39 
     40     private float mLastProjectileTime;
     41     private float mSetStartedTime;
     42     private int mLaunchedCount;
     43     private int mSetCount;
     44 
     45     private boolean mTrackProjectiles;
     46     private int mMaxTrackedProjectiles;
     47     private int mTrackedProjectileCount;
     48 
     49     private Vector2 mWorkingVector;
     50 
     51     private SoundSystem.Sound mShootSound;
     52 
     53 
     54     public LaunchProjectileComponent() {
     55         super();
     56         setPhase(ComponentPhases.POST_COLLISION.ordinal());
     57         mWorkingVector = new Vector2();
     58         reset();
     59     }
     60 
     61     @Override
     62     public void reset() {
     63         mRequiredAction = ActionType.INVALID;
     64         mObjectTypeToSpawn = GameObjectFactory.GameObjectType.INVALID;
     65         mOffsetX = 0.0f;
     66         mOffsetY = 0.0f;
     67         mVelocityX = 0.0f;
     68         mVelocityY = 0.0f;
     69         mDelayBetweenShots = 0.0f;
     70         mProjectilesInSet = 0;
     71         mDelayBetweenSets = 0.0f;
     72         mLastProjectileTime = 0.0f;
     73         mSetStartedTime = -1.0f;
     74         mLaunchedCount = 0;
     75         mSetCount = 0;
     76         mSetsPerActivation = -1;
     77         mProjectilesInSet = 0;
     78         mDelayBeforeFirstSet = 0.0f;
     79         mTrackProjectiles = false;
     80         mMaxTrackedProjectiles = 0;
     81         mTrackedProjectileCount = 0;
     82         mThetaError = 0.0f;
     83         mShootSound = null;
     84     }
     85 
     86     @Override
     87     public void update(float timeDelta, BaseObject parent) {
     88         GameObject parentObject = (GameObject) parent;
     89 
     90         final TimeSystem time = sSystemRegistry.timeSystem;
     91         final float gameTime = time.getGameTime();
     92 
     93         if (mTrackedProjectileCount < mMaxTrackedProjectiles || !mTrackProjectiles) {
     94             if (parentObject.getCurrentAction() == mRequiredAction
     95                     || mRequiredAction == ActionType.INVALID) {
     96 
     97                 if (mSetStartedTime == -1.0f) {
     98                     mLaunchedCount = 0;
     99                     mLastProjectileTime = 0.0f;
    100                     mSetStartedTime = gameTime;
    101                 }
    102 
    103                 final float setDelay = mSetCount > 0 ? mDelayBetweenSets : mDelayBeforeFirstSet;
    104 
    105                 if (gameTime - mSetStartedTime >= setDelay &&
    106                         (mSetCount < mSetsPerActivation || mSetsPerActivation == -1)) {
    107                     // We can start shooting.
    108                     final float timeSinceLastShot = gameTime - mLastProjectileTime;
    109 
    110                     if (timeSinceLastShot >= mDelayBetweenShots) {
    111 
    112                         launch(parentObject);
    113                         mLastProjectileTime = gameTime;
    114 
    115                         if (mLaunchedCount >= mProjectilesInSet && mProjectilesInSet > 0) {
    116                             mSetStartedTime = -1.0f;
    117                             mSetCount++;
    118                         }
    119                     }
    120                 }
    121             } else {
    122                 // Force the timer to start counting when the right action is activated.
    123                 mSetStartedTime = -1.0f;
    124                 mSetCount = 0;
    125             }
    126         }
    127     }
    128 
    129     private void launch(GameObject parentObject) {
    130         mLaunchedCount++;
    131         GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
    132         GameObjectManager manager = sSystemRegistry.gameObjectManager;
    133         if (factory != null && manager != null) {
    134             float offsetX = mOffsetX;
    135             float offsetY = mOffsetY;
    136             boolean flip = false;
    137             if (parentObject.facingDirection.x < 0.0f) {
    138                 offsetX = parentObject.width - mOffsetX;
    139                 flip = true;
    140             }
    141 
    142             if (parentObject.facingDirection.y < 0.0f) {
    143                 offsetY = parentObject.height - mOffsetY;
    144             }
    145 
    146             final float x = parentObject.getPosition().x + offsetX;
    147             final float y = parentObject.getPosition().y + offsetY;
    148             GameObject object = factory.spawn(mObjectTypeToSpawn, x, y, flip);
    149             if (object != null) {
    150 	            mWorkingVector.set(1.0f, 1.0f);
    151 	            if (mThetaError > 0.0f) {
    152 	                final float angle = (float)(Math.random() * mThetaError * Math.PI * 2.0f);
    153 	                mWorkingVector.x = (float)Math.sin(angle);
    154 	                mWorkingVector.y = (float)Math.cos(angle);
    155 	                if (Utils.close(mWorkingVector.length2(), 0.0f)) {
    156 	                    mWorkingVector.set(1.0f, 1.0f);
    157 	                }
    158 	            }
    159 	            mWorkingVector.x *= flip ? -mVelocityX : mVelocityX;
    160 	            mWorkingVector.y *= mVelocityY;
    161 
    162 	            object.getVelocity().set(mWorkingVector);
    163 	            object.getTargetVelocity().set(mWorkingVector);
    164 	            // Center the projectile on the spawn point.
    165 	            object.getPosition().x -= object.width / 2.0f;
    166 	            object.getPosition().y -= object.height / 2.0f;
    167 
    168 
    169 	            if (mTrackProjectiles) {
    170 	                object.commitUpdates();
    171 	                LifetimeComponent projectileLife = object.findByClass(LifetimeComponent.class);
    172 	                if (projectileLife != null) {
    173 	                    projectileLife.setTrackingSpawner(this);
    174 	                    mTrackedProjectileCount++;
    175 	                }
    176 	            }
    177 	            manager.add(object);
    178 
    179 	            if (mShootSound != null) {
    180 	            	SoundSystem sound = sSystemRegistry.soundSystem;
    181 	            	if (sound != null) {
    182 	            		sound.play(mShootSound, false, SoundSystem.PRIORITY_NORMAL);
    183 	            	}
    184 	            }
    185             }
    186         }
    187 
    188 
    189     }
    190 
    191     public final void setObjectTypeToSpawn(GameObjectFactory.GameObjectType objectTypeToSpawn) {
    192         mObjectTypeToSpawn = objectTypeToSpawn;
    193     }
    194 
    195     public final void setOffsetX(float offsetX) {
    196         mOffsetX = offsetX;
    197     }
    198 
    199     public final void setOffsetY(float offsetY) {
    200         mOffsetY = offsetY;
    201     }
    202 
    203     public final void setVelocityX(float velocityX) {
    204         mVelocityX = velocityX;
    205     }
    206 
    207     public final void setVelocityY(float velocityY) {
    208         mVelocityY = velocityY;
    209     }
    210 
    211     public final void setRequiredAction(GameObject.ActionType requiredAction) {
    212         mRequiredAction = requiredAction;
    213     }
    214 
    215     public final void setDelayBetweenShots(float launchDelay) {
    216         mDelayBetweenShots = launchDelay;
    217     }
    218 
    219     public final void setDelayBetweenSets(float delayBetweenSets) {
    220         mDelayBetweenSets = delayBetweenSets;
    221     }
    222 
    223     public final void setDelayBeforeFirstSet(float delayBeforeFirstSet) {
    224         mDelayBeforeFirstSet = delayBeforeFirstSet;
    225     }
    226 
    227     public final void setShotsPerSet(int shotCount) {
    228         mProjectilesInSet = shotCount;
    229     }
    230 
    231     public final void setSetsPerActivation(int setCount) {
    232         mSetsPerActivation = setCount;
    233     }
    234 
    235     public final void enableProjectileTracking(int max) {
    236         mMaxTrackedProjectiles = max;
    237         mTrackProjectiles = true;
    238     }
    239 
    240     public final void disableProjectileTracking() {
    241         mMaxTrackedProjectiles = 0;
    242         mTrackProjectiles = false;
    243     }
    244 
    245     public final void trackedProjectileDestroyed() {
    246         assert mTrackProjectiles;
    247         if (mTrackedProjectileCount == mMaxTrackedProjectiles) {
    248             // Let's restart the set.
    249             mSetStartedTime = -1.0f;
    250             mSetCount = 0;
    251         }
    252         mTrackedProjectileCount--;
    253     }
    254 
    255     public final void setThetaError(float error) {
    256         mThetaError = error;
    257     }
    258 
    259     public final void setShootSound(SoundSystem.Sound shoot) {
    260     	mShootSound = shoot;
    261     }
    262 
    263 }
    264