WPF C# Tutorial – Create a fun Balloon popping game in visual studio

Game engine event –

This is the timer tick event. The reason we called this one game engine is because this event will carry out all of the instructions for this balloon pop game. The full game engine code is below. We will break it down into smaller parts and explain how it all works.

private void gameEngine(object sender, EventArgs e)
        {
            
                scoreLabel.Content = "Score: " + score; // link the score integer to the score label

                // deduct 10 from the intervals number
                intervals -= 10;
                // if interval is less than 1 then we will make new balloons for this game
                if (intervals < 1)
                {
                    // first create a new image brush for the balloons called balloomImage
                    ImageBrush balloonImage = new ImageBrush();
                    // add 1 to the balloon skins integer
                    balloonSkins += 1;

                    // if the skins integer goes above 5 reset back to 1
                    if (balloonSkins > 5)
                    {
                        balloonSkins = 1;
                    }

                    // check which skin number is selected and change them to that number
                    switch (balloonSkins)
                    {
                        case 1:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon1.png"));
                            break;
                        case 2:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon2.png"));
                            break;
                        case 3:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon3.png"));
                            break;
                        case 4:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon4.png"));
                            break;
                        case 5:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon5.png"));
                            break;
                    }

                    // make a new rectangle called new balloon
                    // inside this it has a tag called bloon, height 70 pixels and width 50 pixels and balloon image as the background
                    Rectangle newBalloon = new Rectangle
                    {
                        Tag = "bloon",
                        Height = 70,
                        Width = 50,
                        Fill = balloonImage
                    };

                    // set the top location of the balloon to 600 pixels so it spawns below the main window
                    Canvas.SetTop(newBalloon, 600);
                    // randomly set the left position between these two numbers
                    Canvas.SetLeft(newBalloon, rand.Next(50, 400));
                    // add the new item to the screen
                    MyCanvas.Children.Add(newBalloon);
                    // set the next interval between these two numbers
                    intervals = rand.Next(80, 140);
                }

                //this is the main game loop
                // find any rectangles present in this canvas
                foreach (var x in MyCanvas.Children.OfType<Rectangle>())
                {

                    // if the item is rectangle and has a tag bloon
                    if (x is Rectangle && (string)x.Tag == "bloon")
                    {
                        // randomly select between two numbers
                        i = rand.Next(-5, 5);
                        // move the balloon object towards top of the screen
                        Canvas.SetTop(x, Canvas.GetTop(x) - speed);
                        // randomly move the objects left and right position with i integer values
                        Canvas.SetLeft(x, Canvas.GetLeft(x) - (i * -1));

                    }

                    // if the balloon reach top of the screen
                    if (Canvas.GetTop(x) < 20)
                    {
                        // remove them
                        itemRemover.Add(x);
                        // add 1 missed integer
                        missedBalloons++;
                    }
                }

                // if you miss more than 10 balloons
                if (missedBalloons> 10)
                {
                    gameisactive = false;// set game active to false
                    gameTimer.Stop(); // stop the timer
                                      // show the message box below
                    MessageBox.Show("You missed 10 Balloons, press space to restart");
                }

                // if score if more than 20
                if (score > 20)
                {
                    // change the speed to 6
                    speed = 6;
                }


                // garbage collection
                // remove any item thats been added to the item remover list
                foreach (Rectangle y in itemRemover)
                {
                    MyCanvas.Children.Remove(y);
                }
            }

All of the codes are already explained in the comments (lines that start with the // in front of them)

                scoreLabel.Content = "Score: " + score; // link the score integer to the score label

                // deduct 10 from the intervals number
                intervals -= 10;
                // if interval is less than 1 then we will make new balloons for this game

In this code above we are linking the score label to the score integer in the timer. The timer will update the most frequently so it makes sense to keep this updated at all times. After that line we are deducting 10 from the interval’s integer.

if (intervals < 1)
                {
                    // first create a new image brush for the balloons called balloomImage
                    ImageBrush balloonImage = new ImageBrush();
                    // add 1 to the balloon skins integer
                    balloonSkins += 1;

                    // if the skins integer goes above 5 reset back to 1
                    if (balloonSkins > 5)
                    {
                        balloonSkins = 1;
                    }

                    // check which skin number is selected and change them to that number
                    switch (balloonSkins)
                    {
                        case 1:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon1.png"));
                            break;
                        case 2:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon2.png"));
                            break;
                        case 3:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon3.png"));
                            break;
                        case 4:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon4.png"));
                            break;
                        case 5:
                            balloonImage.ImageSource = new BitmapImage(new Uri("pack://application:,,,/files/balloon5.png"));
                            break;
                    }

                    // make a new rectangle called new balloon
                    // inside this it has a tag called bloon, height 70 pixels and width 50 pixels and balloon image as the background
                    Rectangle newBalloon = new Rectangle
                    {
                        Tag = "bloon",
                        Height = 70,
                        Width = 50,
                        Fill = balloonImage
                    };

                    // set the top location of the balloon to 600 pixels so it spawns below the main window
                    Canvas.SetTop(newBalloon, 600);
                    // randomly set the left position between these two numbers
                    Canvas.SetLeft(newBalloon, rand.Next(50, 400));
                    // add the new item to the screen
                    MyCanvas.Children.Add(newBalloon);
                    // set the next interval between these two numbers
                    intervals = rand.Next(80, 140);
                }

In the if statement above we first check if intervals number has gone below 1. Then we can start spawning different balloons to the screen. See how it works.

First, we create a new image brush called balloon image. This class will help get the images we imported to the game earlier and apply them to new rectangles we will make. After the image brush we are adding 1 to the balloon skin integer. We don’t want to make all of the balloons look the same, we want them to variable so the overall game looks vibrant. This balloon skin integer will be used in a switch statement to define which background image to use for the balloon objects. After that we check if the balloon skin integer has a value higher than 5 if so, we reset it back to 1. We are doing this because we have 5 different images of the balloon so by increasing the number to 5 and resetting, we are ensuring we use different images of the balloons for this game.

After that we have the big SWITCH statement, this statement will check which number is inside the balloon skins integer and assign an image to the balloon image brush class we created earlier.

For example, if the number is 3 then it will assign the 3rd image to the image brush class and that will be assigned as the balloon rectangles background.

After the switch statement we are creating the new rectangle called newBalloon this rectangle will have a tag called bloon, height 70 pixels and width 50 pixels. Lastly, we are linking the fill of the new balloon to the balloon image. After that set top places, the object on the y axis, in this case we are placing the balloon 600 pixels down from top of the screen and the left part of or the x axis is set to random. We don’t want all of the balloon to spawn exactly the same place but we want them to randomly come up so the game play feels organic. We are setting the new objects x axis to be randomly between 50 pixels and 400 pixels.

Last two lines in the code above is adding the new balloon to the canvas and setting the new interval value between 80 and 140.

All of the code above is responsible for making the new balloon and adding a background image to it, now we need to animate and add more rules to these bloons.

                //this is the main game loop
                // find any rectangles present in this canvas
                foreach (var x in MyCanvas.Children.OfType<Rectangle>())
                {

                    // if the item is rectangle and has a tag bloon
                    if (x is Rectangle && (string)x.Tag == "bloon")
                    {
                        // randomly select between two numbers
                        i = rand.Next(-5, 5);
                        // move the balloon object towards top of the screen
                        Canvas.SetTop(x, Canvas.GetTop(x) - speed);
                        // randomly move the objects left and right position with i integer values
                        Canvas.SetLeft(x, Canvas.GetLeft(x) - (i * -1));

                    }

                    // if the balloon reach top of the screen
                    if (Canvas.GetTop(x) < 20)
                    {
                        // remove them
                        itemRemover.Add(x);
                        // add 1 missed integer
                        missedBalloons++;
                    }
                }

Above is the main for each loop, this loop is checking through all of the balloon items in this game, animating them, moving them upwards and giving them the little shake animation. We also need to check if the balloons have left from top of the screens and add that to the missed integer.

The for each loops contains a variable called x, once we identify what we need then we can directly call this x and make changes to all of the items linked to x. the first if statement inside the for each loop is checking if X is a rectangle and it has a string called bloon. If both of these conditions are true then we will apply a random number between -5 and 5 inside the i integer. This integer will be used to get that shake effect in the game. After that we are setting the top location of the balloon inside the set top function, its deducting the value of speed from the current location of the balloon this way the balloon will get pushed upwards on the screen. We are setting the left or x axis of the balloon to the i integer we created earlier. But this one comes with a little twist, the i integer will be multiplied by -1 which means it will have either negative or positive values depending on the random number generator. This way if the i value is 5 it will become -5 or if its -5 it will become 5. This way the balloons will move between left and right quickly mimicking an actual balloon movement.

IF statement in bottom of the code if checking if the balloons have reached top of the screen, if it has then it be removed from the screen by adding it to the item remover list and adding 1 to the missed balloons integer.

                // if you miss more than 10 balloons
                if (missedBalloons> 10)
                {
                    gameisactive = false;// set game active to false
                    gameTimer.Stop(); // stop the timer
                                      // show the message box below
                    MessageBox.Show("You missed 10 Balloons, press space to restart");
                }

                // if score if more than 20
                if (score > 20)
                {
                    // change the speed to 6
                    speed = 6;
                }

In the if statement above we check if we missed 10 balloons during the run time of the game, if so we can set the game is active Boolean to false, stop the game timer and show a message box.

Second if statement is checking if the score is above 20 is so we will increase the speed 6.

                // garbage collection
                // remove any item thats been added to the item remover list
                foreach (Rectangle y in itemRemover)
                {
                    MyCanvas.Children.Remove(y);
                }

 

This is the last part of the game’s engine event, in this part we are removing all of the rectangles we’ve been collecting inside the item remove list. In this for each loop we check if any rectangles exist inside that item remove list, once its found it will be removed from the canvas and from the memory.

mooict wpf tutorial - click on the start button to start debugging the game

With all of that being click on the start button and see how the game works.

mooict wpf tutorial - the final part of the game its working, and all of the elements are working too for this balloon pop game

The works perfect, the balloons are moving up, its shaking side to side looks very nice, game ends when you missed 10, it speeds up when you have 20 than 20, you can reset the game by pressing space bar and you can click and remove items from the screen and lastly the sound works. If you managed to follow this game so far here, very well and be proud of the accomplishment here. See you on the next one. Stay curious moo’ers.

Go to the full source code page to see the full c# script for this balloon popping game.




2 responses to “WPF C# Tutorial – Create a fun Balloon popping game in visual studio”

  1. coco says:

    When I start the game it works fine but after a few pops the game stops and in the .cs says that there is an exception unhandled “the enumerator is not valid because the collection changed.” in:
    foreach(var x in MyCanvas.Children.OfType())

  2. mari says:

    @coco: I had the same problem. My brackets were closing in the wrong place.