Game Center Tutorial: How To Make A Simple Multiplayer Game with Sprite Kit: Part 1/2

Learn how to make a simple multiplayer racing game with Sprite Kit in this Game Center tutorial! 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.

Authenticate the Local User: Implementation

In the Cat Race Xcode project, right click on the CatRaceStarter group and select New Group.

Name the group GameKit. Next, right-click on the newly-created group and select New File…, choose the Objective-C class template and click Next. Name the class GameKitHelper, make it a subclass of NSObject and click Next again. Be sure the CatRaceStarter target is checked and click Create.

Replace GameKitHelper.h with the following:

@import GameKit;

@interface GameKitHelper : NSObject

@property (nonatomic, readonly) UIViewController *authenticationViewController;
@property (nonatomic, readonly) NSError *lastError;

+ (instancetype)sharedGameKitHelper;

@end

This imports the GameKit header file, and then defines two properties – one is a view controller and the other is used to keep track of the last error that occurred while interacting with Game Center APIs. You will learn more about these properties in the sections to come.

Next switch to GameKitHelper.m and add the following right inside the @implementation section:

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

The above method is straightforward. All you are doing here is creating and returning a singleton object.

Next, while still in GameKitHelper.m, add a private instance variable to track if game center is enabled or not as shown below:

@implementation GameKitHelper {
    BOOL _enableGameCenter;
}

Also add the following initializer method to the implementation section. This method will simply set the above variable to true. Hence by default we assume that Game center is enabled.

- (id)init
{
    self = [super init];
    if (self) {
      _enableGameCenter = YES;
    }
    return self;
}

Now it’s time to add the method that will authenticate the local player. Add the following to the implementation section.

- (void)authenticateLocalPlayer
{
    //1
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    
    //2
    localPlayer.authenticateHandler  =
    ^(UIViewController *viewController, NSError *error) {
        //3
        [self setLastError:error];
        
        if(viewController != nil) {
            //4
            [self setAuthenticationViewController:viewController];
        } else if([GKLocalPlayer localPlayer].isAuthenticated) {
            //5
            _enableGameCenter = YES;
        } else {
            //6
            _enableGameCenter = NO;
        }
    };
}

- (void)setAuthenticationViewController:(UIViewController *)authenticationViewController
{
}

- (void)setLastError:(NSError *)error
{
}

It seems like a lot of code, let’s go through it step-by-step to understand how the player is authenticated:

  1. First you get an instance of the GKLocalPlayer class. This instance represents the player who is currently authenticated through Game Center on this device. Only one player may be authenticated at a time.
  2. Set the authenticateHandler of the GKLocalPlayer object. GameKit may call this handler multiple times.
  3. Store any error the callback may have received using the setLastError: method.
  4. If the player has not logged into Game Center either using the Game Center app or while playing another game, the Game Kit framework will pass a view controller to the authenticateHandler. It is your duty as the game’s developer to present this view controller to the user when you think it’s feasible. Ideally, you should do this as soon as possible. You will store this view controller in an instance variable using setAuthenticationViewController:. This is an empty method for now, but you’ll implement it in a moment.
  5. If the player has already logged in to Game Center, then the authenticated property of the GKLocalPlayer object is true. When this occurs, you enable all Game Center features by setting the _enableGameCenter boolean variable to YES.
  6. If the user did not sign in – perhaps they pressed the Cancel button or login was unsuccessful – you need to turn off all Game Center features. This is because, Game Center features are only available if the local player has logged in.

Since the authentication process happens in the background, the game might call the player’s authenticateHandler while the user is navigating through the screens of the game or even while the player is racing.

In a situation like this, you’re going to follow this strategy: whenever the game needs to present the GameKit authentication view controller, you will raise a notification, and whichever view controller is presently onscreen will be responsible for displaying it.

First you need to define the notification name. Add this line at the top of GameKitHelper.m:

NSString *const PresentAuthenticationViewController = @"present_authentication_view_controller";

Now add the following code inside setAuthenticationViewController::

if (authenticationViewController != nil) {
  _authenticationViewController = authenticationViewController;
  [[NSNotificationCenter defaultCenter]
   postNotificationName:PresentAuthenticationViewController
   object:self];
}

This simply stores the view controller and sends the notification.

The last method you need to fill out is setLastError:. This method will keep track of the last error that occurred while communicating with the GameKit service. Add the following code inside setLastError::

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

This simply logs the error to the console and stores the error for safekeeping.

Next, open GameKitHelper.h and add the following extern statement above the interface section:

extern NSString *const PresentAuthenticationViewController;

Next, add the following method declaration to the same file.

- (void)authenticateLocalPlayer;

You now have all the code in place to authenticate the local player. All you need to do is call the above method at the appropriate place.

Adding Game Center authentication to CatRace

Let’s pause for a moment and think about the architecture of the game. The game currently has two view controllers, one that runs the actual game and the other that shows the end result (i.e. whether the player has won or lost). To navigate between these two screens, the app uses a navigation controller.

To get a better idea about the structure, take a look at Main.storyboard:

Storyboard

Since navigation in the app is controller by the navigation controller you’re going to add a call to authenticate the local player there. Open GameNavigationViewController.m and replace its contents with the following:

#import "GameNavigationController.h"
#import "GameKitHelper.h"

@implementation GameNavigationController

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    [[NSNotificationCenter defaultCenter]
       addObserver:self
       selector:@selector(showAuthenticationViewController)
       name:PresentAuthenticationViewController
       object:nil];
    
    [[GameKitHelper sharedGameKitHelper]
        authenticateLocalPlayer];
}
@end

All you’re doing here is registering for the PresentAuthenticationViewController notification and making a call to the authenticateLocalPlayer method of GameKitHelper.

When the notification is received you need to present the authentication view controller returned by GameKit. To do this add the following methods to the same file.

- (void)showAuthenticationViewController
{
    GameKitHelper *gameKitHelper =
      [GameKitHelper sharedGameKitHelper];
  
    [self.topViewController presentViewController:
       gameKitHelper.authenticationViewController
                                         animated:YES
                                       completion:nil];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

The showAuthenticationViewController method will be invoked when the PresentAuthenticationViewController notification is received. This method will present the authentication view controller to the user over the top view controller in the navigation stack.

Time to build and run! If you haven’t logged into Game Center before the game will present the following view:

game_center_login

Enter your game center credentials and press Go. The next time you launch the game, Game Center will present a banner similar to the one shown below:

Game Center banner

Note: When you build a game in Debug mode the system automatically talks to Game Center’s sandbox servers, which you can think of as a “test area” before the app goes live. You can see that you’re in the sandbox by the *** Sandbox *** notification when you login. When you ship your app, it will automatically switch to production.
Ali Hafizji

Contributors

Ali Hafizji

Author

Over 300 content creators. Join our team.