Topics

#64: Turn Based Games 🎲

Topics

Game Center makes it simple to create a multiplayer, turn-based game. It handles matchmaking, turn expirations and much more. Let's take a look at how to use it. First, we'll authenticate the local player (shown in Bite #57), then register a listener on it:


GKLocalPlayer.localPlayer().registerListener(self)

We describe our game's player setup in a match request, then hand it to a new matchmaker view controller.

let r = GKMatchRequest()

r.minPlayers = 2; r.maxPlayers = 2
r.defaultNumberOfPlayers = 2

let vc = GKTurnBasedMatchmakerViewController(
  matchRequest: r
)

vc.turnBasedMatchmakerDelegate = self

presentViewController(vc, animated: true, completion: nil)

At the start of each turn, we download the latest match data from Game Center, and modify it as the player plays. Then at the end of each turn we send our modified match data object back up to Game Center, so other players can download it. We need to download updated match data when the match begins and when our *local player's *turn starts.

For this we implement two functions from two different protocols:

// GKTurnBasedMatchmakerViewControllerDelegate
func turnBasedMatchmakerViewController(viewController: GKTurnBasedMatchmakerViewController, didFindMatch match: GKTurnBasedMatch) {
  dismissViewControllerAnimated(true) { self.updateCurrentMatchData(match) }
}

// GKLocalPlayerListener
func player(player: GKPlayer, receivedTurnEventForMatch match: GKTurnBasedMatch, didBecomeActive: Bool) {
  updateCurrentMatchData(match)
}

When our local player completes their turn, we end the turn and tell Game Center which of the match's participants should go next (only 2 in our case, so we always send the other player):

updateMatchData(wordPlayed)

currentMatch?.endTurnWithNextParticipants(
  [opponent()],
  turnTimeout: GKTurnTimeoutDefault,
  matchData: matchData,
  completionHandler: nil
)

Finally, when someone wins, we set their matchOutcome to .Won and end the match:

let winner = decideWinner()

winner.matchOutcome = .Won

currentMatch?.endMatchInTurnWithMatchData(
  matchData,
  completionHandler: nil
)