Purge Your XNA Game Class |
Caution |
---|
This article discusses how you can use the Service Provider pattern to create a simple, clean Game class in XNA. Please note, the example code uses an obsolete service provider implementation. Have a look a the DigitalRune Samples to see the most recent implementation. |
In all XNA games you have to create your own Game class that derives from the Game base class. Here is a pattern in which we use the service provider pattern to create a clear structure for our game class.
In many XNA games and samples the Game class does a lot of stuff and is maybe the most complex class of the application. This makes the source code difficult to understand and hard to re-use. We suggest two things to improve this:
This topic contains the following sections:
Here is an example for a Game which uses several sub-systems (input, graphics, physics, GUI, game objects for game logic).
public class MyGame : Game { private GraphicsManager _graphicsManager; private PhysicsManager _physicsManager; private UIManager _uiManager; private InputManager _inputManager; private GameObjectManager _gameObjectManager; public MyGame() { _graphicsManager = new GraphicsManager(this) { PreferredBackBufferWidth = 854, PreferredBackBufferHeight = 480, SynchronizeWithVerticalRetrace = false }; Content.RootDirectory = "Content"; IsMouseVisible = true; IsFixedTimeStep = true; } protected override void Initialize() { // ----- Initialize Services. ServiceManager.GlobalServices = Services; Services.AddService(typeof(IGraphicsService), _graphicsManager); _physicsManager = new PhysicsManager(); Services.AddService(typeof(IPhysicsService), _physicsManager); _inputManager = new InputManager(false); Services.AddService(typeof(IInputService), _inputManager); _uiManager = new UIManager(this, _inputManager); Services.AddService(typeof(IUIService), _uiManager); _gameObjectManager = new GameObjectManager(); Services.AddService(typeof(IGameObjectService), _gameObjectManager); // ----- Add GameComponents Components.Add(new MyGameComponent(this)); base.Initialize(); } protected override void Update(GameTime gameTime) { float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds; _inputManager.Update(deltaTime); base.Update(gameTime); _uiManager.Update(deltaTime); _gameObjectManager.Update(deltaTime); _physicsManager.Update(deltaTime); } }
This is it. The private fields define the sub-systems:
The constructor is similar to most other XNA samples.
The Initialize() method does following things:
The Update method updates the sub-systems.
A few important takeaways:
Use the service-manager pattern to structure your subsystems. Separate custom game logic and custom rendering from the main game class. This is one possible design that we have used recently and it has helped to make our code easier to read and to maintain.