Beginning Turn-Based Gaming with iOS 5 Part 1

Jake Gundersen Jake Gundersen

This post is also available in: Chinese (Simplified), French, Russian, Spanish

Learn how to make a turn-based game with Game Center in iOS 5!

Learn how to make a turn-based game with Game Center in iOS 5!

Update 10/24/12: If you’d like a new version of this tutorial fully updated for iOS 6 and Xcode 4.5, check out iOS 5 by Tutorials Second Edition!

Note from Ray: This is the sixth iOS 5 tutorial in the iOS 5 Feast! This tutorial is a free preview chapter from our new book iOS 5 By Tutorials. Enjoy!

This is a blog post by iOS Tutorial Team member Jacob Gundersen, an indie game developer who runs the Indie Ambitions blog. Check out his latest app – Factor Samurai!

In iOS5, Game Center has a new API that makes it even easier to create another type of game: turn-based games!

This new API is perfect for board games, turn-based strategy, word games, and other types of casual turn-based games. You can take a turn in your game, wait for your friend to take his turn, and then get notified when it’s your turn again!

In this tutorial we will build a simple UIKit based game called “Spinning Yarn”, where you take turns writing a story together with a friend.

This is a two part tutorial series. In the this first part of the series, we are going to focus on getting the basic project and matchmaking working. In the next part of the series, we’ll wrap up sending turns and complete our simple turn-based game!

Note that to get the most out of this tutorial, you will need two different devices for testing and two separate Game Center sandbox accounts. I know this is annoying for testing, but it’s an unfortunate fact of life for Game Center development!

And now it’s your turn: keep reading to make a cool turn-based game!

Turn-Based Gaming Overview

In a turn-based game, only one player can affect the game state at a time. This player will hold the baton, or the game state. They will take a turn, which will change the game state, then pass the turn on with the new game state.

However, other players will have ability to observe matches in between their turns. Because the games, or matches, don’t require our constant attention, but can be visited, played, and the we can do other things while we wait, we can be in the middle of many games at once. Because of this, in our game we’ll give the players the ability to switch between the matches they’re currently in.

Here are the major classes in the Turn-Based Gaming API, which we’ll be covering in detail in this tutorial:

  • GKTurnBasedMatch: Contains all the information and game state for a match. We’ll use this object to encapsulate the match players, the match game state, and the important information about who holds the turn and who’s still playing.
  • GKTurnBasedMatchmakerViewController: This will be our primary UI element for interacting with matches, switching between matches, and creating new matches. We’ll use it as our command center.
  • GKTurnBasedEventHandlerDelegate: We will make a helper class implement this protocol, so we can get notifications when the turn moves from player to player, when we are invited to a new match, or when the game ends.

Note that the Game Center app will automatically keep track of who we are playing with and other data about our game, so users can always switch to Game Center to see their game status.

The SpinningYarn Game

If you harken back to your days in grade school, you may remember a writing exercise where each child started writing a story. After a certain period, you passed your paper to your neighbor and he gave you his. You read what he wrote and continued the story. This continued back and forth until you ended up with a story, often with hilarious results!

This is the turn-based game we’ll be making in this tutorial. I’ve made a starter project that contains the UI already made, so we can keep the focus mainly on the Turn-Based Gaming APIs.

So go ahead and download the resources for this tutorial, and you’ll find a starter project inside. Open it up in Xcode and run it. You should see the following UI:

Turn Based Gaming Starter Project

Right now this project just contains a text view displaying some sample text, and a text field at the bottom of the screen that you can enter text into. Note it doesn’t actually do anything yet – it’s just placeholder code for now. The app also has a pretty paper background (thanks to playingwithbrushes on Flickr!)

Feel free to look at ViewController.xib to see how the UI is arranged, and take a look at ViewController.m to see the code (it’s very simple at this point). We’ll convert the project into a fully functional game from here!

Setting up Game Center

Before you can start writing any Game Center code, you need to do two things:

  1. Create and set an App ID
  2. Register your app in iTunes Connect

Let’s go through each of these in turn.

Create and Set an App ID

The first step is to create and set an App ID. To do this, log onto the iOS Dev Center, and from there log onto the iOS Provisioning Portal.

From there, select the App IDs tab, and create a new App ID for your app, similar to the following (except you’ll be choosing different values):

Creating a new App ID in the iOS Provisioning Portal

The most important part is the Bundle Identifier – you need to set this to a unique string (so it can’t be the same as the one I used!). It’s usually good practice to use a domain name you control followed by a unique string to avoid name collisions.

Once you’re done, click Submit. Then open the SpinningYarn Xcode project, select the spinningyarn target, and in the Summary tab set your Bundle identifier to whatever you entered in the iOS Provisioning portal, as shown below (except you’ll be entering a different value):

Setting the bundle identifier in Xcode

One last thing. Xcode sometimes gets confused when you change your bundle identifier mid-project, so to make sure everything’s dandy take the following steps:

  • Delete any copies of the app currently on your simulator or device
  • Quit your simulator if it’s running
  • Do a clean build with Project\Clean

Congrats – now you have an App ID for your app, and your app is set up to use it! Next you can register your app with iTunes Connect and enable Game Center.

Register your app in iTunes Connect

The next step is to log on to iTunes Connect and create a new entry for your app.

Once you’re logged onto iTunes Connect, select Manage Your Applications, and then click the blue “Add New App” button in the upper left.

On the first screen, enter Spinning Yarn for the App Name, 311 for SKU Number, and select the bundle ID you created earlier, similar to the screenshot below:

Creating a new App in iTunes

Click continue, and follow the prompts to set up some basic information about your app. Note you will probably have to change the name, since I’ve already taken the Spinning Yarn name :]

Don’t worry about the exact values to put in, since it doesn’t really matter and you can change any of this later – you just need to put something (including a dummy icon and screenshot) in to make iTunes Connect happy.

When you’re done, click Save, and if all works well you should be in the “Prepare for Upload” stage and will see a screen like this:

App in Ready to Upload Stage

Click the blue “Manage Game Center” button to the upper right, click the big blue “Enable” button, and click “Done.” That’s it – Game Center is enabled for your app, and you’re ready to write some code!

Update 6/3/12 RedQuark from the forums points out that this is no longer the only step:

“PROBLEM SOLVED! There is a second place you need to enable Game Center in iTunes Connect. Click “View Details” under your app’s icon (under “Versions”) and enable Game Center there too. This should probably be added to the chapter/tutorial.

Here’s the thing though: I had done that already! Somehow, iTunes Connect turned it back off all on its own. At least now I know what to look for should it happen again.”

By the way – inside the “Manage Game Center” section, you might have noticed some options to set up Leaderboards or Achievements. We won’t be using those in this book, but if you ever need them that’s where they are!

Authenticate the Local Player: Strategy

When your game starts up, the first thing you need to do is authenticate the local player.

You can think of this as “logging the player into Game Center.” If he’s already logged in, it will say “Welcome back!” Otherwise, it will ask for the player’s username and password.

Authenticating the local user is easy – you just call authenticateWithCompletionHandler. You can optionally pass in a block of code that will be called once the user is authenticated.

But there’s a trick. There’s another way for the user to log in (or log out!). He can be using your app, switch to the Game Center app, log or out from there, and switch back to your app.

So your app needs to know whenever the authentication status changes. You can find out about these by registering for an “authentication changed” notification.

So, our strategy to authenticate the player will be as follows:

  • Create a singleton object to keep all the Game Center code in one spot.
  • When the singleton object starts up, it will register for the “authentication changed” notification.
  • The game will call a method on the singleton object to authenticate the user.
  • Whenever the user is authenticated (or logs out), the “authentication changed” callback will be called.
  • The callback will keep track of whether the user is currently authenticated, for use later.

Now that you’re armed with this plan, let’s try it out!

Authenticate the Local User: Implementation

In the SpinningYarn Xcode project, create a new file with the Objective-C class template. Name the class GCTurnBasedMatchHelper and make it a subclass of NSObject.

Then replace GCTurnBasedMatchHelper.h with the following:

#import <Foundation/Foundation.h>
#import <GameKit/GameKit.h>
 
@interface GCTurnBasedMatchHelper : NSObject {
    BOOL gameCenterAvailable;
    BOOL userAuthenticated;
}
 
@property (assign, readonly) BOOL gameCenterAvailable;
 
+ (GCTurnBasedMatchHelper *)sharedInstance;
- (void)authenticateLocalUser;
 
@end

This imports the GameKit header file, and then creates an object with two booleans – one to keep track of if game center is available on this device, and one to keep track of whether the user is currently authenticated.

It also creates a property so the game can tell if game center is available, a static method to retrieve the singleton instance of this class, and another method to authenticate the local user (which will be called when the app starts up).

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

@synthesize gameCenterAvailable;
 
#pragma mark Initialization
 
static GCTurnBasedMatchHelper *sharedHelper = nil;
+ (GCTurnBasedMatchHelper *) sharedInstance {
    if (!sharedHelper) {
        sharedHelper = [[GCTurnBasedMatchHelper alloc] init];
    }
    return sharedHelper;
}

This synthesizes the gameCenterAvailable property, then defines the method to create the singleton instance of this class.

Note there are many ways of writing singleton methods, but this is the simplest way when you don’t have to worry about multiple threads trying to initialize the singleton at the same time.

Next add the following method right after the sharedInstance method:

- (BOOL)isGameCenterAvailable {
    // check for presence of GKLocalPlayer API
    Class gcClass = (NSClassFromString(@"GKLocalPlayer"));
 
    // check if the device is running iOS 4.1 or later
    NSString *reqSysVer = @"4.1";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    BOOL osVersionSupported = ([currSysVer compare:reqSysVer     
      options:NSNumericSearch] != NSOrderedAscending);
 
    return (gcClass && osVersionSupported);
}

This method is straight from Apple’s Game Kit Programming Guide. It’s the way to check if Game Kit is available on the current device.

By making sure Game Kit is available before using it, this app can still run on iOS 4.0 or earlier (just without network capabilities).

Next add the following right after the isGameCenterAvailable method:

 
- (id)init {
    if ((self = [super init])) {
        gameCenterAvailable = [self isGameCenterAvailable];
        if (gameCenterAvailable) {
            NSNotificationCenter *nc = 
            [NSNotificationCenter defaultCenter];
            [nc addObserver:self 
              selector:@selector(authenticationChanged) 
              name:GKPlayerAuthenticationDidChangeNotificationName 
              object:nil];
        }
    }
    return self;
}
 
- (void)authenticationChanged {    
 
    if ([GKLocalPlayer localPlayer].isAuthenticated && 
      !userAuthenticated) {
        NSLog(@"Authentication changed: player authenticated.");
        userAuthenticated = TRUE;           
    } else if (![GKLocalPlayer localPlayer].isAuthenticated && 
      userAuthenticated) {
        NSLog(@"Authentication changed: player not authenticated");
        userAuthenticated = FALSE;
    }
 
}

The init method checks to see if Game Center is available, and if so registers for the “authentication changed” notification. It’s important that the app registers for this notification before attempting to authenticate the user, so that it’s called when the authentication completes.

The authenticationChanged callback is very simple at this point – it checks to see whether the change was due to the user being authenticate or deauthenticated, and updates a status flag accordingly.

Note that in practice this might be called several times in a row for authentication or deauthentication, so by making sure the userAuthenticated flag is different than the current status, it only logs if there’s a change since last time.

Finally, add the method to authenticate the local user right after the authenticationChanged method:

#pragma mark User functions
 
- (void)authenticateLocalUser { 
 
    if (!gameCenterAvailable) return;
 
    NSLog(@"Authenticating local user...");
    if ([GKLocalPlayer localPlayer].authenticated == NO) {     
        [[GKLocalPlayer localPlayer] 
            authenticateWithCompletionHandler:nil];        
    } else {
        NSLog(@"Already authenticated!");
    }
}

This calls the authenticateWithCompletionHandler method mentioned earlier to tell Game Kit to authenticate the user. Note it doesn’t pass in a completion handler. Since you’ve already registered for the “authentication changed” notification it’s not necessary.

OK – GCTurnBasedMatchHelper now contains all of the code necessary to authenticate the user, so you just have to use it! Switch to AppDelegate.m and make the following changes:

// At the top of the file
#import "GCTurnBasedMatchHelper.h"
 
// At the end of applicationDidFinishLaunching, right before 
// the return YES
[[GCTurnBasedMatchHelper sharedInstance] authenticateLocalUser];

This creates the Singleton instance (which registers for the “authentication changed” callback as part of initialization), then calls the authenticateLocalUser method.

Usually you’d have to add the Game Kit framework to your project as well, but I’ve already added this for you in the Build Phases\Link Binary with Libraries section of your target settings.

That’s it! Compile and run your project, and if you’re logged into Game Center you should see something like the following:

Welcome Back from Game Center

Turn-Based Gaming Basics

Now that we’re successfully authenticating with Game Center and have a starter project ready, we’re ready to start talking about the meat of this tutorial: Turn-Based Gaming.

In a turn-based game, you don’t need to play at the same time as our opponents (although you can be). For example, you can take your turn while your friend is asleep, and then they can wake up, take their turn while you’re showering, and so on. A player can be in the middle of playing many of these asynchronous matches at the same time.

Visualize control of the game as a baton in a relay race. Only one player can hold the baton (or take a turn) at a time. When the baton is passed, it needs to contain everything that the player needs to know about that game.

To understand more about how it works, let’s start by reviewing the Turn-Based Gaming classes in more detail.

GKTurnBasedMatch

This class stores information about an individual match, such as:

  • creationDate: The date that the match was first created.
    currentParticipant: The GKTurnBasedParticipant who currently holds the baton (his/her turn). More on this below.
  • matchID: An NSString uniquely identifying the match. This is typically long and not easily readable.
  • message: An NSString to be displayed to help the user identify the match in the GKTurnBasedMatchmakerViewController. You can set this to whatever you want.
  • participants: An NSArray of all GKTurnBasedParticipants who are included in the match (includes those who have quit).
  • status: The current state of the match, as an GKTurnBasedMatchStatus. Includes values like Open, Ended, Matching, etc.

GKTurnBasedParticipant

This class stores information about an individual player, such as:

  • playerID: An NSString unique identifier about the player, never changes. This is not the same as the user’s Game Center nickname, and you should usually not display this because it isn’t easily readable.
  • lastTurnDate: An NSDate of last turn. This is null until the player has taken a turn.
  • matchOutcome: The outcome of the match as a GKTurnBasedMatchOutcome. Includes values such as Won, Lost, Tied, 3rd etc.
    status: The current state of the player, as a GKTurnBasedParticipantStatus. Includes values like Invited, Declined, Active, Done, etc.

GKTurnBasedMatchmakerViewController

This is the standard user interface written by Apple to help players work with turn-based gaming matches. It allows players to:

  • Create matches. You can use this view controller to create matches, either by auto match or by invitation. When you create a new match, you get to play the first turn right away (even if the system hasn’t found an auto match partner yet!) When the system has found someone and they take their turn, you’ll get a notification again. Note that there is currently no programmatic was to create new matches except by using this controller.
  • Switch matches. As discussed earlier, you can have many turn-based games going on at once. You can use this view controller to view different games you’re playing – even if it’s not your turn or the game is over (you can view the current game state in that case).
  • Quit matches. Finally, you can use the view controller to quit from a match you no longer want to play.

GKMatchRequest

You use this to initialize a GKTurnBasedMatchmakerViewController, much the same way you create a match for normal (live) Game Center multiplayer games.

When you create a GKMatchRequest, you specify a minimum and maximum number of players. You can also segment players (by location, skill level, custom groups, etc.) using this object.

GKTurnBasedMatchmakerViewControllerDelegate

When you create a GKTurnBasedMatchmakerViewController, you can specify a delegate that implements this protocol. It provides callback methods for when the view controller loads a new match, cancels, fails due to error, etc.

GKTurnBasedEventHandler

Last but not least, this singleton class has a delegate protocol, GKTurnBasedEventHandlerDelegate that provides notifications when the turn passes from one player to another, when we’re invited by a friend to a match, or when the game ends.

Apple’s Turn Based Match View Controller

The first thing we need to do to play a turn-based match is create one! As discussed above, we can do that using Apple’s provided GKTurnBasedMatchmakerViewController, so let’s create a button we can to presend it to the screen.

Add the gameCenterButton.png file from the resources for this tutorial into your project, and add a new button to the ViewController.xib as shown below:

Adding the present method

Once you’ve added the button, set its type to Custom in the Attributes Inspector, and the Image to gameCenterButton.png. You can hit command equals to easily autosize the button to the same size as the image.

Then make sure the Assistant Editor is up and showing ViewController.h, and control-drag from the button down below the @interface. Set the Connection type to Action, name the method presentGCTurnViewController, and click Connect.

Note: Although I’m using the Game Center icon for this tutorial, you shouldn’t use the game center icon in your apps. This practice is discouraged by Apple, and may cause an app to be rejected. Their reasoning is that Game Center is not just the view controller, it is leaderboards, achievements, view controllers (turn based and live) and using this button creates an inconsistent user experience across different apps. So in your apps, you should use some other kind of visual icon or button.

Now, we’re not actually going to do the heavy lifting to present the GKTurnBasedMatchmakerViewController inside our ViewController class. Rather, we’ll let the GCTurnBasedMatchHelper class do all that work for us. This way, the Game Center code will be nicely separated and more easily reusable in future projects.

So open up GCTurnBasedMatchHelper.h and add a new instance variable and method into the header:

// New instance variable
UIViewController *presentingViewController;
 
// New method
- (void)findMatchWithMinPlayers:(int)minPlayers 
  maxPlayers:(int)maxPlayers 
  viewController:(UIViewController *)viewController;

Here we create a new variable to store the view controller that will present the GKTurnBasedMatchmakerViewController, and a method that we’ll use to present it to the screen to find a match with a specified number of players.

Next switch to GCTurnBasedMatchHelper.m and add the following method after authenticateLocalUser:

- (void)findMatchWithMinPlayers:(int)minPlayers 
  maxPlayers:(int)maxPlayers 
  viewController:(UIViewController *)viewController {
    if (!gameCenterAvailable) return;               
 
    presentingViewController = viewController;
 
    GKMatchRequest *request = [[GKMatchRequest alloc] init]; 
    request.minPlayers = minPlayers;     
    request.maxPlayers = maxPlayers;
 
    GKTurnBasedMatchmakerViewController *mmvc = 
      [[GKTurnBasedMatchmakerViewController alloc] 
        initWithMatchRequest:request];    
    mmvc.turnBasedMatchmakerDelegate = self;
    mmvc.showExistingMatches = YES;
 
    [presentingViewController presentModalViewController:mmvc 
      animated:YES];
}

First we check the status of gameCenterAvailable. We can’t do anything if game center isn’t connected, so in that case we bail.

If we’re connected, then we set up a GKMatchRequest. This object is the same as we would use for any multiplayer game center game. We are setting the minimum and maximum players for the request. It will control the GKTurnBasedViewController, not allowing us to include more than our max players or less than our min players.

We’re going to let up to 12 players play a game of SpinningYarn at a time. Because the game isn’t live, the amount of data and bandwidth required for a turn-based game is less intensive and so it’s easier to have many players in a game. 4 players is the maximum for a live multiplayer game, but the turn-based game can support up to 16!

We then create a new GKTurnBasedMatchmakerViewController, passing in the GKMatchRequest. We set the delegate of that object to self (GCTurnBasedMatchHelper). This will throw an error which we’ll fix soon.

Then we set the showExistingMatches property to YES. This property controls what’s presented to the user. If we set it to YES then we’ll see all the matches we have been involved in. This includes current matches where it’s the player’s turn, matches where it’s some other player’s turn, and matches that have ended.

There’s a ‘+’ button on the top right that can be used to create a new game. This presents a view that starts with the minimum number of players, and we can add players until we reach the specified max. Each slot can be filled with an invitation to a specific player, or can be an automatch slot. If we set the showExistingMatches property to NO, then we’ll be presented only with the create new game view.

Almost done – we just need to call this new method. Open ViewController.h and import the helper’s header at the top of the file:

#import "GCTurnBasedMatchHelper.h"

Then switch to ViewController.m and implement presentGCTurnViewController as follows:

- (IBAction)presentGCTurnViewController:(id)sender {
    [[GCTurnBasedMatchHelper sharedInstance] 
      findMatchWithMinPlayers:2 maxPlayers:12 viewController:self];
}

If you build and run now you’ll see the GKTurnBasedMatchmakerViewController presented when you tap the game center button:

Creating a new match in Game Center

Of course, if you try to create a match or do anything else, the game will crash, because we haven’t implemented the delegate methods yet! So let’s fix that next.

Implementing the Matchmaker View Controller Delegate

The first step is to open GCTurnBasedMatchHelper.h and modify the @interface as follows:

@interface GCTurnBasedMatchHelper : NSObject 
  <GKTurnBasedMatchmakerViewControllerDelegate> {

Here we simply mark our helper class as implementing the delegate protocol for the matchmaker view controller.

Next, switch to GCTurnBasedMatchHelper.m and add some placeholder implementations of the protocol at the end of the file:

#pragma mark GKTurnBasedMatchmakerViewControllerDelegate
 
-(void)turnBasedMatchmakerViewController: 
  (GKTurnBasedMatchmakerViewController *)viewController 
  didFindMatch:(GKTurnBasedMatch *)match {
    [presentingViewController 
      dismissModalViewControllerAnimated:YES];
    NSLog(@"did find match, %@", match);
}
 
-(void)turnBasedMatchmakerViewControllerWasCancelled: 
  (GKTurnBasedMatchmakerViewController *)viewController {
    [presentingViewController 
      dismissModalViewControllerAnimated:YES];
    NSLog(@"has cancelled");
}
 
-(void)turnBasedMatchmakerViewController: 
  (GKTurnBasedMatchmakerViewController *)viewController 
  didFailWithError:(NSError *)error {
    [presentingViewController 
      dismissModalViewControllerAnimated:YES];
    NSLog(@"Error finding match: %@", error.localizedDescription);
}
 
-(void)turnBasedMatchmakerViewController: 
  (GKTurnBasedMatchmakerViewController *)viewController 
  playerQuitForMatch:(GKTurnBasedMatch *)match {
    NSLog(@"playerquitforMatch, %@, %@", 
      match, match.currentParticipant);
}
 
@end

The first method (didFindMatch) is fired when the user selects a match from the list of matches. This match could be one where it’s currently our player’s turn, where it’s another player’s turn, or where the match has ended.

The second method (wasCancelled) will fire when the cancel button is clicked.

The third method (didFail) fires when there’s an error. This could occur because we’ve lost connectivity or for a variety of other reasons.

The final method (playerQuitForMatch) method is fired when a player swipes a match (while it’s their turn) and quits it. Swiping a match will reveal a quit (if it’s a match that is still active) or remove button. If a player quits a match while it’s still their turn, they need to handle the match, update it’s state, and pass it along to the next player. If a player were to quit without passing the turn on to the next player, the match would not be able to progress forward!

A match that is finished will stay on Apple’s servers and can be viewed by players that participated in it. If one player removes the match, it will no longer show up in that player’s list of matches. However, because there are multiple players involved in a match, that match data still persists on the Game Center servers until all players have removed it.

For now, or each of these methods we’re just dismissing the view controller and logging out some information. An exception is the playerQuit method, where we don’t dismiss the view controller, because the user might want to keep doing something else.

Build and run now. Start a new match with an auto-matched player and you should have a log that looks like the following:

Console showing turn based match found

Note how the view controller dismisses immediately after you start a new match, even though it couldn’t possibly have found a player to join your game yet! If you look at the logs, you’ll see one of the GKTurnBasedParticipants is yourself (the local player) and the second has an id of null (it hasn’t found a partner for you yet).

Keep playing around to see if you can get the other log messages to appear. If you press the cancel button, or swipe a started match, you should see the cancelled or player quit messages, and if you disconnect your network and try to start a match you’ll see the did fail message.

Console showing player quit

Congratulations, you have successfully created a turn-based match between two devices!

Take a well-deserved breather for now, and in the next tutorial we’ll add the fun part – sending the turns and completing our simple turn-based game!

Where To Go From Here?

In the second part of the tutorial, we’ll add in the code so players can send turns back and forth, and end up with a simple but fun turn-based game!

This tutorial is part of our new book iOS 5 By Tutorials. If you like this tutorial you might want to consider picking up the book – we have another entire chapter on turn-based gaming over and above what we’re posting for free here! :]

If you have any questions or comments on this tutorial or on turn-based gaming in iOS 5 in general, please join the forum discussion below!

This is a blog post by iOS Tutorial Team member Jacob Gundersen, an indie game developer and co-founder of Third Rail Games. Check out his latest app – Factor Samurai!

Jake Gundersen
Jake Gundersen

Jacob is an indie game developer and runs the Indie Ambitions blog. Check out his latest app - Factor Samurai! You can find him on Twitter.

User Comments

38 Comments

[ 1 , 2 , 3 ]
  • I think I may have jumped the gun early on my previous post.
    After giving up and leaving the 2 devices running, I noticed when I cam back about 1/2 an hour later that the turn had actually been passed and the other device notified.
    After the first few turns happened almost instantly, I was not waiting long enough, some of my turns on the sandbox devices can take up yo 5-10 minutes to either send or receive the notification

    Paul
    c4digit
  • Just a quick one. If you got 2 or more simultaneous games and its your turn, would it be easy to add a "next game" button on the game screen?
    zeiteisen
  • Thank you for nice tutorial.

    Just one question.

    In this example we use callbacks handleTurnEventForMatch and turnBasedMatchmakerViewController for taking match status after opponent's turn
    inside methods we can bind our current view with match in Game Center self.currentMatch = match;

    is it possible to bind any game's view with some match in game center without GameCenter interface (now: open GKTurnBasedMatchmakerViewController -> select some game and after waiting callback in didFindMatch)

    for example: we have root controller with list of games and game controller

    is it possible to select already played game in game's list (open game controller) and set self.currentMatch for this match using already saved matchID or something else (without callback didFindMatch)

    Thanks for answer
    sankey
  • Hi,

    I've been happily using spinningyarn as a basis to learn how turn based gaming work on ios. I've also been able to implement my game to a playable version. But for the past 2 days, my game stopped working. I narrow it down at endTurnWithNextParticipant. GameCenter returns the following error;

    "The requested operation could not be completed due to an error communicating with the server." UserInfo=0x10c48f90 {NSUnderlyingError=0x10cc72f0 "The operation couldnt be completed. status = 5008, missing required key: turns", NSLocalizedDescription=The requested operation could not be completed due to an error communicating with the server.}

    Can't figure out what was going since it's been working fine for over a few weeks. Just for sanity check, I ran the spinningyarn demo and I also hit the same problem. I'm suspecting something is going on on the server side but I can't be sure. Was wondering whether you can confirm this. Thanks and great work on the demo. It has been immensely helpful to me and I'm sure for a lot of other dev.
    hafiz.awang
  • Any updates to the issue of handleTurnEventForMatch not getting called? I only receive the notifications about 20% of the time.
    Bartos88
  • Hi evryone
    I got a little question about this tutorial. I'm wondering how can use classes created before part "Apples Turn Based Match View Controller"
    without using view in Xcode 5.0 (i'm also using cocos2D 2.x). Because i already have create all stuff and just want to add GameCenter to make turn gaming.

    In an other way i got one semantic issue in GCTurnBasedMatchHelper.m
    //at this line
    mmvc.turnBasedMatchmakerDelegate = self;
    //Assigning to 'id' from incompatible type 'GCTurnBasedMatchHelper *'

    So if anyone as a suggestion about those things ?
    Nomad
  • sorry for the issue message that was this one ->
    Assigning to id from incompatible type GCTurnBasedMatchHelper *
    Nomad
  • Assigning to id GKTurnBasedMatchmakerViewControllerDelegate from incompatible type GCTurnBasedMatchHelper *
    Nomad
[ 1 , 2 , 3 ]

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in May: Procedural Level Generation in Games with Kim Pedersen.

Sign Up - May

Coming up in June: WWDC Keynote - Podcasters React! with the podcasting team.

Sign Up - June

Vote For Our Next Book!

Help us choose the topic for our next book we write! (Choose up to three topics.)

    Loading ... Loading ...

Our Books

Our Team

Tutorial Team

... 55 total!

Editorial Team

  • John Clem

... 22 total!

Code Team

  • Orta Therox

... 1 total!

Translation Team

  • Niccolò Passolunghi
  • Przemysław Rembelski

... 38 total!

Subject Matter Experts

  • Richard Casey

... 4 total!