Last Fall I took a game design class at my University. Far from design, the class mainly consisted of game programming, with some lectures on design. As part of the class, we were required to program several games, the last game being a large group project. The professor supplied us with two separate engines to use for our games – one using C++ and the other Java. We decided to roll our own.
Thus began work on the WSUXNA engine – a simple 2D game engine built using Microsoft’s XNA Game Studio Express Beta 1 (which was released in the middle of our first project) – and later XNA Beta 2. I did most of the engine coding for the Beta 1 engine (a three-day effort), and recoded the whole thing for Beta 2. It was a huge amount of code (thousands of lines), and by the end of Beta 2, a fully-commented and working engine.
Building on Common Ground
You may recognize this pattern, though not in this format. This is the subject-observer design pattern from the Gang of Four. It’s also pretty much a simplified version of the Event model in the .NET framework. This is one of the basic components of the WSUXNA engine – it allows the engine to maintain a hierarchical architecture (nothing can directly touch anything above it in the architecture).
The purpose of this design pattern is to let components that are lower in the hierarchy notify components above themselves about some event, such as the death of a component (so it can be removed from a collection), or perhaps that a component has moved by the movement manager (and its visual position should be updated as well). When a component is created by a manager (more on those later), the component inherits the Subject class and the Manager implements the IObserver interface. You can see what these contain above.
When a subject is created, the manager will register events with the component through the AttachNotifier method. This will register a delegate (pointing to the manager’s implementation of the Notify method) with the subject, to be called when an event (e.g. “die”) is raised. The subject places this delegate in a dictionary that contains a list of delegates to call whenever a certain event is raised (e.g. “die”, again). Later, the manager can detach the notifier if it wishes by using the DetachNotifier method of the subject.
So, for example, the entity manager might be called upon to create a brick in a Breakout game. The entity manager will need to know when the brick has been destroyed, so it can be removed from the entity manager’s list of items needing updating. The game manager will also need to know when the brick has been destroyed so it can add points to the game state. Both will register a “die” notifier with the brick so that when it is destroyed (i.e. when it “die”s), it will notify them both before removing itself.
Like I said, this is basically a simple implementation of the Event handling capabilities of the .NET framework. If you chose to use something like this in your own designs, I’d suggest exploring the Event handling already present in C#. At the time, I overlooked Events – but by doing so I gained better understanding of them and was able to have more control over how my engine worked.
Next: The rest of the basics – Managers and Components.
Note: Do you like the class diagram above? It was created by importing my code into Visual Studio 2005 Professional and creating a class diagram from the code. They’re a really awesome way to design code, and I’d like to see them included in XNA Game Studio Express. Shall we campaign for them?