XNA Components – Better Structure And Organization

XNA has been really quite nice to play with, a pleasant change from the grind of UDK or Source where everything is done for me, and UI is simple – a lie on Source mind you. Building the Hades POC out in XNA has been fun because it feels like I have been on an educational adventure, experimenting and rebuilding portions of the game slowly and analyzing the results then rehashing it and repeating. Of all of the elements/tools in XNA that I’ve been able to use, tripped over and even those I thought I understood but didn’t  one stands out – I love the fact that components exist.

In a moment ill show you how I used components to ensure that my screenshot mechanism never includes the debug information but always includes the screen, also known as the back buffer.

Disclaimer: All of the code & discussion below refers to XNA 4.0

What Are Components?

For more detailed vaguery you can always look at the MSDN, but I think the best way to approach this is by example.

Let’s say you have a submarine, and you happen to be the chief of the boat. How do you get information about the boat. Sure you could reach your hand out of the closest window and measure the speed of the water as it washes past, stick your head out and listen for other boats in the waters and or look down to see what your ground clearance is, but … really that would be insane. Instead you would likely go to the radio room and ask about the sonar/radar information to figure out where you are in the water and in relation to what objects, to the engine room and inquire about the boat’s speed and a good portion of these systems are available to you on the bridge. Each of these sections are responsible for their own information management – meaning you wont likely go to the radio room and ask about the engines or how well the bilge pump is working – but they are each quite important.

These are the components of your submarine, each with a purpose and a priority – in an emergency you wont likely shut down your engine room, but the galley may be. You wont likely shut down sonar if you are tracking a ship, but you may want to cut back on your cavitation to ensure they don’t hear you.

Yes I loved watching Das Boot and Crimson Tide – truly amazing movies.

Anyways, In XNA we have two types of component GameComponent [1] and DrawableGameComponent [2] with a very simple difference – DrawableGameComponents have their draw method called automagically, while both have their Update, Initialize and given that they don’t skip the call to base.Initialize they will also have their LoadContent methods called. This is really where polymorphism can bite you, because a number of things are handled behind the scenes, to trigger other things and help you out and make it easier for you to build quickly in XNA.image

Before we get into any code examples you should know that this is only true if you add the component before the game executes its base.initialize method. If you do it at any other time, you will need to initialize your own components, which to be fair is not any more complicated than executing its method, but well… we wouldn’t be using C# if we wanted to call all of our functions explicitly… especially considering we have libraries for that.

A Simple Component

So what does a component look like?

public class MyComponent : GameComponent
{
    public MyComponent(Game g)
        : base(g)
    {
        g.Components.Add(this);
    }
    
    public override void Initialize(GameTime gt)
    {
        Trace.WriteLine("I have been initialized!");
        base.Initialize(gt);
    }
    
    public override void LoadContent(GameTime gameTime)
    {
        Trace.WriteLine("I have had my content loaded!");
    }
    
    public override void Update(GameTime gameTime)
    {
        Trace.WriteLine("I have been updated!");
    }
}

While this is definitely a very simple class with some overridden methods, it is also quite powerful. Adding this component is as simple as creating it, I recommend you do it in your Game.Initialize method just before your call to base.Initialize. You should note, though, that you cannot create multiple of these components. Adding two components of the same class will result in a failure and probably a frown because I warned you and you didn’t listen. You aren’t the first to find out how wise I am.

The only difference between this and the DrawableGameComponent is that the drawable would also override the Draw method, which is called according to the XNA game loop standards.

Under the hood, kinda

So you have a game, its got a bunch of components and they are all updating willy nilly. Sometimes it works out as you want and sometimes it doesn’t, but typically something is looking weird.there are a couple of mechanisms that you can use to help maintain control over your Components.

To begin with – UpdateOrder, an integer index for a grouping of components to occur at that point, where lower numbers go earlier than higher numbers. Both GameComponent and DrawableGameComponent have this as a property. You can of course be arbitrary, but I would highly recommend the use of an enum:

public enum EComponentOrder
{
    First = int.MinValue,
    Standard = 0,
    PreScreenshot = 250,
    Screenshot = 500,
    Postscreenshot = 750,
    Last = int.MaxValue
}

As an example setup for my own components, I need my input manager to be updated at the beginning of any of my processing, so it gets an UpdateOrder of First, most of my game play and scene management goes on at Standard, The UI/HUD is updated on top of that, PreScreenshot, and so on. Although the pre, post and last are not likely to be an issue for update, DrawOrder exists for all DrawableGameComponents with the same outcome – sorted draw calls. This is the mechanism that I use to ensure that debug data doesn’t appear on my screenshots, I simply don’t draw it yet!

The other mechanism for flow control for components is the Enabled property, which is the switch for whether the Update method is called or not. DrawableGameComponents also have a Visible property that is used to control whether something is drawn or not. In order to trigger my screenshot component I simply make it visible, and like the film inside of a camera it becomes visible renders the back buffer out to a png and hides itself.

Examples of components I have created so far include FPS Counters, Keyboard Input reporting, entity tracking, scene/game state management, and for whatever it is worth – my physics library is entirely controlled and threaded through a component, so clearly this simple component within XNA can be quite handy to keep around and use to segregate functionality that needs to be togglable.

One final word – you can also provide delegates to update other components or classes as to whether a component has its update/draw order changed or when it is toggled to visible/enabled, but that is likely to be an unnecessary addition for most of us who are just into rapid application development in C#.

best wishes, if any questions come up please don’t hesitate to ask.

References

  1. http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.gamecomponent.aspx
  2. http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.drawablegamecomponent.aspx

Leave a Reply