This time around, we’ll be doing a bit of refactoring to make the code easier to deal with, and adding in some death behavior. To begin with, we’ll need to start with the code from last week, so go ahead and pick that up from the SkyDrive share.

To begin with, let’s update the Initialize and LoadContent methods, and move some of the setup into a new method called NewGame. This will allow us to reset the game back to it’s initial state more easily, such as when you get killed by running into an enemy.

Initialize
  1. protected override void Initialize()
  2. {
  3.     random = new Random();
  4.  
  5.     base.Initialize();
  6. }

LoadContent
  1. protected override void LoadContent()
  2. {
  3.     // Create a new SpriteBatch, which can be used to draw textures.
  4.     spriteBatch = new SpriteBatch(GraphicsDevice);
  5.  
  6.     txPlayer = Content.Load<Texture2D>("Triangle");
  7.     txBullet = Content.Load<Texture2D>("Bullet");
  8.     txEnemy3 = Content.Load<Texture2D>("Enemy-3");
  9.     txEnemy4 = Content.Load<Texture2D>("Enemy-4");
  10.     txEnemy5 = Content.Load<Texture2D>("Enemy-5");
  11.     txEnemy6 = Content.Load<Texture2D>("Enemy-6");
  12.  
  13.     NewGame();
  14. }

NewGame
  1. private void NewGame()
  2. {
  3.     triangleColor = Color.White;
  4.  
  5.     timeToSpawn = new TimeSpan(0, 0, 0, 0, 1000);
  6.     timeToShoot = new TimeSpan(0, 0, 0, 0, ShootDelay);
  7.  
  8.     player = new Player() { Avatar = txPlayer, Position = Vector2.Zero, Rotation = 0f };
  9.     bullets = new List<Bullet>();
  10.  
  11.     enemies = new List<Enemy>();
  12.     enemies.Add(new Enemy() { Avatar = txEnemy3, Position = new Vector2(600f, 200f), Rotation = 0f, Speed = 3f });
  13.     enemies.Add(new Enemy() { Avatar = txEnemy4, Position = new Vector2(600f, 300f), Rotation = 0f, Speed = 3.5f });
  14.     enemies.Add(new Enemy() { Avatar = txEnemy5, Position = new Vector2(600f, 400f), Rotation = 0f, Speed = 4f });
  15. }

If we update the collision detection, we can call NewGame now if the collision happens, which means we can reset the game with ease. Also, while I was setting this up, I found a bug in the code based around the origin of the drawing and the rectangle we were using for collision. The updated code in the Update method looks like the following:

Updated Collision Detection
  1. if (new Rectangle((int)enemy.Position.X - enemy.Avatar.Width / 2, (int)enemy.Position.Y - enemy.Avatar.Height / 2, enemy.Avatar.Width, enemy.Avatar.Height).Contains((int)player.Position.X, (int)player.Position.Y))
  2. {
  3.     triangleColor = Color.Red;
  4.     NewGame();
  5. }

Now, when you die, the game resets. It might make more sense to freeze the game, and wait for the player to choose to continue before resetting the game. To do that, let’s create a new variable to say whether the player is alive or not. Let’s call it isPlayerDead

isPlayerDead
  1. bool isPlayerDead;

And initialize it to false in the NewGame method

Initializing isPlayerDead
  1. isPlayerDead = false;

Then check if the player is dead in the Update method

Update
  1. if (isPlayerDead)
  2. {
  3.     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  4.     {
  5.         NewGame();
  6.     }
  7. }
  8. else
  9. {
  10.     // Everything else in Update
  11. }

This means that the Collision detection from above needs to be updated once more to set the boolean rather than calling NewGame directly.

Collision Detection
  1. if (new Rectangle((int)enemy.Position.X - enemy.Avatar.Width / 2, (int)enemy.Position.Y - enemy.Avatar.Height / 2, enemy.Avatar.Width, enemy.Avatar.Height).Contains((int)player.Position.X, (int)player.Position.Y))
  2. {
  3.     triangleColor = Color.Red;
  4.     isPlayerDead = true;
  5. }

And we’ve now got a game that actually ends when you die, and let’s you start a new game. Sounds like we’re ready for scoring. We’ll add that in next week. See you then.

Download the latest version of the source code.