GamerServicesComponent
One of the first platform differences is the requirement (or lack thereof) of having a GamerServicesComponent in your application. Well, that’s not entirely true—a GamerServicesComponent is never required, but the tasks it performs are required on some platforms.
This component does two major things that you could also do on your own, but this just simplifies it some. First, it calls GamerServicesDispatcher.Initialize, which is required before calling the other method it automatically calls for you, GamerServicesDispatcher.Update. On Xbox 360 and the Windows platforms, you must call both Initialize at the start of your app, as well as Update every frame for all Gamer Services functionality to work, including the Guide class. On the Windows Phone 7 platform, you do not have to call these methods to use the Guide class, but you do have to use the other components in the Gamer Services namespace. This is important as you find out later.
Now, the easiest way to have the correct methods called for you without you having to think about it is to add a GamerServicesComponent to your game’s Components list. This is commonly done by adding a new component to your components collection during initialization:
Components.Add(new GamerServicesComponent(this));
If you’re creating an Xbox 360 or a
Windows game, add a component similar to this to your game if you’re
using Gamer Services. Do not add this component if you are using Windows
Phone 7 and using only the Guide class.
Guide Class
You used the onscreen keyboard API from the Guide.
For now, let’s go through each of the
APIs that work across all the platforms XNA supports. First, create a
Windows Phone 7 game project.
Trial Mode
Trial mode is, in short, awesome,
and it is required if you plan on selling your game. A well-designed
trial mode can be the difference between someone buying your game and
not. Far too many developers don’t take enough time to make a good trial
experience and their game suffers for it.
The default trial mode
experience is different depending on which platform you target. For
example, in order to implement a trial mode for a game you plan on
publishing via Xbox LIVE Indie Games on Xbox 360, you don’t have to do
anything, and the system handles everything for you. Granted, it won’t
necessarily be a very good trial, but it will be a trial mode
nonetheless! Conversely, the system does essentially nothing for you for
a Windows Phone 7 project, aside from notifying you when you are and
are not in trial mode. This means that for a good trial mode (and upsell
opportunities), you need to implement them yourselves.
Of course, being in trial
mode also means different things to the system as well. Xbox LIVE Indie
Games cannot use multiplayer features in trial mode, but there is
nothing stopping a Windows Phone 7 game from doing so.
So after all that, what is
trial mode exactly anyway? It is the mode that your game is running in
when the user has not purchased the game yet. Both of the currently
available publishing pipelines (for Windows Phone 7 and Xbox 360)
require you to have a trial version of the game (that is free to play)
so users have an idea of what the game is like and if they want to play
it more, or better yet, to buy it.
The major goal of any trial mode
is to convert people who are playing your game from a free customer to a
paid customer. You need to convince them that what they are playing is
so great that they need to pay whatever price you deem your creation
worth. Luckily, you have a lot of latitude in defining that.
One of the first things you
need to know is whether or not you are actually running in trial mode.
This is easily determined by looking at the Guide.IsTrial API call. In a published game, the API returns true if the game is currently running in trial mode (for
example, has not been purchased). It returns false if it is not running
in trial mode (for example, it has been purchased). This is pretty cut
and dry, and for all published games, you can be assured it is correct
and react accordingly.
Note
IsTrial can take up to 60ms to return on Windows Phone 7 projects, so do not call this every frame on those types of projects.
One of the problem’s you run
into during development is how you can actually test that your trial
code is working correctly. Again, the differing underlying systems
provide different levels of support for testing trial modes. For
example, on the Xbox 360, after you deploy your game, you can launch it
in trial mode for testing via the system UI, like you see in Figure 1.
However, on Windows Phone 7,
there is no way to launch the game in trial mode via the system UI, and
even if there were, there isn’t a way to actually debug your code while
trial mode is running (a problem shared by Xbox). During debugging, the
default state of the game is considered unlocked because the majority of
your game code and work is done for the case where trial mode is set to
false.
Knowing this, there is an added property on the Guide class to help with this, named SimulateTrialMode. In order to turn on trial simulation, this property needs to set before the first Update call. In the new project, add the following line in the game’s constructor:
Guide.SimulateTrialMode = true;
This tells the runtime
that you want to simulate the trial mode, which forces a game that is
not in trial mode to return true from the IsTrial property. This ensures that IsTrial returns true until you either turn off via SimulateTrialMode, or when you simulate purchasing of the game.
Note
After a game’s trial status has gone from IsTrial being true to IsTrial being false, from trial simulation, purchasing, or any other mechanism, it never returns to the state where IsTrial returns true unless the application is exited and restarted.
You’re probably thinking to
yourself, wait a minute, simulate purchasing of the game? As mentioned
earlier, the best trial modes are an introduction to the game with the
hope of getting your customer to purchase it. This implies that you need
a way to enable the user to actually do just that. To show how this
works, let’s simulate it via one of the gestures in the touch class, so
add the following to your game’s constructor as well:
TouchPanel.EnabledGestures = GestureType.Tap | GestureType.Hold;
You use only one of these for
now, but add them all now so you don’t have to change it later. Now, add
the following code to your Update method to handle the gestures:
while (TouchPanel.IsGestureAvailable)
{
GestureSample gesture = TouchPanel.ReadGesture();
switch (gesture.GestureType)
{
case GestureType.Hold:
if (Guide.IsTrialMode)
{
Guide.ShowMarketplace(PlayerIndex.One);
}
break;
}
}
The important piece here is the Guide.ShowMarketplace
call, which is where you have the opportunity to sell your game. For a
game that has already been released, this brings up the system user
interface to enable customers to purchase your game. If they do so, they
switch immediately to the purchased version (IsTrial
returns false). In debugging builds, this call instead shows a simple
message asking if you would like to simulate the purchase of the game,
much like you see in Figure 2.
Note
The check for IsTrial here isn’t necessary, because the ShowMarketplace call silently no-ops if you are not in trial mode; it was added for completion sake.
The ShowMarketplace call
is intended to be a fire and forget it type of method. You don’t need
to check its return (it has none), and the only exception it will ever
throw is if you pass an invalid value to its parameter. For Windows
Phone 7 projects, the parameter should always be PlayerIndex.One,
and for Xbox projects, it should be the index of the player who is
initiating the purchase screen. Depending on what happens during the
call, the value of IsTrial might change, and that is what your game should key on.
An example of a good trial
mode with upsell is a simple game with multiple levels. You can allow
players to play the first five levels in the trial mode and when they
finish those levels, bring them to a new screen saying that they could
continue the game right now by purchasing the full game and using the ShowMarketplace API to take them there.
As was mentioned earlier,
the system handles everything (including upsell) for your game on Xbox
360. There is a strict time limit on all trial games (exactly 8 minutes
as of this writing, but is subject to change at any time), and when the
time limit expires a new screen appears on top of the game enabling
users to continue if they purchase the game, or to exit the game. This
screen obscures the majority of the game behind it (the entire title
safe area, plus some), and no input is routed to the game when that
screen is up. The Guide.IsVisible property also begins to return true.
This brings us to the next property available on the Guide, IsVisible.
This returns true if the guide is currently visible (for example, your
game is obscured), and false otherwise. For example, change the Clear call in your Draw method to the following:
GraphicsDevice.Clear(Guide.IsVisible ? Color.Black : Color.CornflowerBlue);
Now, if you run your
application and hold the screen down to make the gesture fire, when the
simulate purchase screen is up, the entire screen turns black, rather
than the faded CornflowerBlue. The most
common usage of this property is to ensure you don’t attempt to load
another dialog when one is already obscuring your game, which you see in
a few moments.
The last property we talk about in this section is the IsScreenSaverEnabled property, which you can add to your project in the constructor:
Guide.IsScreenSaverEnabled = false;
The name of the property is a
bit misleading, but what it does is quite simple. It enables (or
disable) the system from thinking the user has stopped playing it. On
the Xbox 360, this
manifests itself by dimming the screen; on Windows Phone 7, it manifests
itself by engaging the lock screen. If you had an area of the game
where you expect long periods of time without user interaction (for
example, playing a very long cut scene on Xbox, or a game that is
controlled completely by the accelerometer on the phone), you should set
this property to false so the system doesn’t kick in and dim the screen
or lock it. You shouldn’t carelessly set this property to false all the
time though.
Note
The IsScreenSaverEnabled
property is application specific, not system wide, so even if you set
it to false and exit the game, it reverts back to the system setting
after the application quits.
The last method that we
discuss in this section is a common way to show simple messages. The
marketplace simulated purchase uses this API behind the scenes. As you probably surmised, this API
is ShowMessageBox. This API follows the standard .NET async pattern, so it is actually split into two separate APIs, BeginShowMessageBox and EndShowMessageBox. Add a new case statement into the gesture code in your Update method:
case GestureType.Tap:
if (!Guide.IsVisible)
{
Guide.BeginShowMessageBox("Testing", "This is a test message box.",
new string[] { "ok", "cancel" }, 0, MessageBoxIcon.None,
new AsyncCallback((result) =>
{
int? button = Guide.EndShowMessageBox(result);
}), null);
}
break;
The first parameter to the BeginShowMessageBox
API is the title of the message box, followed by the actual text of the
message to be displayed. Next is an array of strings that represent the
text that the buttons for the message box will have. For Xbox, this
array must have at least one member in it, and up to a maximum of three,
and on Windows Phone, it needs to have either one or two members. After
the buttons are listed, the next parameter controls which button is the
default selected button. This parameter has no effect on Windows Phone
projects. Lastly, is the MessageBoxIcon parameter that controls the icon the message box displays on Xbox, and the sound it makes on Windows Phone.
After the async call finishes, call the EndShowMessageBox
method to get the button that was pressed. It returns the index of the
button name or null if the message box was cancelled (by either the B
button on Xbox or the Back button on Windows Phone).
This overload of BeginShowMessageBox
enables anyone to use the dialog. However, on Xbox 360, if you want a
specific player to be the only one who can respond to the dialog, use
the other overload that includes the PlayerIndex parameter and pass the index of the player you want to control the message box in the parameter.