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

Advanced State System: Concept and Base

In the IComponent interface we are essentially copying over functionality from the XNA Framework’s GameComponent and DrawableGameComponent classes and compacting it all. Note that we also include a parameter for the Initialize function so that classes do not need to require the use of a parameterized constructor. This becomes important when you introduce a factory design pattern and want to instantiate a generic type on the fly (requires the use of an empty constructor). After creating this interface, be sure to update the IStateObject interface to reflect the inheritance.

?View Code CSHARP
1
interface IStateObject : IComponent { }

Now are we ready to create the StateManager class? No, not quite. One more piece of code needs to be created! Because we are allowing for the notion of Draw and Update order for our objects, we need to make sure that a collection of these objects can be updated! The following class shows you a little of how to manage this. To obtain the ListBase class, please refer to Appendix A. Also note that this class only takes into consideration the DrawOrder of each item.

?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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
 
namespace AdvancedStateSystem {
    class ComponentCollection : ListBase<IComponent> {
        private Game game = null;
 
        protected override void OnItemAdded(object sender, EventArgs e) {
            base.OnItemAdded(sender, e);
 
            IComponent component = sender as IComponent;
 
            if (component != null)
            {
                if (Game != null)
                    component.Initialize(Game);
            }
 
            Sort(new DrawOrderComparer());
        }
 
        protected override void OnItemRemoved(object sender, EventArgs e) {
            base.OnItemRemoved(sender, e);
 
            IComponent component = sender as IComponent;
        }
 
        public void Draw(GameTime gameTime) {
            for (int i = 0; i < Count; i++)
                if (this[i].IsVisible)
                    this[i].Draw(gameTime);
        }
 
        public void Update(GameTime gameTime) {
            for (int i = 0; i < Count; i++)
                if (this[i].IsEnabled)
                    this[i].Update(gameTime);
        }
 
        public void Initialize(Game game) {
            Game = game;
 
            for (int i = 0; i < Count; i++)
                if (!this[i].IsInitialized)
                    this[i].Initialize(game);
        }
 
        protected Game Game {
            get { return game; }
            private set { game = value; }
        }
    }
 
    class DrawOrderComparer : IComparer<IComponent> {
        public int Compare(IComponent x, IComponent y) {
            if (x.DrawOrder < y.DrawOrder)
                return -1;
            else if (x.DrawOrder > y.DrawOrder)
                return 1;
 
            return 0;
        }
    }
}

Now that we have that out of the way, we are finally able to start work on the state manager! It turns out that the state manager is incredibly simple. It holds a list of the state objects, updates them and draws them.

?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
24
25
26
27
28
29
30
31
32
33
34
35
using System;
using Microsoft.Xna.Framework;
 
namespace AdvancedStateSystem
{
    class StateManager
    {
        private ComponentCollection currentObjects = new ComponentCollection();
 
        public StateManager(Game game)
        {
            currentObjects.Initialize(game);
        }
 
        public void Load(params IStateObject[] objectsToLoad)
        {
            currentObjects.AddRange(objectsToLoad);
        }
 
        public void Remove(IStateObject stateObject)
        {
            currentObjects.Remove(stateObject);
        }
 
        public void Update(GameTime gameTime)
        {
            currentObjects.Update(gameTime);
        }
 
        public void Draw(GameTime gameTime)
        {
            currentObjects.Draw(gameTime);
        }
    }
}

Leave a Reply