WPF C# Tutorial – Create a space battle shooter game in Visual Studio

Full Source C# for the Space Shooter Game Tutorial in WPF-

Below are all of the code and logic for the space shooter game in WPF. XAML code for this project is available on the first page so this is the C# script that makes the game work in the background. The green lines are all comments so you can use them or dispose them if you wish. One of the important programming principle is that you comment on the code. if you are using this as a course work please make sure you use your own comments and change the project to your requirement and not submit this as your own work.

Leave a comment for us to see how you got on with the project, we will be very pleased to read your comments.

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_shooter_game
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //make a game timer
        DispatcherTimer gameTimer = new DispatcherTimer();
        // move left and move right boolean decleration
        bool moveLeft, moveRight;
        // make a new items remove list
        List<Rectangle> itemstoremove = new List<Rectangle>();
        // make a new random class to generate random numbers from
        Random rand = new Random();


        int enemySpriteCounter; // int to help change enemy images
        int enemyCounter = 100; // enemy spawn time
        int playerSpeed = 10; // player movement speed
        int limit = 50; // limit of enemy spawns
        int score = 0; // default score
        int damage = 0; // default damage

        Rect playerHitBox; // player hit box to check for collision against enemy


        public MainWindow()
        {
            InitializeComponent();

            gameTimer.Interval = TimeSpan.FromMilliseconds(20);
            // link the game engine event to the timer
            gameTimer.Tick += gameEngine;
            // start the timer
            gameTimer.Start();
            // make my canvas focus of this game
            MyCanvas.Focus();

            // make a new image brush instance called bg
            ImageBrush bg = new ImageBrush();
            // pass the purple image as the bg image source
            bg.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/purple.png"));
            // set bg to tile mode 
            bg.TileMode = TileMode.Tile;
            // set the height and width of bg image brush
            bg.Viewport = new Rect(0, 0, 0.15, 0.15);
            // set the bg view port unit
            bg.ViewportUnits = BrushMappingMode.RelativeToBoundingBox;
            // assign bg as the background of my canvas
            MyCanvas.Background = bg;


            // make a player image, image brush
            ImageBrush playerImage = new ImageBrush();
            // load the player image into it
            playerImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/player.png"));
            // assign the player to the player rectangle fill
            player.Fill = playerImage;
        }

        private void onKeyDown(object sender, KeyEventArgs e)
        {
            // if the left key is pressed
            // set move left to true


            // if the right key is pressed
            // set move right to true

            if (e.Key == Key.Left)
            {
                moveLeft = true;
            }
            if (e.Key == Key.Right)
            {
                moveRight = true;
            }
        }

        private void onKeyUp(object sender, KeyEventArgs e)
        {
            // if the left key is released
            // set move left to false


            // if the right key is released
            // set move right to false

            if (e.Key == Key.Left)
            {
                moveLeft = false;
            }
            if (e.Key == Key.Right)
            {
                moveRight = false;
            }

            // if the space key is released
            // make a new rectangle called new bullet
            // give this rectangle a tag called bullet
            // height set to 20, width set to 5
            // background colour white and border colour red

            if (e.Key == Key.Space)
            {
                Rectangle newBullet = new Rectangle
                {
                    Tag = "bullet",
                    Height = 20,
                    Width = 5,
                    Fill = Brushes.White,
                    Stroke = Brushes.Red
                };

                // place the bullet on top of the player location
                Canvas.SetTop(newBullet, Canvas.GetTop(player) - newBullet.Height);
                // place the bullet middle of the player image
                Canvas.SetLeft(newBullet, Canvas.GetLeft(player) + player.Width / 2);
                // add the bullet to the screen
                MyCanvas.Children.Add(newBullet);
            }
        }

        private void makeEnemies()
        {
            // this function will make the enemies for us including assignning them images

            ImageBrush enemySprite = new ImageBrush(); // make a new image brush called enemy sprite

            enemySpriteCounter = rand.Next(1, 5); // generate a random number inside the enemy sprite counter integer

            // below switch statement will check what number is generated inside the enemy sprite counter
            // and then assign a new image to the enemy sprite image brush depending on the number

            switch (enemySpriteCounter)
            {
                case 1:
                    enemySprite.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/1.png"));
                    break;
                case 2:
                    enemySprite.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/2.png"));
                    break;
                case 3:
                    enemySprite.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/3.png"));
                    break;
                case 4:
                    enemySprite.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/4.png"));
                    break;
                case 5:
                    enemySprite.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/5.png"));
                    break;
                default:
                    enemySprite.ImageSource = new BitmapImage(new Uri("pack://application:,,,/images/1.png"));
                    break;
            }

            // make a new rectangle called new enemy
            // this rectangle has a enemy tag, height 50 and width 56 pixels
            // background fill is assigned to the randomly generated enemy sprite from the switch statement above

            Rectangle newEnemy = new Rectangle
            {
                Tag = "enemy",
                Height = 50,
                Width = 56,
                Fill = enemySprite
            };


            Canvas.SetTop(newEnemy, -100); // set the top position of the enemy to -100
            // randomly generate the left position of the enemy
            Canvas.SetLeft(newEnemy, rand.Next(30, 430));
            // add the enemy object to the screen
            MyCanvas.Children.Add(newEnemy);

            // garbage collection
            GC.Collect(); // collect any unused resources for this game
        }

        private void gameEngine(object sender, EventArgs e)
        {
            // link the player hit box to the player rectangle
            playerHitBox = new Rect(Canvas.GetLeft(player), Canvas.GetTop(player), player.Width, player.Height);

            // reduce one from the enemy counter integer
            enemyCounter--;

            scoreText.Content = "Score: " + score; // link the score text to score integer
            damageText.Content = "Damaged " + damage; // link the damage text to damage integer

            // if enemy counter is less than 0
            if (enemyCounter < 0)
            {
                makeEnemies(); // run the make enemies function
                enemyCounter = limit; //reset the enemy counter to the limit integer
            }

            // player movement begins

            if (moveLeft && Canvas.GetLeft(player) > 0)
            {
                // if move left is true AND player is inside the boundary then move player to the left
                Canvas.SetLeft(player, Canvas.GetLeft(player) - playerSpeed);
            }
            if (moveRight && Canvas.GetLeft(player) + 90 < Application.Current.MainWindow.Width)
            {
                // if move right is true AND player left + 90 is less than the width of the form
                // then move the player to the right
                Canvas.SetLeft(player, Canvas.GetLeft(player) + playerSpeed);
            }

            // player movement ends

            // search for bullets, enemies and collision begins

            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 reached 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))
                            {

                                itemstoremove.Add(x); // remove bullet
                                itemstoremove.Add(y); // remove enemy
                                score++; // add one to the score
                            }
                        }

                    }
                }

                // outside the second loop lets check for the enemy again
                if (x is Rectangle && (string)x.Tag == "enemy")
                {
                    // if we find a rectangle with the enemy tag

                    Canvas.SetTop(x, Canvas.GetTop(x) + 10); // move the enemy downwards

                    // make a new enemy rect for enemy hit box
                    Rect enemy = new Rect(Canvas.GetLeft(x), Canvas.GetTop(x), x.Width, x.Height);

                    // first check if the enemy object has gone passed the player meaning
                    // its gone passed 700 pixels from the top
                    if (Canvas.GetTop(x) + 150 > 700)
                    {
                        // if so first remove the enemy object
                        itemstoremove.Add(x);
                        damage += 10; // add 10 to the damage
                    }

                    // if the player hit box and the enemy is colliding 
                    if (playerHitBox.IntersectsWith(enemy))
                    {
                        damage += 5; // add 5 to the damage
                        itemstoremove.Add(x); // remove the enemy object
                    }
                }


            }

            // search for bullets, enemies and collision ENDs

            // if the score is greater than 5
            if (score > 5)
            {
                limit = 20; // reduce the limit to 20
                // now the enemies will spawn faster
            }

            // if the damage integer is greater than 99
            if (damage > 99)
            {
                gameTimer.Stop(); // stop the main timer
                damageText.Content = "Damaged: 100"; // show this on the damaged text
                damageText.Foreground = Brushes.Red; // change the text colour to 100
                MessageBox.Show("Well Done Star Captain!" + Environment.NewLine + "You have destroyed " + score + " Alien ships");
                // show the message box with the message inside of it
            }

            // removing the rectangles

            // check how many rectangles are inside of the item to remove list
            foreach (Rectangle y in itemstoremove)
            {
                // remove them permanently from the canvas
                MyCanvas.Children.Remove(y);
            }


        }

    }
}

 




7 responses to “WPF C# Tutorial – Create a space battle shooter game in Visual Studio”

  1. Daniel Rymes says:

    Having difficulties with URI definition. The original version failed during the build. Code compiled fine after replacing with relative version: `new Uri(@”../images/player.png”, UriKind.Relative)`. However, app is breaking, because it can’t find the image in …\bin\Debug\images\purple.png.

    Wondering if the issue could be related to URI syntax of if something’s wrong with the build process (e.g. missing/wrong item csproj). Any fix suggestions?

  2. Anhar Ali says:

    Hi Daniel, you made the images folder inside the debug folder. This folder needs to be in the main application directory. In page 1 of the tutorial it shows how to make the folder inside the solutions explorer, and then you can import the images into it.

  3. David Macák says:

    Thank you for this tutorial. I am new to C# and WPF and just found your fantastic web and your tutorials. I like this style of tutorials where you actually make something useful and fun. I made this and learned a lot by writing the code myself rather than ctrl+v.

    Also after limit = 20; it gets much harder 😀

  4. Hi Mr. Moo says:

    Well done thank you for all the education to the internet!!!!!!!!!!!! <3

  5. Matthew Marse says:

    a fun tutorial to do because we are in space shooting alien space *suits* I mean if that’s not fun

  6. Davor Kreß says:

    Your sites are very helpful and cool. Thank you very much.

  7. Anhar Ali says:

    Thank You. 🙂