Search

Login



Privacy Policy

New user sign-up is disabled because of spam bots harassing this domain. Until I found a working solution, you can use the contact form and ask me for a new account. Sorry.
-Cygon

Advertising

Home Blog Game Development Game Architecture Day 2

Game Architecture Day 2 Print E-mail
Written by Markus Ewald   
Tuesday, January 19 2010 19:24

Stylish logo of two engaged gears with the text XNA Game Architecture

Welcome to day 2 of the XNA Game Architecture series!

I have thought hard about whether I should just assume a certain level of object oriented programming knowledge in this series. People picking up these articles likely already have some knowledge about objects and design, so I settled on a quick run-over of the principles that hopefully won't bore the seasoned developers and provide a good reference for people just starting out!

If you already know all this, feel free to skip ahead until it becomes interesting again or to the next chapter ;)!

Modularization

Many programmers using XNA to learn programming end up with something like this:

UML diagram of a huge Game class with dozens of members

That's quite okay for someone doing his first steps, but obviously, as the code grows larger, this kind of design becomes pretty hard to maintain and it will be increasingly difficult to remember what all those fields are there for and where the code for doing something needs to go.

No programmer is capable of keeping every method and every field of even a moderately sized game in his head at once, so we break the problem down into small parts that we can understand - using methods and classes. It's a bit more work to write those classes and to wire them up to each other, but if we do our job well, the project is much easier to maintain and we have more fun working on it, too!

Here's what might become of above class with some modularity applied:

UML diagram of a lean Game class encircled by several other classes

Knowing what to turn into classes and how to make them interact with each other comes with experience. And hopefully, by the end of this series, you will have a bit more of that! ;)

Encapsulation

As the game grows, the number of classes will also grow until there are too many of them interacting with each other to keep track of. So classes alone are not the final solution to keeping a game's code base manageable.

One method of combatting this complexity is to limit the amount of members exposed by a class. This is best illustrated with an example: Imagine you were writing a DVD burning application. At some point, you will have to delve into the gory details of the some obscure API used to control the DVD drive.

One could sprinkle bits of this code all over the application. The drive selection dialog would contain some code that looks at what DVD drives are available, the burn dialog would contain some code that sends the data to be burned to the DVD drive bit by bit, and so on -- like this:

UML diagram of a DVD burning application with IOCTLs in the Form classes

But this makes it hard to keep track of what's going on. Worse even, if you later port that application, say from WinForms to WPF, you have to isolate all those pieces of code from its dialogs and re-add them to the WPF code. And if you decide to also create a command-line version of the application, oh well...

Instead of spreading the DVD drive control code everywhere, you can encapsulate all that complicated stuff behind a small class:

class DvdWriter {
  public DvdDrive[] GetDrives();
  public void WriteIso(DvdDrive drive, string isoPath);
  public void VerifyDvd(DvdDrive drive);
}

There might be a lot going on behind those three methods, there might even be multiple classes involved - the point is, from the outside (meaning the rest of the application), only those three methods are visible.

UML diagram of a DVD burning application with IOCTL logic in a separate class

  • When modifying the DvdWriter class, you only need to be concerned with doing what the three methods promise to do. You can completely eradicate the rest of the application's code from your mind.
  • Vice versa, when working on other parts of the application, you don't have to remember the details of how the DVD drive control code works. There are three simple methods to call and their names reveal exactly what they do.

Of course, the art lies in finding appropriate places where the interactions between classes can be trimmed down to just a few methods. This, too, is a matter of experience. Good programmers intentionally design towards making it possible to build self-contained, encapsulated classes. One trick is to look for where the concerns change: the dialog is concerned with managing the user interface, the DVD drive control code is concerned with burning data to a DVD - thus, these two don't belong together.

Abstraction

Quite often, classes have to interact with each other. As an example, one class might manage your particle systems, another might manage your graphics device (like XNA's GraphicsDeviceManager class ;)). That particle system manager needs to access the graphics device to render its particle systems. But you don't want to let the classes directly access each other, otherwise you'd end up with this:

UML diagram showing a particle system class directly accessing the graphics device

Where is the problem with that?

  • By directly accessing the GraphicsDeviceManager, the ParticleSystemManager would become dependent upon this very class. Should you later decide to create a particle system editor in WinForms which doesn't use the GraphicsDeviceManager, you would have to rewrite a lot of code to get it working.
  • The ParticleSystemManager has access to everything the GraphicsDeviceManager provides. Does it make sense that the ParticleSystemManager is theoretically able to toggle between full screen and windowed mode?

    This concern might not seem terribly obvious (after all, the .NET Framework gives any part of your program access to lots of silly things it wouldn't want to do), but the idea is that exposing only what's needed makes it easier to change used classes or to change or replace them.

What you need then is an interface for the GraphicsDeviceManager. One that lets other classes access only those parts they're supposed to use.

Luckily, the XNA Framework provides just such an interface. It's called IGraphicsDeviceService and the GraphicsDeviceManager implements it. So instead of directly accessing the GraphicsDeviceManager, you can do this:

UML diagram showing the particle system accessing the graphics device through an interface

Now the ParticleSystemManager will accept any class that implements the IGraphicsDeviceService interface. If you decided to write aforementioned particle system editor, you could implement IGraphicsDeviceService in a Control or Form and the ParticleSystemManager could work with it - without changing a single line of code.

Next Chapter

In the next chapter, I will finally start writing some code and explain the concept of Dependency Injection and how to wire up a game's classes with each other using an Inversion of Control container.

 

Comments  

 
0 #1 Allan Chaney 2010-01-20 21:44
Thanks for posting these articles. I think OOP is a perfect topic to cover all throughout your series. Please do not assume an understanding of OOP principles and I would encourage you to provide explanations that cover the "Why" you chose to organize things the way you do. I think you will find that a lot of aspiring game developers know very little about OOP principles especially if they are hobbyists with no formal programming training. I'm an old school programmer from before OOP existed. I have found that just about all tutorials seem to assume you know OOP. The samples at the Creator's Club website are notorious for poor to no OOP/design explanations. Anyway, I look forward to more entries.
Allan
Quote
 
 
0 #2 Wesley 2010-01-23 13:58
I don't think explaining OOP inside this article is a good idea. There are a lot of artictles that are dedicated to this subject.

There are less articles explaining how to start programming a game than articles explaining OOP.
Quote
 
 
0 #3 Cygon 2010-01-24 20:32
@Allan: Thanks for the encouragement!

My worry was that this series might turn into yet another OOP intro, of which there are already enough out there that explain this topic better than me.

Summarizing the concepts like I did in this part of the series feels like the right way to go, too. I can keep those with a basic grasp of OOP in the boat and get on with my goal of explaining how to put together a game.
Quote
 
 
0 #4 Cygon 2010-01-24 21:16
@Wesley: My talking! ;)

I am trying to avoid going down to the basics, but without this intermediate chapter, it would have been hard to explain the 'why' when I begin using IoC.

I'll keep the OOP concepts at the summary level, that way, those readers hearing something for the first time know what I'm talking about and what search terms to use for finding further information on the topic and those already aware of a concept hopefully won't get bored!
Quote
 
 
0 #5 ProtheonX 2010-02-28 20:23
I am looking forward to the rest of this series. More than the use of OOP I am looking forward to seeing use of Ninject and your Nuclex framework. Keep 'em coming.
Quote
 
 
+2 #6 Wesley 2010-03-03 11:08
Hey, When is chapter 3 comming out? I'm kinda curious :)
Quote
 

Add comment


Security code
Refresh



Joomla Template by Joomlashack