Latest Entries »

Another post – another library! Yeah, I messed up with the last one, a silly mistake that should have been spotted a lot earlier on which meant that any kind of interruption in the game would cause big problems. No pausing, no tombstoning…

However, this also provided a good opportunity to update to the latest version of Monogame – well worthwhile as the new version sorts out landscape orientation in WP8 as well as better back-button handling. I also wanted to sort out my VS2012 setup so I could run the WP8 versions of my creation in the emulator (no substitute for a device, but a must-have for on-train development). Needless to say, there were problems…

The Downloads

At this point in time, the updated version of Monogame has not been baked into the installable that hooks into Visual Studio, so this must be downloaded from GitHub. I’ve heard that the fork required has now been merged into the main branch, which can be found here. Download the ZIP, it’s easier! Unzip it, but don’t build – I’ll come to why in a moment.

Assuming you have the Monogame templates installed into Visual Studio (available here if you don’t), the required template at the time of writing is the Monogame Windows Phone 8 Project – this will come with Monogame pre-referenced. Pull this reference out, then go to where you unzipped the new Monogame ZIP to and add the Monogame.Framework.WindowsPhone.sln project to your new game solution, then add a reference in your game to the Monogame project.

The reason for adding the Monogame framework as a project (rather than building and including a DLL) is that at this time, you cannot build a Monogame project in Visual Studio using the “Any CPU” setting. So building an ARM version of the Monogame framework would limit you to running on a device, and similarly the x86 build would confine you to the emulator. By including and building the framework with the solution, you can chop and change as required!

Sort that config!

However, a pesky reference to the old version of Monogame is left when building in x86 mode, which will block compilation! To sort this out, open the solution’s .csproj file in your favourite text editor and scroll towards the end – eventually you will come across an ItemGroup tag with the following comment: A reference to the entire .Net Framework and Windows SDK are automatically included. Following this is the conditional reference to the old version of Monogame when running in x86 mode – remove or comment this whole block out (including the itemgroup tags) to be rid of it!

Fix the XAML

Finally, there’s a couple of changes needed in the code generated by the template in order to make things work. Firstly, go to the GamePage.xaml file, delete everything inside the “phone:PhoneApplicationPage” node and replace with the following:


<Grid x:Name="LayoutRoot">
<MediaElement />
<DrawingSurface x:Name="XnaSurface" />
</Grid>

Similarly, if you want your game to run in landscape orientation, alter the “SupportedOrientations” and “Orientation” attibutes of the “phone:PhoneApplicationPage” node to have a value of “Landscape” in both cases.

Next, open the code file for the xaml page (GamePade.xaml.cs) – there will be a line something like _game = XamlGame<Game1>.Create("", XnaSurface);. Change the “XnaSurface” to “this”.

Wire up the Back Button

Congratulations! You now should have a Monogame project that will build an deploy on either a device or the WP8 emulator, dependent on your choice from ARM or x86 build config. However, if you run this, you will notice that the back button no longer quits the application – this now needs to be wired up manually, just as with good old XNA. So go to the Update method of your Game1 class and add the following:


if (GamePad.GetState(0).Buttons.Back == ButtonState.Pressed) { Game.Exit(); }

Should look very familiar to any former XNA coders!

And that’s it! Once again, great job to the Monogame team for their amazing work.

Advertisements

Full Circle

Tomorrow (April 20th) marks a Leda landmark – a whole year since the launch of the Arcade Collection for Windows Phone.

Five games. Over 130,000 downloads. Android versions in beta. Huge support from Nokia and various features on the Windows Store. Our very first expo. Way beyond anything I expected!

In another milestone, it’s just over three years since I first posted here. So now, three years plus on, with five launches behind me, what am I doing?

Creating a new resource library!

There are a number of reasons behind this: Firstly, since building the original versions of the Windows Phone libraries (which were essentially the guts of AstroSwag), there are load of features and refinements that I’ve wanted to add – skeletal animation, for example. Secondly, while these libraries ported over to Android ok, there were several bits of conditional code and work-arounds required – never idea. But the big clincher was the double-whammy from Microsoft of Windows Phone 8 launching on completely new hardware to the Windows Phone 7 (and therefore no path to upgrade), and the “official” cut-off of XNA.

So on one hand, we have the carrot of Monogame and with it the opportunity of breaking into new markets and arenas, and on the other, the stick of both Leda’s primary platform and development framework being phased out. No brainer, really.

The objective of the new library build is to create a single codebase in Monogame to target Android and Windows Phone 8 with minimum platform-conditional code. It’s going well – so far, the only time this has been necessary has been due to the fact that Monogame automatically handles landscape/portrait orientation on Android, but not on WP8, requiring manual rotation of the back-buffer and touch locations. A lot of the basics are in – simple drawables, improved collision handling (from Blade Force Rescue), bone-based objects and automated animation (from the Dream-Build-Play prototype). There’s still a lot more to do, but this is certainly a big step forward.

With all the groundwork done, the last step of the plan was the actual port of Galaxy Raiders to Android. Apart from a few bumps, this proved to be incredibly easy: from “new project” to runnable game took just over an hour and most of that was getting all the content and project structure set up correctly in the Monodevelop project, and configuring the Android-specific bits. In fact, I was so impressed at how this went that I went straight into porting Crack the Crypts: again this was 95% straightforward, and this also proved to be the case for the other three titles.

That’s not to say that everything went entirely smoothly – after all, Galaxy Raiders was about the simplest game in the collection and as other titles were converted, a few niggles came to light…

Premultiplied Alphas

Monogame on the Android handles alphablending a bit differently to XNA, meaning that some textures that were translucent under XNA render as solid. The remedy to this is to save the textures concerned with premultiplied alphas. Pixelformer provides a nice, simple solution for this – simply import the problem texture then export it with the “premultiplied alphas” option checked. The only thing to watch out for here is that textures treated in this manner can then exhibit artefacts under XNA, so it’s wise to keep two versions for this.

Generated Textures and RenderTarget2D

As mentioned in part 2 of this series, RenderTarget2Ds do not resaturate when the onResume event fires – this problem is shared by Texture2Ds generated at runtime by means of the SetData method. However, I found that trying to re-instate the contents of either of these following an onResume led to an almighty crash – it was as if the reference to the RenderTarget2D or Texture2D was being restored properly, but the actual surface that their content was rendered on was not.

Moreover, the onResume event fires not only when the game regains focus from another application, but also during the start-up cycle as well (again, see the “lifecycle” diagram in part 2). Ultimately, the simplest option was to replace runtime-generated Texture2Ds with prerendered textures loaded via Content.Load, and refactor to remove the use of RenderTarget2Ds – working round would have been possible, but this would have meant a sizable refactor my main library, with all the knock-on effects that would have in the XNA version.

Quantity of Renders

Way back when Paul was working on the Windows Phone version of InterSceptre, we soon found that there was a limit to the number of textures that could be rendered before suffering performance hits. This limit appears to be a lot lower on the Android version, which led to the single biggest refactor of porting the Arcade Collection. The lesson here is that it pays to not be lazy and just go ahead and render even when something is offscreen. Similarly, particle systems may need a bit of a retune (Incoming!).

Sound and Music

This caused the biggest headaches of the lot. On both XNA and Monogame, looped MP3 playback is not seamless – there’s a bit of a break when the sound ends before it restarts. On XNA, the way round that was to have the sound as a WAV file and use a SoundEffectInstance with IsLooped set to true.

However, in Android there is a limit on the size of a WAV file (about 1MB) – if an oversized sample is loaded, it will either cut off part way through or – if looped – not play at all. On top of this, even if it is not too big, a looped WAV file will cut off after a given time, which I understand is normal behaviour for the way Android handles WAVs.

Unfortunately, there is no easy answer to this problem. WAVs work fine for smaller, non-looped sounds, while OGG’s superior compression handles bigger effects (although these still cut off if too long). For looped sounds and music, the solutions I have so far are:

  • Convert to MP3 and trim: This only works if there’s a pause at the end of the sound or tune before it loops. By trimming a bit off the end of the MP3 (I found about a quarter of a second worked quite well), the delay between stop and restart will pad out the missing bit of silence and the sound will loop in time.
  • Repeat the sound/tune multiple times in a single MP3: If the maximum duration that the sound/tune needs to play for is known, such as a level that only lasts for two minutes, load the WAV into a decent audio editing tool (like Audacity), copy-paste it end to end as many times as required in order to run for the necessary length of time and export to MP3 (Audacity needs the LAME MP3 encoder to do this). This negates the need for looping.
  • Play the WAV every [n] updates: This method will allow looping over an unknown length of time, howver it is not a very good solution, as the loop timing for the sound has to devide by the duration of an update in order to loop correctly, plus you are at the mercy of any performance spikes etc.

Another Sound Gotcha: When playing MP3s in Android, make sure MediaPlayer.IsRepeating is set to false. The MP3 will loop regardless of whether or not this flag is set – however, if set to true, the MP3 will start playing again upon exiting the game!

Closing Thoughts

On the whole, the process of converting from Windows Phone-XNA to Android-Monogame has been a lot easier than I had thought it was going to be. The hardest bits turned out to be non-XNA related (getting the environment set up and patching in the advertising), and while there are some niggles that remain unsolved (or at least, not resolved to my satisfaction), these are only to be expected and will either be fixed or worked round. The fact that right now only six weeks after starting this project, the biggest issue remaining is the rotor blade sound effect in Blade Force Rescue (currently using the “play every [n] updates” method) speaks volumes.

So – the verdict on Monogame? Sold! We now have licenced versions for both Android and iOS, all five Arcade Collection games have now been ported to Android (iOS will hopefully happen later in the year), and we’re about to demo both these new version and their Windows Phone counterparts at our very first trade show! So a much deserved kudos to the Monogame team for not just saving a great framework, but extending it to reach so many more people.

Finally, thanks to anyone who has read this, and if you’re looking at porting from XNA to Monogame-Android, I hope what I have found on my journey helps…

What Happens Next?

Branching out into Android will be a big step for Leda Entertainment, and we’re really looking forward to seeing how things go at GEEK 2013. As for Monogame, we’re looking at iOS conversion of the Arcade Collection at some point in the not too distant future… but first, it’s time to see what we can do with the Windows Phone 8!

Since conception, web interaction has been at the heart of the Arcade Collection, both to drive competitiveness among players via online high score tables, and also to try and monitize a little – originally via a Paypal-driven credit-based pay-to-play in-app purchase system (which I never did get round to blogging about!), which was later replaced by in-game advertising, largely due to the fact that very few players realised how the credit system worked which got a lot of bad review backlash. Ah experience, great teacher but damn cruel in how it doles out lessons sometimes…

Anyway, all the in-house web communication stuff is boxed up in another library, along with various other classes common to the entire Arcade Collection (dialog boxes in Arcade Collection chrome and that sort of thing), and these worked pretty much straight out of the box. Yeah, I couldn’t believe it either. However, advertising…

The Great Divide

XNA for the Windows Phone does not natively support any kind of advertising. Silverlight apps – yes, there’s a plug-in control for it, but XNA… nada. In fact, at the time the Arcade Collection was created, the only viable means of providing in-game adverts in XNA was via the AdDuplex XNA (as used by Paul in Rummycomb) – and this limited support, coupled with low returns for our paid games AstroSwag and InterSceptre certainly contributed to the decision to create the ill-fated credit system. Matters have improved since then, with the SilverXNA concept (hosting an XNA game inside a Silverlight app, allowing the use of the plug-in control), and also with AdRotator for XNA, which ultimately replaced the pay-to-play mechanic.

Google on the other hand have pretty much got themselves where they are today by advertising, and Android is natively supported by an Admob SDK (there’s also now a Windows Phone 7 version but once again, no XNA support). The only issue here is that the SDK is for java, whereas Monogame is C#… but there’s ways round that, which I’ll come to.

The Setup

So the first thing to do – register with admob, set up an entry for Galaxy Raiders in the apps/sites area, and download the SDK.

Registration is simply a matter of creating a Google account. Creating the app/site entry was also pretty straightforward – the only point of minor confusion was the “Android Package URL” field, which is mandatory and starts of prepopulated with “market://”. Obviously Galaxy Raiders is not yet on the market (yet) but this can be linked through to a regular webpage instead – in my case, the Arcade Collection games page on the Leda site. Completing this yielded the publisher ID (the admob identifier for the game – so “Publisher ID” is a tad misleading, I think!), and the option to download the SDK.

Cutting to the Code

I’m not going to go into huge detail about what needs to be done here – instead, I’ll hold my hands up and admit that once again I followed a tutorial, and it would be wrong of me to take the credit here. Basically, what the implementation entailed was adding the .jar file into the project and creating means of invoking the java functions in C#. So once again, it was time for another blue-screen test app to prove the concept.

The “Gotcha” to watch for here is that to implement admob, there are a couple of changes needed in the AndroidManifest.xml file. This file is required by every Android app – however, when creating a new project in Monodevelop, it does not appear anywhere in the solution explorer. The mistake I made was looking at sample projects then just adding the missing file into my test project, causing lots of crashes (and swearing) when trying to build the project – I’m guessing that Monodevelop did not recognise my added file as being the correct manifest file and tried to add its own at build time.

So – the correct way to add this file into the project is:

  • Right-click the project in the solution explorer and select “Options” from the context menu to open the Project Options window
  • Expand the “Build” node on the left hand list and select “Mono for Android Application”
  • Click the “Add Android Manifest” button

This then adds the missing file into the “Properties” folder of the project which can be edited as required, and it was only because of a screenshot I found on a forum that figured out this process.

Into the Arcade

With a working proof of concept (advert over cornflower blue), the next step was to hook it up for Galaxy Raiders.

The XNA version of the game incorporates the XNA AdRotator project – obviously, this was not included in the Android version. However, on top of this (again, in the library I was working on in the previous post) is a static handler class that provides simple hooks into AdRotator from the game: again, this had been left out of the Android build, and the function calls commented out. So this brought about the only real change in the codebase between XNA and Android – the Android version of the library needed its own version of this handler class with the same function signatures to ensure seemless transition between the two versions of the game.

The big difference between the adverts for each project is that the XNA AdRotator project exists within the game solution, so it is easy to hook into and thus position the adverts or toggle whether or not to display. In Android Monogame, the advert exists within a separate view that is instantiated by the activity that wraps the XNA game, so a means to hook into it at game level has to be provided. So whereas the XNA version of the handler makes the calls to AdRotator to set things up when it initialises, the Android version requires the Advert view to be passes into it. With this in place, it was then a simple matter to create static methods with the required signatures in order to show, hide and position adverts.

Closing Thoughts

I’m still blown away at how smoothly the conversion of the high score table web access went, and I take my hat off to all those involved with Monogame, Mono and Lidgren for an amazing job. The adverts did cause a lot of pain, especially the issue of adding the manifest file – the only reason I figured out what to do was because I saw a screenshot on a forum with properties that looked like what I needed so I opened the same window for my project and found the “Add Manifest” button. I’m also still wrestling with correct positioning in Landscape mode, but that’s just number crunching.

What Happens Next?

The tools are in place. The libraies are ready. The web side services are set up and good to go. Next stop – conversion of Galaxy Raiders!

Galaxy Raiders – and pretty much everything else I’ve written – sits on top of a library of classes that handle a load of basic essentials: base classes for objects that are drawn on-screen, move around and collide, manager classes for collections of textures and sound effects, touch input handlers, game state control, common untility functions… all that sort of stuff. So getting this ported to Monogame was a key step in bringing Galaxy Raiders to Android.

Having successfully got an XNA template game running in Android, the temptation would have been to just dive on in and go for the conversion, hoping the Monogame would handle all the heavy lifting. But I had already decided to go slowly and test step-by-step: first by plugging in blocks of functionality to my original test template, then plugging in the library bit by bit, ultimately aiming for something not too dissimilar to what I put together in “Boxing it all up“, when I was testing tombstoning on the WP7. Good job too, as this certainly saved a lot of headaches (and swearing) when things didn’t go as planned.

The Life of an Android App

One thing it is vital to understand coming from WP7 to Android, is that the Android app (or “activity” as it is often referred to) lifecycle is very different to its WP7 counterpart, in that even if it loses focus, it keeps running – this explains it nicely:

The Android App Lifecycle

Changes in state have to be handled accordingly, and this does not just mean pausing the game when focus is lost: it’s critical to remember that this is not XNA on the Windows Phone, so the way things react behind the scenes when focus is lost or re-gained may not be – and indeed are not – as expected.

Monogame Assets

Monogame does not have a content pipeline like XNA – however, in most of the cases I needed, it can cope with loading the uncompiled versions of the asset files instead (the notable exception being spritefonts). Instead of a separate Content project, there is an Assets folder in the Monogame Android project, which contains a Content folder that can be treated as the root folder of the Content project when using Content.Load. However, it appears that Mono is a fussier about folder names than XNA – for example, folder names begining with an underscore (ie: “_Compiled”) work in XNA, but throw a “file not found” exception in Mono, which resulted in my having to rework my standard folder structure a little (and a significant amount of the swearing at this stage of the project).

Textures

One problem I found with XNA back in the AstroSwag days was that Content.Load did not actually load content on request – rather, all compiled content was loaded when the app was started, leading to several seconds of waiting before you got a response out it. Since this was a possible cause for failing the Microsoft Store certification process, I switched to a solution based on the Texture2D.FromStream method, loading the raw .png files.

This does not work with Monogame.

The initial load-up is fine, but – as I hinted at earlier when reviewing the Android activity life cycle – if focus is lost, the texture data loaded in this manner is also lost, and does not resaturate when focus is regained. I tried several approaches to get this working, but could not come up with a reliable solution, and ended up putting in a compiler directive to us Texture2D.FromStream for Windows Phone and Content.Load on the Android. Since Android content is not compiled into the app, but copied with it, it looks like this will not cause the dalyed-startup problems Content.Load caused on the Windows Phone – but without device testing, this is still not for certain.

Sound Effects

Just like Textures, my XNA audio handler class would use SoundEffect.FromStream to allow me to load sound effects on the run from .wav files.

This does not work with Monogame – in fact, all the forum crawling I did points to this method of the SoundEffect class not being supported by Monogame yet. So once again, another compiler directive and back to Content.Load for the Android. Moreover, while researching this, I remember reading that there’s a maximum limit for wav file sizes on the Android – not a problem for Galaxy Raiders as the sounds are small and simple, but there may be a requirement for more complicated games with more featured soundtracks to use MP3 files.

Spritefonts

As mentioned earlier, unlike Textures2Ds and SoundEffects, SpriteFonts have to be compiled to work with Monogame – again, no problem for Galaxy Raiders, the font is already compiled into the Windows Phone version of the project. The alternative is to take the approach that Paul did for InterSceptre and render out a bitmap font on a Texture2D… and then manually handle all the conversion of strings to segments of texture, kerning, spacing etc… this allows for some very funky-looking coloured fonts, but is a lot of extra work (if memory serves, Paul’s remark on this was “never again” !)

Render Targets, Input and Scaling

While this did not come up in the initial wave of conversion and test work, this is worth a mention as this caused significant headaches.

One of the joys of working on the WP7 was that you knew that regardless of handset, you were getting a 480×800 screen. Not so with the Android – there are a vast swathe of screen resolutions out there, and without scaling appropriately, you either end up with your app sitting in the top left corner of the screen on an too high a resolution or worse, just the top-left corner of your app on lower resolutions.

The obvious answer is instead of drawing straight to the screen, create a RenderTarget2D, render everything out to it, then draw this on your actual screen, scaled and/or positioned accordingly to your device dimensions – while scaling up your touch locations etc. the opposite way accordingly. Because my game state management system is based on a Scene class that controls, updates and renders all objects that are part of that scene, plugging this is was not too much of a problem, apart from the obvious changes that the Scene content had to be rendered to the RenderTarget2D in the Update call, as switching RenderTargets during the Draw call causes everything to go wrong.

However! As with textures loaded from stream, Monogame loses the drawing surface of the RenderTarget2D when the activity loses focus… but not the reference to the RenderTarget2D. This means that when the activity resumes, the game tries to render to a surface that no longer exists and throws a bunch of OpenGL exceptions. Ouch.

The solution lies outside the XNA code, in the Activity class that wraps around the Game class (see “Just Five Lines of Code” in the previous post) – any RenderTarget2Ds must be properly cleaned up and disposed of when the activity loses focus.

using System;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Provider;

using Microsoft.Xna.Framework;

namespace RenderTargetTest
{
	[Activity (Label = "RenderTargetTest", MainLauncher = true)]
	public class Activity1 : AndroidGameActivity
	{
		private RenderTargetTextXNA.Game1 _Game = null;

		protected override void OnCreate (Bundle bundle)
		{
			base.OnCreate (bundle);

			RenderTargetTextXNA.Game1.Activity = this;
			_Game = new RenderTargetTextXNA.Game1();
			SetContentView(_Game.Window);
			_Game.Run();
		}

		protected override void OnPause ()
		{
			// Handle any focus loss processes including cleaning down any RenderTarget2Ds
			_Game.HandleFocusLoss();
			base.OnPause();
		}

		protected override void OnResume ()
		{
			base.OnResume();

			// Handle any focus gain processes including creating any RenderTarget2Ds
			_Game.HandleFocusGain();
		}
	}
}

The HandleFocusLoss and HandleFocusGain methods are added to the main Game class as generated by XNA and are a means of hooking into the game from the activity – much like the tombstoning process on the Windows Phone. These methods then iterate through all the objects within the game – in my case, each Scene – creating and disposing of RenderTarget2Ds as appropriate.

There two important points to note here:

When Losing Focus – the RenderTarget should be disposed of and the variable pointing to is must be set to null. So each Scene in my game has the following method:

public virtual void PrepareForFocusLoss ()
{
	if (_ScalingBuffer != null) { _ScalingBuffer .Dispose (); }
	_ScalingBuffer = null;
}

If the variable (_ScalingBuffer) is not set to null, the corresponding “resume” function does not know to re-instantiate the RenderTarget2D and we’re back to OpenGL exceptions.

When Gaining Focus – The activity lifecycle shows that the Resume event is not exclusive to focus regain after an Pause event – it also happens when the game is first started. So anything functionality that is called when the game resumes after a Pause also happens when the game first starts. This can be useful – ie: our RenderTarget2D is always set up – but can also cause problems – for example, if there are any game settings changes following a restore but not in a new game.

Closing Thoughts

Taking small steps really helped through this stage of the conversion process – knowing that textures loading via Content.Load resumed correctly for example (via directly coding into the XNA test app) meant that when things went wrong, I knew where to start looking, and also helped push me in the right direction for other problems. From my forum trawling, it would seem that RenderTarget2D is not well known or documented, so hopefully this will save some heartache for others trying to convert to Android.

What Happens Next?

With the library conversion complete and tested, we’ve got everything we need to make Galaxy Raiders work as a game. However, arcade games are all about those high scores – and Galaxy Raiders is no exception! To get to those high score tables, we need to talk to the internet…

As it turned out, this was probably the hardest bit. One of the things that really made XNA stand out for me was the ease of getting started – just download the Windows Phone 7 SDK and install and bang! There’s VS2010 Express, complete with the templates to get you started.

Not so, Monogame.  Depending on whether or not you have Visual Studio professional (I don’t), and whether or not you’re aware of the installer (I wasn’t!), there’s a lot of stuff to download and install in the right order, and getting everything working took several iterations of uninstall-reinstall everything, and a considerable amount of swearing. I’ll be the first to admit, I have an appauling record when it comes to getting anything that isn’t an off-the-shelf package to install and work correctly, so if anyone knows better, please correct in the comments.

Anyway – as mentioned, creating a new XNA game for Windows Phone project in Visual Studio will give you everything you need to get a nice cornflower blue screen in the WP7 emulator. So objective number one was simply to get the same effect on the Android emulator.

Gotcha! #1

Now herein lies the first gotcha – Monogame 3.0 up requires the emulator to have GPU acceleration. However, when running through the tutorial linked from the Monogame site, none of the emulator configurations that came with it appeared to support this option. This resulted in one of the more major bouts of swearing. Moreover, downloading the latest Android SDK with a view to getting the required emulator configurations didn’t seem to help – the just did not appear on the virtual device manager. Much time was spent searching for a solution, and while I’m sure there’s a simpler way to do it, the only thing that seemed to resolve this was to uninstall everything, then download and install the Android SDK first.

Download and Install Everything+KitchenSink

Next jobs – install Monodroid, OpenTK and Monodevelop (in the case of the last of these making sure I had .NET 4.0 and GDK#), as per the aforementioned tutorial. Simple enough, although sometimes getting the latest version was not as simple as would have been expected, and I still do not know how I’ve ended up with OpenTK v0.9.9.3 and 1.0 – and the newer one doesn’t seem to work.

Then the was Git. By name and by nature. This requires installation of msysgit and (because while Git is a mystery to me, Git on a command line interface is doubly so) TortoiseGit, and between trying to get these installed and actually cloning the Monogame repository, this was the single biggest sticking point and cause of swearing – literally hours of poring over Google trying to figure out why I was getting an error about updating submodules and how to resolve it… Yeah, I know what everyone must be thinking now. Go on, snigger. Then Google “monogame install tutorial” and see where it leads you – this is why I wasn’t aware of the installer at the time, which could have saved me a lot of pain!

So the sequence I ended up with getting everything I needed:

  1. Download/install the latest Android SDK
  2. Download and install Monodroid for Windows (yes, I did get the Mac installer once!)
  3. Download and install OpenTK
  4. Download and install Monodevelop for Windows, ensuring I had .NET4.0 and GDK# 2.12.0
  5. Download and install msysgit
  6. Download and install TortoiseGit

Gitting Underway…

With everything downloaded and installed, the next stage was to clone the Monogame Git repository. This is all in the Monogame tutorial, although I had trouble with TortoiseGit not finding Git.exe, which turned out to be somewhere other than the tutorial anticipated – but that was just doing a search of my hard drive while making a coffee. However, when cloning the repository in TortoiseGit, make absolutely 100% sure that the “recursive” checkbox is checked. Seriously. Maybe it was because I’d got the hump at how much trouble I’d had already by this stage, but I missed it at least once, leading to further swearing bouts. Maybe the installer would have been a better bet – I don’t know. This worked for me, and I’m scared that I’ll break it if I mess with it.

Last step of the setup – building the Monogame for Android framework. This was a matter of firing up my newly installed Monodevelop, opening the Monogame.Framework.Android solution and building it. Although – of course – I did hit the snag that the project would not build because the reference to OpenTK was missing. Getting round this was a matter of:

  1. Searching for OpenTK.dll in Windows Explorer (and having another coffee)
  2. Opening the project references (“Project” menu, “Edit References”)
  3. On the window this opened, selecting the “.NET Assemblies” tab
  4. Entering the full path and name to OpenTK.dll

The Stage is Set

Framework built, time to build the test project – finally! I’d already created a new test project in Visual Studio (start VS, new project, new windows phone game, enter a name and done), so it was just a case of getting this into Mono:

  1. Start Monodevelop and create a new Mono for Android Application
  2. Add Lidgren.Network.Android project to the solution – this is needed for the Monogame Android frame and is located in the Third Party folder of all the files that came down with Monogame. Right-click the solution, select “Add”, “Add Existing Project” and locate.
  3. Add Monogame.Framework.Android project to the solution – same process as Lidgren except this is in the Monogame.Framework folder (a lot easier to find, despite the file selector insisting on starting from your project folder each time)
  4. Add references to these projects and OpenTK into the test project – right click the “references” node of the test project and select “edit references”, then check the appropriate checkboxes on the “All” tab.
  5. Add a link from the “Game1.cs” class to the project from the Visual Studio version – right click the test project in the solution explorer, select “Add”, “Add Files”, then select the file in the XNA version of the project and choose to “add a link” to the file (very cool feature, means only one file to maintain across both VS and Mono versions of the project).

Just Five Lines of Code

So everything downloaded, created and linked – just one last thing to do, which is to have the Android activity (the thing that runs the app on the Android) invoke the XNA game loop that makes Game1.cs do its thing. At last, it’s back to some code!

The magic happens in the Activity1 class (Activity1.cs, added by default to the project). When first created, it looks like this:

using System;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace SimpleAndroidTest
{
    [Activity (Label = "SimpleAndroidTest", MainLauncher = true)]
    public class Activity1 : Activity
    {
        int count = 1;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById (Resource.Id.myButton);
            
            button.Click += delegate {
                button.Text = string.Format ("{0} clicks!", count++);
            };
        }
    }
}

This builds and runs, but instead of a nice XNA cornflower blue, this pops a button on the screen which counts the number of times it has been clicked. So the first step was getting rid of all the code inside the OnCreate method except for the base.OnCreate (bundle); line – the int count = 1; can go as well as it’s not getting used. Then:

  1. Add the XNA framework to the activity in the using statements
  2. Change the Activity1 class to inherit from AndroidGameActivity instead of Activity
  3. Under the base.OnCreate (bundle); line, add the following:
    SimpleXNATest.Game1.Activity = this;
    SimpleXNATest.Game1 Game = new SimpleXNATest.Game1();
    SetContentView(Game.Window);
    Game.Run();
    

So after these changes, Activity1.cs ended up looking like this:

using System;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

using Microsoft.Xna.Framework;

namespace SimpleAndroidTest
{
    [Activity (Label = "SimpleAndroidTest", MainLauncher = true)]
    public class Activity1 : AndroidGameActivity
    {
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            SimpleXNATest.Game1.Activity = this;
            SimpleXNATest.Game1 Game = new SimpleXNATest.Game1();
            SetContentView(Game.Window);
            Game.Run();
        }
    }
}

Build and run, and…..

XNA Template running in Android

Success! Lovely cornflower blue…

Huzzah!

A Couple More Gotchas

For anyone reading this and thinking “if he can muddle through, so can I” – here’s a couple more things to watch for:

The Android Emulator is Dog-Slow. Seriously, it’s like a one-legged tortoise, especially if it’s your first run: obviously you have to select an emulator to load if you haven’t already got one up and running, but this then needs to load a bunch of stuff before it can even think about running your app. From my experience, first run can take five minutes plus between selecting to run and actually getting a result, with subsequent runs around the two-minute mark. Keep an eye on your deploy to device window (should open from a tab at the bottom-right on Monodevelop if not already open), which will keep you posted as to what is happening – watch those progress bars slowly crawl upwards! When done, this should switch to an output window, which (after a bit of a delay) will start spinning out a load of log messages as things start to happen – OpenGL surfaces are created etc. Eventually these should settle down to one or two different messages (normally along the lines of “Skipped X frames because the main thread is running slow”) and you should see your end result. Go make a coffee, walk the dog, watch “Gone with the Wind” while you’re waiting…

Monodevelop is not 100% stable. At least, it hasn’t been on my Win7 box. Most the time it sits just fine, but every now and then I get a flurry of crashes – and this is even when I’ve got nothing aart from Monodevelop and my Android emulator running off a fresh boot. However, the recovery mechanism is pretty good – I’ve lost very little to this (except time), very little swearing has been involved. Not a big bugbear – just something to watch out for.

Closing Thoughts

As I said right at the start, getting off the ground to this stage was probably the hardest bit. Maybe it’s just me – something always seems to go wrong with these sort of setup processes for which a solution is not easily forthcoming. As a result, I’m willing to bet that there’s a few bits in there that will make more seasoned Mono people go “Should have done this…” or “What the hell?” – fair enough. End of the day, we got there! But one of XNA’s big plusses for me was that I could just download and go straight into what I enjoy doing (tinkering with game code), so it would be very nice to see something similar for Monogame, and it would probably open it up to a lot more indie coders for whom every minute counts.

What Happens Next?

So that’s step 1 out of the way – a basic XNA template running under Android. Next up, some game essentials – graphics and sound!

A good while back – in fact a couple of months after launching AstroSwag and InterSceptre, my co-developer Paul made a brief foray into the world of Android, looking to port ‘Sceptre over. Now, it would be very easy for me to go on about kharma telling him that it was time to put ‘Sceptre to bed and do something else (sorry, Paul!), but it turned out to be a complete nightmare, and we very shortly after dropped the idea of going cross platform to instead build up our catalogue and gain further experience on the Windows Phone 7, in the hope that the then-nascent platform would start to gain a bit more traction.

A lot has changed since then – most notably Microsoft’s decision to drop XNA support. Which has ultimately led us to Monogame.

For us, Monogame appeared to have two major advantages: First it effectively provides XNA that will run under the new Windows Phone 8, with access to all the bells and whistles that normal XNA doesn’t get. Second – and rather more immediately attention grabbing (since I don’t have a Windows 8 machine or phone yet) – is its ability to operate cross-platform. According to the everything I had heard, all that was needed was a bit of tweaking and an XNA game could be made to run on Android or iOS with minimum fuss.

So I decided to put this to the test. The plan: port Galaxy Raiders – the first and almost the simplest title from the Leda Arcade Collection – to a “playable” state for Android, running under emulation…

Okay, so I guess the nearly nine months makes me about the worst blogger in the known universe!

First of all – yes, the “big project” I was banging on about was the Leda Arcade Collection. It always struck me that phone gaming was better suited to the “quick blast” type of game, rather than the sprawling epics we see on PC/consoles, and the chance to pay tribute to the 80s video arcades – which kick-started my wanting to write games – was too good to pass up! So the idea was to build a framework to allow for rapid arcade-style game development allowing for online support, and get some games out there!

So the first three titles have been live for about three months now, and overall, the project has succeeded beyond expectations:

On top of this, we’ve had great support from Nokia and WP7Connect, and were featured several times on the Microsoft Marketplace, so this is way above and beyond anything we’ve done before! The reviews make for interesting reading – there appears to be a strong “love or loathe” feeling to the collection – and I’d be very interested in getting reviewer age vs. score data – I’d be willing to bet that a lot of our 4/5 star ratings come from early 30’s upwards, while ones and twos largely come from kids who expect their games to be like this…

Where things have not gone as well as I hoped was “making money”. Partly in tribute to the arcade games of old, and partly just to see if it could be done and whether it would get any return, the arcade collection games were designed to run on a credit-based payment system – each player gets an online credit account, which is consumed at a given rate per game and when this runs out, they have to either buy more or wait for a monthly top-up. With no in-app purchase support, I ended up having to build this myself (which someone has asked me to blog about, so that will get a post of it’s own). But this has not really caught on. Still, never mind – it was always intended as an experiment and there are other ways to monitize the collection – if we decide to go that way.

So – where are we now? Well, around the time of Dream.Build.Play launching, Paul and I were considering entering – for my part, this involved some R&D work on skeletal animation – again, I may do a full post on this in the future. That project never came to fruition, but the animation worked out pretty well:

And of course, there’s the next arcade collection title, which will launch in (literally) a couple of days:

What’s next? Well, that’s a little up in the air. Microsoft’s recent announcements about Windows 8/Windows Phone 8 and the future of XNA have shaken things up, and I’m still waiting on the repercussions to settle. Maybe in a few months time, I’ll be doing everything all over again in C++/DirectX – or something else. But at the end of the day, the arcade collection shows me that there are lots of Windows Phone 7 gamers out there, and they’re not going anywhere for a while.

So as I mentioned in my previous post, one of the various things I have been working on as part of this new projects, is web-linked leaderboards. Except I found out recently that I’m not allowed to call them “Leaderboards” any more, as that’s a Microsoft Xbox Live reserved term – or something crazy like that.

Again, this was intended as building on what I’d learned from AstroSwag – the most important lesson being about scope. For a first attempt, AstroSwag had a massive amount of web-based data, which was a lot of effort putting together, and hasn’t really seen much use. Moreover – and I hold my hands up here – because I was so wowed about getting the linkage working, I probably spent too much time on content and I know I spent too little time on robustness. Try getting a high-score when you’re on an underground train… guilty as charged, I’m afraid!

With this new project, robust web-data handling is vital (and not just for leaderboards – hint! hint!) – the class involved has to be able to deal with failures in both sending and retrieving data and react appropriately. Moreover, I wanted to build a system that would allow a board to be either web or device based, with no apparent difference in use.

So – while I’m not going to go into the guts of any code here, let’s look at my Leaderboard class and its public properties and methods:

Properties:

  • IsAvailable
  • WebActionInProgress
  • CutoffDate
  • SimulateWebFailure

Methods:

  • Constructor
  • Generate
  • AttemptNameEntryAdd
  • Populate
  • GetPage
  • ClearCache

Most of the properties are fairly obvious – CutoffDate was added to save the number of leaderboards a single game would need (all-time and recent can both be done in one hit), and SimulateWebFailure made testing the robustness nice and easy!

The methods – again, quite straightforward. “Generate” allows pre-population of a local based board for when the game is first run, “GetPage” returns the board entries for the relavant page index and ClearCache again is for testing purposes – and incidentally, gives the only indication of what’s going on under the hood:

The first part of the process lies in the constructor: by passing empty values as the identifiers for the board as held server-side, the board flags itself as local only, which determines the way the Populate and AttemptNameEntryAdd methods behave.

In order to provide the required robustness, the board stores itself locally, even if it’s web based. When Populate is called, if the web request fails, it then falls back onto this local copy – obviously local-based boards don’t bother with this and go straight to file. So apart from when the game is first run and there is no fall-back file, there is always data to draw from – and, incidentally, a means to power local-only boards.

The other side of the coin is adding new entries. Again – if the board is local, it just inserts the name into the board and stores it. However, should the web upload fail, the new entry is cached locally. So again, robustness criteria are satisfied as the player’s new score will still be shown on both local and web-based leaderboards, regardless of upload success.

To bring the process full circle, we go back to the “Populate” method. Before attempting to download the new entries, the class checks for the presence of a cache file – if this is found, an attempt is made to upload each entry, with failures being held and re-cached so no data is lost.

Of course, rolling it into a live environment requires some considerations, too – as the web operations are asynchronous and with the difference in speed between wifi and phoneline web access, it is entirely possible that the front end may hit a point where the data is required before the website callback has completed. At present, it’s simple enough to monitor the “WebActionInProgress” property and display a suitable “loading”-style icon – but the next obvious step would be to populate from the local file until the web version is completed.

But for now, it’s a good, solid base to work from that provides the robustness needed. Even on the underground.

Once again, a long spell of silence. Part of this is because I have had no idea what to write – in here that is. Another part is that finishing AstroSwag kind of left me in limbo – various projects competing for attention, but no real direction or emphasis – and then when I did figure out what I wanted to do next, I decided to keep it under wraps.

This is still the case – this new project is a biggie, comprised of a number of sections, and draws from all the experiences I have had with AstroSwag (and not just the coding, but the sales side too), and everything preceding it.

So no details on exactly what I’m working on. No screenies! Sorry. The good news is that all the concepts have been proved and tested, Paul’s on board, and it should now be just a matter of getting the components written.

What I can divulge is some of the background stuff, and there are two sides to this. One is the web-linked leaderboards – these will get a post of their own as they’re worth looking at in a bit more depth. They’re also part of something bigger, but I can’t go into detail without giving the game away…

The other is a new “game basics” library I’ve been building up – ever since day one I’ve wanted a generic set of components to handle the common, low level stuff like basic in-game objects, game state management, tombstoning and file handling and so on. Thanks largely to AstroSwag, this has now come about, offering these key basics:

  • The GameWrapper class – wraps the standard XNA base game class and sets up instances of standard handlers, attaches tombstone events and so on
  • Instantiated Handers – GameComponent-based manager classes that are typically instantiated at “Game” level and are offered as a property of the game
    • SceneHandler – manages the flow between game scenes (title, gameplay etc.) including activation and deactivation effects
    • InputHandler – provides an interface to touches, gestures and accelerometer data
  • Static Handlers – Globally available functionality for a particular data type
    • FileHandler – allows manipulation of local files and also manages StorableObject collections for tombstoning
    • TextureHandler – maintains a library of Texture2Ds and provides ability to load these without using the content pipeline
    • AudioHandler – library of sound effects and music, plus load outside content pipeline functionality and volume controls
  • The Utility class – loads of useful static functions! Random generators, angle calculations, standard message dialogs etc
  • Generic Particle System – handle particles and particle emitters. The main handler (ParticleSystem) can be wrapped to provide a game-specific interface
  • Dialog System – create and handle dialogs to display over a scene
  • Base Classes – various low-level classes to build up the game from
    • Scene – basic functionality for a game scene including transition and tombstone/dialog close handling stubs
    • StoreableObject – allows inheriting classes to be stored as part of a FileHandler collection with functions to store and retrieve data
    • DrawableObject – maintains position, frame and visibility for an object on screen with option to tombstone and draw functionality. Inherits from StoreableObject.
    • CollidableObject – maintains collision data (either radius or bounding box) and provides collision detection/reaction functionality. Inherits from DrawableObject.
    • MobileObject – maintains movement/scale/spin speeds for an object with update functionality. Inherits from CollidableObject.
    • TileMap – maintains a tile-based map, handling its positioning relative to the viewing port and that of any linked objects

While still being tweaked and added to, this vastly simplifies and speeds up getting a game up and running – The source below is a scene I put together to test tombstoning, but could easily become the kernel of a complete game:

public class TestScene : Scene
{
    private MobileObject _TestObject;
    private List _TestList;
    private bool _CleanExit;

    public TestScene(GameWrapper Owner)
        : base(Owner, "TestScene")
    {
        _TestObject = new MobileObject(this, "TestObject", "TestCollection");
        _TestList = new List();
        _CleanExit = false;
    }

    public override void CompleteInitialization()
    {
        _TestObject.SetTexture("Player", 0);
        _TestObject.Depth = 0.5f;

        if (FileHandler.FileExists("Leda_TSTest"))
        {
            FileHandler.LoadCollectionSettings("Leda_TSTest");
            foreach (string s in FileHandler.LastLoadedObjectNames)
            {
                if (s.StartsWith("ListObject"))
                {
                    MobileObject Temp = new MobileObject(this, s, "TestCollection");
                    Temp.SetTexture(s, 32, TextureHandler.Textures[s].Bounds.Height, 0);
                    Temp.Depth = 0.5f;
                    _TestList.Add(Temp);
                }
            }
            FileHandler.RestoreCollectionSettings("TestCollection");
            FileHandler.DeleteFile("Leda_TSTest");
        }
        else
        {
            _TestObject.Position = new Vector2(Constants.ScreenWidth, Constants.ScreenHeight) / 2.0f;
            _TestObject.Visible = true;
            _TestObject.SetCollisionArea(new Rectangle(2, 0, 28, 32));
            _TestObject.Velocity = Vector2.Zero;
            _TestObject.Active = true;

            for (int i = 0; i < 5; i++)
            {
                MobileObject Temp = new MobileObject(this, string.Concat("Enemy",i), "TestCollection");
                Temp.SetTexture(string.Concat("Enemy", i), 32, TextureHandler.Textures[string.Concat("Enemy", i)].Bounds.Height, 0);
                Temp.Depth = 0.5f;
                Temp.Position = new Vector2((i + 1) * 48.0f, 100.0f);
                Temp.Visible = true;
                Temp.SetCollisionArea(new Rectangle(0,0,Temp.FrameSize.X,Temp.FrameSize.Y));
                Temp.Velocity = new Vector2(Utility.GetNextRandom(4.0f) * Utility.GetNextRandomSign(), Utility.GetNextRandom(4.0f) * Utility.GetNextRandomSign());
                Temp.Active = true;
                _TestList.Add(Temp);
            }
        }

        base.CompleteInitialization();
    }

    public override void Update(GameTime gameTime)
    {
        if (Input.BackButtonTapped)
        {
            _CleanExit = true;
            _Owner.Exit();
        }

        if (Input.TouchLocation(0).X != float.NegativeInfinity)
        {
            _TestObject.Rotation = Utility.PointToPointAngle(_TestObject.Position, Input.TouchLocation(0)) + MathHelper.PiOver2;
            _TestObject.Velocity = Vector2.Normalize(Input.TouchLocation(0) - _TestObject.Position) * 10.0f;
        }

        _TestObject.Update();
        _TestObject.Position.X = MathHelper.Clamp(_TestObject.Position.X, 0, Constants.ScreenWidth);
        _TestObject.Position.Y = MathHelper.Clamp(_TestObject.Position.Y, 0, Constants.ScreenHeight);
        _TestObject.Velocity *= 0.95f;

        for (int i = 0; i < _TestList.Count; i++)
        {
            if ((_TestList[i].Position.X + _TestList[i].Velocity.X < 0) || (_TestList[i].Position.X + _TestList[i].Velocity.X) > 480)
            {
                _TestList[i].Velocity.X = -_TestList[i].Velocity.X;
            }
            if ((_TestList[i].Position.Y + _TestList[i].Velocity.Y < 0) || (_TestList[i].Position.Y + _TestList[i].Velocity.Y) > 800)
            {
                _TestList[i].Velocity.Y = -_TestList[i].Velocity.Y;
            }

            if (_TestList[i].CheckCollision(_TestObject) != null)
            {
                _TestList[i].Reset();
            }

            _TestList[i].Update();
        }

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {
        SpriteRenderer.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
        _TestObject.Draw(0);

        for (int i = 0; i < _TestList.Count; i++)
        {
            _TestList[i].Draw(0);
        }

        SpriteRenderer.End();

        base.Draw(gameTime);
    }

    public override void HandleTombstone()
    {
        if (!_CleanExit)
        {
            FileHandler.StoreCollectionAsFile("TestCollection", "Leda_TSTest");
        }
        base.HandleTombstone();
    }
}

So – how does this work? Well, first of all, we set up our “Player”:

_TestObject = new MobileObject(this, “TestObject”, “TestCollection”);

Thanks to the inheritance structure of MobileObject, this will have movement, collision and position information, can be drawn on screen. The second and third parameters ensure that this object is linked to the “TestCollection” collection of StoreableObjects in the FileHandler – the ramifications of this will be seen in a minute. We also set up a list of MobileObjects, which will hold our “Enemies”

CompleteInitialization is a method of the Scene class, and is called by the SceneHandler, usually when all content has loaded. This handles various bits of setup – textures and so forth, but the important line is the “FileHandler.FileExists” test, as this is checking for the presence of the file generated when the Scene is tombstoned. If this is found, the FileHandler loads the file (“FileHandler.LoadCollectionSettings(“Leda_TSTest”);”), rebuilds the object list, then populates the settings of all objects within the TestCollection collection (“FileHandler.RestoreCollectionSettings(“TestCollection”);”). If the file is not found, the objects are set up using their defaults.

The Update method handles input, movement, and collision checks. Input is taken from the Input property of the Game class that owns the Scene (_Owner) and applied to allow the scene to be exited (via the back button), and also check for touch data – this is then used to update the Velocity property of our “Player” so it moves towards the touch point, with an additional clause to slow the movement down if no touch data is found and keep within the screen boundaries. Similarly, checks are made against each of our “Enemies” positions to keep them onscreen. Movement is simply a matter of calling the Update method of each MobileObject – the class also exposes a static function to allow arrays/lists to be updated with a single call. Finally, we use the CheckCollision function for each enemy to see if it has collided with the player and if it has, we turn the enemy off.

Like Update, the Draw method is simply a matter of calling Draw for each DrawableObject – however note the numeric parameter for each Draw call. This allows layering of DrawableObjects outside the normal depth buffer facility, so SpriteBatch.BlendMode can be changed – this allows drawing of game objects in AlphaBlend mode, then swicthing to Additive for lighting and particle effects, then back to AlphaBlend again for any status panels etc.

Finally “HandleTombstone” is called when a tombstone event occurs while the scene is running – this checks to see if we have chosen to exit the scene and if not, calls the FileHandler method to store all objects in the TestCollection in the tombstone file.

Obviously, there’s set-up required around this to load the content, instantiate the scene and add it to the SceneHandler etc., but without breaking out from the base classes provided by the library, this is the kernel for a very basic game, complete from setup to exit.