JSEDLAK » Blog Archive » Advanced State System: Concept and Base

Advanced State System: Concept and Base

The states themselves need to be lightweight objects that define something about the objects that use them. For this we introduce the notion of a struct rather than constants or enumerations. The main reason behind this is that certain platforms do not allow you to inject items into an enumeration. The secondary, and maybe more important, reason is that enumerations cannot have properties. Remember that each state has to declare something different for the object. While the object knows what to do in that state, it may not know much about the external properties of the state.

Let’s jump into some code, shall we? I assume that you know how to create an XNA game or library. I will be using a game project from the XNA 3.0 Beta. Add to this project a file called IStateObject.cs so we may declare the interface for what a state object is required to implement. The state object is incredibly simple: it has to be able to transition between states and must know what state it is in as well as what state it is moving towards.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
 
namespace AdvancedStateSystem
{
    interface IStateObject
    {
        void Transition(State newState);
 
        State CurrentState { get; }
        State NextState { get; }
 
        StateManager StateManager { get; set; }
    }
}

Next up we will declare what exactly a state is. Remember that states must have some basic notion of how to affect each object. In our case, we add properties to know whether or not an object should be drawn or updated while in a specific state. We also have to introduce a few operators to know whether or not one state is the same as another.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace AdvancedStateSystem
{
    public struct State
    {
        public float Time { get; set; }
 
        public bool CanDraw { get; set; }
 
        public bool CanUpdate { get; set; }
 
        public ushort Key { get; set; }
 
        public static bool operator ==(State a, State b)
        {
            return a.Key == b.Key;
        }
 
        public static bool operator !=(State a, State b)
        {
            return a.Key != b.Key;
        }
    }
}

Furthermore, we introduce the notion of time for each state. In our case this is the time we want the object to take to transition into that state. In another article we will cover more advanced timing including how states interact when collisions occur on the time scale. For now, a simple transition time will do the trick.

Now that we have states and a way to manage objects that have a state, we can begin working on the manager that does the grunt work. However, before we get to that, we need one more little item. We have designed the states around the idea that each object can be drawn or updated so we need to introduce this to the objects as well. For simplicity’s sake, I will declare a new interface which the IStateObject interface will inherit.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using Microsoft.Xna.Framework;
 
namespace AdvancedStateSystem
{
    interface IComponent
    {
        void Initialize(Game game);
 
        void Draw(GameTime gameTime);
        void Update(GameTime gameTime);
 
        bool IsVisible { get; set; }
        bool IsEnabled { get; set; }
        bool IsInitialized { get; }
 
        int DrawOrder { get; set; }
        int UpdateOrder { get; set; }
    }
}

Leave a Reply