//Helper method to validate the spaceships movement, returns true if movement is valid, false if not private bool ValidateMovement(Vector3 futurePosition, BoundingSphere planetBoundingSphere, Turret[] turrets) { BoundingSphere futureBoundingSphere = BoundingSphere; futureBoundingSphere.Center = futurePosition; //Check for collision with planet if (futureBoundingSphere.Intersects(planetBoundingSphere)) { return false; } //Loop through turrets and check for collisions for (int i = 0; i < turrets.Length; i++) { if (futureBoundingSphere.Intersects(turrets[i].BoundingSphere)) return false; } return true; }
/// <summary> /// The update method where the logic for the movement of the spaceship is calculated. /// </summary> /// <param name="keyboardState">The current state of the keyboard</param> /// <param name="planetBoundingSphere">The bounding sphere of the planet</param> /// <param name="turrets">The array of turrets in the game</param> public void Update(KeyboardState keyboardState, BoundingSphere planetBoundingSphere, Turret[] turrets) { Vector3 futurePosition; //The position the spaceship will move into at this gamestep, unless a collision will stop it float turnAmountSide = 0; float turnAmountUp = 0; //Check if any keys are pressed down, if any are, add or subtract from that turn variable if (keyboardState.IsKeyDown(Keys.A)) { turnAmountSide = 0.03f; } else if (keyboardState.IsKeyDown(Keys.D)) { turnAmountSide = -0.03f; } if (keyboardState.IsKeyDown(Keys.S)) { turnAmountUp = 0.03f; } else if (keyboardState.IsKeyDown(Keys.W)) { turnAmountUp = -0.03f; } //Calculate the rotation quaternion by creating angles from the turn amount values. //Code from: http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2/Flight_kinematics.php Quaternion additionalRot = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), turnAmountSide) * Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), turnAmountUp); Rotation *= additionalRot; //Calculate the position from the rotation Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), Rotation); futurePosition = Position + addVector * GameConstants.ShipVelocity; //Validate the spaceship's movement (only move it if the future position won't intersect the bounding sphere of the plabet or a turret) //If it can move to the future position, update the current position, and update the bounding sphere to the new position if (ValidateMovement(futurePosition, planetBoundingSphere, turrets)) { Position = futurePosition; IsCrashing = false; BoundingSphere updatedSphere; updatedSphere = BoundingSphere; updatedSphere.Center = Position; BoundingSphere = new BoundingSphere(updatedSphere.Center, updatedSphere.Radius); } else { IsCrashing = true; } }
/* * Helper method for finding a random turret out of the turrets that are closest to the ship. * Used when calculating which turret to fire a missile from */ private Turret closestTurretToShip() { //Work out how closest turrets to use to pick a random turret from //This is worked out to be 20% of the total turrets, and at least 1 int numFiringTurrets = numTurrets / 5; if (numFiringTurrets > 10) { numFiringTurrets = 1; } //Create an array for the current closest turrets, and a corrosponding array to //hold their distances from the spaceship, for example, the distance from the spaceship //of a turret at index 3 in the first array will be held in index 3 of the second array Turret[] closestTurrets = new Turret[numFiringTurrets]; float[] closestTurretDistances = new float[numFiringTurrets]; //Initialise the arrays with dummy initial values for (int i = 0; i < numFiringTurrets; i++) { closestTurrets[i] = new Turret(); closestTurretDistances[i] = float.MaxValue; //High number, so turrets will always replace these } //Iterate through each turret, checking if it is closer to the spaceship //than any turrets in the current array of closest turrets for (int i = 1; i < turrets.Length; i++) { float distance = Vector3.Distance(spaceship.Position, turrets[i].Position); bool finished = false; int j = 0; while (!finished && j < numFiringTurrets) { //If is is closer if (distance < closestTurretDistances[j]) { //swap it in at the same index of the turret it was closer than closestTurrets[j] = turrets[i]; closestTurretDistances[j] = distance; finished = true; //Stop iterating } j++; } //Sort and reverse the array, so the furthest turrets will always be considered first Array.Sort(closestTurretDistances, closestTurrets); Array.Reverse(closestTurretDistances); Array.Reverse(closestTurrets); } //Randomly pick a turret from the array of closests turrets, and return it int turretToPickIndex = random.Next(0, numFiringTurrets); return closestTurrets[turretToPickIndex]; }
/* * Resests the game objects and some variables to the starting configurations. * Much of this is very similar to the LoadContent method. */ private void ResetGame() { //Settings to reset to start a new game retrievedFuelCells = 0; menuScreenCounter = 0; stepCounter = 0; playerHealth = GameConstants.PlayerStartHealth; //Create new fuelcells, turrets and missiles fuelCells = new FuelCell[numFuelCells]; turrets = new Turret[numTurrets]; readyMissiles = new List<Missile>(); firedMissiles = new List<Missile>(); //Load the fuelcells, turrets and missiles in the same way they were loaded in LoadContent for (int i = 0; i < numFuelCells; i++) { Vector3 axis = new Vector3((float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5)); float angle = (float)random.NextDouble() * 6.242f; fuelCells[i] = new FuelCell(); fuelCells[i].LoadContent(Content, "Models/fuelcell", axis, angle, planet.BoundingSphere); } for (int i = 0; i < numTurrets; i++) { Vector3 axis = new Vector3((float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5)); float angle = (float)random.NextDouble() * 6.242f; turrets[i] = new Turret(); turrets[i].LoadContent(Content, "Models/turret", axis, angle, planet.BoundingSphere); } for (int i = 0; i < GameConstants.NumMissiles; i++) { readyMissiles.Add(new Missile()); readyMissiles[i].LoadContent(Content, "Models/missile", spaceship); } explosions.Clear(); //Remove all occuring explosions //Initial spaceship starting location and rotation spaceship.Position = new Vector3(0, 300, 1000); spaceship.Rotation = Quaternion.Identity; exhaustParticleEmitter = new ParticleEmitter(fireParticles, 1000, spaceship.Position); }
/// <summary> /// Load all game objects with their models, as well ad initialising sounds and other /// entities used in the game. Sets up spaceship starting location. /// </summary> protected override void LoadContent() { //Create a new SpriteBatch, which can be used to draw 2D graphics. spriteBatch = new SpriteBatch(GraphicsDevice); //Create a graphics device variable device = graphics.GraphicsDevice; //Load content of misc game entities statsFont = Content.Load<SpriteFont>("Fonts/stats_font"); skyboxEffect = Content.Load<Effect>("Effects/skybox_effect"); splashScreenTexture = Content.Load<Texture2D> ("Images/splash_screen"); //Load object models spaceship.LoadContent(Content, "Models/spaceship"); planet.LoadContent(Content, "Models/planet"); boundingSphere.Model = Content.Load<Model>("Models/sphere"); skyboxModel = LoadSkyboxModel("Models/skybox", out skyboxTextures); //Iteratively load content for fuelcells, also generate the random seeds which will be used in calculating positions and rotation for (int i = 0; i < numFuelCells; i++) { Vector3 axis = new Vector3((float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5)); float angle = (float)random.NextDouble() * 6.242f; fuelCells[i] = new FuelCell(); fuelCells[i].LoadContent(Content, "Models/fuelcell", axis, angle, planet.BoundingSphere); } //turrets loaded in the same was as fuelcells for (int i = 0; i < numTurrets; i++) { Vector3 axis = new Vector3((float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5), (float)(random.NextDouble() - 0.5)); float angle = (float)random.NextDouble() * 6.242f; turrets[i] = new Turret(); turrets[i].LoadContent(Content, "Models/turret", axis, angle, planet.BoundingSphere); } //Populate the ready missile array with all the missiles for (int i = 0; i < GameConstants.NumMissiles; i++) { readyMissiles.Add(new Missile()); readyMissiles[i].LoadContent(Content, "Models/missile", spaceship); } //Load sounds, and start playing music explosionSound = Content.Load<SoundEffect>("Sound/explosion"); fuelCellPickupSound = Content.Load<SoundEffect>("Sound/fuelcell_pickup"); music = Content.Load<Song>("Sound/music"); MediaPlayer.Play(music); //Initial spaceship starting location and rotation spaceship.Position = new Vector3(0, 300, 1000); spaceship.Rotation = Quaternion.Identity; exhaustParticleEmitter = new ParticleEmitter(fireParticles, 1000, spaceship.Position); }