PopIt Game – Abstract & Sealed Classes

PopItCd

PopItMainForm

This simple game demonstrates more class / object inheritance along with showing how abstract and sealed classes work together. Along with my previous programs on using arrays to store data. You will notice from the class designer picture that the RoundPopper, StringPopper, and RectanglePopper classes all derive from the Popper abstract class. Also the OvalPopper derives from the RoundPopper classes while deriving from the OvalPopper class. I know more complicated that it needs to be. I just did it this way to show the inheritance concepts.

Now onto viewing the source code. Or you can download the source.

MainForm Class


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PopIt
{
    public partial class MainForm : Form
    {
        PoppersList _poppersList = new PoppersList();           //For the list of poppers.
        private Color _popperColor = Color.Red;                 //For the popper color.
        private int _hits = 0;                                  //Hit counter.
        private int _popperCount = 4;                           //Number of poppers.
        private int _timerMilliseconds = 6000;                  //Refresh time.
        private int _popperSize = 40;                           //Size of our popper.
        private int _maximumPoppers = 6;                        //The maximum number of poppers.
        Random _random = new Random();                          //Random generator.

        public MainForm()
        {
            InitializeComponent();

            //Setting up the progress bar.
            remainingToolStripProgressBar.Minimum = 0;
            remainingToolStripProgressBar.Maximum = _timerMilliseconds;
            remainingToolStripProgressBar.Step = processTimer.Interval;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            addPoppers();
            mainPictureBox.Invalidate();
        }

        private void addPoppers()
        {
            //Add until we reach the current maximum
            while (_poppersList.Length < _popperCount)
            {
                //Generate random x and y positions. If they overlap don't worry.
                int x = _random.Next(0, mainPictureBox.ClientRectangle.Width - _popperSize - 1);
                int y = _random.Next(0, mainPictureBox.ClientRectangle.Height - _popperSize - 1);
                int number = _random.Next(0, 3);

                //Create a rectangle and determine which object to display.
                Rectangle rectangle = new Rectangle(x, y, _popperSize, _popperSize);
                if (number == 0)
                    _poppersList.Add(new RectanglePopper(rectangle, _popperColor));
                else if (number == 1)
                    _poppersList.Add(new RoundPopper(rectangle, _popperColor));
                else if (number == 2)
                    _poppersList.Add(new StringPopper(rectangle, _popperColor));
                else
                    _poppersList.Add(new OvalPopper(rectangle, _popperColor));
            }
        }

        private void mainPictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            //Disable the timer.
            processTimer.Enabled = false;

            //Check all the poppers to see if we hit.
            for (int i = 0; i < _poppersList.Length; i++)
            {
                if (_poppersList[i].Hit(new Point(e.X, e.Y)))
                {
                    //Update the status label with hits using pre-increment.
                    popsToolStripStatusLabel.Text = "Pops: " + (++_hits).ToString();

                    //Delete the popper from the list.
                    _poppersList.Delete(_poppersList[i]);
                }
            }
            //Re-enable the timer and force a repaint event.
            processTimer.Enabled = true;
            mainPictureBox.Invalidate();
        }

        private void mainPictureBox_Paint(object sender, PaintEventArgs e)
        {
            //Clear everything on the screen.
            e.Graphics.Clear(mainPictureBox.BackColor);

            //Draw all of the poppers.
            for (int i = 0; i < _poppersList.Length; i++)
                _poppersList[i].Draw(e.Graphics);
        }

        private void processTimer_Tick(object sender, EventArgs e)
        {
            //Disable the timer.
            processTimer.Enabled = false;

            //Determine the next progress bar value.
            int value = remainingToolStripProgressBar.Value - remainingToolStripProgressBar.Step;

            //Prevent the progress bar value from going below 0, and update the progress bar.
            if (value < 0)
                value = 0;
            remainingToolStripProgressBar.Value = value;

            //Only process if we are short any poppers, and we've reached the end of the timer.
            if (_poppersList.Length < _popperCount && value == 0)
            {
                if (_poppersList.Length == 0)
                {
                    //Only increment popper count if cleared within the time frame.
                    if (_popperCount <= _maximumPoppers)
                        _popperCount += 1;
                }
                //Add the necessary poppers.
                addPoppers();
            }
            //Reset the progress bar.
            if (value == 0)
                remainingToolStripProgressBar.Value = remainingToolStripProgressBar.Maximum;

            //Re-enable the timer and force a repaint event.
            processTimer.Enabled = true;
            mainPictureBox.Invalidate();
        }

        private void resetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ResetGame();        //Resetting the game board.
        }

        //Setting the game to beginner game settings.
        private void beginnerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            processTimer.Enabled = false;                                   //Stopping the timer.
            _hits = 0;                                                      //Resetting the number of current hits.
            popsToolStripStatusLabel.Text = "Pops: " + _hits.ToString();    //Resetting the number of hits display.
            _popperCount = 4;                                               //Changing the inital popper count.
            _timerMilliseconds = 6000;                                      //Speeding up the timer countdown.
            _popperSize = 40;                                               //Decreasing the popper size.
            _maximumPoppers = 6;                                           //Increasing the maximum popper count.
            processTimer.Enabled = true;                                    //Re-enabling the timer.
            ResetGame();                                                    //Resetting the game.
        }

        //Setting he game to intermediate game settings.
        private void intermediateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            processTimer.Enabled = false;
            _hits = 0;                                                      
            popsToolStripStatusLabel.Text = "Pops: " + _hits.ToString();    
            _popperCount = 6;                                               
            _timerMilliseconds = 4000;                                      
            _popperSize = 30;                                               
            _maximumPoppers = 10;                                           
            processTimer.Enabled = true;                                    
            ResetGame();                                                    
        }

        //Setting the game to advanced game settings.
        private void advancedToolStripMenuItem_Click(object sender, EventArgs e)
        {
            processTimer.Enabled = false;                                   
            _hits = 0;                                                      
            popsToolStripStatusLabel.Text = "Pops: " + _hits.ToString();    
            _popperCount = 10;                                               
            _timerMilliseconds = 2000;                                      
            _popperSize = 20;                                               
            _maximumPoppers = 15;                                           
            processTimer.Enabled = true;                                    
            ResetGame();                                                    
        }

        //Method used to reset the game board.
        private void ResetGame()
        {
            //Looping thru the array, removing each item, and clearing the array.
            for (int i = 0; i < _poppersList.Length; i++)
            {
                _poppersList.Delete(_poppersList[i]);
            }
            _poppersList.Clear();
            mainPictureBox.Invalidate();
        }
    }
}

PoppersList Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PopIt
{
    public class PoppersList
    {
        private Popper[] _poppers = null;

        //The indexer.
        public Popper this[int index]
        {
            get { return _poppers != null ? _poppers[index] : null; }
        }

        //Count of the poppers.
        public int Length
        {
            get { return _poppers != null ? _poppers.Length : 0; }
        }

        //Adding a popper.
        public int Add(Popper popper)
        {
            //Create or resize our poppers array.
            if (_poppers == null)
                _poppers = new Popper[1];
            else
                Array.Resize(ref _poppers, _poppers.Length + 1);

            _poppers[_poppers.Length - 1] = popper;
            return _poppers.Length;
        }

        //Deleting a popper.
        public void Delete(Popper popper)
        {
            if (_poppers != null && _poppers.Length > 1)
            {
                Popper[] newPopper = new Popper[_poppers.Length - 1];
                int counter = 0;
                
                foreach(Popper item in _poppers)
                    if (item != popper)
                        newPopper[counter++] = item;

                Clear();
                _poppers = newPopper;
            }
            else
                Clear();
        }

        //Clearing all the poppers.
        public void Clear()
        {
            if (_poppers != null)
            {
                //Remove the reference to the popper objects, then undimension the poppers array.
                Array.Clear(_poppers, 0, _poppers.Length);
                _poppers = null;
            }
        }
    }
}

Popper Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace PopIt
{
    public abstract class Popper
    {
        public Color PopperColor;
        public int X;
        public int Y;
        public int Width;
        public int Height;
        public string Message;
        public Font MessageFont;

        public Popper(Rectangle rectangle, Color color)
        {
            PopperColor = color;
            X = rectangle.X;
            Y = rectangle.Y;
            Width = rectangle.Width;
            Height = rectangle.Height;

            //Randomizing the letters displayed on the screen.
            string[] randomLetters = { "#", "%", "&", "@" };                //Storing the letters to be used.
            Random random = new Random();                                   //Creating a Random object.
            int randomNumber = random.Next(0, randomLetters.Length);        //Getting a random number to be used as an idexer.
            string letter = randomLetters[randomNumber];                    //Using the indexer to set the random letter.
            Message = letter;
            MessageFont = new Font("Arial", 16);
        }

        public Rectangle GetRectangle()
        {
            return new Rectangle(X, Y, Width, Height);
        }

        public abstract void Draw(Graphics graphics);

        public abstract bool Hit(Point point);
    }
}

RoundPopper Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace PopIt
{
    public class RoundPopper : Popper
    {
        public RoundPopper(Rectangle rectangle, Color color) : base(rectangle, color)
        {
            //Constructor to enable us to call the base contructor.
        }

        public override void Draw(Graphics graphics)
        {
            //Draw the ellipse.
            graphics.DrawEllipse(new Pen(base.PopperColor), base.X, base.Y, base.Width, base.Height);
        }

        public override bool Hit(Point point)
        {
            //Calling the abstract base class method.
            return base.GetRectangle().Contains(point);
        }
    }
}

StringPopper Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace PopIt
{
    public sealed class StringPopper : Popper
    {
        public StringPopper(Rectangle rectangle, Color color) : base(rectangle, color)
        {
            //The child constructor that enables us to call the base constructor.
        }

        public override void Draw(Graphics graphics)
        {
            graphics.DrawString(base.Message, base.MessageFont, new SolidBrush(base.PopperColor), base.X, base.Y);
        }

        public override bool Hit(Point point)
        {
            return base.GetRectangle().Contains(point);
        }
    }
}

RectanglePopper Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace PopIt
{
    public sealed class RectanglePopper : Popper
    {
        public RectanglePopper(Rectangle rectangle, Color color) : base(rectangle, color)
        {
            //The constructor to enable us to call the base constructor.
        }

        public override void Draw(Graphics graphics)
        {
            //Draw a rectangle.
            graphics.DrawRectangle(new Pen(base.PopperColor), base.X, base.Y, base.Width, base.Height);
        }

        public override bool Hit(Point point)
        {
            //Call the abstract base class method.
            return base.GetRectangle().Contains(point);
        }
    }
}

OvalPopper Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace PopIt
{
    public sealed class OvalPopper : RoundPopper
    {
        public OvalPopper(Rectangle rectangle, Color color) : base(rectangle, color)
        {
            //The child constructor that enables us to call the base constructor.
        }

        public override void Draw(Graphics graphics)
        {
            int newWidth = base.Width / 2;      //Getting the new width so the ellipse looks like an oval shape.

            graphics.DrawEllipse(new Pen(base.PopperColor), base.X, base.Y, newWidth, base.Height);
        }

        public override bool Hit(Point point)
        {
            return base.GetRectangle().Contains(point);
        }
    }
}

Leave a comment