Thursday, February 23, 2012

MonoGame: Getting Started 3/3

Now let us create an Android project for the game. To start the project the following files are need:
  • Activity class file
  • Manifest file
  • Project file
  • Solution file
  • Icon file
In Android each app needs to have at least one Activity class. Therefore create a file inside your Android directory with the name Activity1.cs and the following content:
using Android.App;
using Android.OS;
using Android.Util;
using Android.Views;
using Android.Widget;
using Android.Content.PM;

namespace MyNamespace
{
    [Activity(Label = "MyGame Label", 
       MainLauncher = true, 
       Icon = "@drawable/icon", 
       ScreenOrientation = ScreenOrientation.Portrait,
       ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, 
       LaunchMode=LaunchMode.SingleInstance
    )]
    public class Activity1 : Microsoft.Xna.Framework.AndroidGameActivity
    {
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
     
            MyGame.Activity = this;
            var game = new MyGame ();
            
            FrameLayout fl = new FrameLayout(this);
            fl.AddView(game.Window);                               
            SetContentView (fl);            

            game.Run ();            
        }
    }
}
Inside this source change the MyNamespace and MyGame to fit your project. Next we need a manifest file. For that create a directory Properties and inside create the file AndroidManifest.xml with this content:

Before saving it you have to change the package tag to your game name and application label. The manifest file is the configuration file for your Android app. E.g. the minSdkVersion 8 means the Android API 8, which is Android 2.2. So this manifest file supports devices from version 2.2 upwards. Also the permissions of what features your application uses are defined in this file. Please read the Android docs to find out more about the manifest file:
http://developer.android.com/guide/topics/fundamentals.

Now go back to your Android source directory and create the project file MyGame.android.csproj with the following content:
You have to change the RootNamespace and AssemblyName tag to match your project. Also check if the ProjectReference tag of MonoGame and Lidgren point to your local installation path.
Now create the solution file for this project MyGame.sln and copy this content:
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lidgren.Network.Android", "..\..\MonoGame\ThirdParty\Lidgren.Network\Lidgren.Network.Android.csproj", "{565129E0-4EE5-4F6F-B403-C3484C9740BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Framework.Android", "..\..\MonoGame\MonoGame.Framework\MonoGame.Framework.Android.csproj", "{BA9476CF-99BA-4D03-92F2-73D2C5E58883}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9C06E528-B9C7-4115-81C1-0E572103B242}"
EndProject
Global
 GlobalSection(SolutionConfigurationPlatforms) = preSolution
  Debug|Any CPU = Debug|Any CPU
  Release|Any CPU = Release|Any CPU
 EndGlobalSection
 GlobalSection(ProjectConfigurationPlatforms) = postSolution
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Release|Any CPU.Build.0 = Release|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Release|Any CPU.Build.0 = Release|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Release|Any CPU.Build.0 = Release|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Release|Any CPU.Build.0 = Release|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Release|Any CPU.Build.0 = Release|Any CPU
 EndGlobalSection
 GlobalSection(NestedProjects) = preSolution
 EndGlobalSection
 GlobalSection(MonoDevelopProperties) = preSolution
  StartupItem = BulletBabs.Android.csproj
  Policies = $0
  $0.DotNetNamingPolicy = $1
  $1.DirectoryNamespaceAssociation = None
  $1.ResourceNamePolicy = FileFormatDefault
 EndGlobalSection
EndGlobal
Here again check if the path to the MonoGame and Lidgren project files point to your local MonoGame installation.
The one file remaining now is an icon for your game. For that you should create the folders Resources/drawable and place a png image file with the name Icon.png inside. Make the resolution of this file 96x96 pixel.

Now you are ready to open the solution file in either Visual Studio or MonoGame, depending on your installation option of Mono for Android. First check if the references to the MonoGame and Lidgren project are correct. Then add your game by using add project to add the project file we created before.
If you created and placed all files correctly you should now see all files inside your project map. Again please the if the references to MonoGame are correct.
Now you have to proceed similar as with the iOS project. First you add all your game source files as link to your project. At this point you should then already be able to compile your game. If not, try to find and fix the errors.
Once your game compiles you are ready to add the content files. If you haven't, please read the remarks to that in the iOS part before. On Android all content goes into an Assets folder. Therefore you need to add your content files in a folder Assets/Content. Change the options of each file to "Build Type: AndroidAsset".

Now you are ready to deploy and run your game on the Android emulator. However, the Android emulator is so slow - at least on my computer - that running and debugging is cumbersome. For a first test it should be fine though.
Unfortunately, if you are seriously porting your game to Android, you are not finished her yet. Unlike WP7 and iOS, Android does not take care about your application when it gets suspended and resumed. On Android you have to handle it yourself. The magic word here is Lifecycle Management, you can start getting the idea be reading the official Android docs:
http://developer.android.com/reference/android/app/Activity.html
To make things worse, your application's OpenGL context will get invalid once your app is resumed, resulting in broken textures. Hopefully in later versions Mono for Android or MonoGame will take care of that. By the time of writing however, you will have to take care about this yourself. You should check the discussion board of MonoGame on how you could handle it. I am not very satisfied with the hack I am using for my games so far myself.

I hope this blog post is useful to show how fast you can get your XNA game running on iOS and Android. However, if you seriously planning to publish your game on these platforms, you also need to read about and understand their special technical differences and issues.

Tuesday, February 21, 2012

MonoGame: Getting Started 2/3

Next we set up the iOS project. Inside the iOS directory create a file called AppDelegate.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

using Microsoft.Xna.Framework;

namespace MyNamespace
{
 // The UIApplicationDelegate for the application. This class is responsible for launching the 
 // User Interface of the application, as well as listening (and optionally responding) to 
 // application events from iOS.
 [Register ("AppDelegate")]
 class Program : MonoGameProgram 
 {
  private MyGame game;

  public override bool FinishedLaunching (UIApplication app, NSDictionary options)
  {
   // Fun begins..
   game = new MyGame();
   MonoGameGame = game;
   game.Run();
   return true;
  }

  static void Main (string [] args)
  {
   UIApplication.Main (args,null,"AppDelegate");
  }
 }
}

Change MyNamespace to your namespace and MyGame to your game class name.
The second file we need is Info.plist. If you are new to Apple, a plist file is a configuration file for the application. Create the file like this:


 MinimumOSVersion
 4.1
 UIDeviceFamily
 
  2
 
 UISupportedInterfaceOrientations
 
  UIInterfaceOrientationPortrait
 



Now we only need a solution and a project file. For the project file, create a text file with the name of your game dot ios dot csproj, e.g. MyGame.ios.csproj and copy this content:


  
    Debug
    iPhoneSimulator
    10.0.0
    2.0
    {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
    Exe
    MyGame.ios
    MyGameios
  
  
    true
    full
    false
    bin\iPhoneSimulator\Debug
    DEBUG; IOS;
    prompt
    4
    false
    None
    true
  
  
    none
    false
    bin\iPhoneSimulator\Release
    prompt
    4
    false
    None
  
  
    true
    full
    false
    bin\iPhone\Debug
    DEBUG;
    prompt
    4
    false
    true
    iPhone Developer
    
    
  
  
    none
    false
    bin\iPhone\Release
    prompt
    4
    false
    iPhone Developer
  
  
    
    
    
    
    
  
  
    
  
  
    
  
  
  
    
      {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}
      MonoGame.Framework.iOS
    
  
  
    
  

Change the tag RootNamespace and AssemblyName to meet your game name and check the tag ProjectReference for the path to MonoGame project file to point on your disk.
Finally create a solution file e.g. MyGame.ios.sln with this content:
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lidgren.Network.iOS", "..\..\MonoGame\ThirdParty\Lidgren.Network\Lidgren.Network.iOS.csproj", "{734EAA48-F1CA-481A-B391-0285BC0E8B40}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Framework.iOS", "..\..\MonoGame\MonoGame.Framework\MonoGame.Framework.iOS.csproj", "{DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}"
EndProject
Global
 GlobalSection(SolutionConfigurationPlatforms) = preSolution
  Debug|iPhoneSimulator = Debug|iPhoneSimulator
  Release|iPhoneSimulator = Release|iPhoneSimulator
  Debug|iPhone = Debug|iPhone
  Release|iPhone = Release|iPhone
 EndGlobalSection
 GlobalSection(ProjectConfigurationPlatforms) = postSolution
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhone.ActiveCfg = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhone.Build.0 = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhone.ActiveCfg = Release|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhone.Build.0 = Release|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhone.Build.0 = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhone.ActiveCfg = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhone.Build.0 = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhone.ActiveCfg = Debug|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhone.Build.0 = Debug|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhone.ActiveCfg = Release|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhone.Build.0 = Release|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhone.ActiveCfg = Debug|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhone.Build.0 = Debug|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhone.ActiveCfg = Release|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhone.Build.0 = Release|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
 EndGlobalSection
EndGlobal

Again change the path of the MonoGame project and the Lidgren.Network project to match your local installation.
Next open the solution with MonoDevelop. If you edited the path correctly you should have the MonoGame and Lidgren project there. If you entered the path wrong than just add them with add project.
Now use add project to add the project file of your game that you created before. Here also check that the reference to MonoGame is correct. So far you should only have two files in the project. The AppDelegate.cs and the Info.plist.
Now add the source code of your game to the project. Add each of your source files, except for the Program.cs. Add the source files as link, so you will use the same files for all platforms and not copies.
If everything worked fine, you should now be able to compile the source code. If you run across code that won't compile with MonoGame, you should use defines for each platform as work around.
The last step that remains is adding your content to the project. Obviously you don't have the content pipeline from the original XNA in MonoGame. But that is no problem as most content types can be read by MonoGame directly without being pre-processed. If you created the project file as described before, you already should have a Content folder inside your project. Now add all your content from the WP7 content folder there. As with the source code, you should add them as link to prevent them from being copied.
The only content file I ran across so far that is not supported, is .spritefont. To add this type of content, you have to take the compiled file from the bin/Content directory of your WP7 folder. The compiled file has the ending .xnb. Just copy the fontname.xnb to your MyGame.ios/Content folder and add this in the project instead of the original spritefont file.
For each content file in your project you have to set the option "Build action Content". Also be aware, that iOS, unlike Windows, is case sensitive to your content file names. For example, if your Content folder is upper case but in your source code you reference to lower case, you will end up in an exception at runtime.
Now you should be able to compile your game and test it on the emulator. On my MacMini the emulator runs rather slow. With an actual device, deploying, debugging and running is much better.


MonoGame: Getting Started 1/3

In this post I will give a short walk-through on how to port your existing XNA game to iOS and Android using MonoGame. MonoGame is an open source implementation of the XNA framework. To keep things simple you should start with a simple 2D game
MonoGame is based on Mono, so you need to install Mono first. For iOS and Android you need the Mono libraries MonoTouch and/or Mono For Android from Xamarin. For MonoTouch you need an Apple PC. To write the source code you will use MonoDevelop. For Mono For Android you can choose to use either an Apple PC or a Windows PC. On Apple you again have to use MonoDevelop. On Windows you can choose between Visual Studio or MonoDevelop. Unfortunately Visual Studio Express will not work as it does not support plug-ins.

You can get evaluation versions from Xamarin here:

MonoTouch for iOS:
http://xamarin.com/monotouch
Mono For Android:
http://xamarin.com/monoforandroid

To install these please follow their installation documentation.
MonoTouch install:
http://docs.xamarin.com/ios/getting_started/installation
Mono For Android install:
http://docs.xamarin.com/android/getting_started/installation

You will also find a lot of useful tutorials and an API reference on their webpage.

Now you are ready to start with MonoGame. First get the following downloads.

Download MonoGame (currently 2.1) from here:
http://monogame.codeplex.com/
You could also get the source of the developer branch from their GitHub repository but I recommend starting with the stable download version.
Second get the samples from their GitHub:
http://github.com/CartBlanche/MonoGame-Samples

After you extracted the MonoGame source to an appropriate path on your computer, you are ready to go.

MonoGame does not come with a script that will convert your project file automatically, so you have to do this by hand. Basically you have to create a solution and project file for iOS and Android each. The best way to create these is to take these files from the MonoGame sample applications and edit them in a text editor. But before doing this you should make sure that these run fine.
Therefore open an iOS and/or Android sample project and run them in the emulator. Make sure that all references to Mono and MonoGame are correct. Once the sample runs, you are ready for the next step.
I recommend creating a new directory for each platform to keep things more clear. A directory structure for a typical XNA game then may look like this:


MyGame +-MyGameContent
       +-MyGame
         +- Properties
       +-MyGame.ios
         +-Content
       +- MyGame.android
         +-Assets
           +-Content
         +-Properties
         +-Resources


I keep the WP7 default directories for the project and content and then add additional directories for iOS and Android. Inside each platform directory I then create an additional content directory. For Android this has to be inside an directory called Assets.

Thursday, February 16, 2012

Cross platform mobile game development

On this blog I plan to give some insights on my development that I think might be useful to others. In this first post, I will give an overview on what tools I use and why I chose them.

When I first came in contact with C# as a tools developer at the German game studio Radon Labs (developer of Drakensang) in 2008, I quickly fall in love with it. Having used C++ for about 10 years till then, I felt that computer languages finally had advanced. Soon I started to use XNA for private projects and even ported my Virtual Reality library to XNA. With the release of Windows Phone 7, I couldn't resist the temptation of developing apps in C# and entered the world of smart phones with an HTC HD7.

When I decided to quit my job as a C++ developer and become a full time indie game developer last year, I began looking into cross platform possibilities for smart phones. My preconditions were:

  • C#
  • Support of iOS, Android and Windows Phone 7
Obviously these preconditions made it hard to find any usable solution at all. I finally looked into these options:
Unity 3D is obviously the most advanced of these choices, being a full featured game engine since many years. Unfortunately it lacks the support of WP7. WP7 might not be of much commercial interest right now, but because it is the OS I privately use, I didn't want to ignore it. Furthermore, if you want to have the advanced features of Unity 3D, it becomes rather pricey.

Delta Engine is a .NET based game library in C# with a multi-platform approach. It is developed by the German game studio MobileBits, which is using it itself for their mobile game development. It looked very promising for me and I was very excited when the beta started. It is rather comprehensive and has a well known XNA developer behind it. Unfortunately the support for iOS and Android was not available to beta users at that time.

Actually from MonoGame I expected the least but got surprised. MonoGame is an open source project to provide the XNA framework to Mono, which is an open source implementation of Microsoft's .Net framework. Mono is available for Windows, MacOS and Linux. However, the Mono libraries for iOS and Android are not free and you need to buy them from Xamarin. And these are mandatory if you want to use MonoGame on iOS or Android. For testing, you can get these for free, but they will only run in the emulator and will not deploy to an actual device. I gave it a try and was surprised how easy it was to got my source code compiled and up running in the emulator. However, MonoGame so far only works stable for 2D functions, if you develop 3D games, you will have to wait for a later update.

I have used MonoGame for two games (Santa Melia and Bullet Babs) now. I use Windows Phone as my lead development platform. After I complete the WP7 version I first port it to iOS and then Android. For my second game Bullet Babs, porting source code didn't take more than a day for each platform. I spent more time recreating graphics for the different resolutions and aspect ratios and the store submission procedures. You have to create icons and screenshots for each platform. I will share some of my experiences with MonoGame as well as my multi-platform approaches and general C# tips in following posts.