XNA Arcade tutorial (2 of 5) – The AbstractGame and ArcadeGamesManager

This is an introduction to how we will create the basis for all the games (AbstractGame)
which can be loaded and played in the XNA Arcade. We will also create a helperclass
(ArcadeGamesManager) which can load these classes and their resources from external
assemblies (DLLs).


2012-10-18_112144

Why an AbstractGame class?

At its core, what we want is to have something (a small game) behave differently depending on which game it is - but we should be able to load them all in the same way from the hostgame.
So our coder-mindset says: "Different things which should appear alike in code - AHA, WE NEED AN INTERFACE!!".
Next our coder-mindset says "...but wait - we can probably implement some of the code in a superclass, to avoid having to code everthing again whenever we make a new game - AHA, WE CAN MAKE AN ABSTRACT SUPERCLASS!!!Smiley med åben mund
Basically, an abstract class is a class which you can't "new up" (instantiate) and it is often used to write code to reuse in subclasses.

The basic structure - Draw() and Update()

Since we are already familiar with the idea of the Game class in XNA, we will let the AbstractGame class have an Update and a Draw method as well. This simplifies running the subgame in the hostgame as the calls to Update and Draw in the hostgame will just forward the calls to Update and Draw in the whatever game is currently loaded.

updatedrawonsubgame

This effectively puts the hostgame out of the loop. So we need some way to return control when the subgame has ended. We do this by letting the hostgame read a public variable called GameOver on the subgame. The subgame can then set this variable to true when the hostgame should take control again. Here's code from the hostgame, calling the subgame's Update and Draw:

//To hold the currently running subgame
AbstractGame _currentGame;

protected override void Update(GameTime gameTime)
{
    //if we're playing a game
    if (_currentGame != null)
    {
        //if the game is over, empty the current game
        //thereby returning to the game selection screen
        if (_currentGame.GameOver)
        {
            _currentGame = null;
        }
        else
        {
            //call the update method of the game being played
            _currentGame.Update(gameTime);
        }
    }
}

protected override void Draw(GameTime gameTime)
{

    if (_currentGame != null)
    {
        //use that game's Draw
        _currentGame.Draw(gameTime);
    }
    else
    {
        //draw the hostgame's gameselection screen
    }
}

Give AbstractGame the tools it needs

Since the subgame isn't a real Game class it doesn't have access to the same variables that an ordinary Game does (e.g. ContentManager, GraphicsDevice, etc.). This means we have to supply it with these things. The way I've chosen to handle this is by making a helperclass (ArcadeGamesManager) which is instantiated using a reference to the hostgame. When you want an instance of a game you only need to tell the ArcadeGamesManager what type of game to create and give it a reference to the SpriteBatch you want it to draw on (here the "this" refers to the hostgame where the ArcadeGamesManager is created):

ArcadeGamesManager manager = new ArcadeGamesManager(this);

AbstractGame myGame = manager.CreateGame(typeof(MyChessGame), this.SpriteBatch);

What about resources?

Since we would like the subgames to be selfcontained - so just adding a new DLL to a subdirectory in the hostgame's folder will add new games - we need to be able to contain everything we need inside the DLL: code, graphics, sounds, fonts, etc. How we embed the resources will be covered in part 4, but just know for now, that the AbstractGame class has two ContentManager properties HostContent and LocalContent to be able to load content from both the hostgame and its own DLL.


contentload

The idea behind this is that you want the subgames to be able to stand on their own as well and supply all resources, but if you are developing a gamespack, you might design all subgames to load resources from the main game (fonts, textures, etc.) to give them a coherent look-and-feel.

This gives you both possibilities Smiley

Sample code

HostContent.Load("background"); //loads from the hostgame

LocalContent.Load("background"); //loads from the game's own DLL

Rolling your own subgame

Since you don't construct your own instances of your games, but leave that up to the ArcadeGamesManager, you may still want to do some intialization (load resources, set variables, etc.). The AbstractGame defines an Initialize method which you can override. Just make sure you call

base.Initialize(...)

as the first line in your own Initialize method, so the AbstractGame is initialized as well.

In my next (upcoming) blogpost I will look at how we inspect the DLL files and make it possible for the player to select a game to run:

Next chapter: Part 3 - Creating the hosting game and selecting a game to play

Leave a Reply