The XNA 3.1 architecture for games: Part 1

I wanted to make a post about design documents for XNA games, but I realized it wouldn’t be very helpful without a little background knowledge on how the XNA framework is designed.  I’ll get that out of the way, and then we can get to the fun stuff.

As a disclaimer, I’m not an expert on the framework, and a lot of the details on how it works are hidden.  There are literally reams of documentation at the MSDN which you can read to find out how it really works.  My post is based on my experience working with the framework so far.

The first thing to know is that the framework is based on the Model-View-Controller (MVC) design paradigm.  In short, the Model is the set of objects being operated upon, the View is what is drawn on the screen, and the Controller is what receives input (note: time is an input) and applies it to the Model and the View.  This is an extremely useful design paradigm for any graphics-driven application, and is especially useful for games.  Keeping the drawing function and the updating function separate allows us to change our interface without affecting the game logic, and having a separate model allows us to use object-oriented principles when constructing our game.

So now when we look at the stock XNA project template, we see the direct parallels between XNA and MVC.  Our project has one class (the “Game”), which inherits from the XNA Game class, and implements:

  • a constructor (the first entity in our model)
  • an Initialize() function (for setting the beginning state for our model)
  • LoadContent() and UnloadContent() functions (for bringing external files like textures into memory)
  • a Draw() function (our view)
  • an Update() function (our controller)

This is sufficient to make a very simple game, like the one described in the XNA tutorial.  But only a very simple game can get by with the model they describe, which is just a Game class and a couple of generic GameObjects representing the player, some bullets,  and some enemies.  Modern games need a structure of menus, a complex hierarchy of objects (possibly including more objects than can even fit into memory at any given time), some means to safely save session information to files on the hard disk, and so on.  The XNA framework can do all of these things for us, but we need to extend our paradigm a little bit further.

The first thing we need to understand is how our MVC functions are being called.  C programmers will probably have noticed that we are missing a main() function, which is where all of our functions would usually be coordinated.  This function exists, but it’s at a higher level.  When you created your game, a Program.cs class was automatically created containing the main() function:

namespace Test2D
   static class Program
      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      static void Main(string[] args)
         using (Game1 game = new Game1())

Okay, so that’s how our game class gets instantiated.  But we still don’t know anything about how our MVC functions are being called; they’re being handled by this silly Run() function that’s defined in the Game class we’re inheriting from.  All those details are being hidden from us.  With a little bit of reading and experimentation, though, we can glean an order:

  1. Our constructor is called when the class is instantiated
  2. The LoadContent() function is called to bring everything into memory that needs to be there.  For us, this is usually graphics content files, but can include video and sound too.  Be careful to only load stuff that you’re actually going to use!
  3. Before the first frame is drawn, the Initialize() function is called.  This is mainly to prepare things for drawing and handling input.  Any static classes that are needed should be initialized here, and the viewport size should be defined.
  4. The Draw() and Update() functions start being called, once for each frame.  By default, they’re called 60 times per second.  If you’re on a crappy computer or you’ve loaded too much stuff into memory, 60 calls per second might be too much and the computer could start thrashing.  This is where the technical limitations of XNA will show up, and this is why you need to be careful when loading and unloading content.
  5. When the class is exited, the UnloadContent() function is called to clear everything out of memory.  This is really important if you have multiple game components, because you don’t want to clog memory with stuff that’s not being used on screen.

Alright, now we should be comfortable with what the XNA framework is doing, and we have a basic model in our heads for simple games.  Remember, the goal here is to provide enough of an understanding to be able to produce good design documents for XNA games.  In my next post, I’ll extend our model to include game components, including the screen manager which is used in the self-contained screen model which is exceptionally useful for XNA games.

Combat Engine prototype

Posted in Development, XNA

Leave a Reply