XNA Arcade tutorial (3 of 5) – Creating the hosting game and selecting a game to play
What we will cover
In this tutorial we will look at how to use the ArcadeGamesManager to inspect external DLLs for games, how to get information about them and how to instantiate a selected game and run it.
Information about what games are available (name and icon)
All games for the Xna Arcade are loaded from DLL files (Assemblies) from the game's folder or subfolders.
Here you can see the main (hosting) game "XnaArcadeTutorial.exe" which relies on the "ArcadeLibrary.dll" (with the ArcadeGamesManager class) for inspecting DLL files with games in them: "SampleGamesPack.dll".
For this tutorial all you need to know is that code in .net is hosted in Assemblies (often .exe or .dll files)which are self-contained units that have both code and a description of the contents. Sometimes the assemblies also contain further resources (text files/images/sound/etc..). For finding games in external assemblies, loading them and getting their icons, I've coded a helperclass, the ArcadeGamesManager.
The ArcadeGamesManager class
The ArcadeGamesManager assists in all the boring housekeeping and let's you concentrate on the fun stuff: Coding Games! . The short version is: the ArcadeGamesManager uses a method called Reflection to inspect an assembly (the dll file with games in) and find out which classes are subclasses of the AbstractGame class, information about these games are returned in a Type object. Type objects contain information about a given class/object and are used as parameters to the ArcadeGamesManager.CreateGame() when you want to instantiate a specific game for playing.
ArcadeGamesManager Codesamples
First code for instantiating a ArcadeGamesManager and using it to get a list of all the playable games:
//initialize a ArcadeGamesManager by sending it a reference to the HostingGame ArcadeGamesManager _gamesManager = new ArcadeGamesManager(this); //get all the games in all DLL files in the executing game's folder or its subfolders List<Type> _games = _gamesManager.GetGamesFromRunningGamesSubfolders();
GetGameThumbnail and GetGameName assist in getting games' names and icons for making a menu for example:
//Iterate through all games and get name and icon for (int i=0; i<_games.Count(); i++) { //get the icon for that gametype Texture2D _gameIcon = _gamesManager.GetGameThumbnail(_games.ElementAt(i)); //read the DisplayName attribute from the class, to show its name string gameName = _gamesManager.GetGameName(_games.ElementAt(i)); //do something with name and icon //... }
After selection of a game has been made and we want to start it, we use the CreateGame() method to create an instance (object) of that Type. How we write code to make a menu and select from the menu is covered in part 4 of this tutorial.
//get the typedescription of the type of game to start Type typeOfGameToStart = _games.ElementAt(_selectedGameIndex); //create an instance of a specific game, and store it in _currentGame AbstractGame _currentGame = _gamesManager.CreateGame(typeOfGameToStart, spriteBatch);
What happens when the ArcadeGamesManager creates a new game
/// <summary> /// Creates a new object of a game from the Type and initializes it /// </summary> /// <param name="gametype">The type of game to instantiate (must be subclass of AbstractGame)</param> /// <param name="game">The hostgame which will run the abstractgame</param> /// <param name="graphics">The GraphicsDeviceManager which this game can interact with</param> /// <param name="spriteBatch">The SpriteBatch for the game to draw to</param> /// <returns>The new instance of the game after it has been initialized</returns> public AbstractGame CreateGame(Type gametype, SpriteBatch spriteBatch) { //make sure the type describes a subclass of AbstractGame if (gametype.IsSubclassOf(typeof(AbstractGame))) { //call the constructor of the class AbstractGame _game = (AbstractGame)Activator.CreateInstance(gametype); //initialize it _game.Initialize(this,spriteBatch); //and return it return _game; } else { throw new Exception("The type " + gametype.Name + " is not a subclass of AbstractGame"); } }
As you can see the ArcadeGamesManager calls the Initialize method of the game it is creating and passes a reference to itself. Here you can see the AbstractGame.Initialize method and what is made ready for your game to take over and do its thing
public virtual void Initialize(ArcadeGamesManager gamesManager, SpriteBatch batch) { //store references for use in this game GamesManager = gamesManager; Game = GamesManager.Game; GraphicsDeviceManager = (GraphicsDeviceManager) Game.Services.GetService(typeof(GraphicsDeviceManager)); Graphics = Game.GraphicsDevice; SpriteBatch = batch; //store the contentmanager which points to the main game HostContent = Game.Content; //store the contentmanager which points to the game's own assembly LocalContent = GamesManager.GetContentManager(this.GetType()); Font = GamesManager.DefaultFont; }