WPF C# Tutorial – Create a Space Invaders game in Visual Studio
- Subject: WPF C# Tutorials
- Learning Time: 4 hours
Full Source For Space Invaders Game in WPF and C#–
Below is the full source code for the space inavders game we created. Use them as you would make sure you use your own comments on this game, this way you can reinforce learning as you are completing different projects.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; // add this for the timer namespace space_invaders { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { // go left and right boolean are set to false bool goLeft, goRight = false; // this list items to remove will be used as a garbage collector List<Rectangle> itemstoremove = new List<Rectangle>(); // this int enemy images will help us change enemy pictures int enemyImages = 0; // this is the enemy bullet timer int bulletTimer; // this is the enemy bullet timer limit and frequency int bulletTimerLimit = 90; // save the total number of enemies int totalEnemeis; // make a new instance of the dispatch timer class DispatcherTimer dispatcherTimer = new DispatcherTimer(); // image brush class that we will use as the player image called player skin ImageBrush playerSkin = new ImageBrush(); // the default enemy speed int enemySpeed = 6; public MainWindow() { InitializeComponent(); // set up the timer and events // link the dispatcher timer to a event called game engine dispatcherTimer.Tick += gameEngine; // this timer will run every 20 milliseconds dispatcherTimer.Interval = TimeSpan.FromMilliseconds(20); // start the timer dispatcherTimer.Start(); // load the player images from the images folder playerSkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/player.png")); // assign the new player skin to the rectangle player1.Fill = playerSkin; // run the make enemies function and tell it to make 30 enemies makeEnemies(30); } private void Canvas_KeyisDown(object sender, KeyEventArgs e) { // this is the key down event // if the left key is pressed set go left to true // if the right key is pressed set go right to true if (e.Key == Key.Left) { goLeft = true; } if (e.Key == Key.Right) { goRight = true; } } private void Canvas_KeyIsUp(object sender, KeyEventArgs e) { // this is the key up event // if the left key is let go set go left to false // if the right key is let go set go right to false if (e.Key == Key.Left) { goLeft = false; } if (e.Key == Key.Right) { goRight = false; } // below you have the if statement that will make the bullets // check if the space key is let go if (e.Key == Key.Space) { // clear all the items from the items to remove list first itemstoremove.Clear(); // make a new rectangle called new bullet and add a tag called bullet, height 20 width 5 backgroubnd white and border to red Rectangle newBullet = new Rectangle { Tag = "bullet", Height = 20, Width = 5, Fill = Brushes.White, Stroke = Brushes.Red }; // place the bullet where the player is Canvas.SetTop(newBullet, Canvas.GetTop(player1) - newBullet.Height); Canvas.SetLeft(newBullet, Canvas.GetLeft(player1) + player1.Width / 2); // add the bullet to the screen myCanvas.Children.Add(newBullet); } } private void enemyBulletMaker(double x, double y) { // this function creates the enemy bullets firing towards the player object in the game // see this function is passing through 2 variables x and y these will be location where we place the bullets // first create a new rectangle // this rectangle will have a tag called enemy bullet, height 40 pixels, width 15 pixels, background yellowm border black and border size 5 Rectangle newEnemyBullet = new Rectangle { Tag = "enemyBullet", Height = 40, Width = 15, Fill = Brushes.Yellow, Stroke = Brushes.Black, StrokeThickness = 5 }; // now we place the bullets top location to the Y variable Canvas.SetTop(newEnemyBullet, y); // set the left location to the X location Canvas.SetLeft(newEnemyBullet, x); // add the bullet to the screen myCanvas.Children.Add(newEnemyBullet); } private void makeEnemies(int limit) { // make a local integer called left and set to 0 int left = 0; // save the enemy limit as as the total enemy totalEnemeis = limit; // this is the for loop that will make all of the enemies for this game // if the limit is set to 10 this loop will run 10 times if set 20 to then 20 times and so on for (int i = 0; i < limit; i++) { // with each loop // will create a new enemy skin image brush to be used with the enemy rectangle ImageBrush enemySkin = new ImageBrush(); // make a new rectangle called new enemy // inside this rectangle we set the properties to tag called enemy 45 height and width and link the enemy skin as the fill Rectangle newEnemy = new Rectangle { Tag = "enemy", Height = 45, Width = 45, Fill = enemySkin, }; // set the starting location of the space inavder Canvas.SetTop(newEnemy, 10); // this is the top location Canvas.SetLeft(newEnemy, left); // this is the left location // add one to the scene myCanvas.Children.Add(newEnemy); // change the to -60 left -= 60; // add 1 to the enemy images integer enemyImages++; // if enemy images integer goes aove 8 // then we set the integer back to 1 if (enemyImages > 8) { enemyImages = 1; } // the switch statement below is checking the enemy images integer // with each number it will assign a new skin to the enemy // this switch statement will run throughout the loop and it will help us make use of those space invader images we imported earlier // it will look for what number is in the enemy images integer and then assign that image to the enemy skin class and then break the loop. switch (enemyImages) { case 1: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader1.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 1 GIF file break; case 2: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader2.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 2 GIF file break; case 3: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader3.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 3 GIF file break; case 4: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader4.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 4 GIF file break; case 5: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader5.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 5 GIF file break; case 6: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader6.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 6 GIF file break; case 7: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader7.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 7 GIF file break; case 8: enemySkin.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/invader8.gif")); // if the enemy images number comes up as 1 we can change the image source to the invader 8 GIF file break; } } } private void gameEngine(object sender, EventArgs e) { // this is the game engine event, this event will trigger every 20 milliseconds with the timer tick // to begin we start with declaring a rect class linking it back to the player 1 rectangle we made in the canvas Rect player = new Rect(Canvas.GetLeft(player1), Canvas.GetTop(player1), player1.Width, player1.Height); // show the remaining space invader numbers on the screen with enemies left label enemiesLeft.Content = "Invaders Left: " + totalEnemeis; // below is the player movement script // in the if statement below we are checking if the player is still inside the boundary from the left position // if so then we can move the player to towards left of the screen if (goLeft && Canvas.GetLeft(player1) > 0) { Canvas.SetLeft(player1, Canvas.GetLeft(player1) - 10); } // in the if statement below we are checking if the players left position plus 65 pixels is still inside the main application window from the right // if so we can move the player towards the right of the screen else if (goRight && Canvas.GetLeft(player1) + 80 < Application.Current.MainWindow.Width) { Canvas.SetLeft(player1, Canvas.GetLeft(player1) + 10); } //decrease 3 from the bullet timer interger every 20 milliseconds bulletTimer -= 3; // when the bullet timer integer reaches below 0 // run the enemy bullet maker function and tell it where to place the bullet on screen if (bulletTimer < 0) { // we want the enemy bullet to be placed directly above the player character // this is why we are passing the player left position + 20 pixels // and the top position will be 10 enemyBulletMaker((Canvas.GetLeft(player1) + 20), 10); // reset the bullet timer back to bullet timer limit value bulletTimer = bulletTimerLimit; } // if the total enemies number goes below 10 // set the enemy speed to 20 if (totalEnemeis < 10) { enemySpeed = 20; } // below is the code for collision detection between enemy, bullets, player and enemy bullets // run the foreach loop make a local variable x and scan through all of the rectangles available in my canvas foreach (var x in myCanvas.Children.OfType<Rectangle>()) { // if any rectangle has the tag bullet in it if (x is Rectangle && (string)x.Tag == "bullet") { // move the bullet rectangle towards top of the screen Canvas.SetTop(x, Canvas.GetTop(x) - 20); // make a rect class with the bullet rectangles properties Rect bullet = new Rect(Canvas.GetLeft(x), Canvas.GetTop(x), x.Width, x.Height); // check if bullet has left top part of the screen if (Canvas.GetTop(x) < 10) { // if it has then add it to the item to remove list itemstoremove.Add(x); } // run another for each loop inside of the main loop this one has a local variable called y foreach (var y in myCanvas.Children.OfType<Rectangle>()) { // if y is a rectangle and it has a tag called enemy if (y is Rectangle && (string)y.Tag == "enemy") { // make a local rect called enemy and put the enemies properties into it Rect enemy = new Rect(Canvas.GetLeft(y), Canvas.GetTop(y), y.Width, y.Height); // now check if bullet and enemy is colliding or not // if the bullet is colliding with the enemy rectangle if (bullet.IntersectsWith(enemy)) { // remove the bullet, remove the enemy and deduct 1 from the total enemies integer itemstoremove.Add(x); itemstoremove.Add(y); totalEnemeis -= 1; } } } } // we are back in the main loop again, this timer we need to animate the enemies // check again if the any rectangle has the tag enemy inside it if (x is Rectangle && (string)x.Tag == "enemy") { // move it towards right side of the screen with the enemy speed integer Canvas.SetLeft(x, Canvas.GetLeft(x) + enemySpeed); // if the enemeies have left the screen from the right if (Canvas.GetLeft(x) > 820) { // position it back in the left Canvas.SetLeft(x, -80); // move it down the screen by 20 pixels Canvas.SetTop(x, Canvas.GetTop(x) + (x.Height + 10)); } // make another local rect called enemy and put the new enemy properites into it Rect enemy = new Rect(Canvas.GetLeft(x), Canvas.GetTop(x), x.Width, x.Height); // check if the player character and the enemy are colliding if (player.IntersectsWith(enemy)) { // stop the timer and show a message that says you lose end game here dispatcherTimer.Stop(); MessageBox.Show("you lose"); } } // back at the main game loop again we need to check for enemy bullets now // check if any rectangle has the enemyBullet tag inside of it if (x is Rectangle && (string)x.Tag == "enemyBullet") { // if we have found it then we will drop it towards bottom of the screen Canvas.SetTop(x, Canvas.GetTop(x) + 10); // if the bullet has gone passed the screen then we can add it to the remove list if (Canvas.GetTop(x) > 480) { itemstoremove.Add(x); } // make a new local rect called enemy bullets and put the enemy bullets properites into it Rect enemyBullets = new Rect(Canvas.GetLeft(x), Canvas.GetTop(x), x.Width, x.Height); // check if the enemy bullet or the player rectangle is colliding if (enemyBullets.IntersectsWith(player)) { // if so stop the timer and show you lose message // game ends here dispatcherTimer.Stop(); MessageBox.Show("you lose"); } } } // this is the garbage collection loop // check for every rectangle thats added to the itemstoremove list foreach (Rectangle y in itemstoremove) { // remove them permanently from the canvas myCanvas.Children.Remove(y); } // if total enemies is 0 if (totalEnemeis < 1) { // stop the timer and show you win message dispatcherTimer.Stop(); MessageBox.Show("you win"); } } } }