What’s New with Game Center in iOS 6

Note from Ray: This is the seventh iOS 6 tutorial in the iOS 6 Feast! This tutorial is an abbreviated version of one of the chapters from our new book iOS 6 By Tutorials. Ali Hafizji wrote this chapter – the same guy who’s written several Android tutorials for this site in the past. Enjoy! […] By Ali Hafizji.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Enabling Game Center features

Click the blue Manage Game Center button and then click the Enable for Single Game button. Awesome! You have just enabled Game Center for your game. Yep, it is as simple as clicking a button – but you still have a bunch of code to write. :]

You aren’t done with this section yet – you still need to add a leaderboard. You might wonder why you have to bother with leaderboards since this chapter is about challenges – don’t worry, you will see why later!

For now, take my word at it and add a leaderboard and some challenges, starting with a leaderboard. Click the Add Leaderboard button and select the Single Leaderboard type. You will be presented with a form, like so:

Enter the leaderboard reference name as High Scores and the leaderboard ID as HighScores.

Note: I generally recommend you keep the leaderboard/achievement ID as an extension of the package name. For example, in the above case for me it would be com.ali.MonkeyJump.HighScores (you would need to replace the com.ali part to match your own setup). But for the purposes of this tutorial, just name it plain HighScores (without the reverse domain name prefix) to keep things simple.

Set the Sort Order as High to Low and the Score Format Type as Integer. Finally, click on the Add Language button. Enter the language details as shown below:

Adding an image is not mandatory, but is always a good practice. The one used above is included in the iTunes resources (it’s named icon_leaderboard_512.png), and you can use it here for the high scores leaderboard. When you’re done, click Save.

Finally, click on the Done button. For now, one leaderboard is enough, but in the future if you want to add more, you now know the drill.

Authenticating the local player

Before you start writing code, you need to import the GameKit framework. Open the MonkeyJump project in Xcode 4.5 and navigate to the target settings. Open the Build Phases tab and expand the Link Binary With Libraries section. Click the “+” button and add the GameKit framework to the project.

Next you will write code to authenticate the player. Without authenticating the player, you cannot use any of the awesome features that Game Center provides.

Player here means the user who is playing your game. In Game Center terms, this is the GKLocalPlayer.

Player authentication is a simple two-step process:

  1. First you make an authenticate call to the Game Center platform.
  2. The platform then asynchronously calls you back when authentication is complete. If the player was already logged in (95% of the time), a welcome banner is presented. If not, then a login screen is presented which also allows the player to register.

Let’s write some code. You are going to use a singleton pattern, so that all the Game Center code is in one class.

Right-click on the MonkeyJump group in Xcode and select New Group. Name the group GameKitFiles. Next, right-click on the newly-created group and select New File…, then select the Objective-C Class template. Name the class GameKitHelper and make sure it extends NSObject.

Replace the contents of GameKitHelper.h with the following:

//   Include the GameKit framework
#import <GameKit/GameKit.h>

//   Protocol to notify external
//   objects when Game Center events occur or
//   when Game Center async tasks are completed
@protocol GameKitHelperProtocol<NSObject>
@end


@interface GameKitHelper : NSObject

@property (nonatomic, assign)
    id<GameKitHelperProtocol> delegate;

// This property holds the last known error
// that occured while using the Game Center API's
@property (nonatomic, readonly) NSError* lastError;

+ (id) sharedGameKitHelper;

// Player authentication, info
-(void) authenticateLocalPlayer;
@end

The code is self-explanatory and is heavily commented. All you are doing here is declaring two methods and two properties – one is the delegate, and the other will hold the last error that occurred while using the GameKit framework.

Switch to GameKitHelper.m and replace its contents with the following:

#import "GameKitHelper.h"
#import "GameConstants.h"

@interface GameKitHelper ()
        <GKGameCenterControllerDelegate> {
    BOOL _gameCenterFeaturesEnabled;
}
@end

@implementation GameKitHelper

#pragma mark Singleton stuff

+(id) sharedGameKitHelper {
    static GameKitHelper *sharedGameKitHelper;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedGameKitHelper =
                [[GameKitHelper alloc] init];
    });
    return sharedGameKitHelper;
}

#pragma mark Player Authentication

-(void) authenticateLocalPlayer {
    
  GKLocalPlayer* localPlayer =
    [GKLocalPlayer localPlayer];

    localPlayer.authenticateHandler =
    ^(UIViewController *viewController,
      NSError *error) {
        
        [self setLastError:error];
        
        if ([CCDirector sharedDirector].isPaused)
            [[CCDirector sharedDirector] resume];
        
        if (localPlayer.authenticated) {
            _gameCenterFeaturesEnabled = YES;
        } else if(viewController) {
            [[CCDirector sharedDirector] pause];
            [self presentViewController:viewController];
        } else {
            _gameCenterFeaturesEnabled = NO;
        }
    };
}
@end

You have declared a variable called _gameCenterFeaturesEnabled. This BOOL variable will be true if authentication was successful, and in any other case will be false.

The way to authenticate a player has changed in iOS 6.0. All you need to do now is set the authenticationHandler of the GKLocalPlayer object, as seen in the -authenticateLocalPlayer method. The authenticationHandler is a block that takes two parameters and is called by the Game Center platform.
This block is called by the system in a number of scenarios:

  • When you set the authenticationHandler and request for the player to be authenticated.
  • When the app moves to the foreground.
  • On sign-in, i.e., if the player has not signed in before a sign-in screen is presented, any interaction on that screen leads to the authenticationHandler being called.

The authenticationHandler has two arguments:

  • A UIViewController representing the login view controller if you need to present it; and
  • An NSError object in case authentication happens to fail.

Notice that in the block, you first check if the local player is authenticated. If the player has already been authenticated, then all you need to do is set the _gameCenterEnabled flag as true and get on with your game.

If the login view controller (i.e., the first parameter of the authenticationHandler) is not nil, it means that the player has not logged into Game Center. If so, you first pause the game and then present the login view controller to the player. If the player logs in or selects the Cancel button on the login view controller, this handler is called again.

In earlier versions of Game Center, the developer did not have the power to decide when to present the login view controller. This new method gives developers more control, which is always a good thing. ☺

Finally, if authentication fails you need to gracefully fall back and disable all Game Center features. This is achieved in this app by setting the _gameCenterFeaturesEnabled flag to false.

In order for the code in authenticateLocalPlayer to work, you need a few more bits of code. Add the following to GameKitHelper.m:

#pragma mark Property setters

-(void) setLastError:(NSError*)error {
    _lastError = [error copy];
    if (_lastError) {
        NSLog(@"GameKitHelper ERROR: %@", [[_lastError userInfo] 
          description]);
    }
}

#pragma mark UIViewController stuff

-(UIViewController*) getRootViewController {
    return [UIApplication 
      sharedApplication].keyWindow.rootViewController;
}

-(void)presentViewController:(UIViewController*)vc {
    UIViewController* rootVC = [self getRootViewController];
    [rootVC presentViewController:vc animated:YES 
      completion:nil];
}

The above three methods set up a few things needed by authenticateLocalPlayer:

  1. The lastError property is declared as a readonly property. Hence, you cannot assign to it directly. So you need a setter method that will take care of setting the lastError property. That’s what setLastError: is.
  2. The Game Center login controller needs to be displayed to the user so that s/he can actually login. The presentViewController: and getRootViewController methods handle discovering the root view controller for the application and then displaying the login view via the root view controller.

Awesome! Now it’s time to put GameKitHelper to the test. Open Prefix.pch and add the necessary import:

#import "GameKitHelper.h"

Next, open MenuLayer.m and add the following code to onEnter (right below the initial [super onEnter]). This will authenticate the player every time the menu screen is presented

[[GameKitHelper sharedGameKitHelper]
                authenticateLocalPlayer];

Build and run the application, and now when the menu view controller appears you will see one of the following screens:

The image on the left shows the login view controller, presented in case the user was not logged in with Game Center. The image on the right shows the welcome banner, displayed every time an authentication call is successful.

Note: To test the authentication, first logout of Game Center and then login through the MonkeyJump app. This will run Game Center in sandbox mode. Additionally, this probably will not work on the Simulator (at least, it didn’t work at the time of writing). You would need to test this on an actual device.

Ali Hafizji

Contributors

Ali Hafizji

Author

Over 300 content creators. Join our team.