In this chapter, we’re going to be building the main class of our engine, rightfully called “Engine”. Start off by adding a new file to your “Components” folder called “Engine.cs”. Add the following code to create a static class called “Engine”. The difference between this and all the other classes we’ve created so far is that it doesn’t have to be instantiated (using “new ObjectType();”). Instead we can get its members using “Engine.MemberName”. Here is the starting code:
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Innovation
{
public static class Engine
{
}
}
We are going to add some member variables to the Engine class. Add the following to our class:
// The GraphicsDevice the engine is using public static GraphicsDevice GraphicsDevice; // The Engine's SpriteBatch public static SpriteBatch SpriteBatch; // The collection of GameScreens we are managinng public static GameScreenCollection GameScreens = new GameScreenCollection(); // The current GameTime public static GameTime GameTime; // Whether the Engine has been initialized yet public static bool IsInitialized = false;
Next we are going to create a method to initialize the engine. This method accepts an IGraphicsDeviceService object which helps us set up the Engine’s graphics. If initializing from the Game class, this is the GraphicsDeviceManager graphics that is created in the default Game template. The initialize method can be found below:
// Initializes the engine
public static void SetupEngine(IGraphicsDeviceService GraphicsDeviceService)
{
// Setup the GraphicsDevice and SpriteBatch
Engine.GraphicsDevice = GraphicsDeviceService.GraphicsDevice;
Engine.SpriteBatch = new SpriteBatch(GraphicsDeviceService.GraphicsDevice);
Engine.IsInitialized = true;
}
The next method we will need is an update method. This will update all the GameScreens who will then update their components. There is some complex logic in updating and drawing because screens are allowed to block drawing and updating of each other. The update accepts a GameTime to update the internal GameTime, as does the draw method.
// Update the engine, screens, and components
public static void Update(GameTime gameTime)
{
// Update the game time
Engine.GameTime = gameTime;
// Create a temporary list
List<GameScreen> updating = new List<GameScreen>();
// Populate the temp list
foreach (GameScreen screen in GameScreens)
updating.Add(screen);
// BlocksUpdate and OverrideUpdateBlocked login
for (int i = GameScreens.Count - 1; i >= 0; i--)
if (GameScreens[i].BlocksUpdate)
{
if (i > 0)
for (int j = i - 1; j >= 0; j--)
if (!GameScreens[j].OverrideUpdateBlocked)
updating.Remove(GameScreens[j]);
break;
}
// Update remaining components
foreach (GameScreen screen in updating)
if (screen.Initialized)
screen.Update();
// Clear list
updating.Clear();
// Repopulate list
foreach (GameScreen screen in GameScreens)
updating.Add(screen);
// BlocksInput and OverrideInputBlocked login
for (int i = GameScreens.Count - 1; i >= 0; i--)
if (GameScreens[i].BlocksInput)
{
if (i > 0)
for (int j = i - 1; j >= 0; j--)
if (!GameScreens[j].OverrideInputBlocked)
updating.Remove(GameScreens[j]);
break;
}
// Set IsInputAllowed for all GameScreens
foreach (GameScreen screen in GameScreens)
if (!screen.InputDisabled)
screen.IsInputAllowed = updating.Contains(screen);
else
screen.IsInputAllowed = false;
}
The draw method is very similar, we do some logic for BlocksDraw and for the type of components we are supposed to be drawing, and then we draw them.
// Draws the current collection of screens and components. Accepts a
// ComponentType to render
public static void Draw(GameTime gameTime, ComponentType RenderType)
{
// Update the time, create a temp list
Engine.GameTime = gameTime;
List<GameScreen> drawing = new List<GameScreen>();
// Clear the back buffer
GraphicsDevice.Clear(Color.CornflowerBlue);
// Populate the temp list if the screen is visible
foreach (GameScreen screen in GameScreens)
if (screen.Visible)
drawing.Add(screen);
// BlocksDraw and OverrideDrawBlocked logic
for (int i = GameScreens.Count - 1; i >= 0; i--)
if (GameScreens[i].BlocksDraw)
{
if (i > 0)
for (int j = i - 1; j >= 0; j--)
{
if (!GameScreens[j].OverrideDrawBlocked)
drawing.Remove(GameScreens[j]);
}
break;
}
// Draw the remaining screens
foreach (GameScreen screen in drawing)
if (screen.Initialized)
screen.Draw(RenderType);
}
Next we are going to add an IServiceContainer object. This is an object that will keep track of objects called Service Providers. We can retrieve and store Service Providers by their type. For example, to get the GraphicsDeviceService, we would use “Engine.Services.GetService(typeof(IGraphicsDeviceService));”. Or, to store a ContentManager object called “content”, we would use “Engine.Services.AddService(typeof(ContentManager), content);”. We are going to create a class that inherits from IServiceContainer, which contains methods to add, remove, and get services. Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
namespace Innovation
{
public class IEServiceContainer : IServiceProvider
{
// Contains the service types and services
Dictionary<Type, object> services = new Dictionary<Type, object>();
// Add a new service
public void AddService(Type Service, object Provider)
{
// If we already have this type of service provider, throw an
// exception
if (services.ContainsKey(Service))
throw new Exception("The service container already has a "
+ "service provider of type " + Service.Name);
// Otherwise, add it to the list
this.services.Add(Service, Provider);
}
// Get a service from the service container
public object GetService(Type Service)
{
// If we have this type of service, return it
foreach (Type type in services.Keys)
if (type == Service)
return services[type];
// Otherwise, throw an exception
throw new Exception("The service container does not contain "
+ "a service provider of type " + Service.Name);
}
// A shortcut way to get a service. The benefit here is that we
// can specify the type in the brackets and also return the
// service of that type. For example, instead of
// "Camera cam = (Camera)Services.GetService(typeof(Camera));",
// we can use "Camera cam = Services.GetService()"
public T GetService<T>()
{
object result = GetService(typeof(T));
if (result != null)
return (T)result;
return default(T);
}
// Removes a service provider from the container
public void RemoveService(Type Service)
{
if (services.ContainsKey(Service))
services.Remove(Service);
}
// Gets whether or not the container has a provider of this type
public bool ContainsService(Type Service)
{
return services.ContainsKey(Service);
}
}
}
Now we need to create an instance of it in our Engine class. Add the following somewhere in the top of the Engine class:
// The engine's service container public static IEServiceContainer Services;
And the following in the SetupEngine() method:
// Setup the service container and add the IGraphicsDeviceService to it
Engine.Services = new IEServiceContainer();
Engine.Services.AddService(typeof(IGraphicsDeviceService),
GraphicsDeviceService);
Now we are going to create a custom ContentManager and add it to the Engine class. Our ContentManager will expand on XNA’s base ContentManager by allowing us to choose if we want to use the content cache (store loaded objects loaded so we don’t need to load the same asset twice), and allow us to unload specific pieces of content individually instead of unloading everything. Here is the code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Content;
namespace Innovation
{
public class IEContentManager : ContentManager
{
// Do nothing in the constructor except inherit from ContentManager
public IEContentManager(IServiceProvider serviceProvider)
: base(serviceProvider) { }
// Whether or not we should keep objects that have been loaded. This
// way we can avoid loading assets multiple times. However, this may
// lead to problems with multiple objects changing loaded data, such
// as effects on a model
public bool PreserveAssets = true;
// Keep a list of disposable assets and loaded assets
List<IDisposable> disposable = new List<IDisposable>();
Dictionary<string, object> loaded = new Dictionary<string, object>();
// Override loading of assets so we can use our own functionality
public override T Load<T>(string assetName)
{
// Create a new instance of the requested asset
T r = this.ReadAsset<T>(assetName, RecordIDisposable);
// If we are holding on to loaded assets, add it to the list of
// loaded assets
if (PreserveAssets && !loaded.ContainsKey(assetName))
loaded.Add(assetName, r);
// Return the loaded asset
return r;
}
// Internal method to record disposable assets
void RecordIDisposable(IDisposable asset)
{
// If we are monitoring loaded assets, add it to the list of
// disposable assets
if (PreserveAssets)
disposable.Add(asset);
}
// Unload all content
public override void Unload()
{
// Dispose all disposable assets
foreach (IDisposable disp in disposable)
disp.Dispose();
// Clear all loaded assets
loaded.Clear();
disposable.Clear();
}
// Unload a specific piece of content
public void Unload(string assetName)
{
// If the asset has been loaded
if (loaded.ContainsKey(assetName))
{
// If it is disposable, dispose it and take it off the
// list of disposable content
if (loaded[assetName] is IDisposable
&& disposable.Contains((IDisposable)loaded[assetName]))
{
IDisposable obj = disposable[
disposable.IndexOf((IDisposable)loaded[assetName])];
obj.Dispose();
disposable.Remove(obj);
}
// Take it off the list of loaded content
loaded.Remove(assetName);
}
}
}
}
Now we need to add an instance of our content manager to the Engine class. Add the following in the class near the other member declarations:
// The engine's content manager public static IEContentManager Content;
Now initialize it by adding this at the end of SetupEngine():
// Setup the content manager using the service container Engine.Content = new IEContentManager(Services);
Now we are going to do is add some GameScreens to the Engine class. The first GameScreen is called BackgroundScreen, and overrides BlocksDraw, BlocksUpdate, and BlocksInput. This way we can have components running in the background that may need to update or accept input, such as the input class. We will create another called DefaultScreen, and set it to the BackgroundScreen. This screen is the one that components will be created in unless they specify otherwise. We can change the DefaultScreen while running, so new components will be created on that screen instead. If the current DefaultScreen is disabled, it will be set back to the BackgroundScreen. So, add this to the class:
// GameScreen provided by the engine. public static GameScreen BackgroundScreen; // The GameScreen to set to new GameScreens when a screen is not specified public static GameScreen DefaultScreen;
And add this in SetupEngine():
// Setup the background screen
BackgroundScreen = new GameScreen("Engine.BackgroundScreen");
BackgroundScreen.OverrideUpdateBlocked = true;
BackgroundScreen.OverrideDrawBlocked = true;
BackgroundScreen.OverrideInputBlocked = true;
// Set the default screen to the background screen so new screens will
// use it automatically unless told otherwise
DefaultScreen = BackgroundScreen;
The final thing we need to do is create the GameScreenCollection class. This is a class that keeps track of GameScreens. It inherits from KeyedCollection, so it can return a GameScreen by name, like so: “Engine.GameScreens["GameScreenName"]“. This is better than a list because with a list we would have to keep track of number IDs for the screens. It also has some logic to handle the resetting of Engine.DefaultScreen if it is removed. Here’s the code:
using System.Collections.ObjectModel;
namespace Innovation
{
public class GameScreenCollection : KeyedCollection<string, GameScreen>
{
// Allow us to get a screen by name like so:
// Engine.GameScreens["ScreenName"]
protected override string GetKeyForItem(GameScreen item)
{
return item.Name;
}
protected override void RemoveItem(int index)
{
// Get the screen to be removed
GameScreen screen = Items[index];
// If this screen is the current default screen, set the
// default to the background screen
if (Engine.DefaultScreen == screen)
Engine.DefaultScreen = Engine.BackgroundScreen;
base.RemoveItem(index);
}
}
}
Well, thats all for this tutorial! Dont be dissappointed though, we are now done with our engine framework! In the next tutorial we will actually start working on some game components!
Download the Code for this Chapter
Back to Game Engine Tutorial Series
« Community Games Best Practices XNA 3.0 Release Date Announced! »

Hi there,
nice implementation of your Content Manager!Thats one of the missing thing in my engine
Issues:
1) The beginning of this post seems to be a little goofed up. (large gap before the code section starts)
2) The download for the code is an empty archive.
3) Where does the GameScreenCollection come from? I haven’t seen any code for this class yet.(maybe you haven’t covered this yet)
1) Fixed
)
2) Fixed
3) You’re right, I updated the post to include this. (Fixed
Thanks for your feedback!
Issues: (cont)
Found another item. In the Update and Draw methods – in the article you are creating a List when it should be List.
This is correct in your download, just not in the article.
Sorry the comment stripped the greater/less than > < symbols.
the List type is incorrect. The article has “Component” where it should be “GameScreen”
All better
// The Engine’s SpriteBatch
public static SpriteBatch SpriteBatch;
Is it ok to define your variable name to be the same as the class name?
Yeah, its okay to do that. The only time it becomes a problem is if you have an instance with the same name in a class and you try to access a static function or property from the actual Type. For example, if you had an instance called “Vector3 Vector3″ and you wanted to use “Vector3.Dot()”, the instance would get in the way. In that case you would have to use “Microsoft.Xna.Framework.Vector3.Dot()”. But because we won’t usually be accessing the SpriteBatch from inside Engine, it’s ok to call it “SpriteBatch”.
Very, very nice! I’m loving these tutorials so far, however, in the ServicesManager class, I added a genericized version of AddService, similar to how you did in the ContentManager.Load
All you have to do is Engine.Services.AddService(Provider), saving you a couple keystrokes so you don’t have to surround the type with typeof().
Here’s the code for the genericized AddService:
///
/// A really neat shortcut for AddService
///
/// The type of service that provider will provide
/// The actual provider
public void AddService(object Provider)
{
Type Service = typeof(T);
// if we already have a provider of this type, throw
// an exception
if (services.ContainsKey(Service))
throw new Exception(“The service container already has a provider of type ”
+ Service.Name + “.”);
// otherwise add it to the list
services.Add(Service, Provider);
}
That would be good for basic service providers, but it doesn’t work so well when you are trying to be less specific about what type is actually providing the service. For example, later on we have components that require a Camera. However, we would more likely have an FPSCamera providing the service since Camera is very basic (no input). So, we would have a problem when the component went to look for Camera and it wasn’t there. So, be careful using this method.
First, i really like these tutorials!
What i really miss in the tutorial is the the big picture. Something like an UML-Diagram or something. A place where i can see how all these things connect together. That would be cool
Oh, and i have 2 small questions: Why exactly did you made the Engine class static?
I mean if you have to initialize it, why don’t you use a constructor?
And the other thing is: Is it normal to start all function and variable names with capitals? In the file “Game1.cs” the variables name first letter is lowercase. I am just wondering because i have never seen a piece of code where function/variable names where “ucfirst”
. Is that a C# special? Okay, so far ive only seen C, PHP, Java and JS code…
i just wanna make it right and learn the standard-definition of C#.
Hi Sean, thanks for the really nice tutorial series. It’s a well thought out structure and I definitely plan to borrow some of your ideas
One thing on your custom ContentManager: when you Unload(string assetName), you only dispose the actual asset (if it is IDisposable). The problem is that RecordIDisposable(IDisposable asset) will get called on internal IDisposables like the VertexBuffer and IndexBuffer of a Model. The result is that unloading an asset won’t necessarily free all of it’s memory to be garbage collected – particularly bad if you repeatedly load/unload the same asset.
I managed to solve this hairy issue in my ContentTracker class by using reference counting and a Stack (http://www.ziggyware.com/readarticle.php?article_id=231 if anyone’s interested).
Thanks you for sharing your experience. There is an obvious boat load of work in these tutorials, and it means a lot to the community that you’re posting. Please, keep it up!
I’m hoping you can clear something up for me. In the ContentManager’s overridden Load function, it doesn’t appear as though you are actually returning cached assets if they’re already loaded. Shouldn’t the Load function look something like this:
// Override loading of assets so we can use our own functionality
public override T Load(string assetName)
{
// If we are holding assets, and we have already loaded this
// one, grab it from the list and return it
if (PreserveAssets && loaded.ContainsKey(assetName))
return (T)loaded["assetName"];
// Create a new instance of the requested asset
T r = this.ReadAsset(assetName, RecordIDisposable);
// If we are holding on to loaded assets, add it to the list of
// loaded assets
if (PreserveAssets && !loaded.ContainsKey(assetName))
loaded.Add(assetName, r);
// Return the loaded asset
return r;
}
Please correct me if I missed something.
// Clear the back buffer
GraphicsDevice.Clear(Color.CornflowerBlue);
This line in the Engine.Draw() should not be there.
Doing so will override any Background color you set with Screens in the Game Class.
Forget that last comment, I was streamlining the code to my tastes, changing alot of variables to Properties and I forgot to add in the BackgroundScreen was Visble.
Thanks for your great tutorials.
I can adapt it to create my own one.
Only one idea so far that I admit myself I will stick to it, is ‘StateManagement’. FMHO: it will give less for-loop and give more flexible across game’s components.
Anyway though it’s up to the app’s complexity.
Thanks
Sorry if this question sounds a bit newbie, but I am one.
Do all t5he classes; Engine.cs, IEServiceContainer.cs, IEContentManager.cs, and GameScreensCollection.cs all go into the components folder?
I’m a bit unsure about these folders as to what they do, and what they mean. Can anyone help?
thanks in advance
Nick
You can put them in a folder if you want to, you wil have to drag them into one and set the namespace at the top of each file to [yourEngineName].[yourFolderName].
And if you want to use an object that’s in another folder, you add a using statement: “using [yourEngineName].[yourFolderName]“