The XNA Game class is a solid foundation to build your game on.
While you're free to decide not to use the GameComponents
and GameServices part of this class, using it
provides you with a good starting point to organize small to
moderate projects in. But let's first explore what this is
all about!
Exploring GameComponents
Games typically consist of several logical modules that could ideally be reused between different games. For example, a lot of 3D games internally employ a scene graph to manage the visual entities in a game (models, decals and so on). This scene graph could be written in a general manner so that two very different games could use the same scene graph module.
This is exactly what the GameComponent class is about.
Instead of spreading your graphics, scene graph and text rendering
code all over the place, you can cleanly seperate these parts of
your games into components that you can then give to other XNA
developers or reuse in your next project. Here's an example of
which GameComponents you might decide to create for
a simple application:

GameServices
But wait! The TextRenderingComponent needs to access
the GraphicsComponent. And the
SceneGraphComponent needs access to the
GraphicsComponent and the
EffectManagerComponent. Was the separation in vain?
Will all these components need to know of each other and develop
a tightly woven net of interactions that makes it impossible to
take one of them and put it in another project?
Not quite. That's where the GameServices collection
comes into play. Basically, a game service is just an interface
under which you access a component. The built-in
GraphicsComponent, for example, has the built-in
IGraphicsDeviceService service which allows access to
the GraphicsDevice that is managed by the component.
It works like this:
-
First, all
GameComponent-derived classes that you added to your game are created and put into theGameComponentscollection. -
Each time a component is added to the collection, its
OnGameChanging()method is called. Here the component will register its services to theGameServicescollection. -
After all components have been added, the second stage
initialization calls the
Start()method of all components. Here components can pick the services of other components they require.
In the end, your game will not rely on the one and only
GraphicsComponent being there, but on
some component that provides your game with the
IGraphicsDeviceService. And that could be a
different component from game to game.
Your code might even choose to just skip graphics altogether
if there's no IGraphicsDeviceService, but keep
running neverthelesss (in a dedicated server, for example).
GameComponent Interaction
Components that need to access each other do so only through well-defined interfaces that could be provided by a different component in another game, or not at all. See this illustration to get a grasp of the concept:

Take note of the red line. This is how the
SceneGraphComponent accesses the
GraphicsDevice. It does not rely on the
GraphicsDevice being provided by the
GraphicsComponent class, it only expects that
the IGraphicsDeviceService exists in your game.
When to Create GameComponents
Well, that's really up to you. As a rule of thumb, any time you're
writing something you're likely to be needing in your next game, too,
create a GameComponent from it. Even if you need to
modify it for your next game, it will give you a headstart and
promote clean seperation of responsibilities in your code.
Example Code
Need code? Here is the source code for an example component, a
SceneGraphComponent that publishes a service named
ISceneGraphService that can be queried for by the game
class or by other components. If also shows how to use the
IGraphicsDeviceService interface to access the game's
GraphicsDevice
public interface ISceneGraphService {
/// <summary>The root node of the scene tree</summary>
SceneNode Root { get; }
/// <summary>Matrix used to transform 3D to screen coordinates</summary>
Matrix Projection { get; set; }
/// <summary>Matrix that defines the viewer's location in the scene</summary>
Matrix View { get; set; }
}
/// <summary>Component to manage visuals using a scene graph</summary>
/// <remarks>
/// <para>
/// A scene graph bascially organizes 'nodes' in a tree, where each node's position
/// is local to the parent nodes position. If you would model a solar system, the
/// planets would be childs to the sun, while the moons would be childs to their
/// respective planets. Each moon would then only have to remember its position
/// relative to the planet, and whereever the planet goes, the moon will be, too.
/// It is the same for the rotation of the parent node. The orientation of all
/// child nodes is relative to the orientation of the parent nodes.
/// </para>
/// <para>
/// Scene nodes are not required to actually draw anything, you can create them
/// just for the sake of categorization or in order to chain multiple independent
/// transformation matrices without concatenating the intermediate steps. If a
/// scene node wants to draw something, it can get ahold of the GraphicsDevice
/// by navigating back to the game instance through its 'SceneGraph' property.
/// </para>
/// </remarks>
public class SceneGraphComponent
: Microsoft.Xna.Framework.DrawableGameComponent, ISceneGraphService {
/// <summary>Initializes the scene graph</summary>
/// <param name="game">Game instance this scene graph belongs to</param>
public SceneGraphComponent(Game game) : base(game) {
game.Services.Add(typeof(ISceneGraphService), this);
}
/// <summary>Called when all game services have been registered</summary>
public override void Initialize() {
// Query for the graphics device service through which the graphics device
// can be accessed
IGraphicsDeviceService graphicsDeviceService =
(IGraphicsDeviceService)Game.GameServices.GetService(
typeof(IGraphicsDeviceService)
);
/* Example
// Register to the graphics device manager's events in order to get notified when
// our ResourceManagement.Manual resources need to be destroyed or recreated.
graphicsDeviceService.DeviceCreated += new EventHandler(graphicsDeviceCreated);
graphicsDeviceService.DeviceDisposing += new EventHandler(graphicsDeviceDisposing);
graphicsDeviceService.DeviceResetting += new EventHandler(graphicsDeviceResetting);
graphicsDeviceService.DeviceReset += new EventHandler(graphicsDeviceReset);
*/
}
}
cool sample
Weell,
you know, this is the only sample that i found inthe web about game services implementation,
thanks for your help.
If you want and can, please make an extention of this article in next time.
see ya.
thanks!!
thanks a lot man, great read. Only sample to add a service.
Nice
This really came in handy. Not sure why msft doesn't have more tuts for this kind of stuff. Thanks for writing this up!
Thanks!
Indeed, thanks for the writeup on GameServices! It was pretty clear and concise, and perhaps the only one of it's kind on the internet. Microsoft should really have documentation like this in the XNA package, but luckily there is a good community out there!
NEED HELP......
Hi.. ur tut wa grt..
i need some help regarding gameComponents...
i created an interface IScoreBoard for a GC ScoreBoard.
I added it to my game ...
but when i try to access its services in my other components i keep gettin the exception
NULLREFERENCE Exception!!
cud u help plzzz
Debug It
Cud u wrt prop. englsh plz?
My best guess is that you're querying for other GameComponents in your constructor. Only register your services in the constructors, do not query for other services before the Initialize() method was called.
My second best guess is that you simply forgot to actually add your service to the services collection. Might also be that you're adding the service under another Type than what you're querying for.
Post new comment