PlanetX – Unit Testing an XNA game with Resharper and NUnit

I decided to setup some unit testing on my XNA 4 game before it’s too late.

I’m a huge fan of ReSharper (http://bit.ly/ekRH5g ), and I really cannot work without it and a few other plugins installed.

StyleCop for ReSharper (http://bit.ly/f0AKep) is one of them, VSCommands 2010 is another one http://bit.ly/dJPuFA, but this is not time to describe what my ideal setup is.

Back to the Unit Testing, Resharper supports OOTB nunit (http://bit.ly/eVqGrT) and as mocking framework Moq(http://bit.ly/fXXbhT) is my choice.

So, how do you start to test your XNA game?

Well follow these steps:

  • Add a new XNA Windows Game on your solution
  • Remove the Content Project that was created with this Game
  • Select Content References and add the Content Project used in your game
  • [OPTIONAL] Download Moq (http://bit.ly/fXXbhT) and add a reference to Moq.dll or add it using NuGet (http://bit.ly/gu5yxB)
    image
  • Download nunit (http://bit.ly/eVqGrT) and add a reference to nunit.framework.ddl and nunit.core.dll
  • Add a reference to System.Windows.Forms and System.Drawing
  • Create a folder called Helpers
  • Download MockedGraphicsDeviceService.cs and DeviceType.cs from (http://bit.ly/gqWHpP) and place them in the Helpers folder.
  • Create a new class in Helpers called AssemblyUtilities.cs, the class must be like
  • /// <summary>    /// The assembly utilities.    /// </summary>    internal class AssemblyUtilities    {        #region Public Methods
    
            public static void Copycontent()        {            var buildLocation = typeof(AssemblyUtilities).Assembly.CodeBase.Remove(0, 8).Replace((typeof(AssemblyUtilities).Assembly.ManifestModule).Name, string.Empty).Replace("/", @"\") + @"\Content";            var deployLocation = typeof(AssemblyUtilities).Assembly.Location.Replace((typeof(AssemblyUtilities).Assembly.ManifestModule).Name, string.Empty) + @"\Content";            Directory.CreateDirectory(deployLocation);
    
                //Now Create all of the directories            foreach (string dirPath in Directory.GetDirectories(buildLocation, "*", SearchOption.AllDirectories))                Directory.CreateDirectory(dirPath.Replace(buildLocation, deployLocation));
    
                //Copy all the files            foreach (string newPath in Directory.GetFiles(buildLocation, "*.*", SearchOption.AllDirectories))                File.Copy(newPath, newPath.Replace(buildLocation, deployLocation), true);
    
            }
    
            /// <summary>        /// Use as first line in ad hoc tests (needed by XNA specifically)        /// </summary>        public static void SetEntryAssembly()        {            SetEntryAssembly(typeof(AssemblyUtilities).Assembly);        }
    
            /// <summary>        /// Allows setting the Entry Assembly when needed.         /// Use AssemblyUtilities.SetEntryAssembly() as first line in XNA ad hoc tests        /// </summary>        /// <param name="assembly">        /// Assembly to set as entry assembly        /// </param>        public static void SetEntryAssembly(Assembly assembly)        {            var manager = new AppDomainManager();            FieldInfo entryAssemblyfield = manager.GetType().GetField(                "m_entryAssembly", BindingFlags.Instance | BindingFlags.NonPublic);            entryAssemblyfield.SetValue(manager, assembly);
    
                AppDomain domain = AppDomain.CurrentDomain;            FieldInfo domainManagerField = domain.GetType().GetField(                "_domainManager", BindingFlags.Instance | BindingFlags.NonPublic);            domainManagerField.SetValue(domain, manager);        }
    
            #endregion    }

You’ll need this class to fix a problem with the execution context of the tests with ReSharper, and to copy the Content folder from the build folder to the folder where the test is executed

  • Create a new class where you want to place your tests (Tests.cs
  • Add this code to your class
  •  [TestFixtureSetUp]        public void SetUpTest()        {            AssemblyUtilities.Copycontent();        }
    
            [SetUp]        public void SetUp()        {            AssemblyUtilities.SetEntryAssembly();        }

That will call the AssemblyUtilities methods as required

  • Add your test method
  • [Test]        public void Test()        {            var gd = new MockedGraphicsDeviceService(DeviceType.Hardware, GraphicsProfile.HiDef);            gd.CreateDevice();            var contentManager = new ContentManager(gd.ServiceProvider) { RootDirectory = "Content" };            var resource = contentManager.Load<Texture2D>("Sprites/blank");        }

In this method we are using MockedGraphicsDeviceService to semi mock the GraphicsDevice so we can work with around it to test the other components of our game

Two important points:

  1. You have to set your TestGame to run on the full .NET 4 framework in order to make Moq work
  2. image

 

There you have your Unit Test Library ready to use:

image

P.S: you need to have a Sprites/blank.png file on your content project in order for this test to pass

Download the code sample from http://bit.ly/eVxZmr

Enjoy your unit testing Smile

PlanetX, multiplatform: iPhone development (Part:3) – MonoGame–what a mess… – #iPhone #WP7 #Xbox #XNA #Monotouch #XnaTouch

Here I’m publishing a discussion I had via email with Andrew Russell (http://bit.ly/f21nDj) about his forking of XnaTouch project (now called Monogame) and the creation of ExEn.

The guy is a smart .net developer and XNA passionate, he had developed some games for Xbox and WP7 as an Independent Indy Game developer, and I invite you to go and download his games Dark: http://bit.ly/fX3pnQ and Light Blocks http://bit.ly/hiWcsC.

As many other .net developers, he’s trying to find a way to recreate the XNA framework for the iPhone and Android phone.
That would mean 90% code share between Xbox, WP7, Windows, iPhone, and Android, covering a huge percentage of the market.

Unfortunately (IMHO) he decided that XnaTouch (now called monogame) wasn’t good enough, and instead of improving it, he decided to fork it and create a total new product called ExEn (http://bit.ly/hpwjx4).

His Idea is that “combining the work of a dedicated, paid engineer (me) with the work of open source contributors“ will produce a better final result.

While I do not disagree with that, and I think he’s doing a great job trying to finance himself to work full time on the project, I also think that forking the project, and spending time back porting bug fixes (1) from Monogame on his on personal implementation, instead of working WITH the open source contributors is a waste of brain power.

Have a read at hour conversation and let me know what you think.

==================================================

From: smnbss@hotmail.com
Sent: Thursday, February 24/02/2011 12:28 AM
To: Andrew Russell
Subject: Re: ExEn vs monogame

Hi Andrew, a friend of mine just sent me a link to a link that talks
about you http://bit.ly/e94HJG
The idea is uber cool, and as you might know you’re not the one working
on it, http://bit.ly/eaRerW has in mind exactly your same target.
I heard Miguel de Icaza will be helping to port monogame to OSX App
Store too…
Is there any reason why you’re not joining forces with them?
I’ve been working with/on monogame for a few weeks now, and it’ seems
that most of the porting has been done,
but it’s like a mix of XNA 3.1 and 4 apis…
And they’ve now started to implement the android version
Have you already started with your development?
Is there any chance the 2 teams can work on the same codebase/project?
Hope the project will be very successful
Simone
http://about.me/smnbss

From: Andrew Russell
Sent: Thursday, February 24, 2011 6:16 AM
To: simone basso
Subject: Re: ExEn vs monogame

Hi Simone,

It looks like MonoGame is, in fact, the same project as XnaTouch and
that they have very recently renamed themselves.

So, in fact, ExEn *is* MonoGame with a lot of patches to improve
performance and stability. (And a Silverlight port on the side!)

(Admittedly, in the time since opening the ExEn funding project, they’ve
fixed some of the worst bugs themselves. That’s competition for you!)

I am not aware of any current plans by Miguel de Icaza to help port
MonoGame/XnaTouch to any platform. I am under the impression that the
idea was suggested for iOS/MonoTouch at one point – but that no further
action was taken.

For the detailed reasoning why I forked ExEn from XnaTouch and
SilverSprite, read my blog post here:

http://bit.ly/if6yt1

If you have any other questions, I’d be happy to answer them 🙂

Cheers,
Andrew

From: smnbss@hotmail.com
Sent: Thursday, February 24/02/2011 7:08 PM
To: Andrew Russell
Subject: Re: ExEn vs monogame


Sorry for not reading your blog before 🙂

I do not entirely agree with your choice (forking instead of submitting patches) because it seems to me a waste of brain power to create 2 frameworks with the same target (you said you want a fast and reliable framework while the monoxna guys wants completeness). You could have achieved the compile time errors on xnatouch by adding attributes to the unstable methods (something like the Onsolete attribute), helping them at the same time to improve performances.

What the community needs is a fast AND complete framework, without both those characteristics, the framework would be useless…

We developers are strange beasts..
We prefer to fork instead of communicating our ideas 😀

I was starting to work on a porting of a game from xna to monoxna, but at this point I’ll wait and see who wins between you 2 🙂

Keep up the great work

Simone

From: Andrew Russell
Sent: Thursday, February 24, 2011 10:52 AM
To: simone basso
Subject: Re: ExEn vs monogame

Simone,

I wouldn’t worry too much about seeing who "wins". I fully expect ExEn
and MonoGame to end up sharing the best bits of code between each other.
Indeed, I will be looking to incorporate patches from MonoGame into ExEn
during development.

In theory you should be able to write a game for any of the three
platforms (XNA, ExEn, MonoGame) and have a fairly easy job porting
between them.

Regarding completeness vs performance: When I was developing ExEn, I
don’t think I removed anything in XnaTouch simply for being slow,
without replacing it with something better. The stuff that was outright
deleted was either NotImplementedException, or buggy – which, in my
mind, is even worse. So I’ve not really reduced the completeness level,
in terms of practical usage – just API coverage.

Cheers,
Andrew

From: smnbss@hotmail.com
Sent: Thursday, February 24, 2011 11:04 AM
To: Andrew Russell
Subject: Re: ExEn vs monogame

Anyway, the stuff you deleted could have been marked as
[Obsolete("This method is totally bogus", true)]
So the compiler can rise an error if referenced by any 3rd party project
(like your game).

So it would have brought to the attention of the community that some more
work was required.

We could have had a more mature product instead, and a bigger team working
on the project…
I really do not understand why, if the frameworks are interchangeable you
wanted to fork the project and rename it…

Open Source is meant to bring people with the same targets together, not to
divide them creating fragmentation…
It just require a bit of effort from both sides, but it can be achieved.

Do you mind if I publish this email conversation on my blog?
I think it’s an interesting conversation for the people using both the
frameworks

S

From: Andrew Russell
Sent: Thursday, February 24, 2011 3:42 PM
To: simone basso
Subject: Re: ExEn vs monogame

Regarding bogus code:

Really I think that there isn’t that much of a difference between
deleting the "bogus" code and marking it with an attribute. Remember
that deleted code can be brought back from version control if need be.

I personally think deletion is nicer from stylistic and maintenance
standpoints. Maintenance In particular, for ExEn – with such sweeping
changes, reducing the surface area helped significantly.

(Also removing all that code saved many kilobytes on my Silverlight
download size.)

As you say, attributes could act as documentation of unfinished APIs.
But that documentation could also be handled externally.

We could explore these tradeoffs in detail, but really I don’t think it
merits further discussion (tabs vs spaces, anyone?). In either case, no
one would want to actually call these functions.

 

Regarding forking:

You must remember that when I originally forked ExEn (for my own,
internal use), that SilverSprite was a stalled project and XnaTouch was
unuseably buggy and moving extremely slowly. (It seems that SilverSprite
remains stalled, while XnaTouch, now MonoGame, has picked up its pace.)

If I had submitted my changes as a patch, it would have touched the
majority of files in the project. Replacing a large percentage them, and
deleting a few more. As well as a fairly substantial restructure to
merge in a separate project. Not to mention philosophical changes – like
my decision to delete "bogus" code. In light of all this, a fork seemed
highly appropriate.

When I suggested that the projects are interchangeable, I meant
externally. After all – they both attempt to replicate Microsoft’s XNA
API. Internally they are mostly very different.

When I say I will be incorporating patches from MonoGame/XnaTouch, here
is what I mean:

(1) When I start working on ExEn (as a dedicated project, hence the
funding), I will be going through the MonoGame/XnaTouch patch list,
one-by-one, from the point where I was last in-sync. In areas where the
code is identical (eg: GamerServices), I can simply adopt their code.

For the code that is different (did I mention there is a lot?), I will
very carefully have to go through and compare it with the changes I have
made: Did I fix this bug? Is my code better? If not, how can I improve
my code based on their improvements?

So, yes, on the one hand I can see that this has resulted in some
duplicated effort (eg: they’ve fixed bugs that I fixed independently).

But I believe that, for the users of the finished product, the end
result – of combining the work of a dedicated, paid engineer (me) with
the work of open source contributors – will be better than what could be
achieved by pursuing either approach independently.

Please feel free to publish this email exchange on your blog. And I
welcome any more questions you or your readers may have 🙂

Cheers,
Andrew

 

[PS: If you do publish these, let me know when you do. I will gladly
post links.]

PlanetX, multiplatform: iPhone development (Part:2) #iPhone #WP7 #Xbox #XNA #Monotouch #XnaTouch

May be this blue screen does not mean much to you, but any XNA developer will be able to recognize the standard Blue XNA background…

Capture

Basically the same code that works for the WP7, work on the iPhone emulator, on Windows and on the Xbox

image

Tomorrow you’ll see sprites popping out of these small screens Smile.

To achieve this, basically you need to setup monodevelop, monotouch, xnatouch and all that jazz, create a windows Xna game from Visual studio 2010, create a copy of the project for WP7 (right click on the windows project)

image

Then you need to take one of the examples that comes with XnaTouch, delete all the files, and add all the files from the windows xna game.

I suggest you to use linked files in order to have a single codebase, and use svn to share the code between your VS2010 Windows instance and your OSX Monodevelop instance.

I’m using http://www.zennaware.com/cornerstone/ as svn client on OSX. I’ve never used a mac before and the way this svn implementation works is a bit strange to me, but might be more familiar to those coming from the MAC. I prefer a million times Visual Svn, integrated with VS, but there’s noting like that for monodevelop on OSX.

Once you’ve done all this, the project will fail to compile on OSX, because the Microsoft.Xna namespace does not exist, so you have to replace it with

 

#if IPHONE
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using XnaTouch;
using XnaTouch.Framework.Media;
#else
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Media;
#endif

 

Basically, this is my Program.cs file

#region Using Statements
using System;
#if IPHONE
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using XnaTouch;
using XnaTouch.Framework.Media;
#else
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Media;
#endif
#endregion

namespace XPlanets
{
#if IPHONE
    [Register ("AppDelegate")]
class Program : UIApplicationDelegate
{
public override void FinishedLaunching (UIApplication app)
{
// Fun begins..
using (XPlanetsGame game = new XPlanetsGame())
            {
                game.Run();
            }

//MediaLibrary lib = new MediaLibrary();
//object result = lib.Playlists;
}

static void Main (string [] args)
{
UIApplication.Main (args,null,"AppDelegate");
}
}
#elif WINDOWS || XBOX
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main(string[] args)
        {
            using (XPlanetsGame game = new XPlanetsGame())
            {
                game.Run();
            }
        }
    }
#endif
}

and this is my XplanetGame file

using System;
using System.Collections.Generic;
using System.Linq;
#if IPHONE
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using XnaTouch;
using XnaTouch.Framework;
using XnaTouch.Framework.Media;
using XnaTouch.Framework.Graphics;
using XnaTouch.Framework.Input;
#else
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endif

namespace XPlanets
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class XPlanetsGame : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public XPlanetsGame()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

In this way, you have a single codebase, where 90% of the code is exactly the same on all the devices, and you can optimize or customize for a specific device using C# Preprocessor directives.

You’ll see this block many many times:

 

#if IPHONE
//iPhone
#elif XBOX
//XBox
#elif WINDOWS
//Windows
#elif WINDOWS_PHONE
//Windows Phone
#endif

PlanetX, multiplatform: iPhone development

So after 4 days of fight against Apple OSX, VMWare, Virtual Box, Apple SDK download, etc, I was finally able to have my OSX Virtual machine up and running with Mono, Monodevelop, MonoTouch and XnaTouch configured

image

 

If you want to try I suggest you to start from this URL to create the VM:
http://www.sysprobs.com/install-mac-snow-leopard-1063-oracle-virtualbox-32-apple-intel-pc

Then download the Apple SDK from https://developer.apple.com/devcenter/ios/index.action

Finally download MonoDevelop and MonoTouch from http://monodevelop.com/Download/Mac_MonoTouch and http://monotouch.net/DownloadTrial

Make sure you have a MonoDevelop version compatible with Monotouch, and then download the XNA touch example from http://xnatouch.codeplex.com/

 

Good Luck

PlanetX, multiplatform (Windows, WP7, XBOX) and iPhone development

As I mentioned few days ago, I’m helping some friends to port a game from Windows to the XBOX, WP7 and iPhone.

The game was originally developed at the global game jam in Italy, and you can download the original game from this Url http://www.globalgamejam.org/2011/x-planets.

The game was developed using XNA http://msdn.microsoft.com/en-us/aa937791, and I have to say that it’s really incredible the flexibility of that framework. Basically I started to work on that project just a week ago, and the only line of code I had to change to make it work on XBOX and WP7 was

this.cataclysmCount = Enum.GetValues(typeof(CataclysmEnum)).Length;

to

int i = 0;
do
{
    try
    {     
       if(!Enum.IsDefined(typeof(CataclysmEnum), i))
          break;       
       i++;
    }
    catch
    {
     break;
    }
}
while (true);
this.cataclysmCount = i;

This is because Enum.GetValues is not supported in the .NET NETCF implementation that is used on the Windows Phone 7 and on the one used on the XBOX.

The other change I’ll have to make to support the WP7 and XBOX the the code that handle the user input control.

While on windows we have the mouse and the keyboard, on the phone we have the touch sensor and the Accelerometer http://bit.ly/eGq5Be and finally on the XBOX we have the joypad, with the dpad, thumbs sticks and buttons.

The 4th chapter of this book http://amzn.to/frlAmn (Learning XNA 4.0: Game Development for the PC, Xbox 360, and Windows Phone 7) explains you exactly how to do that.

Now, this development on VS 2010 and Windows is all on my comfort zone, but I was also asked to have a look at development for the iPhone.

I do not have a Mac, and i do not have an iPhone, so how can I do my research and study without all those Apple goods? Well, I had to resort to a non official way obviously.

So I found a Virtual machine with OSX (“Mac.OSX.Leopard_VMware.Workstation-TeamWersaq”), and after struggling with it for a good half an hour to make it work (the solution was to use the –legacy switch at the first boot prompt) I finally started to download a long list of software I need to do my experiments.

On codeplex I found an interesting project, called XNATouch, and it looks like it’s the ideal solution for me to keep a shared code base between all my platforms.

The list of software required to develop with XNATouch is the following

1. Installed Apple’s iPhone SDK 4.1

2. Installed Mono for OSX

3. Installed MonoDevelop for OS X

4. Installed The MonoTouch SDK

5. Downloaded XNATouch 1.0

So I’m waiting for the download of iPhone SDK to complete and I’m good to go Smile

image

[UPDATE] BTW, if I make enough money out of it I promise I’ll buy a Mac and an iPhone Winking smile