Archive for July, 2008

Introducing Scurvy.Test

Game development is by its nature a visual thing.  Unit testing is code that tests other code … and code is by its nature a non-visual exercise.  Ever since XNA launched, a recurring thread I’ve often seen is how to best apply unit testing methodology.  Particularly when much of the code-base requires things that wouldn’t typically be available in the context of a unit test such as a graphics device.

I still to this day haven’t seen a comprehensive write-up on this subject. So at the risk of sparking a debate on the subject of whether this should be accomplished with mock objects, or via some other method; I decided to see what it would take to write a unit test framework that allows you to use resources such as the graphics device.

You can find the project on CodePlex here: http://www.codeplex.com/ScurvyTest

On the surface, it has most of the basic features of a unit test framework.  You can add some custom attributes to your unit test classes:

  • [TestClass], to signify this is a unit test class
  • [TestSetup], run before every unit test
  • [TestMethod], the actual unit test
  • [TestCleanup], run after every unit test

This follows suit with most any unit testing framework I’ve come across.  Where things diverge is in the method of running the unit tests.  This framework is designed to run the unit tests in-process. You can run your unit test in one of two ways:

TestRunner<Program>.RunTests(myServiceProvider);

Where the generic argument is any type in the assembly that houses your unit tests.  This automatic mode will run all unit tests.  Good if you want to use this framework in a standalone project (since Scurvy.Test doesn’t actually have any references to XNA libraries).

Here’s where things get interesting though.  What if you wanted to write unit tests that use content managers, or even that render content.  This is (probably) impossible with other unit test frameworks.  However, Scurvy.Test enables these scenarios in a few different ways.

First, the TestRunner class can also be instantiated as a regular instance.

this.runner = new TestRunner<Game1>(this.Services);

this.runner.Update(gameTime.ElapsedGameTime);

this.runner.Draw();

This will cause the test runner to run in manual mode. When you do that, simply call the Update and Draw methods on the test runner instance.  A unit test will be run once every time the Update method is called, unless one of the unit tests specifies an ExitCriteria (more on this in a moment).

Second, a [TestMethod] can either have no arguments, or can accept a TestContext.  This TestContext has two properties:

  1. public IServiceProvider Services
  2. public ExitCriteria ExitCriteria

The IServiceProvider is cool because if you use the “Go To Source” feature on the game class’ .Services property, you’ll notice it’s of type GameServiceContainer, which in turn implements the IServiceProvider interface.  Having a reference to this lets you instantiate ContentManagers, and also query for services like the IGraphicsDeviceService which could be used to instantiate a SpriteBatch.

The ExitCriteria is an abstract class that has the following definition:

public abstract class ExitCriteria
{
public bool IsFinished;
public readonly TestContext Context;

public ExitCriteria(TestContext context)
{
this.Context = context;
}

public abstract void Update(TimeSpan elapsedTime);

public abstract void Draw();
}

With this, you can write a unit test that can render to the game’s viewport and allow a QA tester to verify correctness visually.  Simply set the context’s ExitCriteria method from a unit test, and the framework will take care of executing the exit criteria until it sets the IsFinished property to true.

[TestMethod]
public void ManualContentVerificationTest(TestContext context)
{
context.ExitCriteria = new ContentVerificationExitCriteria(this.content, context);
}

The sample project included in the source code has a manual verification exit criteria that will wait until the tester presses a button.

Right now, the weakest part of this framework is in the feedback department.  If an assert fails or one of the unit tests throws an exception, it will write some information to the Debug stream (which you can see in visual studio’s Output window.  This is ok for now, but I have some plans on how to improve that.

So I’d love to get feedback on this little project, feel free to comment on this post, or on the codeplex site.

Thanks!

Comments (4)

Creating Great Community Games

Nick Gravelyn posted an awesome set of guidelines for XNA community games.  Anyone that is serious about making a nicely polished games should print out that list and make sure their game is up to snuff:

http://xnawiki.com/index.php?title=Creating_Great_Community_Games

Comments

XNA Input Guidelines?

One of the things I’ve noticed about many of the xbox games that are published through traditional channels (ie. retail and xbox live arcade) is that it’s very easy to just pick up and play.  It never really occurred to me that it is likely due to the level of polish that they all probably achieve.

The thought came to me when I was playing the excellent Little Gamers: Teh Game with my son on community games.  We spent a minute or so trying to figure out why the controller wasn’t working.  Even going as far as to restart the xbox to make sure that the controller was still providing input to the console.

After realizing what was going on, it was obvious that the code probably looked something like this:

GamePadState padState = GamePad.GetState(PlayerIndex.One);

if (padState.IsButtonDown(Buttons.Start))
{
this.StartGame();
}

Now, this is by no means a critique of the game … because the game really has a lot of polish (aside from perhaps this one tiny thing).  But the code assumed that the player would always be using the controller designated as “player one”.  When, in reality, I always just pick up whatever controller I see first, regardless of whether it held the player one slot.  The code above could be modified for a single player game as below to determine the controller that the player is using:

for (int i = 0; i < 4; i++)
{
PlayerIndex currentPlayerIndex = (PlayerIndex)i;
GamePadState padState = GamePad.GetState(currentPlayerIndex);

if (padState.IsButtonDown(Buttons.Start))
{
this.CurrentPlayer = currentPlayerIndex;
this.StartGame();
}
}

From that point on, you can use this.CurrentPlayer when querying for input.

I think that this is actually a symptom of a slightly larger problem.  The problem is that there are no standards for XNA games right now.  Microsoft has actually made a conscious decision to avoid publishing standards for XNA games because, unlike the strict TCR (Technical Certification Requirement) that fully licensed commercial games must pass, they wanted to lower the barrier to entry for game development.

This is of course a good thing … however, one of the things that I’ve been wanting for a long time are guidelines for XNA games.  They would offer things that could help a would-be developer add that final polish, that je ne sais quoi.  These guidelines could be provided by Microsoft, but I think it would be equally useful to see them community driven using something like XNAWiki.com.

While I’m on the topic of input …EA Skate's innovative trick control mechanism Paul Varcholik has been experimenting with some very interesting technologies such as training input gestures for the wiimote.  It would be cool to see this extrapolated to a more general application.  This could be used to train combo moves in a fighting game … or perhaps an RPG where spells must be gestured.

Kinda’ like EA Skate :-D

Comments (1)

Exception Handling in XNA

After reading this great article by Jamie Fristrom, I got to thinking about how one should organize their exception handling in an XNA game.  Since there are huge domain differences between an XNA application and a traditional business application, most of the exception handling texts out on the web right now may not offer the best advice.

In the traditional application world, exception handling is all about grace under pressure.  Sure the app has been tested time and again, but surely at some point there will be an unexpected failure somewhere.  Typically this will be with an external resource such as a database, access to a network share, or a web service.  In this case, these external dependencies are well known at design time and developers can code for their eventual failure.

When you start talking about games though, the landscape is usually a little bit different.  There aren’t usually as many external dependencies as there are complex subsystems.  Of course, there are the obvious game data storage (ie. file IO), and network subsystems.  But by and large, your main offenders will occur right at home in your own AppDomain.

In a game, your error handling will usually be with the express intent of helping a developer find the source of the bug as quickly as possible.  In a small team, the developer will usually be running the game with the debugger attached, and will be able to make adjustments on the fly.  However, what if you achieve the dream, and all of a sudden find yourself with funding and a team.  Now the situation is more complex … especially when non-developer QA members enter the picture.

I’m not sure I have the answer (I know, so helpful :-P ).  But I do know that many .NET developers, even those that have been using the tech for years still don’t understand how to properly use exceptions.  The biggest issue is often that either no exceptions are thrown/caught at all, or they are thrown far too often.

If your game has any external touch-points such as networking … then any and all operations on that external resource should have error handling with the assumption that it will fail at some point.

Internal subsystems such as animation libraries, physics engines, and AI modules should also be thought of as a black box resource.  As far as your game is concerned, that call to physicsEngine.Update() could fail with the most obscure rotational flim flam error.  You should structure your error handling to properly report the error to the user/player in a proper fashion such as debug text on the screen, or writing to a log file.  All without affecting the main execution and rendering of the game.

Conversely, the above paragraph assumes that subsystems are properly structured to throw useful exceptions if there is some error state instead of just allowing bad input to cause some unrelated error (NullReferenceExceptions are usually a sign of this).  This can be achieved by input validation … make sure you are in a valid state before continuing.  Once you have identified invalid input, or an invalid state … you should throw a custom exception.  Much has been written about this, but is neatly summed up here:
http://msdn.microsoft.com/en-us/library/ms229064.aspx

If you design it well, a malfunctioning subsystem shouldn’t affect the other subsystems.  For example, if there’s a physics engine error, the rest of your game should continue rendering.  If there’s an error loading a texture, you should probably load a default texture. 

In each case, the game will handle the issue very gracefully; while at the same time notifying the user of the issue, and continuing execution.  If this mantra is followed, it could allow artists to continue working with a certain build, even if there is a minor bug.  This reduces stress on the developers because they don’t have to stop what they’re focusing on to fix a little bug that is stopping the artists from testing their content in-game.

Comments

XNA Secure Unlock System

A recent forum thread unearthed a great idea by Jon Watte

To generate revenue, you could have an unlock mechanism, where someone pays you money and gets an unlock code. The unlock code would be some hash of their gamer tag and a key, and the game would know whether it’s right or not. Because it’s a hash, you can’t use the same unlock code for two different gamer tags. Just beware that if you’re not selling anything tangible, you should budget 10-20% of your revenue to credit card charge-backs and fraud.

I got curious on what it would take for such a solution to be implemented.  The first thing that occurred to me is that there would be two components to this feature.  One would be the in-game unlock mechanism, while the other is the external component that would more-than-likely be implemented as a website.

Sample Code:
http://codecube.net/bloguploads/UnlockCodes.zip

In-Game Implementation

You might initially think that the in-game implementation would be rather simple through the use of the .NET framework’s powerful cryptography namespace.  But alas, if you plan on targeting the XBox 360 or Zune platforms, you will quickly find yourself disappointed.  That namespace is not available on the Compact Framework.

Thankfully, the compact framework has been around longer than XNA … and so others have had the need, and subsequently implemented the solution for this problem:
http://www.flowgroup.fr/en/kb/technical/md5.aspx

From the fine folks at FlowGroup:

The cryptography classes are not available on the Compact Framework 1.0, so we ported the “MD5 Message-Digest Algorithm” from RSA Data Security, Inc. in C#.

With the ability to generate hashes on the compact framework, we can then focus on how we can implement our secure unlock mechanism.  Using three values:

  • Developer Secret: this is a string that is known only to the developer.
  • User Secret: this is something known only to the user.
  • GamerTag: The user’s gamertag.  He must be logged in with this gamertag in order to use the code.

This technique is so simple you’ll kick yourself for not having thought of it.  Taking the three values, simply concatenate them, and then compute the hash using the resulting string.  This provides a very secure way of providing personalized unlock codes.

Even if there were users that wanted to subvert your mechanism and share codes, it would not work.  Let’s say a user with a GamerTag of SxyLvr decides he wants to post his unlock code to the world.  No one else would be able to use it because they would have to be signed in with SxyLvr in order for it to work.

Users will similarly be unable to create codes on their own because they are unlikely to know the developer secret.  That is something that will be known only on the server, and in your game code.  Of course, if you are distributing a windows game, then it can easily be decompiled … but on windows you are free to use more traditional data security techniques; and of course on the xbox (via community games), the user is unable to get access to your binaries

With this in place, we are able to create a simple class that has the following interface:

public class UnlockCodeProvider
{
    public UnlockCodeProvider(string developerSecret, string gamerTag);  
    
    public string ComputeCode(string userSecret);

    public bool Validate(string userSecret, string codeToValidate);
}

I won’t go into the implementation as you can just download the sample code.  But this very simple class can be instantiated by supplying the developer secret, and the gamertag that we are working with.  The two methods allow you to compute a code using the supplied user secret (ComputeCode), while the other one allows you to validate that a code the user supplied is valid (Validate).

This class, and a dreadfully simple “game” shell can be found in the sample download at the top of this post.  This sample shows how to ask the user to log in, get his gamertag; then ask him for the user secret and code he received from the server. 

Once the user supplies this information, the game will validate the code against a locally computed hash.

Server Implementation

The server-side in this equation gives you many many options to choose from.  As mentioned before, this will more than likely be a web application that the developer controls.  The purpose of these unlock codes can be many; for example the developer could charge money for certain cards in a collectible card game.  Or the most active contributors in the developer’s favorite community can be given codes as a reward.

Whatever the reasoning, the server can be used to generate unlock codes that can subsequently be used in-game to unlock whatever.

ASP.NET

I chose ASP.NET for several reasons … I write C# code all day, and thus I am proficient in it.  This also allows me to re-use the exact same UnlockCodeProvider API that the in-game implementation uses. 

I threw together a painfully simple ASP.NET GUI that uses simple web forms (postbacks, et al)

unlock_server_gui

As with the in-game code, this can be found in the sample code found at the top of this article.

PHP

I wanted to write a reference implementation in PHP to illustrate the fact that the server-side implementation isn’t limited to requiring ASP.NET.  You can use any technology that you are familiar with and/or already have infrastructure for.  PHP seems to be a common choice because hosting is so cheap these days.

Unfortunately, due to time constraints, this feature got cut … so I’ll leave it as a user exercise.  I assume though that anyone that’s even modestly familiar with PHP can whip this up in about 30 seconds using the hash function :-)

http://us.php.net/manual/en/function.hash.php

Legality?

Of course, there are certain interpretations of the EULA that suggest this may not be a legal move for XBox games (ie. to sell unlock codes).  According to the ZMan:

I had the same idea but then I wondered how Microsoft would feel not getting a share of the millions I would be sure to make… Shame the EULA Forbids it right now …

b. Programs developed for the Xbox 360 Platform
i. Personal Use.  Use of any programs developed for the Xbox platform using the software is restricted to your personal, non-commercial use. 

That doesn’t mean the idea is dead in the water.  You could always give unlock codes in return for email addresses (that you could then use to notify of your next game).  Or you could give them away for registering on your community site … or really, anything. 

The world doesn’t have to revolve around commercial aims just because Adam Smith says so :-)

Comments (2)

XNA MVP Award for 2008

imageEarlier today, I was informed that I’ve been awarded a DirectX/XNA MVP award for 2008.  One word, Wow :-)

I am very thankful for the award, and want to thank those that have supported me … whether it’s through tolerating the time I spent helping random people on internet forums.  To those that have supported my open source project with feedback and knowledge.  And the few readers of my blog.

Going forward, I’m not sure this is going to change much … especially since the award is for past contributions as opposed to a position that you must work at.  I’m going to continue answering forum posts, writing stuff on my site, expanding Scurvy.Media, and even writing games :-)

I’m really looking forward to what the next year holds.  Thanks Microsoft!

Comments (5)