Learn Object Oriented Programming By Creating a Game

In this tutorial we will be creating a game. A game is a great way to illustrate object oriented programming (OOP). Object oriented programming, as the name suggests, is a style of programming where you model your code after objects, and a game is full of objects. We will have a player, enemies, and bullets. Although probably not award winning, we will also create our own graphics for the game. You can see the complete source code for the game on GitHub. At the end of the guide there will also be a series of practice exercises, as well as some common interview questions that you should be able to answer after going through this guide. We will be using C# as our programming language, a common language that there are many jobs for. We will use Visual Studio Community Edition as our code editor which you can download for free. Don’t worry if you don’t know some of the technologies that we will be using, this is a complete guide and it will show you how to set everything up.

Support

I will do my best to help anyone who follows this guide. Although this guide is as comprehensive as I could make it, if you are new to programming you might feel a little lost from time to time. The first thing you should try is to google your problem. Being able to find solutions on Google is an invaluable skill, and you will be doing a lot of it throughout your career. After having tried to solve the problem yourself, you are more than welcome to email me at codesupport [at] oamatech [dot] com. Please post your code somewhere online that I can access it, preferably GitHub or some other code repository. Don’t add attachments to the email. I am excited by the opportunity to help you learn how to program, and I am happy to help you in any way that I can.

What we will create

We are going to create a 2D game, similar to a spaceship fighter game. There will be a constant stream of enemies coming, and the game will end if any of them reaches you. You will have bullets that you can shoot the enemy with and if you hit one they will die and disappear from the game board. Some of the exercises at the end involve modifying the game.

Before we can create our game there are certain topics we have to learn about, that is what this guide is for after all. Please go through the guide from start to finish, and make sure that you can complete the exercises and interview questions at the end before moving on. You will likely use object oriented programming a lot in your career so getting a good understanding of it is important.

What will you learn?

This guide will teach you more than just object oriented programming and its related concepts. You will also learn how to use Visual Studio, how you can connect GitHub with Visual Studio, and how you can plan out a project like this. Being able to use source control like GitHub is incredible important. There is not a single (hopefully) job where you won’t be using version control.

Things you will learn in this guide:

  • Object Oriented Programming and related concepts
  • How to set up a project in Visual Studio
  • How to connect Visual Studio to GitHub
  • How to plan a project
  • How to implement your project design
  • How to create a game loop
  • How to move items around on the screen

What you will not learn

This is not a complete guide on how to program in general. I expect you to have some knowledge of programming before starting. That being said, I will link to many useful resources throughout the guide, and you could use those to gain more knowledge. I also believe that learning by doing is better than just watching a 20 hour long video course. So if you don’t feel comfortable with programming you can simply look up what you don’t understand as you go along. Since you are learning about what object oriented programming is I will assume that you are fairly new to programming, and this guide has been written with that in mind. You can also download the complete source code from GitHub and start playing around with it.

Why use object oriented programming?

Most who learn programming start out writing all their code in a single file. Many then graduate to splitting their code into multiple files. As you learn more, the code becomes more complex and you need a way to manage that complexity. You need a way to make your programs flexible and reusable. Object oriented programming is a way to solve complex problems with fairly simple code. I say “fairly” because any program can become large and complex, but at least OOP can help you manage that complexity. It is also worth mentioning that planning and design is your best friend when it comes to managing complexity. No tool or pattern will help you more than spending a lot of time thinking through your problem and solution before you write a single line of code.

In order to understand object oriented programming there are a few concepts that need to be covered. They are inheritance, polymorphism, abstraction, and encapsulation. Those four topics are the pillars of OOP. The idea of a class is also central and needs to be covered. The words might seem foreign at first, but once you learn what they are and how you can use them they will become tools that you can use to your advantage. You will also feel more comfortable in interviews for your first job as they will surely ask you about these concepts. Before we can create our game and learn about object oriented programming, we need to learn about classes.

What is a class and how do you create one?

You can not use object oriented programming without being able to use classes, they are the objects in object oriented programming. A class is commonly called a blueprint, and an object is called an instance of a class. You can think of a class as being like the architectural drawings of a house. It tells you how many rooms there are, where the toilets are located, and if there is a garage or not. What it does not say is how many chairs you have in the living room, what color the house is, or how many cars are parked in the garage. An object on the other hand does say those things. An object is like the actual constructed house, with all the details such as the colors of the walls and the number of televisions.

In essence, a class consists of properties and methods. The properties store values and the methods are things that the class can do. A class also has one or more constructors, as well as an access modifier which controls who can use or access the class.

The elements of a class

A class consists of an access modifier, a class keyword, a class name, a constructor, properties, and methods.

Access modifiers

Access modifiers is an important topic. You class, your properties, and your methods will all have access modifiers. The modifier is what determines who can access the class or use a property or method. You don’t always want everyone to be able to access the properties or use the methods in your class. In C# there are six modifiers that you can use. They are public, private, protected, internal, protected internal, and private protected. For a class, if you don’t specify a type then it will be public by default. That being said, you should get into the habit of typing the access modifier as it explicitly states the access level and shows that you are aware of what you are doing. Top level types, such as a class, can only have either public or internal access modifier. If the class is nested inside another class though they can have any of the access modifiers. Top level means that it is not nested inside something else  (except from inside a namespace). It is the “top” level in the file you are writing it in.

Public

As public might suggest, if a class is marked as public then there is no restrictions on who can use the class. This is probably one of the more common modifiers you will use. The same goes for properties and methods, if they are public then there is no limitation on who can use them. As you start learning how to program it is probably best to just stick to public access modifiers. As you feel more comfortable you can start exploring the others and learn when and why to use them.

Private

If private is used then the item can only be accessed from inside the class itself, and from nowhere else. Private is the strictest modifier. This is a great modifier to use if you have properties or methods inside a class that are being used only inside that class. There is no reason to expose things that others do not need or even care about. Once you start caring about security this is a common access modifier as it prevents others from accessing your variables and methods.

Protected

The protected keyword is used when you want to limit the use of a class member to only inside the class itself, or in classes derived from that class. We will get into what derived means when we talk about inheritance.

Internal

Internal means that the code can only be used inside the same assembly. An assembly is a file that is outputted after compiling the program. When using c# they are the .dll files that are produced when you compile your program. The reason why this matters is that you can use other people’s assemblies. But if something is marked as internal, then only code inside that assembly will be able to use it. A library is a good example of something you might use. If there is code in that library that they don’t want to expose they can mark it as internal.

Protected Internal

In protected internal you can access the item anywhere in the same assembly, or from a derived class that is in a separate assembly. This means that you are able to use that functionality as long as you derive from the class.

Private Protected

Private protected limits access to only inside the same class, or in a class derived from that class. That means, if you create an instance of class “A” somewhere, you can not access the property marked as private protected inside of “A”. You can only access the property inside of “A” (that is inside the class itself, not through an instance of the class) or inside a class that derived from “A”.

For now you are probably okay with sticking with public classes. The same goes for methods and properties. We will also use the private modifier to illustrate a concept later in the guide.

Class keyword

There is nothing special to learn about the class keyword. It is simply a keyword for declaring that something is a class. The only thing to keep in mind in C# is that the class keyword is always lower case, while the name of the class should always start with an upper case.

Class name

The main thing to know about class names is that they should start with an upper case letter. A few examples of class names include Television, Laptop, and Book. Those are all words that you could use as a class name. Those classes will then have properties and behaviors associated with them.

Constructor

The constructor is an important part of a class. Actually, it is so important that if you don’t create one yourself you will be given one for free. A constructor’s job is to instantiate a class. If you have ever seen the “new” keyword being used with a class, that is using the constructor to create a new instance of that class. If you have properties in your class, you can pass values to it and have it assign those values to your properties. The constructor you can get for free is called a default constructor, and it does not instantiate any properties in your class.

There is a lot to learn about constructors if you are interested, but for our purpose there are only some things that are of interest.

First, a class can have many constructors, You can use method overloading to create different constructors that are called based on the number of inputs you use.

Second, a constructor always has the same name as the class it is inside. Even if you have multiple constructors they all need to have the same name as the class. What differs among them are the input parameters.

Properties

Properties, also known as variables, are places to store data. A property can pretty much be whatever you would like. You can have strings, integers, objects, arrays, lists, you name it. Properties also uses the access modifiers that we looked at earlier. Also, since properties are inside a class and therefore nested, you can always use all of the access modifiers. You can instantiate values inside a class either through a constructor, or through the class instance at a later point.

Methods

Methods define what a class can do. It is the bread and butter of a class, and you will likely spend most of your time programming on methods. A method is also called a function. You also give access modifiers to methods. Some methods you want to only be called from inside the class, and some methods you want to be able to call from outside the class.

Now that we have looked at access modifiers, the class keyword, the class name, the constructor, properties, and methods, lets look at how to create a class in C#.

The syntax to create a class usually starts with an access modifier, followed by the class keyword, then the class name and lastly a set of curly braces. Everything else goes inside the curly braces. Once we get to inheritance we will see that there is one more thing that can go outside the curly braces but lets hold off for just a bit.

How to create a class

We will create a House class. Remember how a class is like the architectural drawings of a house. We will now define features of our house in the class.

public class House
{
    public int NumberOfRooms {get; set;}
    public int SquareFeet {get; set;}
    public int NumberOfBedrooms {get; set;}
    public int NumberOfBathrooms {get; set;}

    public AlarmSystem SecuritySystem {get; set;}

    public House(int rooms, int squareFeet, int bedrooms, 
         int bathrooms, AlarmSystem system)
    {
        this.NumberOfRooms = rooms;
        this.SquareFeet = squareFeet;    
        this.NumberOfBedrooms = bedrooms;
        this.NumberOfBathrooms = bathrooms;   
        this.SecuritySystem = system;
    }

    public void SetAlarm()
    {
        this.SecuritySystem.SetAlarm();
    }

    public void UnlockAlarm(int code)
    {
         this.SecuritySystem.UnlockAlarm(code);
    }
}

.

How to create an instance of a class

In the example above you can see a series of properties. We even have a class called “AlarmSystem” as a property. A class can have pretty much anything you want as a property. We also have a constructor, notice that the name of the constructor is the same as the name of the class. There is also two methods that call a method on the instance of the “AlarmSystem” class

Now that we have our first class we shall look at how we can create an instance of the class.

// Instance of the alarm system class that we will pass
// to the constructor of the House class. 
AlarmSystem system = new AlarmSystem();

// The house class.
House myHouse = new House(10, 1500, 3, 3, system);

// Now we can also use the method that we created
myHouse.SetAlarm();
myHouse.UnlockAlarm("mySecretPassword123");

We now know quite a bit about classes. We know what a class consists of, what access modifiers we can use,  how to create a class, and how to instantiate one. As we create more and more classes, often we notice that many of them have things in common. For example, if we had a House and a Cabin class. Both a House and a Cabin are buildings. They both have walls, bedrooms, windows, and so on. It can be quite cumbersome to rewrite code to represent common items over and over again for each class. Luckily, we don’t have to. One of the pillars of object oriented programming, inheritance, solves this problem for us.

Inheritance

Inheritance in programming is not so difference from inheritance in real life. Much like how one person can receive things from someone else, so can a class receive things from another class. Inheritance is when a class receives properties, behaviors, and constructors from another class. It is a great tool for code re-usability and flexibility. Inheritance is also an “is-a” relationship. If something inherits from something, that means it should be of the same type, perhaps just more specific. A classic example is if you have a class Person. Then you go ahead and create a class Professor. A professor is a Person right? Also, you can create a class Student which also inherits from class Person, because a student is a person too? You can put common properties in the Person class such as age, gender, height, weight, and so on. You are able to use the Person class to define common properties so that you don’t have to write it twice.

For this guide we are using C#. C# only supports single inheritance, meaning that a class can only inherit from one other class. You can not inherit from two classes at once. You can still have a chain of inheritance going many classes though, but each chain in the link only inherits from one other class. Some of the access modifiers that we discussed limits what can be inherited or used in the child class.

Now how could we apply inheritance to the game we will create? Lets think about our Player and Enemy classes. Both the player and the enemies are in essence game objects, or creatures if you will. Our enemies are monsters and our player is a ship, but they both are items in our game. We can create a class GameObject that holds common properties among the two and then both classes will inherit from our base GameObject class.

With inheritance we can declare certain methods as virtual. A virtual method allows a method to be overwritten in the derived class. If the child class does not overwrite the method then the implementation in the parent class will be used.

Inheritance example

Let us start with creating part of the GameObject class, which will the parent class of both Player and Enemy class.

public class GameObject
{
    // Each object will move on the screen. This is 
    // how fast they will move
    public int Speed {get; set;}
    
    public GameObject(int speed)
    {
        this.Speed = speed;
    }
    
    // Each class will override this method and return
    // the correct graphics for their class
    public virtual Image GetImage() {return null}
    
    // Each object will be able to move in each direction 
    // We will add a function for left and right here
    public void MoveLeft(int speed)
    {
        this.Left -= speed;  
    }
    
    public void MoveRight(int speed)
    {
        this.Left += speed;
    }   
}

We now have a GameObject class that we can use as a base for our other classes. In order for a class to inherit from another class we have to explicitly say so. We do that by using a colon after the class name, followed by the name of the class we want to inherit from.

 
public class ClassA : ClassB 
{ 
    // We can access properties and methods from ClassB here.
} 

Remember that there are access modifiers that limit what we can access when we inherit from a class. Now that we have the GameObject class, we can create an early version of the player class.

public class Player : GameObject
{
    // We don't need to declare any variables here unless
    // we have new ones We get all the properties from the 
    // GameObject class because of inheritance. 
    
    public Player(int speed) : base(speed)
    {
        // We passed the speed parameter to the 
        // parent constructor. We can do initialization
        // unique to the player class here
    }

    // Overriding the virtual method
    public override Image GetImage()
    {
        return Graphics.Hero;
    }
}

There is an important concept in the example above. As you can see we are using something called “base()” in the constructor. The base keyword makes it so that we call the constructor in the parent class. We pass the relevant arguments along and the constructor in the parent class takes care of initializing those variables. We then go ahead and initialize the variables that are custom to the Player class.

Overriding

From time to time there might be methods in the parent class that we would like to use, but we want it to behave slightly different. We want the same name of the method so that we can easily call the same method but have different behavior based on what class it is. We can achieve this through overriding. Each class can have its own implementation of a method.

A common example is if you have a class Shape. The Shape class defines a method called “Draw()”. Then you create multiple classes, square, circle, triangle, and so on. They all implement their own “Draw()” function, because they are drawn differently. So if you create an instance of a circle class and call the Draw method on it, it will draw a circle. The square will draw a square and so on.

We can use virtual method with our move method. All our objects will be moving, but their implementation will be slightly different. Our player will move from side to side and up an down. The enemies will move downwards. Our bullets will move straight forward. A virtual method is great for this, because in our game loop we can call the “update” function on each object, and depending on what the object is it will behave accordingly. This way we don’t have to have all sorts if statements and check what object we are working with, and then do the logic specific to that class. This way we are using concepts from object oriented programming.

Polymorphism

Polymorphism is another important pillar in object oriented programming. Polymorphism is the ability of an object to take on many different forms. Our shape class for example can be a circle, a square, or a triangle. We can assign an instance of class Circle to a variable of type shape. We can also assign an instance of class Square to a variable of type shape. The Shape object can take the form of any derived class, meaning it can take on many different forms. For each shape variable, if we call the “draw()” function it will use the correct draw function from the child class. We will use the same concept with our game. We will assign instances Player, Enemy, and Bullet to variables of type GameObject.

 
public class Shape
{
    public virtual void Draw(){}
}

public class Triangle : Shape 
{
    public void Draw()
    {
        Console.WriteLine('Triangle draw function');
    }
}

public class Square : Shape
{
    public void Draw()
    {
        Console.WriteLine('Square draw function');
    }
}

Shape triangle = new Triangle();
Shape square = new Square();

triangle.Draw(); 
square.Draw(); 

One very important thing to remember is that a parent class can point to a child class, but a child class can not point to a parent class. Specifically, only parent classes can be on the left side of the equal sign, the derived class always goes on the right side of the equal sign.

 
// Allowed
Shape triangle = new Triangle(); 
Shape square = new Square(); 

// Not allowed
Square square = new Shape();
Triangle triangle = new Shape();

Encapsulation

Encapsulation is about packaging code within a logical container or package. You package properties and methods inside a class, effectively encapsulating it. Encapsulation is closely related to abstraction. You encapsulate items by setting their access modifier and moderating their access through what is called getters and setters. A setter allows you to provide a value to a method and that method will set the variable in the class for you. You don’t access the property of the class directly, you do so through a setter. A getter is the same idea,  just opposite. A getter retrieves a specific value for your rather than you going directly to the property yourself. If you remember the access modifiers, you prevent others from accessing your properties by setting them to private. Since your setter and getter methods are inside the class they can still access them. And from the outside you can use the setters and getters because they are not set to private

Example of encapsulation

 
public class Box
{
    private int volume;
 
    public GetVolume(){
        return this.volume;
    }

    public SetVolume(int newVolume){
    {
        this.volume = newVolume;
    }
} 

In C# you automatically get this behavior if you write {get; set} after the variable. You will see this in the guide. In most other languages, you have to write all the setter and getter code yourself.

Abstraction

Abstraction is achieved through encapsulation. Your class provides methods that the user can use. The user has no idea how the methods work, just that they do. Abstraction is hiding away the implementation of your business logic, making it easier and less complex for the consumer.

A real world example of abstraction is a car. You know how to drive a car, you know how to steer and so on. But do you know what happens inside the car when you press the gas pedal or turn the wheel? Those implementations are hidden away from you inside the car. The engineers have provided you with a pedal and a wheel that you can use. You have no idea how they work, just that they do.

We will use abstraction in our game too. In our classes we will have our update/move methods. In our game loop we will only use the move methods, we don’t care how they are implemented, just that they move our objects. Because we hide away the implementation inside the classes, when we are using them at a later point it is a lot easier. We just call the update method and the object updates itself. Since we created the class we know the inner workings of the methods of course. But if we were providing this code to a colleague, they only have to use the specific method, they don’t know anything about how it is implemented.

Summary

We have now learned the basics of object oriented programming. We know how to use classes, the objects in object oriented programming. We know how classes can inherit from other classes. We know how a parent class can point to a child class through polymorphism. We know how to encapsulate methods and properties. And we know how to make code understandable through abstraction.

It is now time to use these skills to create a game. As stated before, a game is full of objects, and it is a great way to explore object oriented programming. Before we can actually write any code or start planning our game we have to set up our development environment. If you have not already downloaded Visual Studio and signed up for a free GitHub account, now is the time to do it. If you happen to be a student you can get a lot of really nice programming tools and free premium GitHub by using their GitHub student pack. If you are a student checking out their student pack is mandatory.

Setting up our development environment

I will be on the windows platform. If you have a Mac or a Linux machine, such as Ubuntu, the steps might be a bit different. You don’t have do use GitHub, but if you want to learn how to easily push your code without having to use the command line then this is good practice.

  1. Sign up for a GitHub account
  2. Download Visual Studio Community Edition.

Connecting Visual Studio to our GitHub account

We will now connect GitHub and Visual Studio 2019.

The first thing we need is the GitHub extension for Visual Studio (VS). To get this, launch VS and open the extension window. At the top of VS There is a button that says “Extensions” -> “Manage Extensions”

Then in the next window you click on “Online” in the left hand side menu, search for “GitHub” in the search box in the upper right hand corer -> Select the GitHub extension -> Click download

After clicking on the “Download” button you have to close Visual Studio for it to complete the installation.

Once you reopen Visual Studio we need to open the “team explorer” window. If it is not already open you can find it by going to “views” -> “Team Explorer”, and it should show up in the right hand menu. It is possible it will show up somewhere else, but each window in VS you can snag to different locations.

In the Team Explorer window there will be a link that says “connect”. When you click this button there will be a popup where you can enter your login details to connect visual studio to GitHub.

When you have logged in you should see a new GitHub section in the Team Explorer window with three options. We can Clone, create, and sing out. We want to create a new repository for your Game which we will call “OamaTechBattleGame”.

When you click on the “create” link you will get another popup where you can fill in some more details. You will give the name of the repository, a description, a local path (this is where on your computer you will save the files), a GitIgnore settings, a license file setting. If you have a premium GitHub account you can also make your repository private.

After clicking the “Create” button you can see in your GitHub that there is a new repository created.

We have now successfully connected GitHub to Visual Studio 2019. If you are using an older version of Visual Studio the only difference should be that where you download the extension in Visual Studio is located slightly different. It should be under tools -> Extensions for older versions.

Some people like to use the command line to push changes to GitHub, but there is really no need to do so. GitHub also has its own software that you can use to upload and download with, but I find that using Visual studio for version control management is quite nice. There is also the topic of branching and merging that we will not get into in this post. Most often you have a master branch where you keep code that works, often your previous production release. And when you want to make some modification you do that is a different branch and merge it into the master branch later. Since this is a brand new repository there is no need to do that, as we don’t have working production code already.

Now that we have set up our development environment we are just about ready to create our game. The last thing we need to do is to actually plan out what we are going to have in our game and how we are going to implement our various features.

Planning our game

There is nothing more important to successfully completing a piece of software than planning. Proper planning will not make you immune to mistakes, but you are much less likely to have to rewrite everything. You can also take your design ideas to someone else who can help you make improvements. It is a lot quicker to draw something on a piece of paper than spending days or even weeks writing code that you have to throw out because it is so bad. Starting over can be quite alluring sometimes when you get stuck, but that is one of the biggest time waste there are. It is better to spend a lot of time planning before so that you minimize the risk of doing that. I can’t stress this enough, planning and design is perhaps the most important step of your development.

Before we write a single line of code we need to figure out all the classes that we are going to have, as well as what properties and methods they shall have. We also need to figure out how we are going to draw things on the screen and how we are going to get the players and enemies to move around.

Let us start by deciding what classes we definitely need to represent the known objects in our game. Most of them we have discussed throughout the guide already.

Classes that we need

  1. GameObject
  2. Player
  3. Enemy
  4. Bullet

GameObject

Properties:
  1. The game object will contain common properties among our three other classes.
    1. int Speed: This is how fast the object will be moving
Methods:
  1. virtual void UpdateObject: The update method will be responsible for moving the object. Each object moves differently so it needs to be overridden in each class.
  2. virtual Image GetImage(): The GetImage method will return the correct image for the specific class.

The game object will also be a User Control. In Visual Studio, a user control is a graphical component, and it will make it a lot easier for us to draw things on the screen. The GameObject class will inherit from the UserControl class, giving us a lot of functionality for free. This is a great example of how we can use inheritance to receive functionality from other classes.

Player

Properties

We will not have any extra properties for the player class.

Methods
  1. override Image GetImage(): This method will return the image for the player class.
  2. override void UpdateObject: The player method will have its own implementation of the update function. The player will react to keyboard input.

Enemy

Properties

The enemy class will also not have any extra properties.

Methods
  1. override void UpdateObject: The enemies will also have their own move implementation. They will not react to keyboard input, but when they make their way across the screen they will start back at the other side but one row lower. If they make it all the way to the player then the game is over.’
  2. override Image GetImage(): Will return the image for the enemy class.

Bullet

Properties

The bullet class will not have any extra properties.

Methods
  1. override void UpdateObject(): The bullet class will have its own implementation of the update function. During each iteration of the game loop we will have the bullet move itself to have it go closer to the target.
  2. override Image GetImage(): Will return the correct image for the bullet class.

When making a a game we also need something called a game loop. The game loop is basically a loop that runs continuously until the game is over. During each iteration of the loop we will update our game. Each iteration we have to move the player and the enemies, we have to check if any of the enemies have reached the player, and we have to check if the player hit any of the enemies with the bullets. For this project we will use Timer class. A Timer will call a method every x milliseconds/seconds. The method we will call will call the UpdateObject on all the GameObjects, as well as check for any collisions.

We are going to use a Windows Form to create the UI for our game. In the code for the Form we are going to have the timer.

Now that we know what classes we need we are ready to set up the structure of our project.

Project Setup

Inside the repository that we created earlier we are going to create a solution. In visual studio, a solution is what holds your projects. A project is a collection of files, where you write code in each file. We are going to have two projects. One for holding all our classes, and one for being our main program that has our game loop and our graphics.

Implementing our game

We are now ready to start creating out very own game using principles from object oriented programming.

Adding the solution

Lets start with creating a new project. It should be a Windows Forms App (.NET Framework). We will be using this because it provides us with an easy way to draw graphics on the screen. The location should be inside the repository folder that you created earlier. You can add a new solution by going to file -> New -> Project – Find Windows Forms app project -> Fill in information -> Check the box for “place solution and project in the same directory”.

Creating a new solution and project in visual studio

Once you click create you will have a brand new solution with a project inside it. The one project that you have now will be the one that is responsible for displaying our graphics. We are going to create another one to hold our game classes.

Uploading our initial files to GitHub

The first thing we will do is actually to check in our code, meaning we will upload it to GitHub. You can do this by going to team explorer -> changes. You will then see an area where you can enter a commit message, and all the files that have changes since last time you checked in. You want the commit message to be as descriptive as possible, so that when you go back and look at old ones you can easily find the one you are looking for.

Click on commit, and then on sync to share the changes with the server. Once you have synced your changes you will be able to see all the files show up in your GitHub account.

Adding a new project

Next we will create the project that will hold our classes. Right click on the solution -> click “Add” -> “New Project”. On the popup screen you should select a .Net Framework class library project. We will simply call this project GameObjects. Delete the default class that is created inside the project, it should be called class1.

Adding more class files

Now we want to add new project files. One for each of the classes that we have planned. You can add a class by right clicking on the project and selecting “New” and then “New Item”. You should select a class file and name it according to the names that we planned. All the files should be C# class files except for the GameObject file.

The GameObject should be a User Control, not a regular class file.

Image of a class file in visual studio

  1. GameObject (User Control)
  2. Player (Class)
  3. Enemy (Class)
  4. Bullet (Class)

Once you are done your solution explorer should look like the following. Notice that the GameObject file has a different symbol than the rest. This represents that it is a user control. If you right click on it and click on view code, you will see that it is a class that inherits from the UserControl objects. It also has a constructor that calls a method to initialize the components of the user control.

Adding custom graphics

I created my graphics using Paint. Feel free to spend some more time to create your own images. The Player and the Enemy are 50×50 pixels, and the bullet is 10×5 pixels. Save them to some location on your laptop and continue with the steps below.

Now we want to add the custom graphics we have made for this game. We do that by right clicking the GameObjects project -> Add -> New Item -> Resources File. I renamed mine to be called “Graphics.resx”.

Now to add our files you click on “Add Resource” -> “Add existing file” -> Select all the images and click open.

Adding visual assets

Filling out the class files

Next lets start filling out our classes. We will start with the GameObject class. 

GameObject.cs
public class GameObject : UserControl{
    public int Speed { get; set; }

    public GameObject()
    {
        InitializeComponent();
    }

    // The child classes will implement GetImage() to return
    // the correct image to use for the specific object.
    public PictureBox GetPictureBox()
    {
        return new PictureBox()
        {
            Image = this.GetImage(),
            Size = new System.Drawing.Size(this.Width, this.Height),
        };
    }
    
    public virtual Image GetImage() { return null; }
    public virtual void UpdateObject(){}

    public void MoveLeft(int speed)
    {
        if(this.Left > 0)
        {
            this.Left -= speed;
        }
    }
    
    public void MoveRight(int speed)
    {
        this.Left += speed;
    }
    
    public void MoveDown(int speed)
    {
        this.Top -= speed;
    }

    public void MoveUp(int speed)
    {
        this.Top += speed;
    }
}

The GameObject class holds the common Speed variable that we will use. The Speed variable determines how fast the items will move across the screen when they update. There are also virtual methods that all the classes need to implement so that they can move across the screen correctly.

Bullet.cs

Note that once you inherit from the GameObject class, the symbol for the class will change in Visual Studio. This shows you that we are inheriting from a UserControl class (Through the GameObject class). You will also see that you will have a graphics designer if you double click on the class after inheriting. You will have to right click on the file and click on “code” to get to where you can write code for the class.

Image of symbols changing

Next let us create the Bullet class. Each time when the player clicks the space bar a new bullet will spawn in front of the spaceship. The bullet will propel itself forward, and if it collides with an enemy then both the enemy and the bullet will disappear.

The bullet class will inherit form the GameObject class, and we need to implement GetImage() and UpdateObject(). The GetImage() method will return the correct image for the bullet class. The UpdateObject() will be responsible for propelling the bullet forward. In the constructor we will also initialize the size of the graphics and the speed of the bullet. If you want to change how fast the bullet travels you can do that here.

The Bullet constructor will take a Point as a parameter. The Point is an object that holds an x,y coordinate, which determines where to place the object on the screen. We will pass this coordinate from the player. As the bullet will spawn in front of the spaceship and we need to know the current location of the player when the user hits the space bar, and pass that into the Bullet constructor.

 
public class Bullet: GameObject 
    public Bullet(Point location)
    {
        // Adds the graphics to the bullet UserControl
        this.Controls.Add(this.GetPuctureBox());

        // Sets how far the bullet will travel each 
        // iteration of the game loop
        this.Speed = 50;

        // Sets the size of the image representing the object.
        // This should match the actual size of the images
        // you have created for the game. 
        this.Height = 10;
        this.Wdith = 5;

        // Sets the starting location of the bullet
        this.Location = location;
    }

    // Returns the Bullet image when we call GetImage
    // on an object of type GameObject
    public override Image GetImage()
    {
        return Graphics.Bullet;
    }

    // Moves the bullet up, and removes the bullet
    // if it has moved out of the visible area.
    public override void UpdateObject()
    {
        this.MoveUp();
        if(this.Top < 0)
        {
            this.ParentForm.Controls.Remove(this);
        }
    }

 

Next let us do the Player class.

Player.cs

Our player will be responding to us clicking on the keyboard. In order to make that happen we have to listen to certain events. We will be listening to the KeyDown and KeyUp events. Each iteration of the game loop, if a key is pressed and it is the left button then our object will move left, if it is the right button then it will move right. If we click the space bar we will fire a bullet.

 
public class Player : GameObject
{

    public Player()
    {
        this.Controls.Add(this.GetPictureBox());
        this.Width = 50;
        this.Height = 50;
    }

    public override Image GetImage()
    {
        return Graphics.Hero;
    }

    public override void UpdateObject()
    {
        if (Keyboard.IsKeyDown(Key.Left))
        {
            this.MoveLeft(this.Speed);
        }
        else if (Keyboard.IsKeyDown(Key.Right))
        {
            this.MoveRight(this.Speed);
        }
        else if (Keyboard.IsKeyDown(Key.Up))
        {
            this.MoveUp(this.Speed);
        }
        else if (Keyboard.IsKeyDown(Key.Down))
        {
            this.MoveDown(this.Speed);
        }
        else if (Keyboard.IsKeyDown(Key.Space))
        {
            GameObject bullet = new Bullet(new Point(this.Left + 25, this.Top -25));
            this.ParentForm.Controls.Add(bullet);
        }
    }
}

Now we need to create the code in the form that will hold our game loop and call UpdateObject() on all our GameObjects.

public partial class Form1 : Form
{
    // Variable to stop the game when the player dies
    public bool GameOver { get; set; }
  
    // Timer that will serve as our game loop
    DispatcherTimer timer = new DispatcherTimer
    { 
        Interval = TimeSpan.FromMilliseconds(50)
    };

    // Timer that will spawn enemies every so often
    DispatcherTimer enemyTimer = new DispatcherTimer
    {
        Interval = TimeSpan.FromMilliseconds(1000)
    };

    public Form1()
    {
        // Create a player object and add it to the screen
        InitializeComponent();
        Player p = new Player();
        p.Speed = 30;
        p.Location = new Point(this.Height, this.Width / 2);
        this.Controls.Add(p);
        init();
    }
    public void init()
    {
        GameOver = false;
 
        // Set which method to call each tick
        // of the timer
        timer.Tick += GameLoop;
        timer.Start();

        // Timer that will spawn an enemy
        enemyTimer.Tick += SpawnEnemy;
        enemyTimer.Start();
    }
    
    public void SpawnEnemy(object sender, EventArgs e)
    {
        // We will use a random number to determine where on the
        // screen the enemy will spawn
        Random rand = new Random();
        int placement = (int)(this.Width * rand.NextDouble());
        if(placement < 50)
        {
            placement = 50;
        }   
        else if(placement > this.Width - 50)
        {
            placement = this.Width - 50;
        }
    
        // Create a new enemy object and add it to the screen.
        GameObject eo = new Enemy(new Point(placement, 0));
        this.Controls.Add(eo);
    }
    
    public void GameLoop(object sender, EventArgs e)
    {
        if (GameOver) return;
       
        // We have to loop over all the obejct on our 
        // UI and call the UpdateObject method. We also 
        // have to check for collisions and
        // update accordingly 
        foreach (GameObject c in this.Controls)
        {  
            c.UpdateObject();
            if (c is Enemy)
            {
                if (GameOver) return;
                foreach (GameObject b in this.Controls)
                {
                    if (b is Bullet)
                    {
                        // If a bullet collides with an enemy
                        // the enemy dies and should be removed.
                        // The bullet will also be removed.
                        if (c.Bounds.IntersectsWith(b.Bounds))
                        {
                            this.Controls.Remove(b);
                            this.Controls.Remove(c);
                        }
                    }
                    else if(b is Player)
                    {
                        // If the player collids with an enemy
                        // the game is over
                        if (c.Bounds.IntersectsWith(b.Bounds))
                        { 
                            timer.Stop();
                            enemyTimer.Stop();
                            GameOver = true;
                            MessageBox.Show("GAME OVER");
                            return;
                        }
                    }
                 }
              }
           }
        }
    }
}

The very last thing that we have to do is to add some code to our Program.cs file. That is the entry point to our game, and we have to launch the form from there.

 
static void Main()
{
    Application.EnableVisualStyles();
    Form1 form = new Form1();
    Application.Run(form);
}

We now have a working game that you can play. Click the green play button in VS to launch the game.  You can see and download the full source code on GitHub.

Button to launch program

Here is a screenshot of the finished game

Image of finished game

We have now created a game using the principles of object oriented programming. We have created classes, used inheritance, and used polymorphism by having our GameObject take on many different forms. We have used encapsulation with getters and setters. And we have used Abstraction through using methods to do all the work for us.

The last thing we will do is to push our changes to our GitHub account. You can do this by right clicking on the solution -> Commit -> Enter commit message -> commit all -> Sync

Exercises for you to do

To cement your knowledge it is important that you actually do some programming yourself. Please try to do the following modifications to the game. Some of these are not particularly easy.

  1. Add lives to the player class. When the enemy hits the player, only stop the game when the player has no lives left
  2. Make the player lose a life if the enemy makes it to the other side of the screen
  3. Display the number of lives on the screen
  4. Create a second type of enemy that takes more bullets to kill.
  5. Make the player have limited bullets

Common interview questions

  1. You can find common object oriented programming interview questions on the following pages:
    1. GeeksForGeeks
    2. Guru99
    3. Medium

If you found this guide helpful, please consider sharing it on your social media. Also, please feel free to email me with any questions you might have. You can find the email in the Support paragraph at the top of the page.