#region File Description //----------------------------------------------------------------------------- // Projectile.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using System.Collections.Generic; using System.Text; using Microsoft.Xna.Framework; #endregion namespace Spacewar { /// /// Represents a projectile in SpacewarGame - retro or evolved /// public class Projectile : SpacewarSceneItem { private static int[] projectileCount = new int[3]; /// /// Which player this projectile came from /// private PlayerIndex player; /// /// The damage that this bullet does /// private int damage; private double endTime; private int projectileType; private bool exploded = false; private Particles particles; private bool projectileArmed; private Vector3 thrust; #region Properties public static int[] ProjectileCount { get { return projectileCount; } } public int Damage { get { return damage; } } #endregion /// /// Cretes a new projectile /// /// Instance of the game /// Which player it came from /// The start position /// The start velocity /// The direction its facing /// The time the projectile was fired public Projectile(Game game, PlayerIndex player, Vector3 position, Vector3 velocity, float angle, TimeSpan time, Particles particles) : base(game) { this.player = player; this.velocity = velocity; this.position = position; projectileCount[(int)player]++; if (SpacewarGame.GameState == GameState.PlayEvolved) { projectileType = (int)SpacewarGame.Players[(int)player].ProjectileType; this.particles = particles; endTime = time.TotalSeconds + SpacewarGame.Settings.Weapons[projectileType].Lifetime; thrust = Vector3.Multiply(Vector3.Normalize(velocity), SpacewarGame.Settings.Weapons[projectileType].Acceleration); radius = 2; damage = SpacewarGame.Settings.Weapons[projectileType].Damage; if (SpacewarGame.GameState == GameState.PlayEvolved) { shape = new BasicEffectShape(GameInstance, BasicEffectShapes.Projectile, projectileType, LightingType.InGame); //Evolved needs scaling scale.X = scale.Y = scale.Z = SpacewarGame.Settings.BulletScale; rotation.X = MathHelper.ToRadians(90); rotation.Y = 0; rotation.Z = (float)angle; } } else { //Build up a retro weapon damage = 5; //One shot kill projectileType = (int)ProjectileType.Peashooter; radius = 1; endTime = time.TotalSeconds + 2.0; acceleration = Vector3.Zero; } //Play 'shoot' sound switch (projectileType) { case (int)ProjectileType.Peashooter: Sound.PlayCue(Sounds.PeashooterFire); break; case (int)ProjectileType.MachineGun: Sound.PlayCue(Sounds.MachineGunFire); break; case (int)ProjectileType.DoubleMachineGun: Sound.PlayCue(Sounds.DoubleMachineGunFire); break; case (int)ProjectileType.Rocket: Sound.PlayCue(Sounds.RocketExplode); break; case (int)ProjectileType.BFG: Sound.PlayCue(Sounds.BFGFire); break; } } /// /// Updates the bullet. Removes it from scene when item is timed out /// /// Current game time /// Elapsed time since last update public override void Update(TimeSpan time, TimeSpan elapsedTime) { //See if this bullets lifespan has expired if (time.TotalSeconds > endTime) { //BFG explodes and has a blast radius if (SpacewarGame.GameState == GameState.PlayEvolved && projectileType == 4 && !exploded) { Sound.PlayCue(Sounds.Explosion); particles.AddExplosion(Position); //We don't delete it this frame but we change the radius and the damage exploded = true; radius = 30; damage = 3; } else { DeleteProjectile(); } } acceleration = thrust; //For the rocket we need particles if (projectileType == 3) { particles.AddRocketTrail(shape.World, new Vector2(acceleration.X, -acceleration.Y)); } base.Update(time, elapsedTime); } public void DeleteProjectile() { if (!delete) projectileCount[(int)player]--; delete = true; } /// /// Checks if there is a collision between the this and the passed in item /// /// A scene item to check /// True if there is a collision public override bool Collide(SceneItem item) { // Until we get collision meshes sorted just do a simple sphere (well circle!) check float currentDistance = (Position - item.Position).Length(); bool colliding = base.Collide(item); // For projectiles, do not allow them to destroy the ship that just fired them! Ship shipItem = item as Ship; if ((shipItem != null) && (shipItem.Player == player)) { if (colliding && !projectileArmed) { colliding = false; } else if (!colliding && !projectileArmed) { // Once projectile is at least 2 ship radii away, it can arm! // This is becuase the bolt launches with your velocity at the time // and the ship can "catch up" to the bolt pretty easily if you are // thrusting in the direction you are firing. if (currentDistance > item.Radius * 2.0f) projectileArmed = true; } } return colliding; } } }