Game Center for iOS: Building a Turn-Based Game | raywenderlich.com

In this tutorial, you’ll learn about authentication with Game Center and how its turn-based mechanics work. In the end, you’ll have the foundations of how to integrate a multiplayer game with GameCenter.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/7544-game-center-for-ios-building-a-turn-based-game

Hi, I got stuck where I need to change online button state:
at this line

// MARK: - Notifications

@objc private func authenticationChanged(_ notification: Notification) {
onlineButton.isEnabled = notification.object as? Bool ?? false
}

My console says unexpectedly find nil in optional (something like this)
I am sure I followed everything exactly.

moreover, the build was fine but crashed when run on simulator.

@naturaln0va Can you please help with this when you get a chance? Thank you - much appreciated! :]

1 Like

Hello, I’m sorry this happened. I assume it’s crashing because the notification is fired before setUpScene(in:) is called. This would result in the onlineButton being nil. To fix this you’ll need to change:

@objc private func authenticationChanged(_ notification: Notification) {
  onlineButton.isEnabled = notification.object as? Bool ?? false
}

to

@objc private func authenticationChanged(_ notification: Notification) {
  onlineButton?.isEnabled = notification.object as? Bool ?? false
}

Let me know if that doesn’t work.

Hi, thank you for your solution.

Actually this was my false. When you say:

To use the authentication notification, add the following to the top of the authenticateHandler block:

NotificationCenter.default .post(name: .authenticationChanged, object: GKLocalPlayer.local.isAuthenticated)

I misunderstood and put that code on top, which was outside, the handler. It now works when I moved it in.

Thank you anyway. Your tutorial is very much enjoying for a newbie like myself.

I’m glad you got it working!

Thanks for the tutorial! One question:

I am trying to use some of the ideas here for another 2-player game, which is in many ways similar to chess but much simpler. However, there are also two “factions” and one of the always starts (similar to “white” in chess). I would like to assign players to these factions before the game (or perhaps give them the possibility to choose). What do you think would be a good way of doing this? I guess what is not very clear to me from your tutorial is how you know that a new game has started, rather than it just being your turn

would appreciate any thoughts on this

@naturaln0va Can you please help with this when you get a chance? Thank you - much appreciated! :]

Sorry for the delay in responding. I’m glad you enjoyed the tutorial!

If you’d like to determine when there is a new game you can check to see if the game model has any information. For instance, in the tutorial inside MenuScene.swift the loadAndDisplay(match: GKTurnBasedMatch) attempts to load the game’s data for a match. If there isn’t any data returned from Game Center then a new game is created.

For your question when you create a new game part of your logic can include setting a state in the model where your game scene would recognize it’s in the “select a faction” state and ask the player to choose. You can also just assign a player at this point if you’d rather not have the players choose.

I hope that helps. Let me know if I can elaborate more, or answer anything else!

Hi. I tried to run this on my iPad Air 2 and it crashed with the following error when I pressed the load Game button.
Nine Knights[664:75183] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Invalid size specified: {768, -70.9119873046875}’
The game ran fine on my iPhone. I made the following change to prevent the crash in iPad Air 2.

Class: GameScene
replace:
let skySize = CGSize(width: viewWidth, height: viewHeight - groundNode.position.y)
with:
let adjustedHeight = max(0, viewHeight - groundNode.position.y)
let skySize = CGSize(width: viewWidth, height: adjustedHeight)

This fixes the crash, but to make the screen look good on both an iPad and iPhone make additional changes:

in Class: GameScene replace:
messageNode.position = CGPoint( x: sceneMargin, y: runningYOffset - (sceneMargin * 1.25))
with:
let messageNodeHeigth = min(runningYOffset - (sceneMargin * 1.25), viewHeight - safeAreaTopInset - (sceneMargin * 3) - 50)
messageNode.position = CGPoint(x: sceneMargin, y: messageNodeHeigth)

in class MenuScene: replace:
runningYOffset -= sceneMargin + logoNode.size.height
with:
runningYOffset -= sceneMargin + logoNode.size.height + (buttonSize.height / 2)

Thanks for point this issue out! I went ahead and updated the sample project based on this. I also made the board smaller on iPad so the layout wasn’t overlapping.

This tutorial is more than six months old so questions are no longer supported at the moment for it. Thank you!