XNA on Linux and Mac with
MonoGame
XNA is a great development framework that lets you create games in C# for Windows, Xbox 360 and Windows Phone 7. A drawback of this framework is that it does not provide support for other platforms. This issue may be about to vanish thanks to MonoGame (and soon ExEn), a portable and open source framework replicating XNA and running on multiple platforms thanks to the Mono and/or .NET runtimes. Thanks to MonoGame, you will be able to develop games for:
The good thing about MonoGame is that it uses the same namespaces XNA uses. Actually, it's a total rewrite of the Microsoft framework so that it works with OpenGL. In theory, an XNA code sample may be recompiled directly with MonoGame without any modification (only the project references need to be modified). Nonetheless, proceed with caution, as for now there is only a 2D support as well as a partial 3D support (ever since version 2.1). It might also be lacking some elements like Sound (which is not totally supported), networking (another networking layer has been implemented for Microsoft Live service is proprietary), etc...
The good thing about MonoGame is that it uses the same namespaces XNA uses. Actually, it's a total rewrite of the Microsoft framework so that it works with OpenGL. In theory, an XNA code sample may be recompiled directly with MonoGame without any modification (only the project references need to be modified). Nonetheless, proceed with caution, as for now there is only a 2D support as well as a partial 3D support (ever since version 2.1). It might also be lacking some elements like Sound (which is not totally supported), networking (another networking layer has been implemented for Microsoft Live service is proprietary), etc...
Prerequisites
Setting up a MonoGame development environment is both simple and complex at the same time... The main issue lies in the many dependencies the framework requires in order to run. Indeed, MonoGame needs:
Once all dependencies installed, a base project can easily be set up. On Linux or Mac, MonoDevelop can be used to provide practical tools such as completion, compiling with a single click. On Windows, you can use Visual Studio, MonoDevelop or SharpDevelop.
- Tao.Sdl.dll (which requires the native SDL library)
- OpenTK.dll (which requires OpenGL in order to work, as well as OpenAL)
- Libgren.Network
Once all dependencies installed, a base project can easily be set up. On Linux or Mac, MonoDevelop can be used to provide practical tools such as completion, compiling with a single click. On Windows, you can use Visual Studio, MonoDevelop or SharpDevelop.
Note: On Ubuntu and Debian operating systems, MonoGame comes in a package that includes MonoDevelop.
Compiling MonoGame
The first thing to do is compiling MonoGame for your platform. The procedure I will be detailing works on both Windows and Linux (and probably Mac, but I don't have one).
MonoGame is released as an archive, thus it first needs to be extracted. Once done, the same must be done with OpenTK (which is released already compiled). I advise using a nightly build of OpenTK (follow the link I provided). When everything is downloaded and extracted, open up the MonoGame solution that's best for you.
The issue you are going to encounter is that the OpendTK reference is missing and you simply need to replace it with the OpenTK version you just extracted. The procedure in pictures:
MonoGame is released as an archive, thus it first needs to be extracted. Once done, the same must be done with OpenTK (which is released already compiled). I advise using a nightly build of OpenTK (follow the link I provided). When everything is downloaded and extracted, open up the MonoGame solution that's best for you.
The issue you are going to encounter is that the OpendTK reference is missing and you simply need to replace it with the OpenTK version you just extracted. The procedure in pictures:
The missing reference is to be deleted.
Use the OpenTK version you just downloaded.
Proceed with caution, using MonoDevelop you need to click "add" so that the reference be added to the solution. Now we only need to build MonoGame. I advise you to build it in release mode (debug mode isn't required in this particular case, since we won't be debugging the MonoGame library).
Now let's move on to the bin/Release folder where you will find 6 .dll files that need to be added to the game project solution.
GamepadConfigControls.dll and Tao.Sdl.dll are used for joystick and Xbox 360 game pad management.
Lidgren.Network.dll provides some networking features.
MonoGame.Framwork.{Linux/Windows/Mac}.dll is the .dll that will make it possible for your game to run on Linux, Windows, iOS and Android.
OpenTK.dll is the library that makes it possible to use OpenGL with C# and it is used by MonoGame to handle display (among other things).
Now let's move on to the bin/Release folder where you will find 6 .dll files that need to be added to the game project solution.
GamepadConfigControls.dll and Tao.Sdl.dll are used for joystick and Xbox 360 game pad management.
Lidgren.Network.dll provides some networking features.
MonoGame.Framwork.{Linux/Windows/Mac}.dll is the .dll that will make it possible for your game to run on Linux, Windows, iOS and Android.
OpenTK.dll is the library that makes it possible to use OpenGL with C# and it is used by MonoGame to handle display (among other things).
Creating a standard project
There is nothing more simple than creating a basic project. First of all, create a new "console" project, then add the following references:
The next step consists in creating 2 C# classes, i.e. 2 files. We shall proceed as Microsoft and and create:
- GamepadConfigControls.dll (provided by MonoGame)
- Lidgren.Network.dll (provided by MonoGame)
- MonoGame.Framwork.{Linux/Windows/Mac}.dll
- OpenTK.dll
- Tao.Sdl.dll
- System (provided by Microsoft/Mono by default)
The next step consists in creating 2 C# classes, i.e. 2 files. We shall proceed as Microsoft and and create:
- Program.cs (that contains our Main method)
- Game1.cs (that contains your game)
Contents of Program.cs
using System; using System; using System.Collections.Generic; using System.Linq; namespace MonoGameTutorial { static class Program { private static Game1 game; [STAThread] static void Main() { game = new Game1(); game.Run(); } } } |
Everything there is classic and I think there is nothing more to say about it. We just create a Game1 instance and run the game.
Contents of Game1.cs
using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; namespace MonoGameTutorial { public class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; public Game1 () { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; graphics.PreferredBackBufferWidth = 640; graphics.PreferredBackBufferHeight = 480; graphics.IsFullScreen = false; Window.Title = "Tutoriel MonoGame 0"; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { base.LoadContent(); } protected override void UnloadContent() { base.UnloadContent(); } protected override void Update(GameTime gameTime) { base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.AliceBlue); base.Draw(gameTime); } } } |
As you can see, that's exactly the same content that can be found in the base file generated by Visual Studio when creating a new XNA game project.
The class inherits from Game and can be seen as the very core of the game. It contains several methods that we will study more in depth now.
The Initialize() method initializes your objects.
The LoadContent() method is used in order to load your content. The content may be sound, textures, XML files, and so on... All this is stored in the Content folder that needs to be placed on the same folder as your game installer. It doesn't exist by default and you will need to create it after compiling (placing your resources inside, of course).
The UnloadContent() method is called when the game exits. That's when all the resources that stem from your objects (graphics, sound, etc...) will be freed.
The Update(GameTime gameTime) method will be used to run your game logic. Typically, that's where we'll run tests about character movement for instance. This method is called in a loop.
And finally, the Draw(GameTime gameTime) method is called in a loop as well (right after Update) and that's where everything visual about the game (sprites, 3D models, effects, etc...) shall be displayed.
The class inherits from Game and can be seen as the very core of the game. It contains several methods that we will study more in depth now.
The Initialize() method initializes your objects.
The LoadContent() method is used in order to load your content. The content may be sound, textures, XML files, and so on... All this is stored in the Content folder that needs to be placed on the same folder as your game installer. It doesn't exist by default and you will need to create it after compiling (placing your resources inside, of course).
The UnloadContent() method is called when the game exits. That's when all the resources that stem from your objects (graphics, sound, etc...) will be freed.
The Update(GameTime gameTime) method will be used to run your game logic. Typically, that's where we'll run tests about character movement for instance. This method is called in a loop.
And finally, the Draw(GameTime gameTime) method is called in a loop as well (right after Update) and that's where everything visual about the game (sprites, 3D models, effects, etc...) shall be displayed.