// collision box radius /// <summary> /// Create a new player ship /// </summary> public PlayerShip( GameManager game, // game manager int player, // player id Model model, // model for player ship EntityList entities, // entity list for ship model float radius) { if (game == null) { throw new ArgumentNullException("game"); } if (entities == null) { throw new ArgumentNullException("entities"); } // save parameters gameManager = game; shipModel = model; shipEntities = entities; playerIndex = player; // create movement controller movement = new PlayerMovement(); movement.maxVelocity = GameOptions.MovementVelocity; // enable collision sound collisionSound = true; // create engine particle system with infinite life time particleBoost = gameManager.AddParticleSystem( ParticleSystemType.ShipTrail, transform); particleBoost.SetTotalTime(1e10f); boostTransform = shipEntities.GetTransform("engine"); // create the ship collision box box = new CollisionBox(-radius, radius); // random bobbing offset random = new Random(player); bobbingTime = (float)random.NextDouble(); // setup 3rd person camera parameters camera3rdPerson = false; chaseCamera = new ChaseCamera(); chaseCamera.DesiredPositionOffset = GameOptions.CameraOffset; chaseCamera.LookAtOffset = GameOptions.CameraTargetOffset; chaseCamera.Stiffness = GameOptions.CameraStiffness; chaseCamera.Damping = GameOptions.CameraDamping; chaseCamera.Mass = GameOptions.CameraMass; }
/// <summary> /// Unload game files /// </summary> public void UnloadFiles() { // unload level levelColor = null; levelCollision = null; levelSpawns = null; levelLights = null; // unload poasticles particleTextures = null; // unload animated sprites animatedSpriteTextures = null; // unload projectiles projectileModels = null; // unload powerups powerupModels = null; // unload players for (int i = 0; i < GameOptions.MaxPlayers; i++) { // must displose player so that it releases its effects if (players[i] != null) players[i].Dispose(); players[i] = null; } // unload hud hudCrosshair = null; hudEnergy = null; hudMissile = null; hudScore = null; hudBars = null; // unload damage texture damageTexture = null; // unload powerups powerup.Clear(); }
/// <summary> /// Load the game files (level, ships, wepons, etc...) /// </summary> public void LoadFiles(ContentManager content) { String level = levelFile + "/" + levelFile; // load level model levelColor = content.Load<Model>("levels/" + level); // load collision model Model collisionModel = content.Load<Model>( "levels/" + level + "_collision"); levelCollision = new CollisionMesh(collisionModel, GameOptions.CollisionMeshSubdivisions); collisionModel = null; // load spawns and lights levelSpawns = EntityList.Load("content/levels/" + level + "_spawns.xml"); levelLights = LightList.Load("content/levels/" + level + "_lights.xml"); // load particle textures if (particleTextures == null) { int i, j = particleFiles.GetLength(0); particleTextures = new Texture2D[j]; for (i = 0; i < j; i++) particleTextures[i] = content.Load<Texture2D>( "particles/" + particleFiles[i]); } // load animated sprite textures if (animatedSpriteTextures == null) { int i, j = animatedSpriteFiles.GetLength(0); animatedSpriteTextures = new Texture2D[j]; for (i = 0; i < j; i++) animatedSpriteTextures[i] = content.Load<Texture2D>( "explosions/" + animatedSpriteFiles[i]); } // load projectile models if (projectileModels == null) { int i, j = projectileFiles.GetLength(0); projectileModels = new Model[j]; for (i = 0; i < j; i++) projectileModels[i] = content.Load<Model>( "projectiles/" + projectileFiles[i]); } // load powerup models if (powerupModels == null) { int i, j = powerupFiles.GetLength(0); powerupModels = new Model[j]; for (i = 0; i < j; i++) powerupModels[i] = content.Load<Model>( "powerups/" + powerupFiles[i]); } // cerate players for (int i = 0; i < GameOptions.MaxPlayers; i++) if (shipFile[i] != null) { Model ShipModel = content.Load<Model>( "ships/" + shipFile[i]); EntityList ShipEnities = EntityList.Load( "content/ships/" + shipFile[i] + ".xml"); players[i] = new PlayerShip(this, i, ShipModel, ShipEnities, GameOptions.CollisionBoxRadius); } else players[i] = null; // create powerups EntityList powerups = EntityList.Load( "content/levels/" + level + "_powerups.xml"); foreach (Entity entity in powerups.Entities) { switch (entity.name) { case "energy": AddPowerup(PowerupType.Energy, entity.transform); break; case "missile": AddPowerup(PowerupType.Missile, entity.transform); break; } } // load hud textures if (gameMode == GameMode.SinglePlayer) { hudCrosshair = content.Load<Texture2D>( "screens/hud_sp_crosshair"); hudEnergy = content.Load<Texture2D>( "screens/hud_sp_energy"); hudMissile = content.Load<Texture2D>( "screens/hud_sp_missile"); hudScore = content.Load<Texture2D>( "screens/hud_sp_score"); hudBars = content.Load<Texture2D>( "screens/hud_sp_bars"); } else { hudCrosshair = content.Load<Texture2D>( "screens/hud_mp_crosshair"); hudEnergy = content.Load<Texture2D>( "screens/hud_mp_energy"); hudMissile = content.Load<Texture2D>( "screens/hud_mp_missile"); hudScore = content.Load<Texture2D>( "screens/hud_mp_score"); hudBars = content.Load<Texture2D>( "screens/hud_mp_bars"); } // load damage indicator texture damageTexture = content.Load<Texture2D>("screens/damage"); }
// level spawn points /// <summary> /// Updates the player ship for given elapsed time /// </summary> public void Update( float elapsedTime, // elapsed time on this frame CollisionMesh collision, // level collision mesh EntityList entities) { if (collision == null) { throw new ArgumentNullException("collision"); } if (entities == null) { throw new ArgumentNullException("entities"); } // updates damage screen time (zero for no damage indication) damageTime = Math.Max(0.0f, damageTime - elapsedTime); // if player dead if (IsAlive == false) { // disable engine particle system particleBoost.Enabled = false; // updates dead time (if zero, player is alive) deadTime = Math.Max(0.0f, deadTime - elapsedTime); // if player dead time expires, respawn if (IsAlive == true) { // reset player to a random spawn point Reset(entities.GetTransformRandom(random)); // add spawn animated sprite in front of player Vector3 Pos = movement.position + 10 * movement.rotation.Forward; gameManager.AddAnimSprite(AnimSpriteType.Spawn, Pos, 140, 80, 30, DrawMode.Additive, playerIndex); // play spawn sound gameManager.PlaySound("ship_spawn"); // reset energy, shield and boost energy = 1.0f; shield = 1.0f; boost = 1.0f; missileCount = 3; } return; } // hold position before movement Vector3 lastPostion = movement.position; // update movement movement.Update(elapsedTime); // test for collision with level Vector3 collisionPosition; if (collision.BoxMove(box, lastPostion, movement.position, 1.0f, 0.0f, 3, out collisionPosition)) { // update to valid position after collision movement.position = collisionPosition; // compute new velocity after collision Vector3 newVelocity = (collisionPosition - lastPostion) * (1.0f / elapsedTime); // if collision sound enabled if (collisionSound) { // test collision angle to play collision sound Vector3 WorldVel = movement.WorldVelocity; float dot = Vector3.Dot( Vector3.Normalize(WorldVel), Vector3.Normalize(newVelocity)); if (dot < 0.7071f) { // play collision sound gameManager.PlaySound("ship_collide"); // set rumble intensity dot = 1 - 0.5f * (dot + 1); gameManager.SetVibration(playerIndex, dot * 0.5f); // disable collision sounds until ship stops colliding collisionSound = false; } } // set new velocity after collision movement.WorldVelocity = newVelocity; } else // clear of collisions, re-enable collision sounds collisionSound = true; // update player transform transform = movement.rotation; transform.Translation = movement.position; // compute inverse transform transformInverse = Matrix.Invert(transform); // get normalized player velocity float velocityFactor = movement.VelocityFactor; // update bobbing bobbingTime += elapsedTime; float bobbingFactor = 1.0f - velocityFactor; float time = GameOptions.ShipBobbingSpeed * bobbingTime % (2 * MathHelper.TwoPi); float distance = bobbingFactor * GameOptions.ShipBobbingRange; bobbing.M41 = distance * (float)Math.Sin(time * 0.5f); bobbing.M42 = distance * (float)Math.Sin(time); bobbingInverse.M41 = -bobbing.M41; bobbingInverse.M42 = -bobbing.M42; // compute transform with bobbing Matrix bobbingTransform = bobbing * transform; // update particle system position particleBoost.Enabled = true; particleBoost.SetTransform(boostTransform * bobbingTransform); // if shield active if (shieldUse) { // update shield position animatedSpriteShield.Position = bobbingTransform.Translation + 10f * bobbingTransform.Forward; // update shiled charge shield -= elapsedTime / GameOptions.ShieldUse; // if shield charge depleted if (shield < 0) { // disable shield shieldUse = false; shield = 0; // kill shield animated sprite animatedSpriteShield.SetTotalTime(0); animatedSpriteShield = null; } } else // change shield shield = Math.Min(1.0f, shield + elapsedTime / GameOptions.ShieldRecharge); // if boost active if (boostUse) { // increase ship maximum velocity movement.maxVelocity = GameOptions.MovementVelocityBoost; // apply impulse force forward AddImpulseForce(transform.Forward * GameOptions.BoostForce); // set particle system velocity scale particleBoost.VelocityScale = Math.Min(1.0f, particleBoost.VelocityScale + 4.0f * elapsedTime); // update shield charge boost -= elapsedTime / GameOptions.BoostUse; // if boost depleated if (boost < 0) { // disable boost boostUse = false; boost = 0; } } else { // slowly returns ship maximum velocity to normal levels if (movement.maxVelocity > GameOptions.MovementVelocity) movement.maxVelocity -= GameOptions.BoostSlowdown * elapsedTime; // slowly returns particle system velocity scale to normal levels particleBoost.VelocityScale = Math.Max(0.1f, particleBoost.VelocityScale - 2.0f * elapsedTime); // charge boost boost = Math.Min(1.0f, boost + elapsedTime / GameOptions.BoostRecharge); } // charge blaster blaster = Math.Min(1.0f, blaster + elapsedTime / GameOptions.BlasterChargeTime); // charge missile missile = Math.Min(1.0f, missile + elapsedTime / GameOptions.MissileChargeTime); // update chase camera chaseCamera.ChasePosition = transform.Translation; chaseCamera.ChaseDirection = transform.Forward; chaseCamera.Up = transform.Up; chaseCamera.Update(elapsedTime, collision); }