Professional Documents
Culture Documents
Programming Guide
Contents
Contents
Achievements 66
Checklist for Supporting Achievements 66
Designing an Achievement 67
Create Achievements That Show the Different Things Players Can Do in Your Game 68
Create Achievements That Require Different Levels of Skill or Dedication 68
Create Achievements for Different Sections Or Modes Present in Your Game 68
Use Hidden Achievements to Delight and Reward the Player 69
Save Some of Your Budget for Later Versions of Your Game 69
Configuring Achievements in iTunes Connect 69
Adding Achievement Support to Your Game 71
Reporting Achievement Progress to Game Center 71
Contents
Challenges 81
Checklist for Supporting Challenges 82
Issuing Challenges from Your Game 82
Displaying the Challenge User Interface 82
Displaying and Dismissing the Challenge View Controller 83
Best Practices for Issuing Challenges 84
Receiving Information About Existing Challenges 85
Reacting to Challenge Events 87
Responding to Challenge Events 87
Responding When the Local Player Selects a Challenge 89
Matchmaking Overview 90
Game Center Supports Multiple Kinds of Matches 90
Game Center Provides Multiple Ways to Connect Players into a Match 91
Matchmaking and Gameplay Are Separate Tasks 92
You Can Match Across Different Versions of Your Game 92
Creating Any Kind of Match Starts with a Match Request 93
A Match Request Must Specify the Number of Players in the Match 94
Inviting a List of Players 95
Player Groups 95
Player Attributes 96
Contents
Contents
Table 4-4
Table 4-5
Table 4-6
Listing 4-1
Listing 4-2
Listing 4-3
Listing 4-4
Listing 4-5
Listing 4-6
Listing 4-7
Listing 4-8
Listing 4-9
Listing 4-10
Listing 4-11
Listing 4-12
Listing 4-13
Listing 4-14
Achievements 66
Table 5-1
Table 5-2
Table 5-3
Listing 5-1
Listing 5-2
Listing 5-3
Listing 5-4
Listing 5-5
Listing 5-6
Listing 5-7
Listing 5-8
Listing 5-9
Achievement properties 70
Achievement language properties 70
Classes in Game Kit used to implement achievement support 71
Reporting progress on an achievement 72
Reporting progress on an achievement for another player 73
Reporting progress on multiple achievements 73
Loading achievement progress 74
Resetting achievement progress 77
Displaying the achievements page of the Game Center user interface. 78
Responding when the player dismisses the Game Center content 79
Retrieving achievement metadata from Game Center 79
Loading a completed achievement image 80
Challenges 81
Table 6-1
Table 6-2
Table 6-3
Listing 6-1
Listing 6-2
Listing 6-3
Listing 6-4
Listing 6-5
Listing 6-6
Listing 6-7
Listing 6-8
Listing 6-9
Matchmaking Overview 90
Figure 7-1
Table 7-1
Table 7-2
Table 7-3
Listing 7-1
Listing 7-2
Listing 7-3
Listing 7-4
Listing 7-5
Figure 10-1
Figure 10-2
Figure 10-3
Figure 10-4
Figure 10-5
Figure 10-6
Table 10-1
Table 10-2
Table 10-3
Table 10-4
Table 10-5
Table 10-6
Listing 10-1
Listing 10-2
Listing 10-3
Listing 10-4
Listing 10-5
Listing 10-6
Listing 10-7
Listing 10-8
Listing 10-9
Listing 10-10
Listing 10-11
Listing 10-12
Listing 10-13
10
People love to play games. Games on the App Store are no exceptiongames continue to be the most popular
category of apps on iOS. Games are inherently a social activity. Sometimes, this social interaction is part of the
game itself, such as when the game provides competitive or cooperative multiplayer gameplay. But even for
games intended for single-player experiences, players like to see and share their accomplishments.
Because social gaming is such an important part of the game-playing experience, Apple supports it directly
with the Game Center service. Game Center allows a players devices to connect to the Game Center service
and exchange information.
Each player performs different activities but all of them are interacting with Game Center:
Bob uses the Game Center app provided by Apple to view his scores earned in a game that supports Game
Center. The Game Center app shows both Bobs scores and scores earned by other players. Even though
the scores are displayed by the Game Center app, the score data and formatting are provided to Game
Center by the game.
Joe is playing an adventure game that supports achievements. He just discovered an item for a quest he
wants to complete. The game sends a message to Game Center to update the progress stored there.
11
Mary, Alice, and Charlie are playing a game that supports Game Centers matchmaking. Game Center allows
the three players devices to find and connect to each other. The game exchanges data between the
participants through Game Centers servers.
Sara plays another multiplayer game also using Game Centers matchmaking. Saras game supports
turn-based play and Sara has received a push notification that it is her turn to act.
At a Glance
Game Center is best viewed as a collection of interconnected components that provide features both to game
developers and to end users:
The Game Center service is the online portion of Game Center. The Game Center servers store player and
game data and vend the data and other services to Mac and iOS devices.
The Game Kit framework provides classes that developers use to add support for Game Center to their
games. Game Kit is available starting in iOS 4.1 and OS X v10.8.
The Game Center app provides a centralized app that players use to access Game Centers features.
For players to take advantage of Game Center in your gameand for your game to be visible in the Game
Center appyou must explicitly add support for Game Center to your game. You do this by implementing
authentication and then at least one other Game Center feature.
Some Game Resources Are Provided at Runtime by the Game Center Service
All apps include images and localized text inside of its bundle that are used to display the apps user interface.
The app loads these resources from the bundle as needed. When you design a Game Center-aware game,
some of the resources you create are not stored in the bundle. Instead, those resources are uploaded to the
Game Center service during development of your game. At runtime, your game downloads the resources from
Game Center. The main reason for storing these resources on Game Center is that those resources are also
used by the Game Center app. For example, when the Game Center app displays one of your games
leaderboards, it downloads the resources you provided so that it displays the score data the same way as your
game.
The requirement that some of your resources be provided to Game Center affects how you design, develop,
and test your game.
12
Relevant Chapter: Developing a Game Center-Aware Game (page 17), Testing Your Game
Center-Aware Game (page 151)
13
A real-time match requires all of the players to be connected to Game Center simultaneously. Game Kit
provides classes that implement the low-level networking infrastructure to allow the devices to exchange
data in real time.
14
A hosted match is similar to a real-time match, but involves your own server in the match. In this model,
you use Game Center to perform matchmaking but design and implement your own low-level networking
code.
A turn-based match uses a store-and-forward model. Your game stores a snapshot of the match data on
the Game Center servers where it can later be downloaded by any players in the match. At any given time,
one of the players is designated as the person who can take a turn in the match. Your game downloads
the match data, the player takes a turn, then your game uploads the modified match data to Game Center.
When a players turn ends, your game designates the next player to act and that player receives a push
notification.
Exchanges allow players who are not the current player to take actions within your game. A player
initiates an exchange by sending an exchange request to one or more other players. These players
are then able to respond to the exchange or let it time out. During the exchange, updates are also
sent to the current player so that match data can be updated.
Relevant Chapter: Matchmaking Overview (page 90), Real-Time Matches (page 100), Hosted
Matches (page 122), Turn-Based Matches (page 125)
15
Prerequisites
Before attempting to create a Game Center-aware game, you should already be familiar with developing apps
on whichever platform you are targeting:
See Also
See Game Kit Framework Reference for details on the Game Kit framework.
The GKAuthentication sample demonstrates how to implement user authentication.
The GKLeaderboards sample demonstrates how to implement leaderboards.
The GKAchievements sample demonstrates how to implement achievements.
The following WWDC session videos also describe Game Center features:
16
Adding Game Center support requires more than simple coding changes. Game Center imposes specific
requirements on the design of your game. For example, to implement leaderboards, your game must have a
way to quantitatively measure a player's performance. But more than that, Game Center changes how you
design and test your game. You aren't simply adding code to your app; you are also configuring assets used
by Game Center. These assets are configured separately from your app bundle but are intimately tied to the
code in your game. You need to test these pieces to ensure that all of the pieces work correctly together.
To create a Game Center-aware game, you need to understand these basics before you begin writing code.
17
Figure 1-1 shows an example model for a games user interface, shown as a series of screens and transitions
between them. Not all games use this exact organization of user interface screens, but it provides a useful
starting point for a discussion of how adding Game Center might alter your games user interface.
Figure 1-1
When this sample game is launched, the first thing the player sees is a loading screen. Games often require
large, memory-intensive images, 3D models, sounds and game data. These resources must be accessed quickly
while the game is running. Often, to accomplish this, a game loads critical resources when first launched and
keeps them in memory until the app terminates. A typical loading screen displays information about the game
or your company, along with a progress bar or an animated user interface while the content loads.
After the game has loaded enough resources, it transitions to a menu screen. Typically, this is the first interactive
screen the player sees. The menu screen has a series of buttons that players use to launch the gameplay or
other features of the game. For example, any or all of the following functions are commonly accessed from
the menu screen:
18
Using the the screen flow shown in Figure 1-1, tapping the single-player Play button allows the user to choose
the color of their team and the type of transportation they will use in the game. The purpose of this screen is
to provide the player with options on how they want to play the game. Depending on the design of your game,
this configuration process could be a simple interface on a single screen or a complex series of user interface
screens. For example:
A puzzle game that allows the player to select a particular puzzle to play.
A role-playing game that has a series of screens that allow the player to configure a character.
The gameplay screen is where the bulk of your game logic executes. This part of your project includes rendering
code, user interface interactions, and game logic that executes your games concept. Depending on the type
of game you are implementing, your apps gameplay can be a single screen or a series of multiple screens with
transitions between them.
After the player completes a game, an epilogue screen appears to tell the player how they did. For example,
a game that includes a scoring mechanism can show the player how their score was calculated. Once the player
dismisses this screen, the game transitions back to the main menu.
19
Figure 1-2 shows the example game modified to incorporate Game Center.
Figure 1-2
Game Center-enabled UI
All Game Center apps must authenticate the player. The authentication typically begins as soon as the user
starts your game. In the sample game, the authentication process begins while the title screen is displayed. If
a player is not currently signed in to Game Center, the title screen is temporarily replaced with Game Centers
authentication screen. This screen stays up until the player completes the authentication process or cancels.
Either action returns the player to the title screen. If a player is already signed in to a Game Center account,
then the authentication screen is never displayed. Instead, a banner is briefly displayed to welcome the player
back without leaving the main menu.
The menu screen now includes buttons to display Game Center content. When the player presses one of these
buttons, the game allocates, initializes and presents one of Game Kits user interface classes. When dismissed,
control returns back to the title screen.
The game shown in Figure 1-2 has also been modified to provide a multiplayer game mode. As with single-player
mode, the game presents a series of screens to configure the game. Some of these screens are specific to the
game and are used to configure the games options. Other screens display the built-in matchmaking user
20
interface. Note that your own games configuration screens can appear both before and after the matchmaking
screen. The choices made before a matchmaking screen appears are usually choices that affect the matchmaking
experience. For example, the player can choose a specific map to play on, so that they can be matched with
players interested in the same map. The configuration screens that appear after matchmaking is complete are
used to allow the players, now connected into a match, to make other decisions about how the match is played.
Both sets of screens include match configuration data that must be synchronized to all players in the match.
Finally, a Game Center-aware game can be launched because the player received a push notification related
to Game Centerfor example, when the player has been invited to join a match. If your game was launched
as a result of a push notification, it can transition directly into a matchmaking screens immediately after the
authentication process completes. In this case the title screen appears only for a brief period of time.
While Figure 1-2 (page 20) focuses on new screens of content to display, the content on existing screens can
change too, or the tasks you perform on those screens can change. For example, at the end of the match, you
can have your game report the score it displays to a Game Center leaderboard. Similarly, during gameplay, as
a player makes progress towards an achievement, your game sends the updated progress to Game Center.
It is important that you remember that this is only one possible way to design your games user interface. You
should consider other alternatives when building your user interface, and choose one that makes the most
sense for your game. For example, many games use a customized graphics design with a consistent artistic
theme. In this case, the standard user interface classes of Game Center wont match your games theme. So,
one question you must ask is whether you want to use the standard user interface (which takes little effort to
add) or whether you want to incorporate your own custom user interface. If you decide to create a custom
user interface, you should further decide whether to create that user interface as distinct screens of content
or incorporate the content into existing interfaces, such as your games menu screen.
Feature
Requirements
Limitations
Assets
Leaderboard
Scoring mechanism
Maximum number of
leaderboards, formatting options
for leaderboard scores
Strings,
leaderboard
sorting, artwork
21
Feature
Requirements
Limitations
Assets
Leaderboard
Sets
A leaderboard
Maximum number of
leaderboards and sets allowed.
All apps in a group must either
have sets or not have sets.
Strings,
leaderboard
grouping, artwork
Achievement
Maximum number of
achievements per game,
maximum point allocation.
Strings, artwork
Challenges
Matchmaking
Multiplayer game
design
Custom invitation
sound
22
You develop and test your app on your own development machine. App resources are embedded in the
app bundle you create using Xcode. The process of building your app includes these resources in the final
bundle, where they are loaded by your apps binary at runtime.
When your app is complete, you submit the app bundle for review by copying it to iTunes Connect. At
the same time, you create a record in iTunes Connect using the same bundle ID as the one in your app
bundle. This record includes metadata that describes the app; most of this data is used to describe your
app in the App Store. Once submitted, Apple reviews your app and it is either approved or denied.
After your app is approved, you choose when it is published. Once published, the app bundle and metadata
are copied from iTunes Connect to the App Store. There, users discover and purchase the app. Once
purchased, the app bundle is downloaded to the users device.
23
Figure 1-4 shows the additional steps required and the process when creating Game Center assets. Although
this step is not shown, your app bundle and metadata are submitted to iTunes Connect as before.
Figure 1-4
Originally, the iTunes Connect record was created at the end of the development process, when you were
ready to submit the app for review. When creating a Game Center-aware game, you create the iTunes
Connect record as soon as you are ready to implement and test your Game Center features. The iTunes
Connect record is needed to authorize your game to access the Game Center service.
Assets you create in iTunes Connect are automatically copied to a special test environment provided by
Apple. This environment mimics the regular Game Center service but is private to developers. Development
builds of your game automatically load the assets from the test environment.
24
When your game is published, the Game Center assets are copied to the Game Center service in the same
way that your game is copied to the App Store. These builds of your game load the assets from the live
Game Center servers.
Once your assets are published to the live servers, some assets become more difficult to change because
they are already in use by players and live versions of your game. For example, leaderboard scores are
formatted using the leaderboard assets you created. If you changed your scoring mechanism and changed
your leaderboard assets to match, older scores would still be posted on Game Center and would be
inconsistent with newer scores. For this reason, some assets you create cannot be modified after a version
of your game that uses those assets ships. You should set up your development process to ensure that
your assets (and the related code) are extensively tested before you submit your game for review so that
changes to these assets are not necessary.
Game Groups
Game Groups are an additional feature in iTunes Connect that allow you to tie multiple Game Center-aware
games into a single connected group that shares some portion of your Game Center content. Each game in
the game group is a distinct game on iTunes Connect with its own record. However, some assets are shared.
The benefit of a game group is that you can ship multiple distinct versions of your game on the App Store but
still allow these games to act as if they are a single game online. For example:
Shared game assets. You create a common pool of leaderboards and achievement assets that are shared
by all versions of your game. If a player has both versions of your game, items earned in one version are
visible in the other.
Matchmaking compatibility. This allows you to specify which versions of your game can form matches.
You ensure that all games in a compatibility group share the same networking code. A matchmaking
group can even be formed between different versions of a game shipping with a single bundle ID. For
example, if you shipped four versions of your game (1.0, 1.1, 2.0, 3.0), you could specify that version 1.0
and version 1.1 of the game could play together, because nothing in version 1.1 changed the networking
implementation.
25
Game Groups impose additional process overhead on your game design. Now, instead of merely having to
deal with synchronization issues between your game code and the assets you create in iTunes Connect, you
now also need to synchronize any implementation changes between the different game implementations.
See Groups in iTunes Connect Developer Guide for information on how to create and manage game groups
in iTunes Connect.
2.
Define your game mechanics, keeping in mind the requirements and limitations of Game Center.
3.
Implement your game engine, ignoring Game Center for now. Focus on developing the other aspects of
your game, such as your game engine and gameplay. You do this to avoid needing to create an iTunes
Connect record earlier than you need to.
4.
Create an iTunes Connect record for your game, using the games bundle ID. Enable Game Center in
the iTunes Connect record; setting this flag in the iTunes Connect record authorizes the Game Center
service to allow your game to connect to it.
b.
c.
Enable Game Center in this app ID; this authorizes the app on the device to contact Game Centers
servers.
d.
Create a new provisioning profile using this new explicit app ID.
e.
Test to ensure you can build and sign your game using this profile.
f.
g.
5.
If your game requires Game Center, add the Game Center key to the list of capabilities your app requires
from the device. See Requiring Game Center in Your Game (iOS only) (page 27).
6.
If your game does not require Game Center, you should establish a weak link from your game to the Game
Kit framework. Then, when your game launches, test to make sure that Game Center is supported. See
Optionally Supporting Game Center in Your Game (page 27).
7.
Implement authentication.
8.
9.
Test your Game Center features using the Game Center development environment.
26
27
Game Center provides two distinct types of user interface elements for you to use in your game. The first type
is intended to be displayed modally by your game, covering your own games user interface and temporarily
interrupting the normal flow of your game. Typically these user interface screens allow a player to interact
with content loaded from Game Center or to perform Game Center tasks. When the player finishes interacting
with one of these screens of content, your game shows the next appropriate screen, either by returning to
one of your game screens or by advancing to another screenful of content.
In iOS, a fullscreen user interface is packaged as a view controller, and follows the standard conventions of
view controllers on the system. One of your games view controllers is expected to present these view controllers
when needed, and later respond when the view controller is dismissed. On OS X, a special class provided by
Game Kit provides a similar infrastructure so that your game can present the user interface. Other chapters in
this document show the iOS code for presenting a view controller; this chapter shows you how to use the
GKDialogController class to present one of these view controller on OS X.
The second type of user interface element is a banner that is displayed for a short time to the player. Afterwards,
the banner automatically disappears from the screen. While players can interact with some banners, usually
banners are simply used to display a message to the player. Game Center displays many banners on behalf of
your game, but you can also present your own banners to the player if your game has information you need
to display.
- (void) showGameCenter
28
{
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController
alloc] init];
if (gameCenterController != nil)
{
gameCenterController.gameCenterDelegate = self;
[self presentViewController: gameCenterController animated: YES
completion:nil];
}
}
Listing 2-2 shows a typical implementation of the delegate, which simply dismisses the presented view controller.
Listing 2-2
Responding when the player finishes viewing the Game Center content
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController
*)gameCenterViewController
{
[self dismissViewControllerAnimated:YES completion:nil];
}
In most cases, your game would pause gameplay or other real-time behavior when displaying one of these
standard user interface classes. When the view controller is later dismissed, it can resume these activities.
- (void) showGameCenter
{
29
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController
*)gameCenterViewController
{
GKDialogController *sdc = [GKDialogController sharedDialogController];
[sdc dismiss: self];
}
- (void) showBanner
{
NSString* title = [self generateTitle];
NSString* message = [self generateBannerMessage];
[GKNotificationBanner showBannerWithTitle: title message: message
completionHandler:^{
[self advanceToNextInterfaceScreen]
30
}];
}
31
Players are a critical part in any game that supports Game Center, because all Game Center features are related
to the players. As a game developer, you need to understand some of the infrastructure that Game Center
uses to support player accounts and how you implement it in your app. After reading this chapter, you will
understand how to manage player information in your game. In particular, youll learn:
How a player logs themselves into Game Center and how your game knows whether a player is logged
into a device it is running on
How to implement support in your game so that a player can invite other players to become friends on
Game Center
32
about a local players friends or allow the player to invite players to become friends. For example, you can use
this functionality to allow a player to send a friend invitation to a player they just met in a match played within
your game.
33
over other players. The local player is the player that is currently authenticated to play on that device. In Figure
3-1, two players are connected in a network match. On the left device, Bob is the local player and Mary is a
remote player. On the right device, Mary is the local player and Bob is a remote player.
Figure 3-1
Almost all classes in Game Kit that send data to or retrieve information from Game Center expect the device
to have an authenticated local player. The work those classes do is always on behalf of the local player. For
example, if your game reports scores to a leaderboard, it can only report a score earned by the local player. As
such, before using any Game Center features, your game must first authenticate that there is a local player on
the device. Game Kit returns an error to your game if it attempts to perform Game Center-related tasks that
require an authenticated player when one isnt available on the device.
Important: Games that support multitasking should take special note of this behavior. When your game
moves into the background, the player may launch the Game Center app and sign out. Also, another player
might sign in before control is returned to your app. Whenever your game moves to the foreground, it may
need to disable its Game Center features when there is no longer an authenticated player or it may need
to refresh its internal state based on the identity of the new local player.
34
Table 3-1
Property
Description
playerID
A string that holds the player identifier string used to retrieve this player information.
displayName
A user-readable string you can display for this player in your own user interface. For
example, in a network match, you might show the display names for each player in
the match so that everyone knows who they are playing against.
isFriend
A Boolean value that states whether the player is a friend of the local player. Note
that this property reflects the general design of Game Center; all information returned
to your game is based on the local player that is signed in to the device.
The GKLocalPlayer class is a special subclass of the GKPlayer class, and includes additional properties
specific to the local player:
The friends property is populated with the identifier strings for other players on Game Center that are
marked as the local players friends.
Table 3-2
Property
Description
friends
An array of player identifiers for the players who are friends of the local player. This
property is populated only after your game specifically requests a list of identifiers for
the local players friends from Game Center.
underage
A Boolean value that states whether the local player is underage. Some Game Center
features are disabled when the value of this property is YES; Game Center returns a
GKErrorUnderage error if you try to use those features. Your game can also use this
property to decide whether it should disable some of its own features for an underage
player.
In addition to the display name for a given player, if the player has provided a photo, you can download that
players photo to your game and use it in your games user interface.
35
36
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError
*error){
if (viewController != nil)
{
//showAuthenticationDialogWhenReasonable: is an example method name.
Create your own method that displays an authentication view when appropriate for
your app.
[self showAuthenticationDialogWhenReasonable: viewController];
}
else if (localPlayer.isAuthenticated)
{
//authenticatedPlayer: is an example method name. Create your own
method that is called after the loacal player is authenticated.
[self authenticatedPlayer: localPlayer];
}
else
{
[self disableGameCenter];
}
}];
}
The authentication handler shows the distinct conditions your code needs to handle:
37
If the device does not have an authenticated player, Game Kit passes a view controller to your authentication
handler. When presented by your game, this view controller displays the authentication user interface.
Soon after, your game should pause other activities that require user interaction and present this view
controller. Game Kit dismisses this view controller automatically when complete, and calls your
authentication handler again.
If the authentication process succeeded, the viewController parameter passed into your authentication
handler holds nil. The local player objects authenticated property holds YES and its other properties
are set to match those of the connected player. Your game should complete the authentication process.
If the authentication process failed, the viewController parameter passed into your authentication
handler holds nil. The local player objects authenticated property holds NO and its other properties
are cleared. Your game should disable all Game Center features.
Always check the authenticated property on the local player object to determine whether Game Kit was
able to authenticate a local player. Do not rely on the error received by your game to determine whether an
authenticated player is available on the device. Even when an error is returned to your game, Game Kit may
have sufficient cached information to provide an authenticated player to your game. Also, it is not necessary
for your game to display errors to the player when authentication fails; Game Kit already displays important
errors to the player on your behalf. Most authentication errors are returned to your game primarily to assist
you with debugging.
- (void) authenticateLocalPlayer
{
38
Your game should always check the authenticated property on the local player object to determine whether
Game Kit was able to authenticate the player. Do not rely on the error received by your game to determine
whether an authenticated player is available on the device. Even when an error is returned to your game, Game
Kit may have sufficient cached information to provide an authenticated player to your game. Also, it is not
necessary for your game to display errors to the player when authentication fails; Game Kit already displays
important errors to the player on your behalf. Most authentication errors are returned to your game primarily
to assist you in debugging it.
Receiving a GKErrorGameUnrecognized error means that you have not enabled Game Center for your
app in iTunes Connect. Sign in to your iTunes Connect account and verify that your app has Game Center
enabled. Also, confirm that the bundle identifier in your Xcode project matches the bundle identifier you
assigned to your app in iTunes Connect.
Receiving a GKErrorNotSupported error means that the device your game is running on does not
support Game Center. You should disable all Game Center related features.
Enable Other Game Center Code Immediately After a Player Is Successfully Authenticated
Once the player has been successfully authenticated, your game can read other properties on the local player
object to determine the players display name and other attributes. You can also use other classes that access
Game Center. In most cases, your game should immediately enable other code related to Game Center. For
example, here are some common tasks that most games perform after successfully authenticating the local
player:
Read the displayName property to retrieve the local players name. Use this display name throughout
your game when you want to refer to the player; do not prompt the player separately for their name.
39
Add event handlers to receive events for Game Center features. For example, turn-based matches, real-time
matches and challenges all require event handlers to process Game Center events. Because your game
may have been launched specifically to receive a pending invitation; adding event handlers immediately
after authenticating the player allows those events to be processed promptly.
Retrieve the local players previous progress on achievements. See Listing 5-4 (page 74).
Retrieve a list of player identifiers for the local players friends. This is a first step before loading more
detailed information about those players. See Retrieving the Local Players Friends (page 41).
If your game stores its own custom information for a particular player (such as state variables indicating
the players progress through your game), your completion handler might also load this data so that it
can restore the players progress.
Like other multitasking apps, your game should archive its state before moving into the background.
As soon as your game moves to the background, the value of the local player objects authenticated
property becomes and remains invalid until your game moves back to the foreground. You cannot read
the value to determine if the player is still authenticated until Game Kit reauthenticates the player and
calls your authentication handler. Your game must act as though there is not an authenticated player until
your completion handler is called. Once your handler is called, value stored in the authenticated property
is valid again.
If the value of the authenticated property changed to NO, then there is no longer a local player authorized
to access Game Center content. Your game must dispose of any Game Kit objects that were created using
the previous local player.
If the value of the authenticated property is YES, then there is a local player authenticated on the
device. However, a new player may have logged in. Your game should store the player identifier for the
local player after it authenticates the player. Then, on future calls to your completion handler, compare
the value of the local player objects playerID property to the identifier stored by your game. If the
identifier changed, then a new player has signed in. Your game should dispose of any objects associated
with the previous player and then create or load the appropriate state for the new local player.
40
- (void) retrieveFriends
{
GKLocalPlayer *lp = [GKLocalPlayer localPlayer];
if (lp.authenticated)
{
[lp loadFriendsWithCompletionHandler:^(NSArray *friendIDs, NSError *error)
{
if (friendIDs != nil)
{
[self loadPlayerData: friendIDs];
}
}];
}
}
Listing 3-4
- (void) retrieveFriends
{
GKLocalPlayer *lp = [GKLocalPlayer localPlayer];
if (lp.authenticated)
41
{
[lp loadFriendsWithCompletionHandler:^(NSArray *friends, NSError *error) {
if (friends != nil)
{
[self loadPlayerData: friends];
}
}];
}
}
42
If Game Kit was unable to load information for all of the players, it provides an error to the completion handler.
When this occurs, the players parameter may provide a partial array for the players that Game Kit was able
to obtain information about. For this reason, Listing 3-5 tests the error condition separately from processing
the array of player objects.
43
Listing 3-7 shows one way your view controller can allow a player to send a request to other players. For this
method, an array of player identifiers is passed in as a parameter. The method instantiates a
GKFriendRequestComposeViewController object, sets its delegate, and adds the list of players intended
to receive the invitation. The view controller then presents the friend request and returns.
Listing 3-7
(void)friendRequestComposeViewControllerDidFinish:(GKFriendRequestComposeViewController
*)viewController
{
[self dismissViewControllerAnimated:YES completion:nil];
}
44
Many games offer scoring systems that measure how well a player does in the game. Scores are not just a way
for players to measure their own progress; they also provide a way for players to compare their skills with those
of other players. In Game Center, a leaderboard is a database of score data. Your game posts scores to a
leaderboard so that the player can later view those scores.
When you add leaderboards to your game, you define what a score means in your game and how score data
is formatted for display.
Before you add leaderboards, add code to authenticate the local player. See Working with Players in
Game Center (page 32).
2.
Decide how you want to use leaderboards in your game. You choose how many leaderboards to use and
how each leaderboard interprets its score data. You are free to design a different scoring mechanism for
each leaderboard. See Leaderboards Require a Scoring Mechanism (page 46).
3.
Go to iTunes Connect and configure the leaderboards for your game. For each leaderboard, you configure
the kind of score recorded and how the score is formatted for display. Leaderboard formatting can be
localized for different languages and regions. See Working with Leaderboards in iTunes Connect (page
48).
4.
Add code to report scores to Game Center. See Listing 4-3 (page 52).
5.
Add code to display a leaderboard to the local player. See Working with the Default Leaderboard (iOS
7) (page 53).
Optionally, you can retrieve score data from Game Center and use it to create your own custom leaderboard
user interface. See Retrieving Score Data (page 55).
45
You also decide the order in which scores are ranked. When scores are ranked low-to-high, a lower score is
considered a better scorefor example, a racing game that records the time it took to complete the race. In
this circumstance, a faster timethat is, a lower scoreis better, so a sorting order of low-to-high is appropriate.
In contrast, a game that adds points to the players total for each successful action taken in the game expects
that a higher score is better, so a high-to-low sorting order would be more appropriate.
Once you have the formatting type and sorting order chosen, you also customize the final results with a
localized formatting string. For example, if you chose to represent the score as an integer, you might choose
point and points as the English localization for singular and plural values of scores stored in that leaderboard.
Other games might use the same score type, but use different localized strings ( laps, cars).
When you design a scoring mechanism, make sure that you consider the range of possible (legal) score values.
When you create the leaderboard description, you can also provide minimum and maximum values for scores
reported to it. Providing a score range adds a layer of security onto your leaderboard, because it reduces the
likelihood that a player can cheat if they discover a way to report an absurdly high score.
46
A game with multiple levels of difficulty can have a different leaderboard for each level of difficulty.
A game with different maps (levels, tracks) can have a different leaderboard for each map.
A game with different play modes (rule sets) can have a different leaderboard for each play mode.
You might create multiple scoring mechanisms that evaluate the players skill in different ways, and create
a different leaderboard for each. For example, a racing game might evaluate the players best track time,
best lap time, as well as a score based how well the player drifts while driving around the track. Evaluating
players in different ways allows players to find multiple ways to improve their skills.
To allow leaderboards to be differentiated from each other in your game, you assign each leaderboard a
leaderboard ID, also known as a category. Your game uses a leaderboard ID to report the score to the
appropriate leaderboard. For example, if your game included three leaderboards for different levels of difficulty,
you might use myGame.easy, myGame.normal and myGame.hard as the leaderboard IDs.
47
Only noncombined leaderboards can be included in a combined leaderboard. That is, you cannot combine
other combined leaderboards into a combined leaderboard.
The noncombined leaderboards that are attached to a combined leaderboard must have the same score
format type and sort order. And, in practice, they should share the same scoring mechanism in your game.
Property
Description
Leaderboard
Reference Name
An internal name for your leaderboard, used only in iTunes Connect. This is the
name that you use to search for your leaderboard in iTunes Connect.
Leaderboard ID
48
Property
Description
Choose the type of format in which you want scores to be expressed in the
leaderboardfor example, integer, elapsed time, or money.
Sort Order
Choose between Low to High or High to Low for the display of your
leaderboard scores. Choose Low to High if you want lowest scores displayed
first. Choose High to Low if you want highest scores displayed first.
Score Range
Define the score range using 64-bit signed integers. The values must be between
the long min (-2^63) and long max (2^63 - 1). Any scores outside of this range
will be deleted. Score range values are optional, but if they are added then both
values must be set and they must not be equal. When first adding a score range,
or when changing it in the future to a smaller range that will restrict data, all
data outside of the range will be lost and cant be recovered.
Table 4-2
Property
Description
Language
Name
The name of the leaderboard that appears in the standard leaderboard user
interface.
Score Format
This property determines how your scores are displayed when the leaderboard
is displayed in the specified language. For example, if your leaderboard stores
a score as money, you may want to specify different types of money based on
the language you select. The permitted values for this property are based on
your Score Format Type.
This suffix is added to the end of scores displayed in the singular form. This suffix
is optional, but is useful for clarifying the type of score stored in the leaderboard.
Examples include point, and hit.
This suffix is added to the end of scores displayed in the plural form. This suffix
is optional, and is useful for clarifying the type of score stored in the leaderboard.
Examples include points, coins, and hits.
Image
For more information on setting up your leaderboards in iTunes Connect, see Game Center.
49
Class Name
Class Function
GKScore
A GKScore object holds information for a score that was earned by the
player. Your game creates GKScore objects to post scores to a leaderboard
on Game Center. When a game retrieves score information from a
leaderboard those scores are returned as GKScore objects.
GKLeaderboard
GKGameCenterViewController
GKLeaderboardViewController
The following sections describe common tasks and how to implement them.
- (void) loadLeaderboardInfo
{
[GKLeaderboard loadLeaderboardsWithCompletionHandler:^(NSArray *leaderboards,
NSError *error) {
self.leaderboards = leaderboards;
}];
50
Table 4-4 lists the properties that you typically access on a leaderboard object.
Table 4-4
Property
Description
category
identifier
title
groupIdentifier
Holds the group identifier for when your game shares the leaderboard with
other games in a game group.
51
}];
}
The score object is initialized with the leaderboard ID for the leaderboard it reports its score to and then the
method sets the value property to the score the player earned. The leaderboard ID must be the identifier for
a leaderboard you configured in iTunes Connect. The player who earned the score and the time the score was
earned are set automatically when the score object was created. Scores are always reported for the local player.
Your game should create the score object and report the score to Game Center immediately after the score is
earned. This sets the date and time accurately and ensures that the score is reported correctly. If for some
reason the score could not be reported because of a network error, Game Kit automatically resends the data
when the network becomes available.
Store your games preferences and saved games in a secure format, rather than in clear text. If your games
data is stored in clear text, a player can download the saved game data using iTunes, modify it, and resync
it back to the device. This may allow the player to achieve a higher score than you intended.
52
scoreReporter.context = 0;
The most common time to update the default leaderboard is when you report a score, and Game Kit provides
a convenient way to set the default leaderboard as you report the score. Create the score object, and then set
its shouldSetDefaultLeaderboard property to YES. When the score is reported, the score objects category
becomes the new default leaderboard ID.
Listing 4-5
However, you can also use the GKLocalPlayer object to update the default leaderboard directly.
53
Listing 4-6
Changing the leaderboard in iOS 6 is accomplished by changing the category identifier for the leaderboard.
Listing 4-8 provides an example of how to do this using the
setDefaultLeaderboardCategoryID:completionHandler: method.
Listing 4-8
54
leaderboard page, displaying only scores earned in the last day. The view controller is then presented. In OS
X, you use the GKDialogController class to display the view controller, as described in Displaying Game
Center User Interface Elements (page 28).
Listing 4-9
When the player finishes looking at the leaderboard, the delegate is called. Listing 4-10 shows a typical
implementation, which simply dismisses the presented view controller.
Listing 4-10 Responding when the player dismisses the Game Center content
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController
*)gameCenterViewController
{
[self dismissViewControllerAnimated:YES completion:nil];
}
55
Table 4-5
Property
Effect
playerScope
You can choose whether to restrict the search to the local players friends or to find
scores from any player. Optionally, you can also initialize a leaderboard object to
search for scores for a specific group of players that you supply.
timeScope
You can choose to filter based on when the score was earned.
category
You can choose to filter based on which leaderboard the score is displayed in.
NOTE: Deprecated in iOS 7. Use identifier instead.
identifier
You can choose to filter based on which leaderboard the score is displayed in. For
iOS 7.
range
You can pick scores within a specific range. For example, the range [1,10] returns
the best ten scores found by the query.
Retrieving a subset of leaderboard data stored on Game Center has the following steps:
1.
2.
Discard any scores that do not match the playerScope, timeScope and identifier properties.
Use the category property when supporting games developed for iOS 6 and earlier.
3.
4.
5.
56
Figure 4-1 shows an example of one possible search. The code that performs this search is provided later in
Listing 4-11 (page 58). In this example, scores more than a day old are ignored. Then, from the remaining set
of scores, we see that Bob has two scores, so only his best score is kept. Finally, the scores are sorted and
ranked. The selected range is then returned to the game.
Figure 4-1
57
If you provide a category that matches a combined leaderboard, all of the scores in the single leaderboards
are pooled together before filtering and sorting occurs. Figure 4-2 shows the same scores as in the earlier
example, but now you can see that the scores are actually stored in two different leaderboards that make up
a combined leaderboard.
Figure 4-2
Listing 4-11 shows an example leaderboard data query. The method for this query initializes a new leaderboard
object and configures the playerScope, timeScope, and range properties to grab the top ten scores earned
today.
Listing 4-11 Retrieving the top ten scores
- (void) retrieveTopTenScores
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeToday;
leaderboardRequest.identifier = @"Combined.LandMaps"
leaderboardRequest.range = NSMakeRange(1,10);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores,
NSError *error) {
if (error != nil)
58
{
// Handle the error.
}
if (scores != nil)
{
// Process the score information.
}
}];
}
}
Your game can create a leaderboard request that retrieves scores for a specific list of players you are interested
in. Listing 4-12 provides an array of player identifiers to the query. When you provide a list of players, the
playerScope property is ignored.
Listing 4-12 Retrieving the top scores for players in a match
- (void) receiveMatchBestScores: (GKMatch*) match
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] initWithPlayerIDs:
match.playerIDs];
leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardRequest.identifier = @"Combined.LandMaps"
leaderboardRequest.range = NSMakeRange(1,10);
if (query != nil)
{
[query loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error)
{
if (error != nil)
{
// Handle the error.
}
if (scores != nil)
{
// Process the score information.
}
59
}];
}
}
Note: Use leaderboardRequest.category when maintaining games that support iOS 6 and
earlier.
In either case, the returned GKScore objects provide the data your game needs to create a custom user
interface. Your game can use the score objects playerID to load the players alias, as described in Retrieving
Information About Players (page 42). The formattedValue property provides a string with the score value
formatted according to the parameters you provided in iTunes Connect.
Important: You may be tempted to write your own formatting code rather than using the formattedValue
property. Do not do this. Using the built-in support makes it easy to localize the score value into other
languages, and provides a string that is consistent with the presentation of your scores in the Game Center
app.
To maintain an optimal user experience, only query the leaderboard for data your game needs to use or display.
For example, do not attempt to retrieve all the scores stored in the leaderboard at once. Instead, grab smaller
portions of the leaderboard and update your views as necessary.
You can use the context property to store flags that provide additional content. For example, in a racing
game, use the flags to store what kind of car the person completed the racetrack with. Then, in your own
custom leaderboard user interface, you could display the appropriate car image next to each score.
Record the users actions and other data in to a file. You then design your game engine to be able to replay
the contents of that file. You store the file on your own server and use the context field as an index to
reference the file. Your custom leaderboard user interface can then offer the ability to see exactly how
someone earned the score.
60
You can implement the replay directly into your gameplay. For example, in the hypothetical racing game,
you could use a players replay file to display a phantom car for the current player to race against.
Leaderboard Sets
Leaderboard sets offer developers the ability to combine several leaderboards into a single group. iOS developers
are able to create leaderboard sets starting with iOS 7. Leaderboard sets are not supported in OS X v10.9.
The following example shows why you would want to incorporate leaderboard sets in your game.
The created game has several different worlds with each world containing several leaderboardsfor
example, a leaderboard for most coins collected, highest score obtained, and most enemies captured.
The developer combines the different leaderboards into a single leaderboard set for each world.
Users can see a displayed list of world leaderboard sets. Opening a set shows the leaderboards contained
in the set.
61
Important: After you decide to use leaderboard sets, every leaderboard must be placed into a leaderboard
set. You can not have a leaderboard outside of a leaderboard set in games that support leaderboard sets.
Figure 4-3 shows the leaderboards for each world combined into a leaderboard set.
Figure 4-3
Before you add achievements, add code to authenticate the local player. See Working with Players in
Game Center (page 32).
2.
Ensure that your game contains at least one leaderboard. See Adding Leaderboard Support to Your
Game (page 50) for information on creating leaderboards.
3.
Go to iTunes Connect and configure leaderboard sets for your game. For each leaderboard set, add the
desired leaderboards to the leaderboard set. See Working with Leaderboard Sets in iTunes Connect (page
63).
4.
Add code to load the leaderboard sets associated with the current game. See Loading Leaderboard Sets
to Your Game (page 64).
62
5.
Add code to load the leaderboards contained within a leaderboard set. See Loading Leaderboards Within
a Set (page 65).
A game with multiple scoring mechanisms for each world (score, enemies captured, coins collected) can
combine the leaderboards for each world into a leaderboard set.
A game with multiple scoring mechanisms for each world (score, enemies captured, coins collected) can
combine all of the leaderboards for a single scoring mechanism into a leaderboard set.
A game with multiple playable characters (warrior, archer) can combine all of the leaderboards for a
particular character into a single leaderboard set.
You can combine the number of leaderboards and leaderboard sets in any format as long as the individual
maximums are not exceeded. The following are all allowable combinations:
3 leaderboards sets, each containing 50 leaderboards; 2 leaderboard sets, each containing 100 leaderboards;
1 leaderboard set containing 1 leaderboard
63
Class Name
Class Function
GKScore
A GKScore object holds information for a score that was earned by the
player. Your game creates GKScore objects to post scores to a leaderboard
on Game Center. When a game retrieves score information from a
leaderboard those scores are returned as GKScore objects.
GKLeaderboard
GKLeaderboardSet
GKGameCenterViewController
GKLeaderboardViewController
Before you can load the leaderboards contained within a set, you must load the set itself. Retrieve the list of
leaderboard sets for your game from Game Center and display their titles.
64
[GKLeaderboardSet loadLeaderboardSetsWithCompletionHandler:^(NSArray
*leaderboardSets, NSError *error) {
self.leaderboardSets = leaderboardSets;
}];
}
65
Achievements
Achievements are a great way to track what a player has done in your game and to give the player more
incentive to keep playing your game. An achievement represents a quantitative goal that the player can
accomplish in your game. As the local player plays your game, they make progress towards completing the
achievement. When the player meets or exceeds the goal, the achievement is considered earned, and the
player is rewarded. Your game defines the goal and the game mechanics that describe how a player earns the
achievement. In practice, Game Center does not need to know anything about your game design; it only knows
what progress the player has made towards an achievement.
In Game Center, an achievement earns a player achievement points. When you define an achievement, you
decide how many points it is worth. A player can see the total number of points that can potentially be earned
in your game as well as how many points he or she has currently earned. The Game Center app allows players
to compare their achievements with those of friends; this comparison screen includes the total points earned.
When you add an achievement to your game, you configure how the achievement is granted and how it is
described to the player. You also design the game mechanics that allow the player to make progress towards
completing the achievement.
Before you add achievements, add code to authenticate the local player. See Working with Players in
Game Center (page 32).
2.
3.
Go to iTunes Connect and configure the achievements for your game. You provide all of the data needed
to display achievements to the player. See Configuring Achievements in iTunes Connect (page 69).
4.
Add code to report the local players progress to Game Center. By storing the progress on Game Center,
you also make the players progress visible in the Game Center app. See Reporting Achievement Progress
to Game Center (page 71).
5.
Add code to load the local players previous progress on achievements from Game Center. The local players
progress should be loaded shortly after the player is successfully authenticated. See Loading Achievement
Progress (page 74).
66
Achievements
Designing an Achievement
6.
Add code to display the players progress towards achievements. See Displaying the Standard Achievement
User Interface (page 78) to see how your game can display the standard achievements screen.
Optionally, you can retrieve achievement data from Game Center and use it to create your own custom
achievement user interface. See Creating a Custom Achievement User Interface (page 79).
Designing an Achievement
The design of an achievement starts with a simple statement of the achievements goal. Here are some example
goals that can define a game:
Capture 10 pirates.
Defeat 1 boss.
A goal statement describes a triggering condition (Earn first place on a different race track) and a quantity
(5). The triggering condition is essential as it defines something your game logic needs to track. In the racing
example, your game must check the victory conditions at the end of each race, but it also needs to record
which race tracks a player has defeated.
The quantity usually defines how granular the task is for the player. With some achievements, quantity is
irrelevant; the achievement is either earned or not. For example, Defeat the end-game boss is not a goal that
the player generally earns partial credit towards completing. In contrast, a goal of Capture 10 pirates is a
more granular task. Your game needs to track the number of pirates captured and use this count to report
progress to Game Center.
When you design an achievement, consider a few other characteristics: value, visibility, and repeatability. These
characteristics affect more than the design of your game; later, when you define your achievement in iTunes
Connect, youll set attributes based on these characteristics:
The value of an achievement is a measure of how difficult you believe it will be for a player to earn the
achievement. Some achievements are easily earned in a few minutes of play. Difficult achievements might
require hours of focused gameplay or require the player to develop advanced playing skills or strategies
to earn the achievement.
The visibility of an achievement determines whether a player can see the achievement at the start of play
or whether the achievement must be discovered during play. By default, achievements are visible to the
player. This is helpful, because a player can scan the list of available achievements and see what actions
earn rewards. However, some achievements can be more useful if hidden. For example, if your game
67
Achievements
Designing an Achievement
includes a story or plot, listing all of the achievements at the start of play may reveal too much of the story
to the player. Achievements critical to the story can be marked as hidden so that you can choose when
the player sees them.
An achievement is normally not repeatable. After the achievement is earned, the player sees no further
messages about that achievement. If an achievement is marked as repeatable, then each time your game
reports that the player has completed the achievement, the player sees the appropriate reward banner.
You have a lot of room to be creative with the kinds of achievements you create. Here are some common
strategies for designing achievements that can guide you through the process.
Create Achievements That Show the Different Things Players Can Do in Your
Game
When experienced players purchase new games, they examine the list of achievements to see whats possible
in those games. Your list of achievements should strongly communicate what you want players to think about
or do while playing your game. You want achievements to provide a variety of different goals a player can
strive towards. When you provide a variety of goals and achievements, players continue to play your game.
Distinct sets of game rules or rule variants (capture the flag, survival)
A game with an underlying story separated into distinct acts or story arcs
68
Achievements
Configuring Achievements in iTunes Connect
If your game does partition its gameplay into smaller mini-games, define achievements for each, because it
encourages players to try each of the game modes or to complete your game.
You can flip the convention from an achievement being something the player tries hard to earn into
something more ignoble, earned when they fail spectacularly. The achievement then represents a way to
inject humor into the situation. For example, an achievement called Hot Foot that might appear after the
player has fallen into lava 20 times.
Avoid spending all of your budget on the initial version of your game. Save some of your budget to support
updates and new content.
69
Achievements
Configuring Achievements in iTunes Connect
Table 5-1
Achievement properties
Property
Description
Achievement Reference
Name
An internal name that you must provide for each achievement, used only
in iTunes Connect. This is the name you will use if you search for the
achievement in iTunes Connect.
Achievement ID
Point Value
Hidden
Indicates whether the user can earn the achievement multiple times.
Table 5-2
Property
Description
Language
Title
The localized title of this achievement as you would like it to appear in Game
Center.
Pre-earned Description
Earned Description
Image
For more information on setting up your leaderboards in iTunes Connect, see Game Center.
70
Achievements
Adding Achievement Support to Your Game
Class Name
Description
GKAchievement
GKAchievementDescription
Holds the localized text and images for an achievement. The data for
achievement descriptions is retrieved from Game Center at runtime and
is based on the data you provided to iTunes Connect when you created
your achievement there.
GKGameCenterViewController
GKAchievementViewController
The Game Center app can display the players progress towards the achievement.
If a player has multiple devices, your game on another device can retrieve the players progress towards
achievements.
Your game reports the players progress by using a floating-point percentage, from 0.0 to 100.0, that represents
how much of the achievement the player has completed. You decide how that percentage is calculated and
when it changes. For example, if the player earns an achievement simply for discovering a location in your
game, then you would simply report the achievement as 100 percent complete the first time you report progress
to Game Center. On the other hand, for an achievement like Capture 10 pirates, your reporting mechanism
increments by 10 percent each time the player captures a pirate.
When you report progress to Game Center, two things happen:
71
Achievements
Adding Achievement Support to Your Game
If the achievement was previously hidden, it is revealed to the player. The achievement is revealed even
if your player has made no actual progress on the achievement (a percentage of 0.0).
If the reported value is higher than the previous value reported for the achievement, the value on Game
Center is updated to the new value. Players never lose progress on achievements.
When the progress reaches 100 percent, the achievement is marked as completed, and both the image and
completed description appear when the player views the achievements screen.
Listing 5-1 shows how to report progress to Game Center. First, a new achievement object is initialized using
an identifier string for an achievement. Next, the objects percentComplete property is set to reflect the
players progress. Finally, the objects reportAchievementWithCompletionHandler: method is called,
passing in a block to be notified when the report is sent.
Listing 5-1
In iOS 7, you can report achievements for other players when ending a turn-based match. Only the current
player is able to report achievements.
72
Achievements
Adding Achievement Support to Your Game
Listing 5-2
- (void) completeMultipleAchievements
{
GKAchievement *achievement1 = [[GKAchievement alloc] initWithIdentifier:
@"DefeatedFinalBoss"];
GKAchievement *achievement2 = [[GKAchievement alloc] initWithIdentifier:
@"FinishedTheGame"];
GKAchievement *achievement3 = [[GKAchievement alloc] initWithIdentifier:
@"PlayerIsAwesome"];
achievement1.percentComplete = 100.0;
achievement2.percentComplete = 100.0;
achievement3.percentComplete = 100.0;
73
Achievements
Adding Achievement Support to Your Game
Whether reporting progress on a single achievement or on multiple achievements at once, your game rarely
needs to do anything specific when an error occurs. If an error occurs, such as when a network is not available,
Game Kit automatically resends the data at an appropriate time.
- (void) loadAchievements
{
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements,
NSError *error) {
if (error != nil)
{
// Handle the error.
}
if (achievements != nil)
{
74
Achievements
Adding Achievement Support to Your Game
A logical time to load the local players progress is immediately after the player is authenticated.
As the player progresses through your game, you want to update their progress on Game Center. If your game
has previously reported progress towards this achievement, your game should first load the players progress
from Game Center so that you know what progress the player has already made. If the player has made progress
on an achievement that the player has never made progress on before, your game should create a new
achievement object. An easy way to manage these achievement objects in your game is by using a mutable
dictionary, using the identifier property as a dictionary key, and the achievement object as the contents
for that key. Heres how to modify Listing 5-1 (page 72) and Listing 5-4 (page 74) to use a dictionary:
1.
Add a mutable dictionary property to your class that reports achievements; this dictionary stores the
collection of achievement objects.
@property(nonatomic, retain) NSMutableDictionary *achievementsDictionary;
2.
3.
When your game loads achievement data, add the achievement objects to the dictionary.
- (void) loadAchievements
{
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray
*achievements, NSError *error)
{
if (error == nil)
{
for (GKAchievement* achievement in achievements)
[achievementsDictionary setObject: achievement forKey:
achievement.identifier];
}
}];
75
Achievements
Adding Achievement Support to Your Game
4.
Implement a method that tests the dictionary for a particular achievement identifier. If the identifier does
not exist as a key in the dictionary, create a new achievement object and add it to the dictionary.
- (GKAchievement*) getAchievementForIdentifier: (NSString*) identifier
{
GKAchievement *achievement = [achievementsDictionary
objectForKey:identifier];
if (achievement == nil)
{
achievement = [[GKAchievement alloc]
initWithIdentifier:identifier];
[achievementsDictionary setObject:achievement
forKey:achievement.identifier];
}
return achievement;
}
5.
Modify the code in Listing 5-1 (page 72) to call getAchievementForIdentifier: to retrieve the
achievement object.
- (void) reportAchievementIdentifier: (NSString*) identifier
percentComplete: (float) percent
{
GKAchievement *achievement = [self
getAchievementForIdentifier:identifier];
if (achievement)
{
achievement.percentComplete = percent;
[achievement reportAchievementWithCompletionHandler:^(NSError
*error)
{
if (error != nil)
{
// Log the error.
}
76
Achievements
Adding Achievement Support to Your Game
}];
}
}
Report progress on an achievement as soon as the player makes progress. Dont delay reporting until a
later time; if a player earns an achievement, the banner should be displayed immediately.
Report progress only when the player has actually made further progress. Do not report changes to Game
Center if the player has not made progress, because it consumes network resources without actually
changing the state of the data on Game Center.
If the player makes progress on multiple achievements simultaneously, use the technique shown in Listing
5-3 (page 73) to report the progress. Using this class method is more efficient.
If your game displays a custom banner or indicator when a player earns an achievement, set the
showsCompletionBanner property to NO before reporting the achievement to Game Center.
- (void) resetAchievements
{
// Clear all locally saved achievement objects.
achievementsDictionary = [[NSMutableDictionary alloc] init];
// Clear all progress saved on Game Center.
[GKAchievement resetAchievementsWithCompletionHandler:^(NSError *error)
{
if (error != nil)
// handle the error.
77
Achievements
Adding Achievement Support to Your Game
}];
}
When your game resets a players progress on achievements, all progress information is lost. Hidden
achievements, if previously shown, are hidden again until your game reports progress on them. For example,
if the only reason those achievements were originally hidden was that they were associated with an In-App
Purchase, then you would reveal those achievements again.
When the player finishes looking at the leaderboard, the delegate is called. Listing 5-7 shows a typical
implementation, which simply dismisses the presented view controller.
78
Achievements
Adding Achievement Support to Your Game
Listing 5-7
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController
*)gameCenterViewController
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) retrieveAchievmentMetadata
{
[GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:
^(NSArray *descriptions, NSError *error) {
if (error != nil)
{
// Process the error.
}
if (descriptions != nil)
{
// use the achievement descriptions.
}
}];
}
79
Achievements
Adding Achievement Support to Your Game
Although the properties are self-explanatory, one critical property worth noting is the identifier property.
This corresponds to the achievement identifier used in iTunes Connect and on a GKAchievement object. When
you design your custom user interface, you use the identifier property to match each
GKAchievementDescription object to the corresponding GKAchievement object that records the players
progress on that achievement.
The value of the image property is nil until you tell the object to load its image data. Listing 5-9 shows how
your game tells an achievement description to load the image.
Listing 5-9
The GKAchievementDescription class also provides two default images your game can use. The
incompleteAchievementImage class method returns an image that should be used for any achievement
that has not been completed. If your game is unable to load an image for a completed achievement (or you
want to display an image while the custom image is loading), the placeholderCompletedAchievementImage
class method provides a generic image for a completed achievement.
80
Challenges
Achievements and leaderboards both allow players to measure their progress playing your game. But it is also
common for players to want to test their progress against each other. Its more satisfying to beat a friends
score than to merely achieve a decent score. Game Center embraces this idea in the form of challenges. Players
on Game Center can challenge other Game Center members to beat earned scores or achievements. Challenges
represent a different style of multiplayer experience where players compete against each other indirectly.
When a challenge is issued by one player to another, a push notification is sent to the challenged player. The
challenged player can then accept or refuse the challenge. If the player accepts the challenge, the challenge
is placed on a list of challenges associated with that player. Later, if the player beats the challenge, Game Center
notifies both the challenged player and the challenger that the challenge is complete.
Game Center supports two kinds of challenges:
A score challenge is issued based on a leaderboard score previously earned by the challenger. The challenge
is completed when the challenged player earns a better score. When the challenged player beats a score
challenge, Game Center automatically issues a new score challenge to the original challenger. Score
challenges continue to pass back and forth between the two players as they work to beat each others
scores.
An achievement challenge is issued from an achievement that the challenger has already completed.
The challenge is completed when the challenged player completes the achievement.
If your game supports achievements or leaderboards, it automatically supports challenges without requiring
any additional code. In this case, players go to the Game Center app to challenge their friends. However, you
can also customize your game to directly support challenges:
You can allow players to challenge other players from within your game.
You can retrieve the list of open challenges for the local player.
Your game can receive notifications when players tap banners for new challenges.
Your game can receive notifications when players receive or complete challenges. You can even prevent
challenge banners from being displayed when your game is running, allowing you to completely control
the user interface displayed when a challenge event is received by your game.
You can determine whether your game shows challenge banners inside of the game by adding
GKShowChallengeBanners to your Info.plist. See Cocoa Keys for details.
81
Challenges
Checklist for Supporting Challenges
First, add support for leaderboards or achievements to your game. See Leaderboards and Leaderboard
Sets (page 45) and Achievements (page 66).
Optionally, add code to allow a player to send challenges within your game. See Issuing Challenges from
Your Game (page 82)
Optionally, add code to receive and act on challenge notifications. See Receiving Information About
Existing Challenges (page 85) and Reacting to Challenge Events (page 87)
- (void) bossMonsterDefeated
{
GKAchievement *achievement = [[GKAchievement alloc]
initWithIdentifier:@"MyGame.bossDefeated"];
achievement.percentComplete = 100.0;
82
Challenges
Issuing Challenges from Your Game
achievement.showsCompletionBanner = NO;
Listing 6-3 shows the issuing controllers implementation of the delegate method. When the user dismisses
the challenge view controller, the delegate is called. The delegate method takes a parameter that states whether
the player issued a challenge. If the player issued a challenge, then the method retrieves the list of players and
the message from the challenge view controller and issues the challenge. Note that this design gives control
over issuing the challenge to the original view controller. If your design does not need this additional flexibility,
you could simply issue the challenge directly from the challenge view controller instead.
Listing 6-3
- (void) challengeViewController:(MyAchievementChallengeViewController*)controller
wasDismissedWithChallenge:(BOOL)issued
{
83
Challenges
Issuing Challenges from Your Game
Retrieving the list of players with lower scores than the one just earned
84
Challenges
Receiving Information About Existing Challenges
}];
}
Your challenge view controller can then use the score data to populate its user interface. For example, it can
use the player identifiers embedded in the score to load the name and photo of each challenged player. You
can perform a similar operation for achievement challenges using the
selectChallengeablePlayerIDs:withCompletionHandler: class method. Listing 6-5 shows a possible
implementation of this.
Listing 6-5
- (void) showChallengesList
85
Challenges
Receiving Information About Existing Challenges
{
[GKChallenge loadReceivedChallengesWithCompletionHandler:^(NSArray *challenges,
NSError *error) {
if (challenges)
[self presentChallengeList: challenges];
}];
}
Table 6-1 lists the most common properties used to populate your user interface.
Table 6-1
Property
Description
issuingPlayerID
receivingPlayerID
The player identifier for the player that received the challenge.
issueDate
completionDate
Each type of challenge is defined by a distinct subclass of GKChallenge. Table 6-2 lists the subclasses and
how to retrieve the remaining information needed to display the challenge to the player.
Table 6-2
Challenge subclasses
Subclass
Description
GKScoreChallenge
GKAchievementChallenge
86
Challenges
Reacting to Challenge Events
- (void) installChallengeHandler
{
GKChallengeEventHandler *eventHandler = [GKChallengeEventHandler
challengeEventHandler];
eventHandler.delegate = self;
}
In each of these situations, you can customize the behavior using a pair of methods. The methods for overriding
the behaviors are shown in Table 6-3. The first method in each pair allows you to choose whether a banner is
displayed at all. The second method in each pair allows you to handle the event yourself.
Table 6-3
Event
Presentation
shouldShowBannerForLocallyReceivedChallenge:
localPlayerDidReceiveChallenge:
87
Challenges
Reacting to Challenge Events
Event
Presentation
shouldShowBannerForLocallyCompletedChallenge:
localPlayerDidCompleteChallenge:
A remote player
completes a challenge
shouldShowBannerForRemotelyCompletedChallenge:
remotePlayerDidCompleteChallenge:
For example, if you wanted to completely customize the appearance when the local player completes a
challenge, first you would suppress the banner from being displayed, as shown in Listing 6-8:
Listing 6-8
- (BOOL)shouldShowBannerForLocallyCompletedChallenge:(GKChallenge *)challenge
{
return NO;
}
Then you implement a localPlayerDidCompleteChallenge: method to handle the challenge. Listing 6-9
shows a possible implementation of this method. First, it loads the player data for the player issuing the
challenge. In the completion handler for this first call, it then loads that players photo. Finally, when the photo
is loaded, it invokes its own method to display the loaded challenge data.
Listing 6-9
- (void)localPlayerDidCompleteChallenge:(GKChallenge *)challenge
{
NSString *issuerID = challenge.issueingPlayerID;
[GKPlayer loadPlayersForIdentifiers@[issuerID] withCompletionHandler:^(NSArray
*players, NSError *error) {
GKPlayer *player = [players lastObject];
// Load the challenging player's photo.
[player loadPhotoForSize: GKPhotoSizeNormal withCompletionHandler:^(UIImage
*photo, NSError *error) {
[self presentCompletedChallenge: challenge photo: photo
name:player.displayName];
88
Challenges
Reacting to Challenge Events
}];
}];
}
89
Matchmaking Overview
In Game Center, a match is formed when a group of players want to play a game together. Each player plays
the game on their own device, and the experience on each device is tailored to the player playing on that
device with the match as a whole representing a shared experience. To accomplish this, the instances of the
game share data with each other so that there is agreement about the state of the match.
Game Center matchmaking provides the infrastructure needed to allow players to find other players interested
in playing in a match. It allows players to invite specific playersalmost always a friendor to simply find
other players looking for a match in your game. Once those players have been discovered and formed into a
match, Game Center makes it easy for you to implement the networking code needed for your game. When
necessary, Game Kit routes network data through Game Centers servers so that all of the matchs participants
are connected to each other, regardless of where they are or what kind of network they are on.
Matchmaking on Game Center is a complex topic, as there are many kinds of matches you can create and
many ways to create them. This chapter provides an overview of the process. The chapters that follow provide
details on the specific kinds of matches that Game Center offers.
Match Type
Description
Real-time
All of the players are connected to Game Center simultaneously and for the duration
of the match. Game Kit provides all of the low-level networking support for a real-time
match in the GKMatch class. Your game implements its own logic to sit on top of this
networking infrastructure. Although intended for real-time games, it is usable for any
game that requires the players to be connected simultaneously.
90
Matchmaking Overview
Game Center Provides Multiple Ways to Connect Players into a Match
Match Type
Description
Turn-based
The state of the match is stored on Game Centers servers. It is transmitted to the
participants when needed. The participants of the match are not connected to each
other, and are connected to Game Center only when they want to read or write the
match data. When a player takes a turn, his instance of the game updates the match
data stored on Game Center. Game Kit provides support for this match type in the
GKTurnBasedMatch class.
Self-hosted
A networking implementation provided by your game and your own servers. When you
create a hosted match, Game Center helps you find players for your match
(matchmaking), but relies on your game to implement its own low-level networking
code. It is primarily intended for games that already have existing network
implementations.
Your game can present the standard matchmaking user interface. This interface allows players to invite
friends to the match or to allow the remaining empty slots to be filled by other players searching for a
match.
Your game can programmatically invite players or search for other waiting players. In this case, you are
responsible for implementing your own matchmaking user interface to give the player control over this
process. You typically use this approach when you want to add your own steps to the matchmaking process
or when you want the matchmaking user interface to fit with your games artistic style.
A player can use the Game Center app to create a match with another player.
A player can be invited to join a match even when a game is not launched on that players device. When a
player is sent an invitation, a push notification is sent to that players device. When the player accepts the
invitation, the game is launched immediately to handle the invitation. This behavior is important because it
increases the likelihood of players playing your game. In fact, a player can be invited to play in a match for a
game he or she does not own. In this case, the player is immediately offered an opportunity to purchase and
download your game.
91
Matchmaking Overview
Matchmaking and Gameplay Are Separate Tasks
For a real-time match, it is possible for a match to already exist even while you search for more players.
In this case, the match exists simultaneously with the matchmaking process, which means that match
participants can exchange data while additional players are discovered.
For a turn-based match, matchmaking does not need to be complete before a match starts. Instead,
whenever a new player is needed to continue the match, matchmaking automatically executes to fill that
position.
When you create a new version of a game (such as a bug fix), you can declare whether the new version is
compatible with the older versions (and which ones, specifically).
You can create distinct games (with different bundle identifiers) and still allow them to play against each
other.
You can create distinct games on both OS X and iOS and match them against each other.
Important: In each of these cases, all that iTunes Connect and Game Center provides is the ability to create
these larger matching groups across versions and products. Game Center itself does not provide any special
code to make your games compatible. When implementing your code, you are responsible for ensuring
that the network data exchanged between the participants can be interpreted properly by all of the devices
and versions of your game. For example, if you introduce a new version of your game with a different
network data format or a significant change in behavior, you need to ensure that players using this version
are not matched with players using incompatible game versions.
For more information on configuring multiplayer compatibility in iTunes, see Game Center.
92
Matchmaking Overview
Creating Any Kind of Match Starts with a Match Request
Property
Description
minPlayers
The minimum number of players to find for the match. This property must be
set on every match request. See A Match Request Must Specify the Number
of Players in the Match (page 94).
maxPlayers
The maximum number of players to find for the match. This property must
be set on every match request. See A Match Request Must Specify the Number
of Players in the Match (page 94).
defaultNumberOfPlayers
The default number of players to find for the match. This is used to configure
the default user interface to show the appropriate number of player slots.
However, the player can add or subtract slots so long as the number of players
stays between the minimum and maximum number of players, inclusive.
playersToInvite
An optional property that declares a list of player IDs for a set of players to
invite to the match. See Inviting a List of Players (page 95).
inviteMessage
If you are inviting a set of players to the match, you can provide a custom
string message that is displayed to those players. Typically, you provide the
player an opportunity to create this string in your custom user interface, then
use the string provided to populate your match request.
playerGroup
93
Matchmaking Overview
Creating Any Kind of Match Starts with a Match Request
Property
Description
playerAttributes
An optional property that allows you to specify a distinct role the player wants
to play in the match. Use player attributes to allow players to define what or
how they want to play your game. See Player Attributes (page 96).
The minimum number of players must be at least 2. The maximum number of players allowed varies depending
on the kind of match being created. Table 7-2 (page 93) lists the current maximum; this maximum is subject
to change.
Table 7-3
Match Type
Peer-to-Peer
Hosted
16
Turn-based
16
At runtime, your game calls the maxPlayersAllowedForMatchOfType: method to determine the exact
number of players allowed for each kind of match.
94
Matchmaking Overview
Creating Any Kind of Match Starts with a Match Request
The standard user interface allows a player to pick a specific slot in the match and invite a specific person
to fill it. Game Kit reserves places for invited players until they respond or the process times out.
If you are using the programmatic interface for creating a real-time match and you provide a list of players
to invite, Game Center attempts to add only those players into the match. It does not perform the normal
matchmaking process. However, if the match needs more players, your game can create another match
request that performs normal matchmaking. This separation of behaviors allows you to precisely control
when randomized matchmaking occurs.
In a turn-based match, the players are added to the match immediately, but a player is sent an invitation
to join the match only when it becomes that players turn.
Player Groups
Game Centers default behavior is to automatically match any player waiting to play your game into any match
that needs more players. This has the advantage of matching players quickly into matches, but it also means
that players can be added to matches that they are not interested in playing. In that case, you can allow the
players to define the kind of matches they want to play, and then match them only with like-minded players.
This is accomplished with a player group.
A player group is defined by an unsigned 32-bit integer. When you set the playerGroup property on a match
request to 0, then the player can be matched into any waiting match. When you set the playerGroup property
to a nonzero number, then the player is matched only with players whose match requests share the same
player group number. Typically, if your game uses player groups, it provides a custom interface that allows
the player to pick the precise options he or she is interested in. It takes the choices of the player and combines
them to form a player group number.
Here are some examples of how you can partition a list of players:
95
Matchmaking Overview
Creating Any Kind of Match Starts with a Match Request
Although it is up to you to determine exactly how many player groups you want to create, dont create groups
just to create them. Creating many smaller player groups can result in every player waiting for a long time to
play a match. Instead, create large groups that players can identify with.
Listing 7-2 shows how you might configure a match request that uses a player group. In this example, the
player group value is calculated by choosing both the map the player wants to play on and the rules set under
which the player wants to play. A constant for each is chosen and the two are bitwise ORed together to create
a unique number for the player group. Game Center only searches for other players with the same map and
group combination.
Listing 7-2
Player Attributes
A player attribute allows a player to pick the role he or she wants to play within a match. With player attributes,
each player can choose a specific role and Game Center finds a proper mix of players to ensure that all of the
roles are filled.
Here are some ways you can use player attributes in your game:
A game like chess can use player attributes to determine whether a player wants to be the black or white
pieces.
A role-playing game can offer different character roles with distinct strengths, weaknesses, and abilities
that player brings to the match.
A sports game can use player attributes to allow players to specify positions, such as pitcher or quarterback,
on the team.
A turn-based match can assign different locations on the map to distinct factions and use attributes to
ensure that each location is filled.
Roles are checked only for auto-matched players. If the player invites friends to join the match, friends do
not pick a role and do not have an attribute set.
96
Matchmaking Overview
Creating Any Kind of Match Starts with a Match Request
Roles are not displayed in the standard user interface for matchmaking provided by Game Kit. Your game
must provide its own custom user interface to allow players to choose a role.
The match object returned to your game does not tell you which roles the players selected. Your game
must send the role-selection information separately after the match is created.
Your game defines a complete set of roles; all roles defined by your game must be filled by the time the
match is created. Because this calls for careful coordination between the roles that you define and the
number of players allowed in the match. Thus, player attributes require additional design and testing
effort.
If Game Center sees a nonzero player attribute in the match request, it adds players to the match intelligently
so that all of the players, when combined using a logical OR operation, have a complete mask of FFFFFFFFh.
The algorithm looks roughly like this:
1.
2.
Game Center looks for players with match requests that have a non-zero player attributes value. Game
Center searches for players whose masks include set bits that are not currently in the matchs mask.
3.
After a player is added to the match, the value of the new players player attributes value is logically ORed
into the matchs mask.
4.
If the matchs mask does not equal FFFFFFFFh, Game Center searches for other players to join the match.
If the match is complete, but the game still requires more players to reach the minimum, Game Center
continues to search for more players to add.
97
Matchmaking Overview
Creating Any Kind of Match Starts with a Match Request
None of the role masks overlap; if any two masks are joined by AND, the resulting value is always 00000000h.
When all four role masks are logically ORed together, the entire match mask is filled (FFFFFFFFh). This ensures,
in a match with four players, that each role is filled exactly once.
Player Attributes Example: Chess
For chess, you might want to allow players to choose whether they want to play the black pieces, the white
pieces, or they dont care what color they start with. Listing 7-5 (page 98) provides an example set of masks
for this design.
Listing 7-5
#define MyRole_Black
0xFFFF0000
#define MyRole_White
0x0000FFFF
98
Matchmaking Overview
Creating Any Kind of Match Starts with a Match Request
A chess match always requires two players, so with these masks there are four possible combinations of players
that can satisfy the condition for a completed mask:
Two players that do not care which color their pieces are
Figure 7-1
99
Real-Time Matches
In a real-time match, the players are connected to Game Center (and thus to each other) simultaneously. This
form of match is suitable for implementing any type of game that requires live participation. A key advantage
of real-time matches is that Game Kit and Game Center provide extensive support for real-time matches, which
simplifies the code you need to write. In particular, it solves many problems of finding players to join into a
match, it provides a high-level networking interface that lets you ignore many of the problems of the underlying
networking layer, and it provides extensive built-in support for voice chat. Game Kit allows you to focus on
implementing your game without worrying about the precise mechanics of how game and voice data are
delivered.
However, even though Game Kit solves many of these problems, your game design still needs to be prepared
to deal with complex issues that arise from real-time networking, including:
The need for multiple instances of your game (running on different devices) to perform tasks simultaneously
or near simultaneously, while synchronizing states between the devices
Network reliability
Network latency
Implementing a real-time match requires extensive work designing, implementing, and testing your game.
These and other questions impact the design of your gameplay and networking code.
100
Real-Time Matches
Checklist for Adding Real-Time Matchmaking to Your Game
Getting Started
The following tasks must be performed before starting your matchmaking implementation:
If your app is an OS X app, you must add the following entitlements or all real-time functionality fails:
com.apple.security.network.client
com.apple.security.network.server
Add code to your game to authenticate the local player. See Working with Players in Game Center (page
32).
Familiarize yourself with the matchmaking concepts described in Matchmaking Overview (page 90) as
well as the contents of this chapter.
If you are implementing the standard user interface, see Using the Standard Matchmaking User
Interface (page 104).
If you are implementing a custom user interface, see Implementing a Custom Match User Interface (page
108).
Design the network messages your game uses to communicate with other participants in the match. Most
games exchange information at the start of the match to provide each participant the same initial game
state, and then send updates as events occur within the game. See Designing Your Network Game (page
113).
Write code to use the match object to send data to other match participants. Your game encodes the
game state into binary data and uses the match object to transmit it to other players. See Sending Data
to Other Players (page 117).
Implement a match delegate to handle events that can occur during the match:
101
Real-Time Matches
Checklist for Adding Real-Time Matchmaking to Your Game
The delegate is notified when other players are connected at the start of the game. Your delegate
usually waits until everyone is connected before starting the game. See Starting the Match (page
115).
The delegate receives the data that other players send. Your delegate reverses the procedure used
to send the data by decoding and acting on the data from the other players. See Receiving Data from
Other Players (page 117).
If players get disconnected while your game is running, the delegate receives a notification and must
decide whether to discontinue the match or reconfigure your game to handle the reduced number
of players. See Disconnecting from a Match (page 118).
Decide how many voice channels your game needs. For example, a free-for-all match can use a single
channel for all participants while a match with multiple teams might use a separate channel for each team
and an additional channel that includes all players in the game.
If your game is running in iOS, configure an audio session to enable the microphone. All games that record
or play audio must have an audio session. See Creating an Audio Session (iOS only) (page 118).
Create the voice channel by calling the match objects voiceChatWithName: method. The match returns
a GKVoiceChat object. See Creating Voice Channels (page 119).
Call the voice chat objects start method to activate the channel. See Starting and Stopping Voice
Chat (page 119).
Enable the microphone for a chat channel when a player needs to speak into it. Each participant can speak
into only one channel at a time. See Enabling and Disabling the Microphone (page 120).
Provide controls in your game that allow the user to enable and disable voice chat, set volume levels or
mute players within a channel. See Controlling the Volume of a Voice Chat (page 120).
Decide whether your game should support a push-to-talk model or whether it should continuously sample
the microphone. In a push-to-talk game, provide a control that the player presses to transmit voice data
to other players. In a game that continuously samples the microphone, provide a control to mute the
microphone.
Implement an update handler that is called when a player connects or disconnects, or when a player starts
or stops speaking. Typically, you use this handler to update your games user interface to display up to
date information for each player in the voice chatfor example, highlighting a user interface item when
a player is speaking. See Seeing When a Players State Changes (page 121).
102
Real-Time Matches
Overview of Real-Time Matches in Game Center
Class
Description
GKMatchRequest
GKMatchmaker
GKInvite
GKMatchmakerViewController
A view controller class that displays the standard matchmaking user interface.
The default user interface allows players to add friends to the match, search
for other players connected to Game Center, or even find players that are
physically in close proximity to each other, even if they do not currently have
a connection to Game Center.
GKMatch
This object, which is returned to your game, holds information about the
players in the match. Each instance of your game uses its own GKMatch object
to communicate with other players in the match.
GKVoiceChat
Returned by the match object and represents a specific voice channel players
can communicate over.
103
Real-Time Matches
Finding Players for a Match
As the delegate, your view controller (or some other class) must implement a few methods to respond to
events. Each of these methods dismisses the view controller, and then performs any specific actions required
for your game.
The matchmakerViewControllerWasCancelled: delegate method is called when the player cancels the
matchmaking process before a match has been created. Typically, your game dismisses the view controller
and then backs out to the title screen (or some other reasonable user interface screen).
104
Real-Time Matches
Finding Players for a Match
Listing 8-2
- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController
*)viewController
{
[self dismissViewControllerAnimated:YES completion:nil];
// Implement any specific code in your game here.
}
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController
didFailWithError:(NSError *)error
{
[self dismissViewControllerAnimated:YES completion:nil];
// Implement any specific code in your game here.
}
Finally, if a match has been created and everyone is ready to start, your delegates
matchmakerViewController:didFindMatch: method is called. This method returns a GKMatch object
to your game. Typically, when the match starts, the match is returned to all of the participants, so this delegate
method is called on multiple devices at the same time.
Listing 8-4 shows a possible implementation of the delegate method. This method assigns the match object
to a property on the object and then adds the object as the match objects delegate. At this stage of the process,
all the players have been found, but it is possible for the match object to be returned before all players are
successfully connected. If all the players are already connected to the match, the game recognizes this and
immediately begins the match. Otherwise, it does nothing; the match delegate starts the match when the last
player connects. See Starting a match (page 116) for the match delegates role in this launch code.
Listing 8-4
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController
didFindMatch:(GKMatch *)match
{
105
Real-Time Matches
Finding Players for a Match
The acceptedInvite parameter is non-nil when your game receives an invitation directly from another
player. In this situation, the other players instance of your game has already created a match request, so
this instance does not need to create a match request.
The playersToInvite parameter is non-nil when your game is launched directly from the Game Center
app to host a match. This parameter holds an array of player identifiers listing the players to invite into
the match. Your game must create a new match request, assign its parameters as it would normally, and
then set the match requests playersToInvite property to the value passed in the playersToInvite
parameter. When the matchmaking screen is displayed, it is prepopulated with the list of players already
included in the match.
106
Real-Time Matches
Finding Players for a Match
Important: Your game needs to install an invitation handler as early as possible after your game
authenticates the local player; an appropriate place to set the handler is in the authentication handler that
executes after the local player is authenticated. It is critical that your game authenticate the local player
immediately after it launches and that it set the invitation handler immediately after the player is
authenticated.
Listing 8-5
107
Real-Time Matches
Finding Players for a Match
To implement this in your game, create and present a matchmaker view controller just as you did in the default
case. You only do this from one device already participating in the match. After presenting the view controller,
call the view controllers addPlayersToMatch: method, passing in the match to add the players to. The
match interface uses the information in the match request to add players to the existing match, rather than
creating a new match. The match object is still returned to your delegates
matchmakerViewController:didFindMatch: method.
The match is still active while the matchmaking screen is displayed; the devices in the match can still exchange
data with each other. However, you might need to pause the actual gameplay until a new player is found.
Because the match is active, voice chat channels continue working.
This section starts with the simplest scenariofinding a match with no user-interface implementationand
then builds to more detailed concepts needed to build your own user interface.
108
Real-Time Matches
Finding Players for a Match
As in the example with the standard matchmaking interface, you can also add players to an existing match.
Instead of calling the findMatchForRequest:withCompletionHandler: method, your game calls the
addPlayersToMatch:matchRequest:completionHandler: method, passing in the match to add the
players to.
Canceling a Search
The matchmaking process takes time and may not complete quickly enough for some players. If your game
includes support for programmatic matching, it needs to provide a user interface that allows the player to
cancel an active search. Listing 8-7 shows how your game can terminate a pending search.
Listing 8-7
109
Real-Time Matches
Finding Players for a Match
110
Real-Time Matches
Finding Players for a Match
When a match request includes a list of player identifiers, then the matchmaking behavior changes (regardless
of whether you are creating a new match or adding players to a specific match). The normal process of finding
players for the match is suspended. Instead, the only thing the matchmaking code does is extend the invitations
to the players in the match request and wait for responses. Assuming your game does not cancel the
matchmaking process, it completes and returns a match to your game when all the invitations are processed.
Because some of the invitations may not be accepted, it is possible you may receive a match that still needs
more players. With this in mind, your custom user interface should implement the following behavior:
The first time the player invites players to join the match, create the match request with those players and
call the findMatchForRequest:withCompletionHandler: method. Wait for the match to be returned
(or cancel the request if the player cancels the invitations).
If the player wants to add more players to the match after the invitations are processed, perform the same
procedure again, but call the addPlayersToMatch:matchRequest:completionHandler: method
instead.
If the player wants to automatch the remaining slots, create a match request but do not include a list of
players to invite. Call the addPlayersToMatch:matchRequest:completionHandler: method to fill
the remaining slots. You must wait until all invited players have connected as all pending match requests
are cancelled when automatching the remaining player slots.
If the player wants to start the match with the players already in the match, call the
finishMatchmakingForMatch: method to end matchmaking entirely.
If you want to create a match that contains both invited players and automatched players, you must first create
the match with the invited players. After all invited players have connected, you can then add players through
automatching.
Provide a button in your user interface to allow the player to search for nearby players. When pressed,
this button presents a new user interface screen that displays any nearby players it finds. Alternatively,
your user interface can simply display nearby players automatically. If you choose this approach, it usually
makes sense to keep this player list separated from the rest of the user interface.
111
Real-Time Matches
Finding Players for a Match
2.
3.
If the player selects one or more players to send an invitation to, create a match request and add the player
identifiers for those players to the match request. Then, follow the behavior described in Inviting Specific
Players to a Match (page 110).
4.
When your browsing screen is removed from the screen (either because the player canceled browsing or
because he or she invited players already) call the stopBrowsingForNearbyPlayers method.
- (void)findAllActivity
{
[[GKMatchmaker sharedMatchmaker] queryActivityWithCompletionHandler:^(NSInteger
activity, NSError *error) {
if (error)
{
// Process the error.
}
else
{
112
Real-Time Matches
Exchanging Data Between Match Participants
If your game uses player groups, you can use the queryPlayerGroupActivity:withCompletionHandler:
method to retrieve the activity for a specific player group.
The value returned by either method is the number of players who have recently requested a match.
A reliable transmission is simpler, but potentially slower; a slow or error-prone network may require the
device to send the message multiple times before it is successfully delivered to its intended recipients. A
match also guarantees that multiple reliable messages sent from one device to the same recipient are
delivered in the order they were sent.
Messages transmitted unreliably may never reach their destination or may be delivered out of order.
Unreliable transmissions are most useful for real-time transactions where any delay in transmission caused
by using reliable messaging invalidates the contents of the message. For example, if your game transmits
position and velocity information for a dead-reckoning algorithm, reliable messages might provide
positioning data that is badly out of date by the time it is delivered to the recipient. By using unreliable
messages, messages are delivered faster. Your game takes responsibility for network errors by sending
new messages with updated position and reckoning information.
113
Real-Time Matches
Exchanging Data Between Match Participants
The size of your messages also plays an important role in how quickly the data can be delivered to its targets.
Large messages must be split into smaller packets (such splitting is called fragmentation) and reassembled
by each target. Each of these smaller packets might be lost during transmission or delivered out of order. Large
messages should be sent reliably, so that Game Kit can handle the fragmentation and assembly. However, the
process of resending and assembly takes time. You should not use reliable transmissions to send large amounts
of real-time data.
Be mindful that your network data is being transmitted across servers and routers that are out of your control.
Your messages are subject to inspection and modification by other devices on the network. When your game
on one device receives network data from participants on other devices, it should treat that message as
untrusted data, and validate its contents before using it. See Secure Coding Guide for information on how to
avoid security vulnerabilities.
Here are some general guidelines to follow when designing your games networking:
Your message format needs to include a way to differentiate between message types. The GKMatch class
does not know anything about the contents of your messages, so you must implement that functionality
in your game. For example, you might create an enumerated type that identifies different kinds of messages,
and start each message with that enumerated type.
Send messages at the lowest frequency that allows your game to function well. Your games graphics
engine may be running at 30 to 60 frames per second, but your networking code can send updates much
less frequently.
Use the smallest message format that gets the job done. Messages that are sent frequently or messages
that must be received quickly by other participants should be carefully scrutinized to ensure that no
unnecessary data is being sent.
Pack your data into the smallest representation you can without losing valuable information. For example,
an integer in your program may use 32 or 64 bits to store its data. If the value stored in the integer is
always in the range 1 through 10, you can store it in your network message in only 4 bits.
Send messages only to the participants that need the information contained in the message. For example,
if your game has two different teams, team-related messages should be sent only to the members of the
same team. Sending data to all participants in the match uses up networking bandwidth for little gain.
Although the GKMatch object creates a full peer-to-peer connection between all the participants, you can
reduce the network traffic by layering a ring or client-server networking architecture on top of it. Figure
8-1 shows three possible network topologies for a four-player game. On the left, a peer-to-peer game has
12 connections between the various devices. However, you could layer a client-server architecture on top
of this by nominating one of the devices to act as the host. If your game transmits to or from the host
only, you can halve the number of connections. A ring architecture allows devices to forward network
114
Real-Time Matches
Exchanging Data Between Match Participants
packets to the next device only, but further reduces the number of connections. Each topology provides
different performance characteristics, so you will want to test different models to find one that provides
the performance your game requires.
Figure 8-1
graphic name
Game
Centertopologies
Programming Guide
Network
Apple, Inc.
Specify how to handle network disruptions. Networks are an inherently unreliable medium of
communication. A participant can be disconnected at any time while the match is in progress. Your game
must handle disconnection messages. For example, if you implemented your game to use a client-server
topology, then when the server disconnects from the match, your game might want to nominate a new
device to become the new server.
115
Real-Time Matches
Exchanging Data Between Match Participants
Even before the match starts, all players already connected to the match can already exchange data with each
other. This allows your game to create voice channels (or your own user interface) that allows the players
already there to communicate with each other.
Listing 8-10 Starting a match
- (void)match:(GKMatch *)match player:(NSString *)playerID
didChangeState:(GKPlayerConnectionState)state
{
switch (state)
{
case GKPlayerStateConnected:
// Handle a new player connection.
break;
case GKPlayerStateDisconnected:
// A player just disconnected.
break;
}
if (!self.matchStarted && match.expectedPlayerCount == 0)
{
self.matchStarted = YES;
// Handle initial match negotiation.
}
}
116
Real-Time Matches
Exchanging Data Between Match Participants
When the method returns without reporting an error, the message has been queued and will be sent when
the network is available.
117
Real-Time Matches
Adding Voice Chat to a Match
{
Packet *p = (Packet*)[data bytes];
if (p.messageKind == PositionMessage)
// Handle a position message.
}
Mute other players as well as control the overall volume of voice chat.
Choose which channel he or she speaks into, if your game supports multiple channels.
118
Real-Time Matches
Adding Voice Chat to a Match
Note: Your app needs to stop any voice chats currently active after receiving an
AVAudioSessionDidBeginInterruptionNotification. You can restart any voice chats after
receiving an AVAudioSessionDidEndInterruptionNotification.
For more details on creating and using audio sessions, see Audio Session Programming Guide .
After the start method is called, the voice chat object on that device connects to other participants in the
channel if the following are true:
119
Real-Time Matches
Adding Voice Chat to a Match
If either of these conditions is not met, the voice chat object waits until both are true before connecting to
the channel.
Similarly, when a player is ready to leave a channel or whenever you want a channel to be temporarily turned
off, you stop the chat using:
[teamChannel stop];
An advantage to stopping the channel (rather than simply muting the other players) is that the other players
are not required to send data to the player who has left the channel. This decrease in data transmission leaves
more bandwidth available for your games messaging.
Only one channel can enable the microphone at a time. When you enable the microphone for one channel,
the active property on the previous owner is automatically set to NO.
The volume property accepts values between 0.0 and 1.0, inclusive. A value of 0.0 mutes the entire channel;
a volume of 1.0 outputs voice data at full volume.
120
Real-Time Matches
Adding Voice Chat to a Match
Second, your game can selectively mute players in a channel. Typically, if your game intends to mute players,
it should offer a user interface that allows the player to choose which players they want to mute. To mute a
player, you call the voice chat objects setMute:forPlayer: method:
[teamChannel setMute: YES forPlayer: player];
121
Hosted Matches
Hosted matches allow your game to use Game Centers matchmaking service to find players, but use your own
server to connect the players to each other. Hosted matches require you to implement your own custom
low-level networking code, because Game Centers servers are not involved in the match play at all. However,
hosted games offer larger match sizes and the ability to add your own server into every match.
Real-time matchmaking
Hosted matchmaking
matchmakerViewController:
didFindMatch: method to receive the
match.
Your programmatic matchmaking code
calls findMatchForRequest:
withCompletionHandler: to create
a new match.
matchmakerViewController:
didReceiveAcceptFromHostedPlayer: method to
for a match.
122
Hosted Matches
Hosted Matches Overview
Real-time matchmaking
Hosted matchmaking
addPlayersToMatch:
matchRequest:
completionHandler: to add players
findPlayersForHostedMatchRequest:
withCompletionHandler: to find a set of new players
to a match.
Design and implement your own networking code to connect each device to your server.
Design and implement your own networking protocol to inform other devices of the state of any participant
in the match.
Design and implement your own server implementation to map player identifiers to the specific device
connected to your server. Thus, your server becomes responsible for routing network data between players.
If your game uses Game Kits standard matchmaking user interface, you must make sure each device
informs Game Kit after it connects to your server. This information allows Game Kit to update its user
interface.
123
Hosted Matches
Creating a Hosted Match Using the Matchmaker View Controller
player. Your delegate needs to behave differently depending on which device your game is running on:
When called on the players device, the device needs to connect to your own server. When successfully
connected, call the setHostedPlayer:connected: method to tell the view controller that the player
has connected to the match.
When called on another players device, your game needs to determine that it can talk to the new players
device through your server. Once it knows it can send messages to the other client, call the
setHostedPlayer:connected: method to update the user interface.
124
Turn-Based Matches
In a turn-based match, the players of the match do not need to be simultaneously connected to Game Center
to play a match together. Instead, the game uses a store-and-forward approach; one player takes a turn before
passing the next play to another player. The players continue to take turns until the match ends with only one
player able to make changes to the game at a time.
Turn-based matches have many useful characteristics that make them great for implementing board games
and other similar styles of games; for example:
A player can participate in multiple matches simultaneously. A game loads whichever match the player
is interested in viewing or advancing.
A match can be created with less than a full complement of players, even a single player. Other players
are added as needed.
In iOS 7, exchanges are introduced to turn-based matches. Exchanges allow two or more players to take an
action, even when it is not their turn. This allows developers to create more complex and diverse turn-based
games than are currently possible by allowing more than just the local player to make changes to the game.
Some possible uses for exchanges are:
Two players want to trade cards in your game. This can be accomplished during another players turn.
One player wants to auction a card and all players have a chance to bid on the card at the same time.
Two players attack each other. They both take turns through exchanges until finished.
You can build a game by adding exchanges to the existing turn-based gaming model or create a game solely
through the use of exchanges. This chapter first describes how to implement a traditional turn-based match
and then adds information about exchanges later.
When you implement turn-based matches in your game, the list of players, the data for matches, and other
details are all stored on Game Center. Your game downloads this information as needed. Game Center is
primarily responsible for storing data. You are responsible for providing the game logic that uses this
infrastructure. In particular, you define:
125
Turn-Based Matches
Checklist for Implementing a Turn-Based Match
Allow the local player to join a match. See Joining a New Match (page 132).
Allow the local player to see the list of existing matches. See Working with Existing Matches (page 136).
Allow the local player to view the state of a match in progress. See Working with Match Data (page 138).
Allow the player to take a turn in the match. See Advancing the State of the Match (page 141).
When a player leaves a match, set the players match outcome. See Setting the Match Outcome When a
Participant Leaves a Match (page 141).
When all the players have a match outcome set, end the match. See Ending a Match (page 143).
Handle invitations and other match events. See Responding to Match Notifications (page 143).
Expand your game to include exchanges. See Adding Exchanges to a Turn-Based Match (page 145).
126
Turn-Based Matches
The Match Data Represents the State of the Match
At this point, Game Center sees that this match needs a new player to continue play. When Bob searches for
a match, Game Center sees that Bob wants to play the same game as Marry and assigns Bob as a new player
of Marys match. Because this game was waiting on a new player to continue the match, it is now Bobs turn.
Game Center always tracks the players of a match in a specific order. That order never changes for the duration
of the match, regardless of which device your game is running on. In this example, if Mary is in the first seat
(slot), she stays in the first seat for the entire game.
Every match has the concept of the current player. The current player changes throughout the match and
represents the player whose turn it is to act. When that player finishes taking a turn, your game chooses another
player to act. That player is notified that it is now his or her turn and becomes the current player.
127
Turn-Based Matches
The Match Data Represents the State of the Match
At any time, a player in the match can launch your game to view the match. When a player launches the game,
your game loads the match data, interprets it, and displays it to the player.
graphic name
Figure 10-2
Center
Programming
The currentGame
player
wants
to view theGuide
match
Apple, Inc.
Only the current player is allowed to change the match data. Provide the current player with a user interface
that allows them to take actions in the game. As the player takes actions, your game updates the match data
graphic name
and transmits it back
to Game Center.
Game Center Programming Guide
Apple, Inc.
128
Turn-Based Matches
Your Game Decides the Rules of Play
At the start of the match, each player takes a starting turn. Play passes sequentially through the entire
player list. On a starting turn, a player action consists of naming the players empire and choosing options
for how they intend to play in the match. For example, a common 4X trope is for a player to choose a
faction that provides specific advantages and disadvantages during play. After all the players have
completed their starting turns, the match begins by allowing players to administrate their empires.
On an administrative game turn, each active player takes a turn, and play passes sequentially through the
player list. Each participant performs all the actions necessary to control their empire. After all players
complete their orders, the administrative turn ends. Your game then executes all the orders simultaneously,
usually on the client of the last player to take an administrative turn. If any player units come into conflict,
then a conflict game turn is executed; otherwise, a new administrative game turn starts.
On a conflict game turn, the game creates a list of all of the players involved in conflicts. Then, each player
on the list is given a turn to allow them to give combat orders. After all players give orders, the orders are
executed simultaneously and the conflicts are resolved at once. If any players are eliminated as a result of
combat, the game takes them out of the match on future turns. If only one player remains active in the
match, the match ends and that player is declared the winner. Otherwise, play continues with another
administrative game turn.
129
Turn-Based Matches
Your Game Decides the Rules of Play
Figure 10-3 shows how this hypothetical games logic is processed. It has three distinct kinds of player turns,
each with a different user interface, possible user actions, and data to be stored in the match data.
Figure 10-3
Whenever a player takes a turn, the match data indicates what type of turn the player takes. After a player
takes a turn, their actions are stored in the match data. The design also avoids passing turns to other players
for nontrivial reasons. Every player makes multiple decisions at once before passing control to another player.
130
Turn-Based Matches
Save the Match Data Whenever Important Events Occur
When the final player completes a turn, that players game client processes everyones turns simultaneously,
writing any necessary changes to the match data. Although this kind of design is not required, it keeps the
game moving by avoiding small, trivial player turns.
The action should be immediately visible to other players if those players choose to look at the match.
The action should be irrevocable, such as when the action reveals information previously hidden from the
player or generates a randomized result that needs to be persistent.
Class Name
Class Function
GKTurnBasedMatch
Describes a turn-based match stored on Game Center. You use this object
to inspect the current state of the match and to update the state of the
match when the current player takes a turn.
GKMatchRequest
GKTurnBasedParticipant
Describes a player in a match. Most of its properties are read-only, but the
matchOutcome property is not; you assign an outcome to this property
when a player leaves a match.
GKTurnBasedMatchmakerViewController
Provides a standard user interface that allows the local player to create new
matches or view existing matches.
131
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
Class Name
Class Function
GKTurnBasedEventHandler
Item
Limit
Runtime Access
Number of Players
16
64k
132
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
133
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
134
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
One common scenario is supported automatically by Game Center. When a match ends, you can call its
rematchWithCompletionHandler: instance method to create a new match with the same participants.
135
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
Table 10-3 lists the most common actions a player might want to perform on a match.
Table 10-3
Action
Implementation
View a match
136
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
Action
Implementation
Set the players outcome and then call a method to resign from the
match. See Setting the Match Outcome When a Participant Leaves a
Match (page 141).
Set outcomes for all of the players and then call the matchs
endMatchInTurnWithMatchData: completionHandler: method.
Property
Description
matchID
status
message
A text string your game sets to provide a human-readable status for the
match. Typically, you update this property before changing the current
player. The message is displayed by the standard user interface. If you
display a custom interface, you should also display the message.
participants
currentParticipant
The participant object for the next player expected to act in the match.
This object is always one of the objects stored in the participants array.
Table 10-5 lists the most common participant properties used to implement your game.
137
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
Table 10-5
Property
Description
playerID
The player identifier for the player, assuming this seat is filled. Use it to load display
names and photos for the player.
status
Declares whether or not this seat is filled and, if it is, declares whether the player
is still active in the match.
timeoutDate
The time at which the player must act before forfeiting a turn. Your game decides
what happens when a turn is forfeited. For some games, a forfeited turn might end
the match. For other games, you might choose a reasonable set of default actions
for the player, or simply do nothing.
matchOutcome
When a player leaves a match, this property describes what happened to the player.
The player may have won or lost the match.
Encode only player actions: In this design, your match data simply consists of the moves made by the
players. For example, in chess, you know that white goes first, moves always alternate, and a piece moves
from one board position to another. This makes it easy for you to encode each move as the starting and
ending position of the piece moved. The rest of the data (who made the moves) can be completely inferred.
When your game loads the match data, it quickly replays the moves to generate the current board position.
This strategy works best for games with a small number of possible kinds of actions and a small number
of moves per match. Also, with this model, it is very possible for your game to replay the moves in its user
interface, allowing players to see exactly what moves other opponents made to get the board into the
new state. Showing a player these moves makes it very easy for a player to understand how the game got
to the current state.
138
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
Encode only the current state of the match: For very complex games, the actual state required to encode
the game could be very large. In this case, you may need to encode the current state of the match without
worrying about the actions that generated that match data. This is particularly true for very complex games
where the list of moves might grow too large to fit in the available storage space.
This strategy is recommended as a last resort. Players lose all context of what happened on previous turns
of the match. For games with long timeouts between turns, players may grow bored or frustrated if they
cannot remember the state of a match they were playing. This is particularly true when players participate
in multiple matches simultaneously.
Encode the current state of the match and a set of recent player actions: This is a hybrid strategy that
borrows elements from the other two strategies. Essentially, the match data stored on Game Center consists
of a recent snapshot of the match plus other data that encodes recent actions since that last snapshot
was taken. When the data that records the actions grows too large, your game replays some of those
moves to update the match snapshot and then deletes those moves from its list of actions.
With this strategy, you typically need to determine which actions the current player has seen (based on
when they last took a turn). When your game flattens the match data, it never removes any data that
hasnt been seen by all the participants. This allows all participants to see the moves their opponents
made.
Avoid using the NSCoder class except for the most trivial of games. Although useful for general-purpose
apps, the NSCoder class may not archive data in a compact enough format for your game. You cannot
precisely predict the size of the archive it produces. Instead, you allocate your own block of memory and
perform your own data serialization.
Encode individual items as compactly as needed. For example, in a 16-player game, you can encode the
participant number of the player in 4 bits. Balance the need for compactness with the need for readability
in your code. For example, a chess position could be encoded in as little as 6 bits, but in practice a chess
match does not approach the match data limit.
If your game runs in both OS X and iOS, use network data encoding techniques to avoid byte ordering
problems.
139
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
140
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
141
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
If the local player resigns from the match and is also the matchs current player, your game must call the match
objects
participantQuitInTurnWithOutcome:nextParticipants:turnTimeout:matchData:completionHandler:
gives control to another participant. Because of this, you are required to update the match data and provide
a participant list. However, your game also provides a match outcome for the player that just exited the match
essentially, a numerical value that indicates why that player left the match. The participant object for that
player is updated to include this new match state. Once a participant has exited the match, your game may
not make that player the current player.
Game Kit provides some standard values you can use to set the match outcome. See Setting the Match
Outcome in GKTurnBasedParticipant Class Reference .
For example, in Figure 10-4, Bob has just been eliminated from the match. The game chooses to set an outcome
of GKTurnBasedMatchOutcomeFourth and make Mary the new current player. Bob may still view the match,
but may not take actions.
graphic name
Figure 10-4
Game
Programmingfrom
Guide
Bob
has Center
been eliminated
the match
Apple, Inc.
Occasionally a player may resign the game when they are not the current player. To handle this, your game
calls the match objects participantQuitOutOfTurnWithOutcome:withCompletionHandler: method.
You provide a match outcome but do not provide new match data or a participant list.
142
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
Ending a Match
Eventually, your game logic is going to decide that the match is over. All participants in the match must have
a valid match outcome before ending the match. Your game calls the match objects
endMatchInTurnWithMatchData:completionHandler: method to formally end the match. This method
is similar to the other methods that update the match state, but in this case you do not provide a list of
participants because no further actions are allowed in this match. You do update the saved match data to
describe how the match ended. Players can still select this match from the matchmaking user interface; your
game should display the match ending but not allow the player to take actions.
143
Turn-Based Matches
Implementing a Turn-Based Match Using Game Kit
To respond to events, your event handler implements the methods defined by the
GKTurnBasedEventHandlerDelegate protocol. Table 10-6 lists the events. Events received via a push
notification launch your game or bring your game to the foreground (if necessary) and are then delivered to
the game. Foreground events are delivered only if your game was running in the foreground when the event
was received.
When an event is received, your game should pause what it is doing and display a user interface that allows
the player to decide whether to load the notifications match for display. Even if this match is already loaded,
you should reload the matchs data, because it may have been updated by the event.
Table 10-6
Event
Event Type
Push
handleInviteFromGameCenter:
Push
handleTurnEventForMatch:
didBecomeActive:
A match ended
Push
handleMatchEnded:
Foreground
handleTurnEventForMatch:
didBecomeActive:
Foreground
handleTurnEventForMatch:
didBecomeActive:
Push
player: receivedExchangeRequest:
forMatch:
Push
player:
receivedExchangeCancellation:
forMatch:
Push
player: receivedExchangeReplies:
forCompletedExchange: forMatch:
By default, when your game receives a notification, a badge is added to the game icon. Add
GKGameCenterBadgingDisabled to your Info.plist to change this behavior. See Cocoa Keys for details.
144
Turn-Based Matches
Adding Exchanges to a Turn-Based Match
Anatomy of an Exchange
In the basic turn-based match, control of the game moves from player to player, following rules defined by
the app. Only the current player can affect the match, with all other players relegated to observing the match.
This works very well for certain types of games, but as a game turn becomes more complicated, it is not
uncommon for multiple players needing to interact at the same time. Turn-based matches can quickly become
bogged down when each player must perform a small action in order for a turn to be completed. Exchanges
provide you with a way to create complex turns without slowing down the pace of the match.
Using exchanges, you can design your game so that players other than the current player can take actions
during a turn. An exchange is an interaction between the exchange initiator and one or more exchange
recipients. The following workflow is used for an exchange:
The recipient acts on the exchange request and sends their action back to the initiator.
The current player is notified of the completed exchange and updates the match data.
145
Turn-Based Matches
Adding Exchanges to a Turn-Based Match
When a player sends an exchange request, several pieces of information are required to successfully send the
request. There is no particular order in which this information needs to be collected. For example, your game
may ask who the sender wants to trade with before asking which cards to trade, or the sender could choose
cards to give and then designate who will receive the cards.
The nature of the request has to be determined. Is the player asking to trade cards, asking for help in
attacking another player, or something else?
The amount of time the recipients have to respond to the exchange request must be set. You can allow
the sender to choose this or set a hard time limit.
Design your game in such a way that a player can never send an exchange request to a player that has quit
the game. Sending an exchange request to a player that has quit the game will generate an error.
The amount of data that you can send is limited to a maximum of 1k. The data must be comprehensive enough
that the receiving players game can act and present the data to the player in a way that makes sense in the
context of your game. When the exchange request is sent, ensure that the current player also receives the
request data so that the current match can be updated. Listing 10-10 shows a basic exchange request. The
recipient of the exchange is placed into an array and the request is sent to the player listed in the recipients
array.
146
Turn-Based Matches
Adding Exchanges to a Turn-Based Match
Listing
10-10
An exchange can be cancelled by the sender at any time, even after replies have been received. As an example,
this functionality can be used to simulate trading between players. The sender can propose a trade and if the
recipient responds with a different offer, the sender can decline and cancel the exchange. When the sender
cancels an exchange, a push notification is sent to all of the recipients telling them that the exchange has been
canceled.
Listing
10-11
147
Turn-Based Matches
Adding Exchanges to a Turn-Based Match
Listing 10-12 shows a basic reply format. The recipient responds to the exchange request and sends any relevant
data back to the original sender. Your game also needs to send the results of the exchange to the current
player so that they can update the match.
Listing
10-12
-(void) replyToExchange
{
[self replyWithLocalizableMessageKey:key arguments:arguments data:data
completionHandler:^(NSError *error) {
// refresh your match data
}
}
148
Turn-Based Matches
Adding Exchanges to a Turn-Based Match
- (void) advanceTurn
{
NSData *updatedMatchData = [this.gameData encodeMatchData];
NSArray *sortedPlayerOrder = [this.gameData encodePlayerOrder];
NSArray *exchangesToResolve = [this.gameData retrieveCompletedExchanges];
[this.myMatch saveMergedMatchData: updatedMatchData withResolvedExchanges:
exchangesToResolve
completionHandler ^(NSError *error) {
if (error)
{
// Handle the error.
} else {
this.MyMatch.message = [this.gameData matchAppropriateMessage];
[this.myMatch endTurnWithNextParticipants: sortedPlayerOrder
turnTimeOut: GKTurnTimeoutDefault
matchData: updatedMatchData completionHandler ^(NSError
*error) {
if (error)
{
// Handle the error.
}
149
Turn-Based Matches
Adding Exchanges to a Turn-Based Match
}];
};
}];
}
Failing to resolve completed exchanges before ending the turn returns an error.
150
To help you test your game, Apple provides a nonproduction development environment for Game Center.
This development environment duplicates the live functionality of Game Center, but is separate from the live
servers. The development environment allows you to test your Game Center features without making your
game visible to regular users. You should thoroughly test your game in a development environment before
submitting it for approval.
Table 11-1
Build
Audience
Simulator build
Developer
Development environment
Developer build
Developer
Development environment
Beta testers
Development environment
End users
Live environment
A development environment does not allow sharing of information about what games are being played. This
prevents your testers from revealing the existence of your game to other players.
151
The development environment provides you with the ability to send friend requests using Game Center
nicknames only. You can not use a persons email address for a friend request inside of the development
environment.
152
Date
Notes
2013-10-22
2013-09-18
2012-09-19
2012-07-17
2011-03-08
Revised the process for authenticating the local player. Clarified many
aspects of Game Center usage.
2010-10-25
2010-08-27
2009-05-28
2009-03-12
153
Apple Inc.
Copyright 2013 Apple Inc.
All rights reserved.
No part of this publication may be reproduced,
stored in a retrieval system, or transmitted, in any
form or by any means, mechanical, electronic,
photocopying, recording, or otherwise, without
prior written permission of Apple Inc., with the
following exceptions: Any person is hereby
authorized to store documentation on a single
computer for personal use only and to print
copies of documentation for personal use
provided that the documentation contains
Apples copyright notice.
No licenses, express or implied, are granted with
respect to any of the technology described in this
document. Apple retains all intellectual property
rights associated with the technology described
in this document. This document is intended to
assist application developers to develop
applications only for Apple-labeled computers.
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
408-996-1010
Apple, the Apple logo, Cocoa, iTunes, Mac, OS X,
and Xcode are trademarks of Apple Inc.,
registered in the U.S. and other countries.
iCloud is a service mark of Apple Inc., registered
in the U.S. and other countries.
App Store is a service mark of Apple Inc.
iOS is a trademark or registered trademark of
Cisco in the U.S. and other countries and is used
under license.
Even though Apple has reviewed this document,
APPLE MAKES NO WARRANTY OR REPRESENTATION,
EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS
DOCUMENT, ITS QUALITY, ACCURACY,
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR
PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED
AS IS, AND YOU, THE READER, ARE ASSUMING THE
ENTIRE RISK AS TO ITS QUALITY AND ACCURACY.
IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES RESULTING FROM ANY DEFECT OR
INACCURACY IN THIS DOCUMENT, even if advised of
the possibility of such damages.
THE WARRANTY AND REMEDIES SET FORTH ABOVE
ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL
OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer,
agent, or employee is authorized to make any
modification, extension, or addition to this warranty.
Some states do not allow the exclusion or limitation
of implied warranties or liability for incidental or
consequential damages, so the above limitation or
exclusion may not apply to you. This warranty gives
you specific legal rights, and you may also have other
rights which vary from state to state.