8
\$\begingroup\$

I'm trying to write a SpriteManager class in XNA, but I need access to the Game variables. For example, the Game.Content property would be very helpful in loading textures, and Game.GraphicsDevice.Viewport would be helpful in getting the window size.

For now, I have the following class:

public MainGame : DrawableGameComponent
{
    public SpriteManager<Enemy> EnemyManager { get; get; }
    public SpriteManager<Powerup> PowerupManager { get; set; }
    ...
}

I can think of three ways of getting access to these variables in the SpriteManager class:

  1. Make my sprite manager class derive off of GameComponent. This would be ideal, except that my sprite manager is used in MainGame, which is a GameComponent.

  2. Use ((Game) Game1) to access the variables. However, doing this kind of cast is ugly and breaks encapsulation.

  3. Pass everything down from MainGame. For example, EnemyManager needs to load a random enemy type each time it spawns an enemy, so instead of loading the textures in MainGame, pass EnemyManager the Game.Content property and let it handle texture loading. However, I'm not sure if this is the best way of handling the situation. I can't place my finger on it, but it just seems 'wrong' in some way.

I could use some advice on the best way of achieving this.

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Don't do that - make the sprite manager a service instead.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks, this is the first I've heard of game services. It looks similar to dependency injection, but I'm only slightly familiar with it. \$\endgroup\$
    – Daniel T.
    Commented Jul 12, 2011 at 19:00
  • \$\begingroup\$ @Daniel: Dependency injection and service containers are two types of Inversion of Control. See this answer for more details. \$\endgroup\$ Commented Jul 12, 2011 at 19:07
  • 1
    \$\begingroup\$ Everyone is so quick to make it a game service. It's not that bad to make it public. You only have 1 game instance .. \$\endgroup\$
    – Setheron
    Commented Sep 9, 2011 at 20:08
2
\$\begingroup\$

Actually #2 isn't so bad (I will assume you meant to down-cast from Game to Game1). You can enforce the type being Game1 in your constructor like so:

public MainGame : DrawableGameComponent
{
    public MainGame(Game1 game) : base(game) { }
}

You could even make a nice convenience property like this. It will always be safe, providing the underlying DrawableGameComponent doesn't do anything undocumented.

public Game1 Game1 { get { return (Game1)Game; } }

Or if you want to be extremely anal about not casting (and there is really no need to be), you could do this:

public MainGame : DrawableGameComponent
{
    public MainGame(Game1 game) : base(game) { this.Game1 = game; }

    public Game1 Game1 { get; private set; }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .