Game Object State Management in XNA

Vegas Building

Hmm. This sounds a bit deep for a Saturday blog post. I suppose it is, but I got asked a question at Mix 11 and I’ve been pondering it ever since then. The question was about some code like this:

class Cloud : CloudGame.ISprite
{
    public Texture2D CloudTexture;
    public Vector2 CloudPosition;
    public Vector2 CloudSpeed;
    public bool Burst = false;

    public void Draw(CloudGame game)
    {
        if (!Burst)
            game.spriteBatch.Draw(CloudTexture, 
                                                                       CloudPosition, 
                                                                       Color.White);
    }
   // rest of cloud code here
}

This is a tiny part of my “Cloud Bursting” game demo, where players touch clouds to burst them. The above code is the definition of the cloud itself. This has a texture, position, speed of movement and a Burst flag as properties.

Burst is how the cloud “knows” if the cloud has been burst. If the cloud is burst it is not drawn. At the start of the game all the clouds have the Burst flag set to false to indicate that they are still part of the game. As the player touches them the Burst flag is set true.

You see this in a lot of game play situations. Anywhere that things are “killed” they have to be able to remember whether they are still alive or not. The code above is simple and works well, at any instant a cloud is either burst or not. If it is burst (i.e. the Burst flag is true) plays no further part in the game and is not drawn.

However, this design gave rise to the question: “Why do we need to have a flag? Surely it would be more efficient to remove a ‘burst’ cloud from the list of things to be drawn?”

This is a very good question. To understand it you need to remember that in a game we will have many objects on the screen at any given time. To manage this the game contains a collection of some kind (usually a List). During Update and Draw the game works through the list acting on each item in it. If an item is removed from the list it will no longer be part of the game.  When the player bursts a cloud, rather than setting a flag you could just remove that cloud from the list of active game objects.

This approach has the advantage that it is more efficient. Instead of a cloud having to decide not to draw itself the game never tries to draw burst clouds at all.  However, it also adds complication. The game must now have a “master” list of clouds and an “active” list of clouds. At the start of a game the master cloud references are copied into the active list. This is to avoid the overheads of creating and destroying objects, something you really don’t want to be doing on a regular basis.

Furthermore, the time that is saved is probably not going to be that much use to us. If the game works fine with all the clouds visible (which it should do) then saving small amounts of processor time when some clouds are removed is not going to make that much difference to performance. In this situation it is the drawing of the objects that takes the time, not deciding whether or not to draw them.

The fundamental principle here is that you should go for simplicity first, then optimise when you discover you have a performance issue.  I like having the flags present, it makes for greater cohesion and easier debugging. I can look at any cloud and decide whether or not it should be drawn simply by inspecting the flag.  If the flag wasn’t there I’d have to check which lists held the cloud, and so on.

So, I go with internal flags, not lists, which is pretty much what I said at the time as I remember.