One of the problems I often see is that people who are learning tend to spend much of their time learning graphics, and not enough time learning how to structure their game or game engine. In this tutorial series I am going to share what I’ve learned on this topic. This is by no means the only or ‘right’ way to do it, but there certainly are wrong ways, and I hope to help you avoid many of them.
There is a sample on the XNA Creators Club website that is a great starting point for game structure research. The design of the engine we’ll be designing is based partly on this tutorial. (http://creators.xna.com/en-us/samples/gamestatemanagement). So, let’s get started! The basic structure of the engine is as follows:
Game Engine Structure
- Component class: This class is the base that all objects that will be managed by the engine should inherit from. It contains “Update()” and “Draw()” methods to update and draw itself. It also contains a “Visible” property to set whether or not to draw the component.
- GameScreen class: This class contains a group of Components and handles their updating and drawing. It contains “BlocksDraw”, “BlocksUpdate”, and “BlocksInput” properties to block the drawing, updating, and input processing of the screens below. This allows for screens to easily implement functionality like pausing the game. Of course, the screens can override this so that screens that must always draw or update or something similar can still do so.
- Engine class: This is a static class that contains a list of GameScreens. It manages their update and draw, and also contains a number of useful properties, such as a service container, the GraphicsDevice and SpriteBatch, and more.
Setting Up Visual Studio
Before we can start on our code, we need to get Visual Studio set up. We will have two projects in our solution, one for the engine itself and another for the demo game that utilizes it. So, open up Visual Studio, and select File-New Project, and choose type XNA Windows Game Library, and choose a name. I used “InnovationEngine”, but any name will do. When the project is all set up, open up the Solution Explorer and right click your solution (The top node). Select Add-New Project, and choose Type XNA Windows Game. Pick a name (I used “TestEnvironment”), and press OK. Finally, we need to reference our engine project from the game project. Expand the game’s node (It is labelled “TestEnvironment” in the example above”), right click “References”, and choose “Add Reference”. Click on the “Projects” tab and choose the name of your engine project. (In this case, “InnovationEngine”). Add a new folder to your engine project and call it “Components”. We are now all setup. To run the game, right click on it’s project and click “Set as Startup Project”. Now, if you press F5 your game should start up, and present you with a blank blue screen.
This helps us avoid common mistake #1 – Not seperating engine code and game code. This is almost always a good idea, unless the game is very simple. Not only does it help keep things straight in your solution, but it can greatly ease in the creation of an editor later on, and it helps to keep the code in a format that can be reused later on in different games.
Component Class
The first class we need to write is the component class. This is the basis for all objects managed by the engine. Add a new file to the engine project by right clicking on it and selecting Add-New Item-Code File, and call it “Component.cs”. Add the following code to that follow. Note: Please do not just copy and paste the code, actually type it out so you can learn and understand what you’re doing.
using Microsoft.Xna.Framework;
namespace Innovation
{
public class Component
{
// The GameScreen object that owns this component
public GameScreen Parent;
// Whether or not this component has been initialized
public bool Initialized = false;
// Whether or not the GameScreen that owns the component
// should draw it
public bool Visible = true;
// This overloaded constructor allows us to specify the parent
public Component(GameScreen Parent)
{
InitializeComponent(Parent);
}
// This overload allows will set the parent to the default
// GameScreen
public Component()
{
InitializeComponent(Engine.DefaultScreen);
}
// This is called by the constructor to initialize the
// component. This allows us to only have to override this
// method instead of both constructors
protected virtual void InitializeComponent(GameScreen Parent)
{
// Check if the engine has been initialized before setting
// up the component, or the Engine will crash when the
// component tries to add itself to the list.
if (!Engine.IsInitialized)
throw new Exception("Engine must be initialized with "SetupEngine()""
+ "before components can be initialized");
Parent.Components.Add(this);
Initialized = true;
}
// Updates the component - This is called by the owner
public virtual void Update()
{
}
// Draws the component - This is called by the owner
public virtual void Draw()
{
}
// Unregisters the component with its parent
public virtual void DisableComponent()
{
Parent.Components.Remove(this);
}
}
}
This should be pretty self explantory, the important thing to know is that a component is owned by a GameScreen, who calls the component’s update and draw methods every frame.
Having a clearly defined base class helps us avoid common mistake #2 - Not having a class that the engine knows how to work with. If your engine is made up of a bunch of differently formatted classes, then you have to worry about how each component will be updated, drawn etc. Having a base class means that all we have to do is inherit from it, change the update and draw a little bit, and the engine will draw, update, and manage the component for us, without any extra code. This is also useful because every component in the game can be accessed using the type of the base class, even if it is actually a terrain, sky, or anything else. This greatly simplifies our update, render, and component management logic.
Component Interfaces
The next thing we are going to do is define some interfaces for our components. An interface is a way of defining how an object interacts with other objects. It also lets us distinguish between types of objects. The interfaces we will be defining here are I2DComponent and I3DComponent. This allows to tell the engine if our component uses 2D or 3D for drawing and updating. It also allows the engine to get some basic information about an object’s position, rotation, etc. This simplifies things like picking (detecting what a mouse clicked on or what is under a target reticle), and things like adding modifiers in an editor to control position, rotation, etc.
We will also be defining an enum that will list various types of object groups: 2D, 3D, Both, and All. We can use this enum later on for things like rendering water. When drawing the reflections for water, we don’t want to have the HUD elements drawn with it in the reflection, so we can use this enum like this: Engine.Draw(ComponentType.Component3D); This will draw only 3D objects, so the HUD will not be drawn in the reflection. This lets us avoid common misake #3 - Having a base class, but not providing a way to tell the engine anything useful about it. By providing these interfaces, we can modify an object’s position, rotation, scale, etc. regardless of what kind of component it is. The code for the interfaces and object type enum are below. Add these into a new file called ObjectType.cs
using Microsoft.Xna.Framework;
namespace Innovation
{
// Represents a 3D object. These objects will be drawn before
// 2D objects, and will have modifiers automatically provided
// in the editor.
public interface I3DComponent
{
// Position in the Cartesian system (X, Y, Z)
Vector3 Position { get; set; }
// Rotation represented as a Vector3. This shouldn't
// be used for calculations, it is left in so that
// the rotation can be more easily modified by hand
Vector3 EulerRotation { get; set; }
// Rotation as a Matrix. This will give much smoother
// and cleaner calculations that a Vector3
Matrix Rotation { get; set; }
// Scale for each axis (X, Y, Z)
Vector3 Scale { get; set; }
// BoundingBox to use for picking and pre-collision
BoundingBox BoundingBox { get; }
}
// Represents a 2D object. These objects will be drawn after
// 3D objects, and will have modifiers automatically provided
// in the editor.
public interface I2DComponent
{
Rectangle Rectangle { get; set; }
}
public enum ComponentType
{
// Represents all 2D components (I2DComponent)
Component2D,
// Represents all 3D components (I3DComponent)
Component3D,
// Represents all components that are either 2D or 3D
// components
Both,
// Represents all components regardless of type
All
}
}
GameScreen
A GameScreen is a class that contains a group of components, and handles their updating, drawing, and input. It contains the properties BlocksDraw, BlocksInput, and BlocksUpdate. These can be used to control the screens that are “under” then if they are imagined as a stack of GameScreens, with the newest on top.
For example, if you add a new GameScreen with BlocksUpdate, BlocksInput, and BlocksDraw set to true, then you have effectively just created a pause menu. This can save huge amount of time because it is very easy to create screens like this that control those under them. There is no need to create a complex state system to keep track of what the game is doing. We can just add new screens and change their properties to suit our needs.
This brings us to common mistake #4 - Not segregating code into clearly defined sections and creating an overly complex state management system. While this may seem like overkill, and for smaller games it certainly is, this system is extemely flexible and can be expanded with very little effort.
While this kind of state management could be built into the final game itself and not managed by the engine, by including it right into engine itself, we get a flexible design provided right inside the engine, and we have a framework to design our game around.
So, without further ado, here’s the code for the GameScreen. Add it to a new file called GameScreen.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Innovation
{
public class GameScreen
{
// Keep track of all the components we need to manage
public ComponentCollection Components;
// Whether or not to draw
public bool Visible = true;
// Whether or not this screen should block the update of
// screens below (for pause menus), etc.
public bool BlocksUpdate = false;
// Whether or not this screen can override a blocked update
// from an above screen (for a background screen), etc.
public bool OverrideUpdateBlocked = false;
// Same for drawing
public bool BlocksDraw = false;
// Same for drawing
public bool OverrideDrawBlocked = false;
// Same for input
public bool BlocksInput = false;
// Same for input
public bool OverrideInputBlocked = false;
// Whether or not we want to block our own input so we can
// do things like loading screens that will want to accept
// input at some point, but not at startup
public bool InputDisabled = false;
// This is set by the engine to tell us whether or not input
// is allowed. We can still get input, but we shouldn't. This
// is useful because a ProcessInput() type of function would
// make it hard to manage input (because we can't utilize
// events, etc.)
public bool IsInputAllowed = true;
// The name of our component, set in the constructor. This
// is used by the Engine, because a GameScreen can be accessed
// by name from Engine.GameScreens[Name].
public string Name;
// Fired when the component's Initialize() is finished. This can
// be hooked for things like asynchronous loading screens
public event EventHandler OnInitialized;
// Whether or not the component is initialized. Handles firing of
// OnInitialized.
bool inititalized = false;
public bool Initialized
{
get { return inititalized; }
set
{
inititalized = value;
if (OnInitialized != null)
{
// Fire the OnInitalized event to let other's know we
// are done initializing
OnInitialized(this, new EventArgs());
}
}
}
// Constructor takes the name of the component
public GameScreen(string Name)
{
// Setup our component collection
Components = new ComponentCollection(this);
// Register with the engine and set our name
this.Name = Name;
Engine.GameScreens.Add(this);
// Initialize the component
if (!Initialized)
Initialize();
}
// Overridable function to initialize the GameScreen
public virtual void Initialize()
{
this.Initialized = true;
}
// Update the screen and child Components
public virtual void Update()
{
// Create a temporary list so we don't crash if
// a component is added to the collection while
// updating
List<Component> updating = new List<Component>();
// Populate the temporary list
foreach (Component c in Components)
updating.Add(c);
// Update all components that have been initialized
foreach (Component Component in updating)
if (Component.Initialized)
Component.Update();
}
// Draw the screen and its components. Accepts a ComponentType
// to tell us what kind of components to draw. Either 2D, 3D, or
// both. (Useful for drawing a reflection into a render target
// without 2D components getting in the way)
public virtual void Draw(ComponentType RenderType)
{
// Temporary list
List<Component> drawing = new List<Component>();
foreach (Component component in Components)
{
if (RenderType == ComponentType.Both)
{
// If the render type is both, we will draw all 2D or
// 3D components
if (component is I2DComponent || component is I3DComponent)
drawing.Add(component);
}
else if (RenderType == ComponentType.Component2D)
{
// If the render type is 2D, we will only draw 2D
// components
if (component is I2DComponent)
drawing.Add(component);
}
else if (RenderType == ComponentType.Component3D)
{
// If the render type is 2D, we will only draw 3D
// components
if (component is I3DComponent)
drawing.Add(component);
}
else
{
// Otherwise, we will draw every component regardless of type
drawing.Add(component);
}
}
// Keep a list of components that are 2D so we can draw them on top
// of the 3D components
List<Component> defer2D = new List<Component>();
foreach (Component component in drawing)
if (component.Visible && component.Initialized)
{
// If the component is visible and is not loading itself..
if (component is I2DComponent)
{
// If it is 2D, wait to draw
defer2D.Add(component);
}
else
{
// otherwise, draw immediately
component.Draw();
}
}
// Draw 2D components
foreach (Component component in defer2D)
component.Draw();
}
// Disables the GameScreen
public virtual void Disable()
{
// Clear out our components
Components.Clear();
// Unregister from the Engine's list
Engine.GameScreens.Remove(this);
// If the engine happens to have this screen set as the default
// screen, set it to the background screen in the Engine class
if (Engine.DefaultScreen == this)
Engine.DefaultScreen = Engine.BackgroundScreen;
}
// Override ToString() to return our name
public override string ToString()
{
return Name;
}
}
}
One thing to note here is input. We don’t want to limit our input by forcing it all into one function on the GameScreen, because we want to be able to take advantage of things like key press events. So, we have a boolean called IsInputAllowed. This will be calculated by the engine each frame, so when checking input we should also check to see if IsInputAllowed equals true before doing anything. Unless, of course, we want to ignore this to move a camera around in the background of the pause screen or something similar.
The GameScreen class has a member called Components, which is a ComponentCollection. This is a custom collection that handles the management of the Parent value for components when it is moved around various screens. The code for this collection is below. Add it to a file called ComponentCollection.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace Innovation
{
// A custom collection for managing components in a GameScreen
public class ComponentCollection : Collection<Component>
{
// The GameScreen to manage components for
GameScreen owner;
public ComponentCollection(GameScreen Owner)
{
owner = Owner;
}
// Override InsertItem so we can set the parent of the
// component to the owner
protected override void InsertItem(int index, Component item)
{
if (item.Parent != null && item.Parent != owner)
item.Parent.Components.Remove(item);
item.Parent = owner;
base.InsertItem(index, item);
}
// Override RemoveItem so we can set the paren of
// the component to null (no parent)
protected override void RemoveItem(int index)
{
Items[index].Parent = null;
base.RemoveItem(index);
}
}
}
In the next article, we’ll tackle the engine class itself. For now, read through and make sure you understand everything we have so far.
Download the Code for this Chapter



Hey Sean, nice post, I like the BlockInput, BlockUpdate, BlockDraw idea. I’m curious, why didn’t you derive your Component Class from XNA’s GameComponent and/or use XNA’s GameComponentCollection? These classes are very handy, and manage UpdateOrder and DrawOrder among other things that can be quite important. One more thing, how do you handle time based updates/draws? XNA’s GameComponent.Update method gets a GameTime parameter, will you be adding these features later?. C ya.
I didn’t derive from GameComponent because I’d like to allow the engine to function outside the Game class, because it is hard to get it work properly in an editor environment.
As for game time, the Engine class will have a public GameTime object that gets updated at each draw and update. This means we can get the time outside of a function that accepts a GameTime object.
So, you would get the game time through Engine.GameTime
Sean, I was wondering if you could explain ‘public virtual void’ to me, I’m new and wasnt able to find an answer by googling it (which is rare).
BTW Great tutorial, and am looking forward to the next one!
I would explain it to you, but the Microsoft documentation does a much better job than I could in one comment. Check out these links:
http://msdn.microsoft.com/en-us/library/ms173121.aspx
http://msdn.microsoft.com/en-us/library/ms173152(VS.80).aspx
http://msdn.microsoft.com/en-us/library/1h3swy84(VS.71).aspx
Hope they help
Ok, so I think I get it after a couple of hours of tutoring from microsoft. Basically When you set a class as virtual void, you are allowing its derrived classes to invoke their own methods (as long as they use override). This would be useful in the case that a derrived class needs to use some different code from its base class. correct?
Basically, yes. The ‘virtual’ and ‘void’ are not related except that they both describe the function. Because it is ‘virtual’, derived classes can override the function. For example, our components will override update and draw to implement their own functionality.
‘void’ means that the function doesn’t return anything. If we had, for example, ‘int’ instead, then the function would return a number (using ‘return 57;’ for example, to return 57).
‘public’ means that the function is available outside the class. If it was ‘private’ or didn’t have any modifiers at all, then it would only be available inside the class.
Hi Sean. Thaks for this great series
Just one thig I was wondering about is ComponentType.Both…
If you stay with this Types All will be the same like Both. If you add more Types to the Enum the name Both will be quite confusing, won’t it? I guess naming it something like “Drawable” would be the better choice.
We probably aren’t going to be adding more types to this enum, so I don’t see it being a problem. The reason I do this is that ComponentType.Both will only draw components that are either I3DComponent or I2DComponent, and will not draw a component that doesn’t inherit from either of them. This way, we can do things like render into a render target (for example, if we wanted to do split screen, we would need to render everything twice and draw the renders on different parts of the screen), without messing up other components. For example, we will be adding a frame rate component, which does some of it’s logic in it’s draw function. If we called Draw() on it before we were actually done drawing scene, we would get innacurate data from it. Thus, we have ComponentType.Both to act like ComponentType.All, but not draw components that explicitly say they want to be drawn.
Would I be right in saying that after adding all the above code this should not yet build?
Correct. We haven’t added the Engine class yet. At the end of chapter 2 you should be able to build.
Thats what i thought but i was a bit paranoid that maybe i’d messed something up
Thanks.
Awesome tutorial Sean – I have a decent grasp of a lot of small bits, but tieing it all together in a reusable engine environment is something I have no experience with — this is a great help!
Sean, Thanks for this great tutorial. I started programming about 22 years ago, smalls games and such. I have since moved on as a business apps. developer. I have wanted to get back into game design / development for awhile. This will be a great start.
Thanks again for your time and exp.
Have been doing c# for a couple of years (business apps) but discovered XNA just the other day – great tutorial – makes good sense…
Hey Sean. Thanks for great series. Please keep em comming
I just wanted to add tiny detail. In Component.cs it is missing “using System”, so Exception can be reached.
Or other way, changing Exception to System.Exception
I’ve been looking through your XNA game engine tutorials and they seem great. I’ve been programming for a while but I just started with C#. I wanted to point out something that gave me trouble though. When you create your two projects (InnovativeEngine and TestGame) you show an image of your project tree. In this image the Program.cs and the Game1.cs classes have been removed from the InnovativeEngine project. If the user removes these the code will not compile. After some searching online I found out that I needed to set the Output type of the InnovativeEngine project to Class Library in the project properties. That’s all. Keep up the good work.
Well I feel like a horses puhtoot.
“So, open up Visual Studio, and select File-New Project, and choose type XNA Windows Game Library, and choose a name.”
It’s 5am. I’m sorry
Great tutorial, it is nice to see one that has more substance than “how to draw a model to the screen”. It is tutorials like this that will help beginner indie developers get to we they need to be. Thanks for all the information.
I was wondering about this tutorial, Im typing it all out but in my project words like using microsoft and bools set to true ora different colors than yours. Is this simply beacause you set the text colors? Im making the classes with the code files, is this wrong?
It’s because the wordpress plugin I use to post code gets using statements wrong. “using” should be blue and the text should be black, but it makes the text green. It also doesn’t make “true” and “false” blue like it should.
You’re fine.
Hey Sean,
:applauds: honestly, I couldn’t believe this tutorial was for free. I have free access to a lot of the XNA books that are 40-50$ and none of them come close to this.
Components.cs is missing “using System;” namespace otherwise compiler will complain that the exception you are throwing isn’t being recognized.
Off to Chapter 2!
While I’m very new to both XNA and C#, and understand very little of what you’ve written, it really is one awesome tutorial.
After rereading, discussing with a more experienced friend and rereading again I really think I understand now!
Thank you very much for this great tutorial!
Hi, at the Components class i get 6 errors.
Error 1 Newline in constant
Error 2 ) expected
Error 3 The name ‘Engine’ does not exist in the current context
Error 4 The name ‘Engine’ does not exist in the current context
Error 5 The type or namespace name ‘Exception’ could not be found (are you missing a using directive or an assembly reference?)
Error 6 Only assignment, call, increment, decrement, and new object expressions can be used as a statement
please, mail me or MSN me, alt_msn_erik(at)hotmail.com
(at) because of spam protection.
Is it right, that this line
public event EventHandler OnInitialized;
which that method OnInitialized will be set from outside?
Amazing Tutorial… I’ve been working with Xna for about 8 Months now and I have ran into many of these mistakes. It’s great the way that you explain them in a way that makes sense.
This is really the definitive Xna tutorial, because too many other tutorials only show how to make a single linear game. This gives you the Framework to make anything.
Hey just wondering is this gonna show us how to make a game engine and use it ???in a small 3D game project?
-Great- tutorial. I’m only halfway through it, and I can’t stop reading. The only thing I miss is the “discover by yourself” part. Oh well. I guess I’ll get it sooner or later.
I don’t understand how this part is helpful:
// Create a temporary list so the engine doesn’t
// crash if a component is added to the collection
// while updating.
List updating = new List();
Why create a temporary list? I mean, you use all the components from it in the same function anyway o.o Sorry if I missed something.
are we allowd to use this engine anyhow we want?
There is a bool variable named ‘inititalized’ (your spelling not mine) in the GameScreen class code, and its data access isnt set to public, private, or protected. So what does it mean? Also, is it spelt that way as a typo, or is there a genuine reason for it?
thanks in advance
Nick
I am running through your tutorial and I noticed that the quotes around SetupEngine() will cause an error. I just used… well these thing . also, I believe either a using statement for system or system.Exception is required. Both errors were found in the Component class. Just thought I would let5 you know.
Fed up with getting low amounts of useless traffic to your site? Well i want to inform you of a fresh underground tactic that produces myself $900 per day on 100% AUTOPILOT. I possibly could be here all day and going into detail but why dont you merely check their site out? There is a excellent video that explains everything. So if your serious about producing simple cash this is the website for you. Auto Traffic Avalanche