Now it’s time to move on to gamers and profiles.
Rather than starting an entire new project, let’s just remove the four
checks to the WasButtonPressed method in your Update overload. You should also add a new SpriteFont object called font to your Content project because you draw text in a few moments. Then add the following variables:
SpriteFont font;
Gamer lastGamer;
GamerProfile lastGamerProfile;
Texture2D gamerPicture;
Load the font in LoadContent as usual:
font = Content.Load<SpriteFont>("font");
Now, you need to do something with the players that are currently signed in, so first add the following code to your Initialize method to set all the rest of your variables:
SignedInGamer.SignedIn += new EventHandler<SignedInEventArgs>((o,e) =>
{
lastGamer = e.Gamer;
lastGamer.BeginGetProfile(new AsyncCallback( (result) =>
{
lastGamerProfile =
lastGamer.EndGetProfile(result);
gamerPicture = Texture2D.FromStream(
GraphicsDevice, lastGamerProfile.GetGamerPicture());
}), null);
});
The SignedInGamer class has two static events to detect when players are coming and going, namely the SignedIn and SignedOut events. In this example, you hook the SignedIn
event and store the gamer that signed in to your variable. Each gamer
also has an associated profile, which you store here using the async pattern call. There is also a synchronous GetProfile method you can call instead, but using the async
pattern is the correct way to retrieve the profile. Lastly, store the
profile’s gamer picture into a newly created Texture by using the GetGamerPicture method, which returns a stream.
Note
Anyone who is signed in when the game launches receives a SignedIn event fired. You do not need to special case startup.
Next, replace your Draw overload with the following:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
if (gamerPicture != null)
{
spriteBatch.Draw(gamerPicture, new Vector2(400,100), Color.White);
}
if (lastGamer != null)
{
Vector2 pos = new Vector2(50,30);
spriteBatch.DrawString(font, lastGamer.Gamertag, pos, Color.White);
if (lastGamerProfile != null)
{
pos.Y += 20;
spriteBatch.DrawString(font, lastGamerProfile.GamerScore.ToString(),
pos, Color.White);
}
}
spriteBatch.End();
}
Here
you simply use each of the variables you defined so far to display some
information. First, draw the gamer picture onto the screen if the
texture has been created, then draw the gamer tag of the profile after
the gamer is stored, and finally draw the gamer score from the profile.
Because the SignedIn event is hooked
and storing the data for anyone that logs in, if you log in someone new
while this example is running, the data onscreen changes to the new
player.
You can also use the gamer in earlier Guide methods that required a gamer class. As an example, adding the following code to your Update method shows the gamer card of the signed-in profile as seen in Figure 1:
if (WasButtonPressed(Buttons.A, state, lastState))
{
if (lastGamer != null)
{
Guide.ShowGamerCard(PlayerIndex.One, lastGamer);
}
}
Before moving on, let’s take a moment to look at the other pieces of information stored in these objects. The Gamer
object is an abstract class, so it has a few derived classes, but it
only has a couple extra members directly on itself. It has the DisplayName property, which many times is simply the GamerTag, but can be something different. It also includes the Tag property for you to do with what you want. Finally, it has the unsupported LeaderboardWriter property. This property is available only for Xbox LIVE partners.
The GamerProfile
object has quite a few things you haven’t looked at yet though, mostly
around portions of the players’ profiles (imagine that). It has the GamerZone property, which can be Family, Pro, Recreation, Underground, or Unknown. You can also get the Motto property to view a player’s motto, which can be empty if he or she hasn’t set it. You can see the player’s Reputation
by checking that property, which is a float value between 0.0f and 5.0f
representing the number of stars of reputation that player has. The
float values enable you to have fractional stars as well.
You can also use the TitlesPlayed property to determine how many games a player actually played, along with TotalAchievements to see how many achievements he or she earned. Finally, you can use the Region property to determine what region a player is located. This covers all the basic properties for these objects.
Note
In this example, you use the
event to display data about the last person who was signed in; however,
there is a static collection of SignedInGamer called SignedInGamers that enable you to view the collection of gamers currently signed in as well.
Remember that the Gamer class is abstract, which means that the object you are currently using is one of the derived classes; namely, the SignedInGamer object itself. This class has much more data than the abstract Gamer, so update your variable to declare it of the following type instead:
One of the things on this
object are several methods dealing with achievements. Unfortunately,
these methods are available only for partner Xbox LIVE games. There are
plenty of other members you can actually use though.
For one, you can detect whether players are signed in to live via the IsSignedInToLive
property. This is always false for local accounts, but it can be false
for Xbox LIVE accounts as well if they aren’t actually connected to Xbox
LIVE. You can also see which controller is paired with this gamer by
checking the PlayerIndex property.
You can detect whether gamers are in a party by checking the PartySize
property. If it is greater than zero, then they are in a party. If
players are guests of a signed-in Xbox LIVE account, then the IsGuest property returns true. If you need to know whether a certain microphone is the headset for one of your gamers, you can use the IsHeadSet property to detect that as well!
GameDefaults
A feature often overlooked on
Xbox is the fact that gamers can set up a list of defaults for various
options in games that they play. Good games know which of these options
make sense for them and set the default for a player to what they
request. This is found in the GameDefaults object of the GameDefaults property.
There are quite a few Boolean properties available to check including AccelerateWithButtons, AutoAim, AutoCenter, BrakeWithButtons, InvertYAxis, ManualTransmision, and MoveWithRightThumbStick. For example, in a racing game with both an automatic and manual transmission, the default for a gamer is automatic if ManualTransmision is false, and manual transmission otherwise.
The other defaults are more than Booleans. You have both PrimaryColor and SecondaryColor, which are returned as colors (or null). The ControllerSensitivity property is an enumeration that is either High, Medium, or Low. Similarly, the GameDifficulty property is an enumeration that can be Hard, Normal, or Easy. Lastly, the RacingCameraAngle is an enumeration that can be Back, Front, or Inside.
Your game needs to be aware of these properties and set the initial values for a gamer to respect him or her.
Presence
The Presence
property is one of the more interesting things you can use. This
property enables you to set a well-known string that anyone can see to
let others know where a person is in game play. The property itself is a
GamerPresence object that has two properties, PresenceMode that is an enumeration of a series of predefined strings, and PresenceValue that is extra data used for some of the strings. For example, make the following call in your code:
lastGamer.Presence.PresenceMode = GamerPresenceMode.OnARoll;
Now, when someone else looks you up online (via http://xbox.com or Xbox 360), your profile includes the following:
XNA Creators Club
creators.xna.com
On a roll
If this game is published on
Xbox LIVE Indie Games, the first line changes to “Xbox LIVE Indie Games”
and the second is your game’s title. The third line is always the
presence string specified by the PresenceMode property. Some of the values of PresenceMode enable you to add extra data; namely, Stage, Level, Score, CoopStage, CoopLevel, VersusScore.
This enables you to have the presence string say something like
“Playing Stage 3.” Although updating your player’s presence isn’t a
requirement, it certainly adds to the polish of your game and is highly
recommended.
Privileges
Proper handling of the Privileges property is required. These represent the various things gamers may or may not be able to do. Perhaps they are Silver
subscribers, or perhaps they are children whose parents have set up
restrictions on their ability to play. Regardless of the reason, you
should always obey the privileges. If you don’t, the system still
disallows the action, but it can be a very poor user experience, or
worse, a crash.
Privileges come in one of two
forms. They either return a Boolean, in which case the privilege is
either allowed or disallowed, or they can return a GamerPrivilegeSetting, which has three choices: Blocked (they have no access to this feature), Everyone (they have full access to this feature), or FriendsOnly (they have access to this feature only with friends).
The first privilege is AllowOnlineCommunication,
which dictates whether a gamer can have any type of online
communication (text, chat, video, and so on). Check this privilege
before allowing someone to communicate with someone else (such as with
the Guide.ShowComposeMessage method).
Next is AllowOnlineSessions,
which essentially dictates whether a gamer can play multiplayer games. A
good example of using this privilege is to either not show the
multiplayer option or show it but have it disabled in your game. A best
practice is to include some status text informing the player why the
multiplayer is disabled.
After that is AllowPremiumContent, which is mainly used for Xbox LIVE partner games. If you want to restrict your game based on this, you can. The AllowProfileViewing privilege dictates whether the gamer is allowed to view other players’ profiles, so you do not allow them to call Guide.ShowGamerCard, for example, if this privilege is not available.
Next is AllowPurchaseContent,
which dictates whether the gamer is allowed to spend money to purchase
content. This is another place where some best practices can go a long
way. If the gamer is not allowed to purchase, don’t give him or her the
option, disable the option, and don’t call Guide.ShowMarketPlace.
The last two privileges are AllowTradeContent and AllowUserGeneratedContent.
These two can be tricky. For example, if your game enables the creation
of levels, and you can share those levels, that is both user-generated
content and trading content. This is extremely difficult for the system
to detect (and impossible in many cases), so ensure that your game
handles these correctly.
With Friends Like This...
Because some of the
privileges require you to know whether someone is a friend in order to
determine whether an action is allowed, there must be an easy way to
figure this out. Of course, there is! Use the IsFriend method, which returns true if the gamer you pass to it is your friend and false otherwise.
What if you want to see all of your friends though? Well, use the GetFriends
method, which returns to you a collection of all your friends. However,
because it is possible that some of your friends are not signed in
locally, the SignedInGamer object doesn’t work for your collection of friends. Instead, it is a collection of FriendGamer, which has quite a few different members.
You can check the status of your friends via a number of different properties such as IsOnline (to check whether they’re actually signed in), IsAway (perhaps they fell asleep playing a game), IsPlaying (to check whether they’re playing a game), IsBusy (just in case they’re busy), and IsJoinable (to check whether they’re playing a game that can be joined).
You can use the
FriendRequestReceivedFrom property to determine whether you received a
friend request (it returns true if you have, and false otherwise).
Conversely, you can use the FriendRequestSentTo property to see whether you have sent a friend request.
Just like you can set your presence, you can also see your friend’s Presence,
although it is returned as the actual string because it can be from any
game, including games that are not XNA games. You can also use the HasVoice property to determine whether your friend has the voice capability.
Lastly, if you sent an invite
to your friend, you
can get status of that as well. If he or she accepts the invite, the InviteAccepted property returns true. If your friend rejects it, the InviteRejectedProperty returns true (and InviteAccepted remains false). You can also use the InviteSentTo
property to determine whether you actually sent an invite to that
friend. It returns true if you have, and false otherwise. You can also
see whether ’he or she invited you via the InviteReceivedFrom property, which returns true if he or she sent you an invite, and false otherwise.