Application Model Overview
This overview covers the following topics.
- Making a New Game
- Game Loop Timing
- Starting the Game
- Game Components
- Game Services
- Game Components Consuming Game Services
Making a New Game
The first step in creating a new game is to make a class that derives from Game. The new class needs to override Update, Draw, and Initialize. The Update method is responsible for handling game logic, and the Draw method is responsible for drawing each frame. The Initialize method is responsible for game setup before the first frame of the game.
Game Loop Timing
A Game is either fixed step or variable step, defaulting to fixed step. The type of step determines how often Update will be called and affects how you need to represent time-based procedures such as movement and animation.
A variable-step Game calls its Update method as soon as the previous frame is done drawing. Setting Game.IsFixedTimeStep to false causes a Game to use a variable-step game loop. This type of Game requires the game logic and animation code to be based on elapsed time to ensure smooth gameplay. Because the Update method is called immediately after the previous frame, the time between calls to Update can vary. Without taking the time between calls into account, the game would seem to speed up and slow down. The time elapsed between calls to the Update method is available in the Update method's gameTime parameter.
When using a variable-step game loop, you should express rates—such as the distance a sprite moves—in game units per millisecond (ms). The amount a sprite moves in any given update can then be calculated as the rate of the sprite times the elapsed time. Using this approach to calculate the distance the sprite moved ensures that the sprite will move consistently if the speed of the game or computer varies.
A fixed-step Game tries to call its Update method on the fixed interval specified in TargetElapsedTime. Setting Game.IsFixedTimeStep to true causes a Game to use a fixed-step game loop. Using a fixed step allows game logic to use the update as its basic unit of time and assume that Update will be called at the interval specified. When an update runs slower than expected, Game meets this assumption by calling Update extra times and dropping the frames associated with those updates to catch up. This ensures that Update will have been called the expected number of times when the game loop catches up from a slow down.
When using a fixed-step game loop, rates such as the distance a sprite moves can be expressed as game units per Update. This enables you to simply increment the position of the sprite by the sprite's movement rate each Update.
Starting the Game
Game components provide a modular way of adding functionality to a game. You create a game component by deriving the new component either from the GameComponent class, or, if the component loads and draws graphics content, from the DrawableGameComponent class. You then add game logic and rendering code to the game component by overriding GameComponent.Update,DrawableGameComponent.Draw and GameComponent.Initialize. A game component is registered with a game by passing the component to Game.Components.Add. A registered component will have its draw, update, and initialize methods called from the Game.Initialize, Game.Update, and Game.Draw methods.
Game services are a mechanism for maintaining loose coupling between objects that need to interact with each other. Services work through a mediator—in this case, Game.Services. Service providers register with Game.Services, and service consumers request services from Game.Services. This arrangement allows an object that requires a service to request the service without knowing the name of the service provider.
Game services are defined by an interface. A class specifies the services it provides by implementing interfaces and registering the services with Game.Services. A service is registered by calling Game.Services.AddService specifying the type of service being implemented and a reference to the object providing the service. For example, to register an object that provides a service represented by the interface IMyService, you would use the following code.
Services.AddService( typeof( IMyService ), myobject );
Once a service is registered, the object providing the service can be retrieved by Game.Services.GetService and specifying the desired service. For example, to retrieve IGraphicsDeviceService, you would use the following code.
IGraphicsDeviceService graphicsservice = (IGraphicsDeviceService)Services.GetService( typeof(IGraphicsDeviceService) );
Game Components Consuming Game Services
The GameComponent class provides the Game property so a GameComponent can determine what Game it is attached to. With the Game property, a GameComponent can call Game.Services.GetService to find a provider of a particular service. For example, a GameComponent would find the IGraphicsDeviceService provider by using the following code.
IGraphicsDeviceService graphicsservice = (IGraphicsDeviceService)Game.Services.GetService( typeof( IGraphicsDeviceService ) );