baldwin.jpg

Programming with XNA Game Studio

What is OOP and Why Should You Care?

Learn about object-oriented programming in general. Also learn about the structure and syntax of an object-oriented C# program by taking a simple program apart and examining the elements of the program.

Published: 13 January 2010
Validated with Amaya

by Richard G. Baldwin

XNA Programming Notes # 0104


Preface

General

XNA Game Studio 3.1
Note that all references to XNA in this lesson are references to version 3.1 or later.

This tutorial lesson is part of a continuing series dedicated to programming with the XNA Game Studio. I am writing this series of lessons primarily for the benefit of students enrolled in an introductory XNA game programming course that I teach. However, everyone is welcome to study and benefit from the lessons.

An earlier lesson titled Getting Started (see Resources) provided information on how to get started programming with Micorsoft's XNA Game Studio. (See Baldwin's XNA programming website in Resources.)

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Supplemental material

I recommend that you also study the other lessons in my extensive collection of online programming tutorials.  You will find a consolidated index at www.DickBaldwin.com.

What is OOP

What is object-oriented programming (OOP)?

If you Google this question, you will get hundreds of answers. Here is one of those answers.

According to Wikipedia,

"Object-oriented programming (OOP) is a programming paradigm that uses "objects" – data structures consisting of datafields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as information hiding, data abstraction, encapsulation, modularity, polymorphism, and inheritance."

My answer

Here is my answer along with an anecdotal description. Unlike earlier programming styles, object-oriented programming is a programming style that mimics the way most people think and work.

An OOP solution to a problem should resemble the problem, and observers of the solution should be able to recognize the problem without necessarily knowing about it in advance.

For example, an OO program that deals with banking transactions should be recognizable on the basis of the objects that it uses, such as deposit objects, withdrawal objects, account objects, etc.

An anecdotal description

If you have ever assembled a playscape in your back yard, this should sound familiar to you.

When you opened the large boxes containing the playscape, hundreds of objects spilled onto the ground. Those objects may have consisted of braces, chains, swing seats, slides, screws, nuts, bolts, washers, climbing ropes, ladder rungs, and other assorted objects.

Atomic and non-atomic objects

I will refer to (most of) the kinds of object that I have described in the above list as atomic objects. What I mean by that is that they can't be easily subdivided into smaller objects without destroying their functionality.

If you were lucky, some of the objects in the box may not have been atomic objects. Instead they may have been pre-assembled arrangements of atomic objects such as an assembly of seats and braces representing a object on which two children can swing together.

Your job - assemble the objects

Your job was to assemble those hundreds of atomic and non-atomic objects into a final object which you proudly referred to as "The Playscape."

Objects working together

It has been said that a successful object-oriented program consists of a bunch of cooperating software objects working together to achieve a specified behavior.

The overall behavior of the program is the combination of behaviors of the individual objects. For example, some objects may acquire input data, other objects may compute and produce output data, while other objects may display the output data.

It could also be said that a playscape consists of a bunch of hardware objects working together to achieve a specified behavior. The overall behavior of the playscape is the combination of behaviors of the individual objects. For example, the behavior of some of the braces is to stand strong and not bend, while the behavior of a swing chain is to be flexible and move in a prescribed way.

Creating a model

One of the tasks often faced by an object-oriented programmer is to assemble software objects into a model that represents something that exists in the real world. As a very visual example, you might be asked to create an advertising web page showing an animated software model of the playscape that you assembled in your back yard. With the playscape, you were simply required to assemble the existing objects. However, in the object-oriented programming world, you must do more than just assemble objects.

Objects must be designed and manufactured

Getting back to the playscape, each of the objects for the playscape was manufactured before being shipped to you. Even before that, each object was designed by someone and a set of manufacturing drawings was probably created so that the object could be mass produced.

A class is analogous to manufacturing drawings

In OOP, there is a direct analogy to the manufacturing drawings of the hardware world. We call it a class. A class documents the specifications for the construction of a particular type of software object. For example, there is probably a set of classes that describe the specifications for each of the button objects and menu objects at the top of the browser in which you are currently viewing this lesson.

A large library of classes

As an object-oriented programmer, you will typically have access to a large library of existing classes from which you can construct different types of software objects, such as buttons, sliders, etc. For example, you will find links to the various XNA classes here.

Classes of your own design

In addition, you will often need to design and define new classes from which you can construct new types of objects.

Why should you care about OOP?

You need to care about OOP because the language of XNA is C# and C# is an object-oriented programming language. It is not possible to write a C# program without dealing with the object-oriented nature of the language.

It is also not possible to write credible XNA programs without frequent reference to the XNA documentation. Although the use of the XNA framework will shield you from some of the difficulties of object-oriented programming, you will still have both feet in the OOP sandbook as soon as you consult the documentation.

The XNA documentation package is huge

For example, the XNA Framework Class Library lists eleven namespaces (over and above the namespaces in the standard C# library).

One of those namespaces is named Microsoft.Xna.Framework.Graphics. That namespace lists about 175 different classes.

One of those classes is the SpriteBatch class. The SpriteBatch class lists several members including one constructor, four public properties, ten public methods, two protected methods, and one event.

The SpriteBatch class is probably one of the most commonly used classes in the XNA framework so you will need to be able to understand the documentation for all or at least most of the members of that class.

The good news

The good news is that the documentation also provides numerous code samples and explanatory notes to help you use the documentation to write your code correctly.

Three important concepts

Any object-oriented language must support three very important concepts:

We use these three concepts extensively as we attempt to model the real-world problems that we are trying to solve with our object-oriented programs. I will provide brief descriptions of these concepts in this lesson and then explain each concept in detail in future lessons.

Encapsulation example

Consider the steering mechanism of a car as a real-world example of encapsulation. During the past eighty years or so, the steering mechanism for the automobile has evolved into an object in the OOP sense.

Only the interface is exposed

In particular, most of us know how to use the steering mechanism of an automobile without having any idea whatsoever how it is implemented. All most of us care about is the interface,which we refer to as a steering wheel. We know that if we turn the steering wheel clockwise, the car will turn to the right, and if we turn it counterclockwise, the car will turn to the left.

How is it implemented?

Most of us don't know, and don't really care, how the steering mechanism is actually implemented "under the hood." In fact, there are probably a number of different implementations for various brands and models of automobiles. Regardless of the brand and model, however, the human interface is pretty much the same. Clockwise turns to the right, counterclockwise turns to the left.

Expose the interface and hide the implementation

As in the steering mechanism for a car, a common approach in OOP is to "hide the implementation" and to "expose the interface" through encapsulation.

Inheritance example

Another important aspect of OOP is inheritance. Let's form an analogy with the teenager who is building a hotrod. That teenager doesn't normally start with a large chunk of steel and carve an engine out of it. Rather, the teenager will usually start with an existing engine and make improvements to it.

OOP lingo

In OOP lingo, that teenager extends the existing engine, derives from the existing engine, inherits from the existing engine, or subclasses the existing engine (depending on which author is describing the process).

Just like in "souping up" an engine for a hotrod, a very common practice in OOP is to create new improved classes and objects by extending existing class definitions.

Extending the Game class

When you use Visual C# to create a new XNA game project, the IDE creates skeleton code for a new class. As you will learn later in this course, it is then up to you to put some meat on the skeleton and turn it into a game. The first executable statement in the skeleton code is shown in Listing 1.

Listing 1. Extending the Game class.

public class Game1 : Microsoft.Xna.Framework.Game

The code in Listing 1 is the first executable statement in the definition of a new class named Game1 (or whatever name you give the new project). The definition of the new class extends an existing class named Game, which resides in the Microsoft.Xna.Framework namespace. The existing class named Game, is the main controller for your new game. I will have much more to say about the Game class in a future lesson.

Reuse, don't reinvent

One of the major arguments in favor of OOP is that it provides a formal mechanism that encourages the reuse of existing programming elements. One of the mottos of OOP is "reuse, don't reinvent."

Polymorphism example

A third important aspect of OOP is polymorphism. This is a Greek word meaning something like one name, many forms. This is a little more difficult to explain in non-programming terminology. However, we will stretch our imagination a little and say that polymorphism is somewhat akin to the automatic transmission in your car. In my Honda, for example, the automatic transmission has four different methods or functions known collectively as Drive (in addition to the functions of Reverse, Park, and Neutral).

Select Drive to go forward

As an operator of the automobile, I simply select Drive (meaning go forward). Depending on various conditions at runtime, the automatic transmission system decides which version of the Drive function to use in every specific situation. The specific version of the function that is used is based on the current conditions (speed, incline, etc.). This is somewhat analogous to what we will refer to in a subsequent tutorial lesson as runtime polymorphism.

Object-oriented programming vocabulary

OOP involves a whole new vocabulary (or jargon) which is different from or supplemental to the vocabulary of procedural programming.

For example the object-oriented programmer defines an abstract data type by encapsulating its implementation and its interface in a class.

One or more instances of the class can then be created or instantiated.

An instance of a class is known as an object.

Every object has state and behavior where the state is determined by the current values stored in the object's instance variables and the behavior is determined by the instance methods belonging to the object.

Inherited abstract data types are derived classes or subclasses of base classes or super classes. We extend super classes to create subclasses.

Within the program the code instantiates objects (creates instances of classes) and sends messages to the objects by calling the class's methods (or member functions).

If a program is "object oriented", it uses encapsulation, inheritance, and polymorphism. It defines abstract data types, encapsulates those abstract data types into classes, instantiates objects from the classes, and sends messages to the objects.

The members of a class fall generally into one of the following categories:

The individual members of a class can be public, private, or protected.

To make things even more confusing, almost every item or action used in the OOP jargon has evolved to be described by several different terms. For example, we can cause an object to change its state by sending it a message, calling its methods, or calling its member functions. The term being used often depends on the author who wrote the specific book that you happen to be reading at the time.

Hopefully most of this terminology will become clear as we pursue these lessons

Discussion and sample code

I usually try to provide some code in each lesson that you can compile and execute. Listing 2 contains the C# code for a simple program that will display the words "Hello C# World" on the system console screen when you compile and run it. (The system console screen will probably appear as a black window when you run the program.)

You can learn a lot...

You may be surprised at how much you can learn about the structure and syntax of an object-oriented program in C# by taking this simple program apart and examining the elements of the program. Note, however, that this program is strictly class based. It does not instantiate any objects.

Listing 2. Hello World in C#.

//File Program.cs
using System;
namespace Hello01{

    class Hello01{

        static void Main(string[] args){
            Console.WriteLine("Hello C# World");
            //Press any key to dismiss console screen.
            Console.ReadKey();
        }//end Main

    }//end class definition

}//end namespace

A new class definition

The central block of code, bounded by the magenta highlights, defines a new class named Hello01.

The Main method

You probably learned that every C++ program requires a function named main. Execution of the C++ program begins and ends in the main function.

The same is true in C#. Every C# program requires a method named Main (note the upper-case "M"). However, unlike in C++, the Main method in C# must be defined inside of a class definition.

Methods versus functions

Methods in C# are analogous to the functions defined inside a class in C++. However, they are called methods instead of functions in C#.

Definition of the Main method

The block of code bounded by the cyan highlights in Listing 2 defines the Main method.

The WriteLine method

As you may have guessed already, the call to the WriteLine method inside the Main method causes the WriteLine method's argument to be displayed on the system console.

The Console class

Console is the name of a static class in the System namespace. The significance of the class being static is that "You do not need to declare an instance of a static class in order to access its members." Therefore, as I mentioned earlier, this program doesn't purposely instantiate any new objects.

According to the documentation, the Console class "Represents the standard input, output, and error streams for console applications. This class cannot be inherited."

The System namespace

The System namespace actually belongs to the Microsoft .NET framework and the classes in the namespace are available for use by several different programming languages that also belong to the framework such as C#, VB.NET, etc. (See the online .NET Framework Class Library here.)

Members of the Console class

The Console class has many members, about nineteen of which are overloaded versions of the method named WriteLine. (Method overloading means that the same method name can be used two or more times in the same scope as long as the argument list differs from one version to the next.)

The version of the WriteLine method that is called in Listing 2 requires a string object as an incoming parameter. According to the documentation, the behavior of this version of the method is:

"Writes the specified string value, followed by the current line terminator, to the standard output stream."

The dot operator

Note the period that joins the name of the class and the name of the method in Console.WriteLine. When used in this way, the period is often referred to as the dot operator. The dot operator is used in a variety of similar but different ways in C#. In this case, it tells the compiler to look in the Console class for a method named WriteLine that requires an incoming parameter of type string. (It is actually the type of parameter being passed to the method, (string), which specifies which version of the WriteLine method will be executed.)

Namespaces

Briefly, namespaces provide a way to partition the class library and the new classes defined in a program so that it is possible to reference two classes with the same name in the same scope as long as they are in different namespaces. Therefore, whenever you reference a class name in your code, you must tell the compiler which namespace it resides in. This can be done in two ways. One way is to write the namespace in front of the class name joined by the dot operator as in System.Console, or Microsoft.Xna.Framework.Graphics.SpriteBatch.

The "using" declaration

The second way to tell the compiler which namespace the class resides in is through the use of a "using" declaration.

As long as it won't create name conflicts, you can tell the compiler that you are "using" the namespace as shown by the first line with the yellow highlight in Listing 2. Then you don't need to refer to the namespace when you reference a class belonging to that namespace in your code.

Not much help in this case

In this case, since the Console class was referenced only once, it would have been simpler to join the class name with the namespace name using the dot operator and to omit the "using" declaration. However, in those cases where the class name is referenced more than once in the code, it is simpler to declare the namespace at the beginning to avoid having to type it more than once. This is particularly true in the case of the SpriteBatch class shown above where the namespace name contains several levels separated by periods.

Defining your own namespace

When you define a new class, you should always define the namespace in which it resides. (I believe this is a requirement when developing projects using Visual C#.)

The project file structure

Figure 1 shows the project file structure for the Hello01 project. (This image was captured from the Solution Explorer window in the Visual C# IDE.)

Figure 1 Project file structure.
 Project file structure.

The class definition shown in Listing 2 is contained in the file named Program.cs at the bottom of the tree in Figure 1. Note that this file is contained in the folder named Hello01. Also note that the folder named Hello01 is a child of another folder named Hello01 at the top of the project tree. (There are two folders named Hello01 in the project tree.)

The Hello01 namespace

The second line with the yellow highlight in Listing 2 defines the namespace in which the new class resides. Note that it is the name of the folder in which the file resides. Note also that it is specified relative to the top of the project tree.

If the folder containing the class happened to be more than one level down in the project tree, as is the case of the Graphics folder that contains the SpriteBatch class, it would be necessary to use periods to trace down the tree as shown above.

The call to the ReadKey method

Listing 2 also contains a call to a method named ReadKey, which also belongs to the Console class. The purpose of this call is to cause the execution of the program to block and wait until the user presses any key. Otherwise, the console window would appear on the computer screen momentarily and then disappear almost as soon as it appears.

Run the program

I encourage you to copy the code from Listing 2.  Use that code to create a Visual C# Console Application project.  Build and run the project.  Experiment with the code, making changes, and observing the results of your changes.  Make certain that you can explain why your changes behave as they do. 

Summary

You learned something about object-oriented programming in general in this lesson. You also learned quite a bit about the structure and syntax of an object-oriented C# program by taking a simple program apart and examining the elements of the program.


Copyright

Copyright 2009, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is object-oriented programming using Java and other OOP languages.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP). His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments. (TI is still a world leader in DSP.) In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com

-end-