Game Center integration – leaderboards and achievements

Today’s post is going to be a pragmatic and technical one. I’m going to make a brief introduction to Game Center integration for your games. I decided to talk about this topic today because I found some things that I was not expecting about Game Center. So, I going to share my experience.

As you may know, Game Center is Apple’s solution to social gaming experience. It’s not the best social gaming experience, but its acceptance has been very high among iOS users and it’s quite easy to implement. That’s why I finally decided to only support Game Center, forgetting about Open Feint or Plus+.

game center icon

In general, Game Center integration is very easy but not trivial. You need to set a few things before you can start adding leaderboards and achievements into your game. Fortunately, Apple documentation on this topic is excellent. Check it out here.

According to Apple’s documentation, you need to complete six steps to be ready to implement your leaderboards and achievements on your game:

  1. Enable Game Center in iTunes connect. You will need to launch your browser, point to itunesconnect.com and enable and configure Game Center for your game. You will be presented with a nice web interface where you are going to set all the metadata for your leaderboards and achievements. Very easy.
  2. Configure the bundle identifier for your game. You will need to go to the iOS Provisioning Portal to set the bundle identifier for your game. Apple needs it to allow you test your game with a sandbox version of Game Center, for testing purposes.
  3. Link to Game Kit framework. You will need to add the Game Kit framework to your Xcode project.
  4. Import the GameKit/GameKit.h header.
  5. Determine wether your games requires Game Center to work. If your game depends on Game Center to work, Game Center framework must be added as “Required”. However, probably your game uses Game Center as an extra feature, so add it as “Optional” (or “Weak” on versions of Xcode previous to 4).
  6. Authenticate the player when your game starts.

Ok, these are the basic steps. Let’s enter in more detail into some tricky issues.

Set metadata in iTunes Connect

Actually, this is not really tricky, but is a little bit annoying. You will need to set the metadata information of your leaderboards and achievements into iTunes Connect in order to be able to test your game. You will have to introduce by hand some information like the identifier, title, description… Fair enough, right? The problem is that changes on Apple’s database are not performed immediately after you introduce them on iTunes Connect. So, my advise is that you take some time designing your leaderboards and achievements on a Numbers / Excel table and then copy-paste it to iTunes Connect.

Even doing this way, you will probably see that some strings get chopped when being displayed on Game Center iPhone/iPod interface, specially on portrait mode. So, be patient…

Obviously, all the tracking of scores and achievements must be done by you. Game Center only offers a dummy database to save the state, but, for example, the logic needed to determine whether the player has collected 100 stars is your responsibility. Game Center only stores a completed/uncompleted flag and the metadata associated.

Implementation on Xcode

Assuming you have performed the 6 steps described in the introduction, now is time to make things happen :)  As soon as possible, we need to authenticate the player:

- (void) authenticateLocalPlayer
{
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    [localPlayer authenticateWithCompletionHandler:^(NSError *error) {
         if (localPlayer.isAuthenticated)
         {
             // Perform additional tasks for the authenticated player.
         }
     }];
}

Eventually, you will need to report a score:

- (void) reportScore: (int64_t) score forCategory: (NSString*) category
{
    GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease];
    scoreReporter.value = score;

    [scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
       if (error != nil)
       {
            // handle the reporting error
        }
    }];
}

And show the list of leaderboards at Game Center using its default UI:

- (void) showLeaderboard
{
    GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
    if (leaderboardController != nil)
    {
        leaderboardController.leaderboardDelegate = self;
        [self presentModalViewController: leaderboardController animated: YES];
    }
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
    [self dismissModalViewControllerAnimated:YES];
}

We will do something similar to add an achievement:

- (void) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent
{
    GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease];
    if (achievement)
    {
         achievement.percentComplete = percent;
         [achievement reportAchievementWithCompletionHandler:^(NSError *error)
             {
                  if (error != nil)
                  {
                      // Retain the achievement object and try again later (not shown).
                  }
             }];
    }
}

And show the achievements list with its default Game Center UI:

- (void) showAchievements
{
    GKAchievementViewController *achievements = [[GKAchievementViewController alloc] init];
    if (achievements != nil)
    {
        achievements.achievementDelegate = self;
        [self presentModalViewController: achievements animated: YES];
    }
    [achievements release];
}
- (void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
    [self dismissModalViewControllerAnimated:YES];
}

So, basically that’s really it. However, we need to deal with potential network problems. If when reporting a score or an achievement Internet is not available we need to retain it and report it later when network is available. How it is done depends on you. I have decided to save all game progress data to NSUserDefaults. So, when a new highscore is achieved or and achievement is completed I store it on NSUserDefaults and simultaneously report it to Game Center.

Then, after a successful player authentication,  I compare the list of completed achievements on Game Center to my cache list and sync if necessary. Scores are reported to Game Center on every player authentication. Game Center authentication is automatically performed whenever the game goes from background to foreground or is first launched. So I think it would do the work :)

Achievement notification to player

By doing what has been described until now you will have complete support for Game Center leaderboards and achievements. However, what was really surprising for me is that Game Center doesn’t report achievement completion to the player. Player needs to go to the Game Center achievement list to check his achievement completion progress. Not so good :-/

However, I had seen achievement notifications on some games, so something must be out there. After googling a bit I found out this nice post: Game Center Achievement Notification. Great! It is exactly what I was looking for! It is a very easy to use class that allows your game to notify achievements completion with a nice Game Center appeal. So, I encourage you to use it in your games :)

Conclusion

Mental note: integrate Game Center on all your games. It is very easy and I think that makes your game value to increase a lot compared to the effort needed to implement it.

3 thoughts on “Game Center integration – leaderboards and achievements

Leave a Reply