// Project: XnaShooter, File: EnemyUnit.cs // Namespace: XnaShooter.Game, Class: EnemyUnit // Path: C:\code\XnaShooter\Game, Author: Abi // Code lines: 167, Size of file: 4,73 KB // Creation date: 27.12.2006 06:10 // Last modified: 27.12.2006 15:14 // Generated with Commenter by abi.exDream.com #region Using directives using System; using System.Collections.Generic; using System.Text; using XnaShooter.Shaders; using XnaShooter.Graphics; using XnaShooter.Helpers; using XnaShooter.GameScreens; using XnaShooter.Game; using Material = XnaShooter.Graphics.Material; using Microsoft.Xna.Framework; #endregion namespace XnaShooter.Game { /// /// Unit values, used for both the GameAsteroidManager to keep all /// enemy units in the current level and in UnitManager for all active /// units we are currently rendering. /// public class Projectile { #region Variables /// /// Weapon types /// public enum WeaponTypes { Rocket, Plasma, Fireball, /*obs Health, MgItem, PlasmaItem, GattlingItem, RocketItem, EmpItem, */ } // enum WeaponTypes /// /// Unit type, for enemy units this is 3-7 (Kamikaze - Mine). /// Links to the unit settings list in UnitManager. /// public WeaponTypes weaponType; /// /// Damage this unit currently does. Copied from unit settings, /// but increase as the level advances. /// public float damage; /// /// Helper for plasma and fireball effects, rotation is calculated /// once in constructor and used for the effects. /// public float effectRotation; /// /// Max speed for this unit (calculated from unit settings, increased /// a little for each level). Any movement is limited by this value. /// Units don't have to fly as fast as this value, this is just the limit. /// public float maxSpeed; /// /// Current position of this unit, will be updated each frame. /// Absolute position in 3d space. /// public Vector3 position; /// /// Move direction, not used for plasma projectiles, but fireballs will /// be moving towards the player (but not change direction during flight). /// Rockets on the other hand will slowly adjust to the player position. /// public Vector3 moveDirection; /// /// Own projectile? Then it flys up and damages enemies, else it /// is an enemy projectile! /// public bool ownProjectile = false; /// /// Life time of this projectile, will die after 6 seconds! /// private float lifeTimeMs = 0; #endregion #region Constructor /// /// Create unit of specific type at specific location. /// /// Set type /// Set position public Projectile(WeaponTypes setType, Vector3 setPosition, bool setOwnProjectile) { weaponType = setType; position = setPosition; ownProjectile = setOwnProjectile; // 300 dmg for plasma, 1000 for rockets damage = weaponType == WeaponTypes.Plasma ? 300 : 1000; if (ownProjectile == false) { if (weaponType == WeaponTypes.Fireball) { Vector3 distVec = Player.shipPos - position; moveDirection = Vector3.Normalize( Player.shipPos + new Vector3(0, distVec.Length() / 3, 0) - position); damage = 70;// 75; } // if else if (weaponType == WeaponTypes.Rocket) { moveDirection = new Vector3(0, -1, 0); damage = 110;// 125; } // else if } // if if (weaponType == WeaponTypes.Rocket) maxSpeed = 30;//80; else if (weaponType == WeaponTypes.Plasma) maxSpeed = 75;//150; else if (weaponType == WeaponTypes.Fireball) maxSpeed = 20;//45; if (weaponType == WeaponTypes.Plasma || weaponType == WeaponTypes.Fireball) effectRotation = RandomHelper.GetRandomFloat( 0, (float)Math.PI * 2.0f); } // Unit(setType, setPosition, setLevel) #endregion #region Get rotation angle private float GetRotationAngle(Vector3 pos1, Vector3 pos2) { // See http://en.wikipedia.org/wiki/Vector_(spatial) // for help and check out the Dot Product section ^^ // Both vectors are normalized so we can save deviding through the // lengths. Vector3 vec1 = new Vector3(0, 1, 0); Vector3 vec2 = pos1 - pos2; vec2.Normalize(); return (float)Math.Acos(Vector3.Dot(vec1, vec2)); } // GetRotationAngle(pos1, pos2) private float GetRotationAngle(Vector3 vec) { return (float)Math.Atan2(vec.Y, vec.X); } // GetRotationAngle(pos1, pos2) #endregion #region Render /// /// Render projectile, returns false if we are done with it. /// Has to be removed then. Else it updates just position. /// /// True if done, false otherwise public bool Render(Mission mission) { #region Update movement lifeTimeMs += BaseGame.ElapsedTimeThisFrameInMs; float moveSpeed = BaseGame.MoveFactorPerSecond; if (Player.GameOver) moveSpeed = 0; switch (weaponType) { case WeaponTypes.Fireball: position += moveDirection * maxSpeed * moveSpeed; break; case WeaponTypes.Rocket: if (ownProjectile) position += new Vector3(0, +1, 0) * maxSpeed * moveSpeed * 1.1f; else { // Fly to player Vector3 targetMovement = Player.shipPos - position; targetMovement.Normalize(); moveDirection = moveDirection * 0.95f + targetMovement * 0.05f; moveDirection.Normalize(); position += moveDirection * maxSpeed * moveSpeed; } // else break; case WeaponTypes.Plasma: if (ownProjectile) position += new Vector3(0, +1, 0) * maxSpeed * moveSpeed * 1.25f; else position += new Vector3(0, -1, 0) * maxSpeed * moveSpeed; break; // Rest are items, they just stay around } // switch(movementPattern) #endregion #region Skip if out of visible range float distance = Mission.LookAtPosition.Y - position.Y; const float MaxUnitDistance = 35; // Remove unit if it is out of visible range! if (distance > MaxUnitDistance || distance < -MaxUnitDistance * 2 || position.Z < 0 || lifeTimeMs > 6000) return true; #endregion #region Render switch (weaponType) { case WeaponTypes.Rocket: float rocketRotation = MathHelper.Pi; if (ownProjectile == false) rocketRotation = MathHelper.PiOver2 + GetRotationAngle(moveDirection); mission.AddModelToRender( mission.shipModels[(int)Mission.ShipModelTypes.Rocket], Matrix.CreateScale( (ownProjectile ? 1.25f : 0.75f) * Mission.ShipModelSize[(int)Mission.ShipModelTypes.Rocket]) * Matrix.CreateRotationZ(rocketRotation) * Matrix.CreateTranslation(position)); // Add rocket smoke EffectManager.AddRocketOrShipFlareAndSmoke(position, 1.5f, 6 * maxSpeed); break; case WeaponTypes.Plasma: EffectManager.AddPlasmaEffect(position, effectRotation, 1.25f); break; case WeaponTypes.Fireball: EffectManager.AddFireBallEffect(position, effectRotation, 1.25f); break; } // switch #endregion #region Explode if hitting unit // Own projectile? if (ownProjectile) { // Hit enemy units, check all of them for (int num = 0; num < Mission.units.Count; num++) { Unit enemyUnit = Mission.units[num]; // Near enough to enemy ship? Vector2 distVec = new Vector2(enemyUnit.position.X, enemyUnit.position.Y) - new Vector2(position.X, position.Y); if (distVec.Length() < 7 && (enemyUnit.position.Y - Player.shipPos.Y) < 60) { // Explode and do damage! EffectManager.AddFlameExplosion(position); Player.score += (int)enemyUnit.hitpoints / 10; enemyUnit.hitpoints -= damage; return true; } // if } // for } // if // Else this is an enemy projectile? else { // Near enough to our ship? Vector2 distVec = new Vector2(Player.shipPos.X, Player.shipPos.Y) - new Vector2(position.X, position.Y); if (distVec.Length() < 2.75f)//3) { // Explode and do damage! EffectManager.AddFlameExplosion(position); Player.health -= damage / 1000.0f; return true; } // if } // else #endregion // Don't remove unit from units list return false; } // Render() #endregion } // class Unit } // namespace XnaShooter.Game