/// <summary>
        /// Kills this object, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    // play the explosion sound
                    AudioManager.PlaySoundEffect("explosion_medium");

                    // display the rocket explosion
                    if (ParticleEffectManager != null)
                    {
                        ParticleEffectManager.SpawnEffect(
                            ParticleEffectType.RocketExplosion, Position);
                    }
                }

                // stop the rocket-flying sound effect
                if (rocketSound != null)
                {
                    rocketSound.Stop(true);
                    rocketSound.Dispose();
                    rocketSound = null;
                }

                // stop the rocket-trail effect
                if (rocketTrailEffect != null)
                {
                    rocketTrailEffect.Stop(false);
                }
            }

            base.Die(source, cleanupOnly);
        }
Example #2
0
        /// <summary>
        /// Update the particle effect.
        /// </summary>
        /// <param name="elapsedTime">The amount of elapsed time, in seconds.</param>
        public virtual void Update(float elapsedTime)
        {
            // update the position based on the follow-object, if any
            if (followObject != null)
            {
                if (followObject.Active)
                {
                    Position = followObject.Position;
                }
                else
                {
                    followObject = null;
                    Stop(false);
                }
            }

            // update each system
            active = false;
            for (int i = 0; i < particleSystems.Count; ++i)
            {
                if (particleSystems[i].Active)
                {
                    particleSystems[i].Update(elapsedTime);
                    active = true;
                }
            }
        }
Example #3
0
        /// <summary>
        /// Defines the interaction between this projectile and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // check the target, if we have one
            if (target != null)
            {
                // don't bother hitting any power-ups
                if (target is PowerUp)
                {
                    return(false);
                }
                // don't hit the owner if the damageOwner flag isn't set
                if ((this.damageOwner == false) && (target == owner))
                {
                    return(false);
                }
                // don't hit other projectiles from the same ship
                Projectile projectile = target as Projectile;
                if ((projectile != null) && (projectile.Owner == this.Owner))
                {
                    return(false);
                }
                // damage the target
                target.Damage(this, this.damageAmount);
            }

            // either we hit something or the target is null - in either case, die
            Die(target, false);

            return(base.Touch(target));
        }
Example #4
0
        /// <summary>
        /// Kills this ship, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    // update the score
                    Ship ship = source as Ship;
                    if (ship == null)
                    {
                        Projectile projectile = source as Projectile;
                        if (projectile != null)
                        {
                            ship = projectile.Owner;
                        }
                    }
                    if (ship != null)
                    {
                        if (ship == this)
                        {
                            // reduce the score, since i blew myself up
                            ship.Score--;
                        }
                        else
                        {
                            // add score to the ship who shot this object
                            ship.Score++;
                        }
                    }
                    else
                    {
                        // if it wasn't a ship, then this object loses score
                        this.Score--;
                    }

                    // play the player-death sound
                    AudioManager.PlaySoundEffect("explosion_shockwave");
                    AudioManager.PlaySoundEffect("explosion_large");

                    // display the ship explosion
                    if (ParticleEffectManager != null)
                    {
                        ParticleEffectManager.SpawnEffect(
                            ParticleEffectType.ShipExplosion, Position);
                    }
                }

                // clear out the projectiles list
                foreach (Projectile projectile in projectiles)
                {
                    projectile.Die(null, true);
                }
                projectiles.Clear();

                // set the respawn timer
                respawnTimer = respawnTimerOnDeath;
            }

            base.Die(source, cleanupOnly);
        }
Example #5
0
        /// <summary>
        /// Defines the interaction between the asteroid and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // if the asteroid has touched a player, then damage it
            Ship player = target as Ship;

            if (player != null)
            {
                // calculate damage as a function of how much the two GameplayObject's
                // velocities were going towards one another
                Vector2 playerAsteroidVector = Position - player.Position;
                if (playerAsteroidVector.LengthSquared() > 0)
                {
                    playerAsteroidVector.Normalize();

                    float rammingSpeed =
                        Vector2.Dot(playerAsteroidVector, player.Velocity) -
                        Vector2.Dot(playerAsteroidVector, Velocity);
                    float momentum = Mass * rammingSpeed;
                    player.Damage(this, momentum * momentumToDamageScalar);
                }
            }
            // if the asteroid didn't hit a projectile, play the asteroid-touch sound effect
            if ((target is Projectile) == false)
            {
                AudioManager.PlaySoundEffect("asteroid_touch");
            }
            return(true);
        }
 /// <summary>
 /// Kills this object, in response to the given GameplayObject.
 /// </summary>
 /// <param name="source">The GameplayObject responsible for the kill.</param>
 /// <param name="cleanupOnly">
 /// If true, the object dies without any further effects.
 /// </param>
 public virtual void Die(GameplayObject source, bool cleanupOnly)
 {
     // deactivate the object
     if (active)
     {
         active = false;
         CollisionManager.Collection.QueuePendingRemoval(this);
     }
 }
        /// <summary>
        /// Defines the interaction between this power-up and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // if we hit a ship, give it the weapon
            Ship ship = target as Ship;
            if (ship != null)
            {
                ship.Weapon = new DoubleLaserWeapon(ship);
            }

            return base.Touch(target);
        }
        /// <summary>
        /// Spawn a new particle effect at a the position of a given gameplay object
        /// </summary>
        /// <param name="effectType">The effect in question.</param>
        /// <param name="actor">The gameplay object.</param>
        /// <returns>The new particle effect.</returns>
        public ParticleEffect SpawnEffect(ParticleEffectType effectType,
                                          GameplayObject gameplayObject)
        {
            // safety-check the parameter
            if (gameplayObject == null)
            {
                throw new ArgumentNullException("gameplayObject");
            }

            return(SpawnEffect(effectType, gameplayObject.Position, gameplayObject));
        }
Example #9
0
        /// <summary>
        /// Defines the interaction between this power-up and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // if we hit a ship, give it the weapon
            Ship ship = target as Ship;

            if (ship != null)
            {
                ship.Weapon = new DoubleLaserWeapon(ship);
            }

            return(base.Touch(target));
        }
Example #10
0
        /// <summary>
        /// Kills this projectile, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    CollisionManager.Explode(this, source, damageAmount, Position,
                                             damageRadius, damageOwner);
                }
            }

            base.Die(source, cleanupOnly);
        }
        /// <summary>
        /// Kills this object, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                // display the laser explosion
                if (!cleanupOnly && (ParticleEffectManager != null))
                {
                    ParticleEffectManager.SpawnEffect(ParticleEffectType.LaserExplosion,
                                                      Position);
                }
            }

            base.Die(source, cleanupOnly);
        }
Example #12
0
        /// <summary>
        /// Defines the interaction between this power-up and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // if it touched a ship, then create a particle system and play a sound
            Ship ship = target as Ship;

            if (ship != null)
            {
                // play the "power-up picked up" sound effect
                AudioManager.PlaySoundEffect("powerup_touch");

                // kill the power-up
                Die(target, false);

                // the ship keeps going as if it didn't hit anything
                return(false);
            }

            return(base.Touch(target));
        }
Example #13
0
        /// <summary>
        /// Kills this object, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    // play the explosion sound effect
                    AudioManager.PlaySoundEffect("explosion_large");

                    // play the mine particle-effect
                    if (ParticleEffectManager != null)
                    {
                        ParticleEffectManager.SpawnEffect(
                            ParticleEffectType.MineExplosion, Position);
                    }
                }
            }

            base.Die(source, cleanupOnly);
        }
Example #14
0
        /// <summary>
        /// Damage this ship by the amount provided.
        /// </summary>
        /// <remarks>
        /// This function is provided in lieu of a Life mutation property to allow
        /// classes of objects to restrict which kinds of objects may damage them,
        /// and under what circumstances they may be damaged.
        /// </remarks>
        /// <param name="source">The GameplayObject responsible for the damage.</param>
        /// <param name="damageAmount">The amount of damage.</param>
        /// <returns>If true, this object was damaged.</returns>
        public override bool Damage(GameplayObject source, float damageAmount)
        {
            // if the safe timer hasn't yet gone off, then the ship can't be hurt
            if ((safeTimer > 0f) || (damageAmount <= 0f))
            {
                return(false);
            }

            // once you're hit, the shield-recharge timer starts over
            shieldRechargeTimer = 2.5f;

            // damage the shield first, then life
            if (shield <= 0f)
            {
                life -= damageAmount;
            }
            else
            {
                shield -= damageAmount;
                if (shield < 0f)
                {
                    // shield has the overflow value as a negative value, just add it
                    life  += shield;
                    shield = 0f;
                }
            }

            Projectile sourceAsProjectile = source as Projectile;

            if (sourceAsProjectile != null)
            {
                lastDamagedBy = sourceAsProjectile.Owner;
            }
            else
            {
                lastDamagedBy = source;
            }

            return(true);
        }
        /// <summary>
        /// Spawn a new particle effect at a given location and gameplay object
        /// </summary>
        /// <param name="effectType">The effect in question.</param>
        /// <param name="position">The position of the effect.</param>
        /// <param name="actor">The gameplay object.</param>
        /// <returns>The new particle effect.</returns>
        public ParticleEffect SpawnEffect(ParticleEffectType effectType,
                                          Vector2 position, GameplayObject gameplayObject)
        {
            ParticleEffect particleEffect = null;

            if (particleEffectCache.ContainsKey(effectType) == true)
            {
                List <ParticleEffect> availableSystems = particleEffectCache[effectType];

                for (int i = 0; i < availableSystems.Count; ++i)
                {
                    if (availableSystems[i].Active == false)
                    {
                        particleEffect = availableSystems[i];
                        break;
                    }
                }

                if (particleEffect == null)
                {
                    particleEffect = availableSystems[0].Clone();
                    particleEffect.Initialize(contentManager);
                    availableSystems.Add(particleEffect);
                }
            }

            if (particleEffect != null)
            {
                particleEffect.Reset();
                particleEffect.GameplayObject = gameplayObject;
                particleEffect.Position       = position;
                activeParticleEffects.Add(particleEffect);
            }

            return(particleEffect);
        }
Example #16
0
        /// <summary>
        /// Kills this projectile, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    CollisionManager.Explode(this, source, damageAmount, Position,
                        damageRadius, damageOwner);
                }
            }

            base.Die(source, cleanupOnly);
        }
Example #17
0
        /// <summary>
        /// Defines the interaction between this projectile and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // check the target, if we have one
            if (target != null)
            {
                // don't bother hitting any power-ups
                if (target is PowerUp)
                {
                    return false;
                }
                // don't hit the owner if the damageOwner flag isn't set
                if ((this.damageOwner == false) && (target == owner))
                {
                    return false;
                }
                // don't hit other projectiles from the same ship
                Projectile projectile = target as Projectile;
                if ((projectile != null) && (projectile.Owner == this.Owner))
                {
                    return false;
                }
                // damage the target
                target.Damage(this, this.damageAmount);
            }

            // either we hit something or the target is null - in either case, die
            Die(target, false);
            
            return base.Touch(target);
        }
        /// <summary>
        /// Kills this object, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    // play the explosion sound
                    AudioManager.PlaySoundEffect("explosion_medium");

                    // display the rocket explosion
                    if (ParticleEffectManager != null)
                    {
                        ParticleEffectManager.SpawnEffect(
                            ParticleEffectType.RocketExplosion, Position);
                    }
                }

                // stop the rocket-flying sound effect
                if (rocketSound != null)
                {
                    rocketSound.Stop(true);
                    rocketSound.Dispose();
                    rocketSound = null;
                }

                // stop the rocket-trail effect
                if (rocketTrailEffect != null)
                {
                    rocketTrailEffect.Stop(false);
                }
            }

            base.Die(source, cleanupOnly);
        }
Example #19
0
        /// <summary>
        /// Kills this object, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                // display the laser explosion
                if (!cleanupOnly && (ParticleEffectManager != null))
                {
                    ParticleEffectManager.SpawnEffect(ParticleEffectType.LaserExplosion,
                        Position);
                }
            }

            base.Die(source, cleanupOnly);
        }
Example #20
0
        /// <summary>
        /// Defines the interaction between the asteroid and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // if the asteroid has touched a player, then damage it
            Ship player = target as Ship;
            if (player != null)
            {
                // calculate damage as a function of how much the two GameplayObject's
                // velocities were going towards one another
                Vector2 playerAsteroidVector = Position - player.Position;
                if (playerAsteroidVector.LengthSquared() > 0)
                {
                    playerAsteroidVector.Normalize();

                    float rammingSpeed =
                        Vector2.Dot(playerAsteroidVector, player.Velocity) -
                        Vector2.Dot(playerAsteroidVector, Velocity);
                    float momentum = Mass * rammingSpeed;
                    player.Damage(this, momentum * momentumToDamageScalar);
                }
            }
            // if the asteroid didn't hit a projectile, play the asteroid-touch sound effect
            if ((target is Projectile) == false)
            {
                AudioManager.PlaySoundEffect("asteroid_touch");
            }
            return true;
        }
 /// <summary>
 /// Defines the interaction between this GameplayObject and
 /// a target GameplayObject when they touch.
 /// </summary>
 /// <param name="target">The GameplayObject that is touching this one.</param>
 /// <returns>True if the objects meaningfully interacted.</returns>
 public virtual bool Touch(GameplayObject target)
 {
     return(true);
 }
 /// <summary>
 /// Damage this object by the amount provided.
 /// </summary>
 /// <remarks>
 /// This function is provided in lieu of a Life mutation property to allow
 /// classes of objects to restrict which kinds of objects may damage them,
 /// and under what circumstances they may be damaged.
 /// </remarks>
 /// <param name="source">The GameplayObject responsible for the damage.</param>
 /// <param name="damageAmount">The amount of damage.</param>
 /// <returns>If true, this object was damaged.</returns>
 public virtual bool Damage(GameplayObject source, float damageAmount)
 {
     return(false);
 }
Example #23
0
        /// <summary>
        /// Kills this ship, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    // update the score
                    Ship ship = source as Ship;
                    if (ship == null)
                    {
                        Projectile projectile = source as Projectile;
                        if (projectile != null)
                        {
                            ship = projectile.Owner;
                        }
                    }
                    if (ship != null)
                    {
                        if (ship == this)
                        {
                            // reduce the score, since i blew myself up
                            ship.Score--;
                        }
                        else
                        {
                            // add score to the ship who shot this object
                            ship.Score++;
                        }
                    }
                    else
                    {
                        // if it wasn't a ship, then this object loses score
                        this.Score--;
                    }

                    // play the player-death sound
                    AudioManager.PlaySoundEffect("explosion_shockwave");
                    AudioManager.PlaySoundEffect("explosion_large");

                    // display the ship explosion
                    if (ParticleEffectManager != null)
                    {
                        ParticleEffectManager.SpawnEffect(
                            ParticleEffectType.ShipExplosion, Position);
                    }
                }

                // clear out the projectiles list
                foreach (Projectile projectile in projectiles)
                {
                    projectile.Die(null, true);
                }
                projectiles.Clear();

                // set the respawn timer
                respawnTimer = respawnTimerOnDeath;
            }

            base.Die(source, cleanupOnly);
        }
Example #24
0
 /// <summary>
 /// Damage this object by the amount provided.
 /// </summary>
 /// <remarks>
 /// This function is provided in lieu of a Life mutation property to allow 
 /// classes of objects to restrict which kinds of objects may damage them,
 /// and under what circumstances they may be damaged.
 /// </remarks>
 /// <param name="source">The GameplayObject responsible for the damage.</param>
 /// <param name="damageAmount">The amount of damage.</param>
 /// <returns>If true, this object was damaged.</returns>
 public virtual bool Damage(GameplayObject source, float damageAmount)
 {
     return false;
 }
Example #25
0
        /// <summary>
        /// Kills this object, in response to the given GameplayObject.
        /// </summary>
        /// <param name="source">The GameplayObject responsible for the kill.</param>
        /// <param name="cleanupOnly">
        /// If true, the object dies without any further effects.
        /// </param>
        public override void Die(GameplayObject source, bool cleanupOnly)
        {
            if (active)
            {
                if (!cleanupOnly)
                {
                    // play the explosion sound effect
                    AudioManager.PlaySoundEffect("explosion_large");

                    // play the mine particle-effect
                    if (ParticleEffectManager != null)
                    {
                        ParticleEffectManager.SpawnEffect(
                            ParticleEffectType.MineExplosion, Position);
                    }
                }
            }

            base.Die(source, cleanupOnly);
        }
        /// <summary>
        /// Spawn a new particle effect at a given location and gameplay object
        /// </summary>
        /// <param name="effectType">The effect in question.</param>
        /// <param name="position">The position of the effect.</param>
        /// <param name="actor">The gameplay object.</param>
        /// <returns>The new particle effect.</returns>
        public ParticleEffect SpawnEffect(ParticleEffectType effectType, 
            Vector2 position, GameplayObject gameplayObject)
        {
            ParticleEffect particleEffect = null;

            if (particleEffectCache.ContainsKey(effectType) == true)
            {
                List<ParticleEffect> availableSystems = particleEffectCache[effectType];

                for (int i = 0; i < availableSystems.Count; ++i)
                {
                    if (availableSystems[i].Active == false)
                    {
                        particleEffect = availableSystems[i];
                        break;
                    }
                }

                if (particleEffect == null)
                {
                    particleEffect = availableSystems[0].Clone();
                    particleEffect.Initialize(contentManager);
                    availableSystems.Add(particleEffect);
                }
            }

            if (particleEffect != null)
            {
                particleEffect.Reset();
                particleEffect.GameplayObject = gameplayObject;
                particleEffect.Position = position;
                activeParticleEffects.Add(particleEffect);
            }

            return particleEffect;
        }
        /// <summary>
        /// Spawn a new particle effect at a the position of a given gameplay object
        /// </summary>
        /// <param name="effectType">The effect in question.</param>
        /// <param name="actor">The gameplay object.</param>
        /// <returns>The new particle effect.</returns>
        public ParticleEffect SpawnEffect(ParticleEffectType effectType,
            GameplayObject gameplayObject)
        {
            // safety-check the parameter
            if (gameplayObject == null)
            {
                throw new ArgumentNullException("gameplayObject");
            }

            return SpawnEffect(effectType, gameplayObject.Position, gameplayObject);
        }
Example #28
0
 /// <summary>
 /// Defines the interaction between this GameplayObject and 
 /// a target GameplayObject when they touch.
 /// </summary>
 /// <param name="target">The GameplayObject that is touching this one.</param>
 /// <returns>True if the objects meaningfully interacted.</returns>
 public virtual bool Touch(GameplayObject target)
 {
     return true;
 }
Example #29
0
        /// <summary>
        /// Defines the interaction between this power-up and a target GameplayObject
        /// when they touch.
        /// </summary>
        /// <param name="target">The GameplayObject that is touching this one.</param>
        /// <returns>True if the objects meaningfully interacted.</returns>
        public override bool Touch(GameplayObject target)
        {
            // if it touched a ship, then create a particle system and play a sound
            Ship ship = target as Ship;
            if (ship != null)
            {
                // play the "power-up picked up" sound effect
                AudioManager.PlaySoundEffect("powerup_touch");

                // kill the power-up
                Die(target, false);

                // the ship keeps going as if it didn't hit anything
                return false;
            }

            return base.Touch(target);
        }
Example #30
0
 /// <summary>
 /// Kills this object, in response to the given GameplayObject.
 /// </summary>
 /// <param name="source">The GameplayObject responsible for the kill.</param>
 /// <param name="cleanupOnly">
 /// If true, the object dies without any further effects.
 /// </param>
 public virtual void Die(GameplayObject source, bool cleanupOnly) 
 {
     // deactivate the object
     if (active)
     {
         active = false;
         CollisionManager.Collection.QueuePendingRemoval(this);
     }
 }
Example #31
0
        /// <summary>
        /// Damage this ship by the amount provided.
        /// </summary>
        /// <remarks>
        /// This function is provided in lieu of a Life mutation property to allow 
        /// classes of objects to restrict which kinds of objects may damage them,
        /// and under what circumstances they may be damaged.
        /// </remarks>
        /// <param name="source">The GameplayObject responsible for the damage.</param>
        /// <param name="damageAmount">The amount of damage.</param>
        /// <returns>If true, this object was damaged.</returns>
        public override bool Damage(GameplayObject source, float damageAmount)
        {
            // if the safe timer hasn't yet gone off, then the ship can't be hurt
            if ((safeTimer > 0f) || (damageAmount <= 0f))
            {
                return false;
            }

            // once you're hit, the shield-recharge timer starts over
            shieldRechargeTimer = 2.5f;

            // damage the shield first, then life
            if (shield <= 0f)
            {
                life -= damageAmount;
            }
            else
            {
                shield -= damageAmount;
                if (shield < 0f)
                {
                    // shield has the overflow value as a negative value, just add it
                    life += shield;
                    shield = 0f;
                }
            }

            Projectile sourceAsProjectile = source as Projectile;
            if (sourceAsProjectile != null)
            {
                lastDamagedBy = sourceAsProjectile.Owner;
            }
            else
            {
                lastDamagedBy = source;
            }

            return true;
        }