XNA provides a neat little system for you to organize your
game’s different parts in: GameComponent
s.
You can use them to modularize your game’s subsystems,
eg. have a GuiComponent
, PhysicsComponent
,
SceneGraphComponent
etc. so you avoid having all that
code in your Game class, or can use them for your actual
game objects in smaller games.
However, the GameComponent
and
DrawableGameComponent
classes provided
by XNA force you to reference the Game
class. This is unfortunate if you want to use those components
in a WinForms-based XNA application and gets in the way
when you try to write unit tests for your components because
now you have to create a dummy Game
instance as well (and better hope that component won’t
go shopping for references in the Game
‘s
Components
and Services
collections as well).
Luckily, the GameComponentCollection
used by XNA to store your components manages
IGameComponent
s
and updating/drawing are based on the IUpdateable
and IDrawable
interfaces alone, so there’s nothing preventing you from rolling your
own components without referencing the Game
class.
That’s exactly what I did when I started writing an editor for
my Island War game. I simply reimplemented XNA’s
GameComponent
and
DrawableGameComponent
classes, minus
the Game
reference. I named them
Component
and DrawableComponent
(cleverly removing the ‘Game’ from the name to show that these
no longer reference the Game
class):
Users of my components (like my GUI and particle system classes)
wouldn’t notice any difference and could use the classes like
normal GameComponent
s, but the custom base
class allowed me to use this components in a WinForms environment.
Lately, I’ve been tinkering around with SunBurn,
Synapse Gaming‘s
lighting and rendering framework for XNA. Here you have drawable
things that do not access the GraphicsDevice
.
Instead, they will modify SunBurn’s scene graph. Thus, carrying
around the GraphicsDevice
reference in my
DrawableComponent
became essentially dead weight
for the components involved.
So I decided to make a variant of my
DrawableComponent
that would still do all of
the uninteresting stuff managing the Visible
and
DrawOrder
properties, firing events and so on,
but not handle the GraphicsDevice
for me. What
I ended up with is this:
In retrospect, this turns out to be a much cleaner design, too:
The DrawableComponent
only handles the
implementation of the IDrawable
interface instead
of doing both that and managging the GraphicsDevice
.
And the GraphicsDeviceDrawableComponent
(excuse the long name, haven’t found anything more concise yet),
deriving from DrawableComponent
, only handles
the management of the GraphicsDevice
.
This will be a breaking change in the next Nuclex Framework
release, but all you have to do is paste
"GraphicsDevice
" in front of your
"DrawableComponent
". I think this is
nicer than having some
DrawableComponentWithoutGraphicsDevice
class :).
I’d wager that in larger games (which is what my Nuclex Framework
is designed for) a scene graph or something comparable is probably
used in the majority of cases and direct GraphicsDevice
access only happens in some corner cases.