#region File Description //----------------------------------------------------------------------------- // EvolvedScreen.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; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System.Diagnostics; #endregion namespace Spacewar { /// /// SpacewarScreen is the main game screen /// public class EvolvedScreen : SpacewarScreen { private double sunScale = 1000.0; private Asteroid[] asteroids; private float levelTime; private int lastLevelTime; private bool ended; private double endTime; private static string[] scoreLookup = new string[] { "000", "001", "011", "111" }; private static Vector3[] asteroidStarts = new Vector3[] { new Vector3(390, 240, 0), new Vector3(-390, -240, 0), new Vector3(390, -240, 0), new Vector3(-390, 240,0), new Vector3(-390, 240,0), new Vector3(390, 240,0), new Vector3(-390, -240,0) }; private Random random = new Random(); /// /// Creates a new SpacewarScreen /// public EvolvedScreen(Game game) : base(game) { backdrop = new SceneItem(game, new EvolvedBackdrop(game)); const float factor = 46; backdrop.Center = new Vector3(.5f, .5f, 0); backdrop.Scale = new Vector3(16f * factor, 9f * factor, 1f); backdrop.Position = new Vector3(-.5f, -.5f, 0); scene.Add(backdrop); bullets = new Projectiles(game); particles = new Particles(game); ship1 = new Ship(game, PlayerIndex.One, SpacewarGame.Players[0].ShipClass, SpacewarGame.Players[0].Skin, new Vector3(SpacewarGame.Settings.Ships[0].StartPosition, 0.0f), bullets, particles); ship1.Paused = true; ship1.Radius = 15f; if (SpacewarGame.Players[0].ShipClass == ShipClass.Pencil) { ship1.ExtendedExtent[0] = new Vector3(0.0f, 25.0f, 0.0f); ship1.ExtendedExtent[1] = new Vector3(0.0f, -25.0f, 0.0f); } ship2 = new Ship(game, PlayerIndex.Two, SpacewarGame.Players[1].ShipClass, SpacewarGame.Players[1].Skin, new Vector3(SpacewarGame.Settings.Ships[1].StartPosition, 0.0f), bullets, particles); ship2.Paused = true; ship2.Radius = 15f; if (SpacewarGame.Players[1].ShipClass == ShipClass.Pencil) { ship2.ExtendedExtent[0] = new Vector3(0.0f, 25f, 0.0f); ship2.ExtendedExtent[1] = new Vector3(0.0f, -25f, 0.0f); } scene.Add(bullets); asteroids = new Asteroid[SpacewarGame.GameLevel + 2]; for (int i = 0; i < SpacewarGame.GameLevel + 2; i++) { asteroids[i] = new Asteroid(game, random.NextDouble() > .5 ? AsteroidType.Large : AsteroidType.Small, asteroidStarts[i]); asteroids[i].Scale = new Vector3(SpacewarGame.Settings.AsteroidScale, SpacewarGame.Settings.AsteroidScale, SpacewarGame.Settings.AsteroidScale); asteroids[i].Paused = true; asteroids[i].Velocity = (float)random.Next(100) * Vector3.Normalize(new Vector3((float)(random.NextDouble() - .5), (float)(random.NextDouble() - .5), 0)); scene.Add(asteroids[i]); } scene.Add(ship1); scene.Add(ship2); //Added after other objects so they draw over the top scene.Add(particles); //Sun last so its on top sun = new Sun(game, new EvolvedSun(game), new Vector3(-.5f, -.5f, 0)); scene.Add(sun); //Reset health meters. SpacewarGame.Players[0].Health = 5; SpacewarGame.Players[1].Health = 5; } /// /// Update for SpacewarScreen uses the base Update method and adds Sun zoom animation /// and detects the end of the level time /// /// Game time /// Elapsed time since last update /// /// The next gamestate to transition to. Default is the return value of an overlay or NONE. Override Update if you want to change this behaviour /// public override GameState Update(TimeSpan time, TimeSpan elapsedTime) { if (sunScale > 1) { //1st frame always has a big elapsed time so use that to set the start pos if (sunScale > 20.0) { sunScale = 20.0; } else { sunScale -= elapsedTime.TotalSeconds * 15.0; } if (sunScale < 1) { sunScale = 1; paused = false; ship1.Paused = false; ship2.Paused = false; foreach (Asteroid asteroid in asteroids) { asteroid.Paused = false; } //Kick off level timer levelTime = SpacewarGame.Settings.LevelTime; } //Zoom the Sun sun.Scale = new Vector3(SpacewarGame.Settings.Size * (float)sunScale, SpacewarGame.Settings.Size * (float)sunScale, 1f); } base.Update(time, elapsedTime); handleCollisions(time); //Update screentimer if (!paused) { levelTime -= (float)elapsedTime.TotalSeconds; if ((levelTime - lastLevelTime) < 0.0f) { //We have ticked down if (levelTime < 0.0f) { Sound.PlayCue(Sounds.CountDownExpire); } else if (levelTime < 6) { Sound.PlayCue(Sounds.CountDownWarning); } } lastLevelTime = (int)levelTime; } //When we run out of time show the totals if (!paused && (levelTime <= 0.0f)) { //Stop everything while we count up the $$$ paused = true; ended = true; ship1.Paused = true; ship2.Paused = true; ship1.Silence(); ship2.Silence(); foreach (Asteroid asteroid in asteroids) { asteroid.Paused = true; } bullets.Clear(); //No more bullets particles.Clear(); //No more particles endTime = time.TotalSeconds + 5; //Show scores for 5 seconds } if (ended && time.TotalSeconds > endTime) { //Don't need the screen anymore, shut it down! Shutdown(); //Update scores and round SpacewarGame.Players[0].Cash += player1Score * 1000; SpacewarGame.Players[1].Cash += player2Score * 1000; if (player1Score > player2Score) { SpacewarGame.Players[0].Score++; SpacewarGame.GameLevel++; } else if (player2Score > player1Score) { SpacewarGame.Players[1].Score++; SpacewarGame.GameLevel++; } else { //nobody won - tie game //replay that level } if (SpacewarGame.Players[0].Score == 3 || SpacewarGame.Players[1].Score == 3) { return GameState.Victory; } else { return GameState.ShipUpgrade; } } else { return GameState.None; } } /// /// Renders the screen using the base class and adds the HUD /// public override void Render() { //Render scene stuff base.Render(); //If this is the end of level then show the overlays if (ended) { Texture2D overlayTexture = SpacewarGame.ContentManager.Load(SpacewarGame.Settings.MediaPath + @"textures\In-game_score_overlay"); SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque); SpriteBatch.Draw(overlayTexture, new Vector2(70, 200), null, Color.White); SpriteBatch.Draw(overlayTexture, new Vector2(900, 200), null, Color.White); SpriteBatch.End(); } //HUD stuff Font.Begin(); //If this is the end of level then show the scores if (ended) { Font.Draw(FontStyle.WeaponLarge, 100, 240, String.Format("{0} pts x $1,000", player1Score)); Font.Draw(FontStyle.WeaponLarge, 220, 280, "="); Font.Draw(FontStyle.WeaponLarge, 180, 320, String.Format("{0:$##,##0}", player1Score * 1000)); Font.Draw(FontStyle.WeaponLarge, 930, 240, String.Format("{0} pts x $1,000", player2Score)); Font.Draw(FontStyle.WeaponLarge, 1050, 280, "="); Font.Draw(FontStyle.WeaponLarge, 1010, 320, String.Format("{0:$##,##0}", player2Score * 1000)); } //Timer Font.Draw(FontStyle.GameCountDown, 592, 40, String.Format("{0:0}:{1:00}", (int)(levelTime / 60), levelTime % 60)); //Player1/2 labels Font.Draw(FontStyle.GamePlayerNames, 50, 40, "1"); Font.Draw(FontStyle.GamePlayerNames, 1110, 40, "2"); //Weapon icons 01234 is player1 weapons, 56789 is player2 weapons Font.Draw(FontStyle.WeaponIcons, 50, 560, ((int)SpacewarGame.Players[0].ProjectileType)); Font.Draw(FontStyle.WeaponIcons, 1090, 560, ((int)(SpacewarGame.Players[1].ProjectileType) + 5)); //Score buttons Font.Draw(FontStyle.ScoreButtons, 60, 70, scoreLookup[SpacewarGame.Players[0].Score]); Font.Draw(FontStyle.ScoreButtons, 1140, 70, scoreLookup[SpacewarGame.Players[1].Score]); //Health //Fudge factor for BFG icon int xOffset; xOffset = (SpacewarGame.Players[0].ProjectileType == ProjectileType.BFG) ? 12 : 0; Font.Draw(FontStyle.HealthBar, 130 + xOffset, 625, SpacewarGame.Players[0].Health); xOffset = (SpacewarGame.Players[1].ProjectileType == ProjectileType.BFG) ? 16 : 0; Font.Draw(FontStyle.HealthBar, 1170 + xOffset, 625, SpacewarGame.Players[1].Health); //Scores Font.Draw(FontStyle.Score, 300, 15, player1Score); Font.Draw(FontStyle.Score, 940, 15, player2Score); Font.End(); } protected override void handleCollisions(TimeSpan gameTime) { base.handleCollisions(gameTime); bool asteroidHitShip1 = false; bool asteroidHitShip2 = false; //Asteroids do 3 damage and bounce you foreach (Asteroid asteroid in asteroids) { if (!asteroid.Destroyed) { if (asteroid.Collide(ship1) && !ship1.Uncollidable) { asteroidHitShip1 = true; if (!ship1.Invulnerable) { float ship1Speed = ship1.Velocity.Length(); float asteroidSpeed = asteroid.Velocity.Length(); Vector3 tmp = ship1.Velocity; Vector3 vel = asteroid.Velocity; vel.Normalize(); ship1.Velocity = vel * ship1Speed; tmp.Normalize(); asteroid.Velocity = tmp * asteroidSpeed; HitPlayer1(gameTime, 1); ship1.Invulnerable = true; } } if (asteroid.Collide(ship2) && !ship2.Uncollidable) { asteroidHitShip2 = true; if (!ship2.Invulnerable) { float ship2Speed = ship2.Velocity.Length(); float asteroidSpeed = asteroid.Velocity.Length(); Vector3 tmp = ship2.Velocity; Vector3 vel = asteroid.Velocity; vel.Normalize(); ship2.Velocity = vel * ship2Speed; tmp.Normalize(); asteroid.Velocity = tmp * asteroidSpeed; HitPlayer2(gameTime, 1); ship2.Invulnerable = true; } } foreach (Projectile bullet in bullets) { if (bullet.Collide(asteroid)) { particles.AddExplosion(asteroid.Position); asteroid.Delete = true; asteroid.Destroyed = true; bullet.DeleteProjectile(); Sound.PlayCue(Sounds.Explosion); } } } } if (!asteroidHitShip1 && ship1.Invulnerable) { ship1.Invulnerable = false; } if (!asteroidHitShip2 && ship2.Invulnerable) { ship2.Invulnerable = false; } } public override void OnCreateDevice() { base.OnCreateDevice(); foreach (Asteroid asteroid in asteroids) { asteroid.ShapeItem.OnCreateDevice(); } foreach (Projectile bullet in bullets) { bullet.ShapeItem.OnCreateDevice(); } particles.OnCreateDevice(); } } }