Graphics, Media, and Games • iOS • 48:20
Multiplayer games provide the ultimate challenge and have created one of the most compelling genres in the App Store. See how Game Center is taking gaming on iOS a step further with the addition of local multiplayer support. Learn about improvements to the turn-based and online multiplayer APIs and new capabilities for sending invites and having a re-match.
Speaker: Christy Warren
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good morning, everyone, and welcome to Multiplayer Gaming with Game Center. I'm Christy Warren, and I hope you're having a great WWDC. I love it here. New toys, new APIs, new fun. So I'm here to tell you about how to add multiplayer gaming to your game. I'm going to talk about our matchmaking UI, which makes it easy and quick for you to have players connect with other players to play your game.
I'm going to talk about programmatic matchmaking, which will allow you to create a more custom user experience. I'm going to talk about how to Share data between instances of your game via peer-to-peer communications. And I'm going to then take you on a tour through the world of turn-based gaming, which is a great new feature we added in iOS 5 that allows for more freeform and asynchronous gameplay.
But first let's talk about why add multiplayer to your game. Now I know that you're at a multiplayer gaming session, so you probably already want to do this. But let's talk about the benefits. How many of you out there, raise your hands if you have a game on the App Store already? Or are planning on it? Well, one of your biggest challenges, at least from what I hear and what I understand, is discoverability. You've worked long and hard and you've made your game awesome.
But it is just one game out of 650,000 apps on the App Store. And there are players like me who love games and want to play your game, but how do I discover them? Well, let's suppose I own a copy of your game and my friend Nate over here doesn't.
If it's single player, I could just wait until I see him next time. I go into the office or whatever and say, "Hey, you know, this game is awesome. Why don't you download and buy it?" If your game supports multiplayer and I own it, I can invite him to play, and he'll see this on his screen. And when he taps on this, It'll take him right to a buy button and he can buy your game. This is free and easy viral marketing that you get by just supporting multiplayer.
Furthermore, multiplayer makes your game stand out. If I just play a single player game, I'm playing against AI. I'm going to go off in the corner and play. I might earn an achievement. I killed 30 robots. Okay, whatever, move on. There's another 599,000 games on the App Store, or apps on the App Store.
But if it's multiplayer and I'm playing a game, say I'm playing a tennis game with Nate and he aces me five times and he gets the five aces achievement, I'm going to see that on his office door and I'm going to hear about it for the next two weeks.
Suddenly, your game moves from being just a personal experience to being woven into my social milieu, increases engagement and competition, and it makes those leaderboards and achievements really matter. Because suddenly, I've got to play them, I've got to beat them, I've got to make up for that mistake.
And finally, the top games in the App Store support multiplayer. If you look back over the history of gaming in the last 10 or 20 years, think about the names that stand out, that have large and long-lasting communities. Websites dedicate them, or even conventions. These games support multiplayer.
Wouldn't you like a chance for your game to gain immortality? So what's new in iOS 6? Well, we give you a new and streamlined matchmaking UI that lets your players get into your game quickly. We also give you the ability to discover players on nearby devices. So even if they're not your friends, you know, if he's running a game and she's running a game right here in this room, I can find them, connect with them, and play with them. with him. We also support, in addition to programmatic auto-match, we support programmatic invites. So now the full functionality of our standard UI is available to you programmatically, so you can make it blend better with your application or your game.
Also... Also, when your game is over, on the Game Over screen, you can add a re-match button and get your players back into the action right away. And also we support the ability to do host selection. What this means is if we have four devices, it's often a good idea to pick one device to act as the master. And now we make that really easy to do. And for turn-based gaming, we support better handling of missed turns and the ability to save your match data in the middle of a turn.
But perhaps the biggest feature new in iOS 6 is the ability to face off with your friends on the Mac. And this is awesome. There have been success stories where developers have ported their iOS game to the Mac in just a few days, at least get it up and running. So the relatively small amount of engineering work, you can open up this additional platform. New customers, newer App Store, you know, great opportunity to expand your base and get visibility. So let's talk about the styles of multiplayer. We support three styles: peer-to-peer, turn-based, and server-based.
Peer-to-peer supports 2-4 players. Turn-based supports 2-16. And server-based is also 2-16. The gameplay in peer-to-peer is simultaneous. This means I get my device, three of my friends get their devices, we connect up and we play together. It's kind of the classic way we do multiplayer. Turn-based is a different breed. In turn-based, I can create a match. I can pass the turn to another.
And when I'm not playing, I don't even have to be at the table. I can walk away, I can tweet, I can do whatever I want. And only when it becomes my turn again do I have to return to that game. So it actually supports a mobile lifestyle even more nicely than peer-to-peer. and server base. So the sequence is a sequential play. Server base is usually simultaneous. I mean, yes, there are chess servers out there where you can play turn-based games online, but this is typically to implement your MMORPG or similar massively online service.
The hosting on peer-to-peer is either a particular device or distributed. Turn-based is fully distributed. Server-based is your server. The communication in peer-to-peer is point-to-point or broadcast. Turn-based is just point-to-point. And server-based is developer-defined. We provide the APIs to do data transmission for turn-based and peer-to-peer and in-server. You're on your own. Sorry.
Let's talk about peer-to-peer multiplayer. A few concepts for those of you who may not be familiar with this. We're going to illustrate this with an example of a four-player game. Dungeon, death, cage match. The idea is you get together with four other players, you pick a hero or a monster, and you get in and you rumble with them.
So to set this game up, the first thing you do is you begin the matchmaking process. This creates the game table, and the game table represents your communication channel. This is how all the data moves back and forth, the state changes and notifications occur, and even handles the invite process. So the first thing we do is we invite my friends, in this case Sue and Bob. The fourth player is one of those famous players to be named later.
So Sue and Bob accept, and now they're in the channel. Depending on how you implement this, you could even at this point set up a voice chat, which you can read about in the documentation. Or you could start some initial game activity. But in this case, let's say we're gonna move on and find this fourth player. In this case, Meg joins in. And now that everyone's present, we're good to go. We can play.
So to build this, these are the tasks you have to do. You have to implement the process of picking the players via invite or nearby players or via auto-match. And by nearby players, I mean other people running the devices in the same room. Then once we're invited, we wait for the players to connect and observe their state changes. And then once we're ready to go, we play and we send and receive data.
So on the left here, there's entry points. And let's talk about that for a moment. You know, there's three entry points that a user will -- : The first is kind of obvious. You'll have a button in your game, play multiplayer. When they press it, the UI comes up and they can immediately press play to go into the game. And this is our new UI.
It's really awesome. If you tap the close box, it will make that slot go away. It has two to four players. And when they hit the close box, it will go to three players. Hit it again, it will go to two. And you have the ability to add them back in.
If you hit invite friends, it'll bring up a friend picker and let you choose some friends to play. And once you choose them, You'll go right into the game adding any auto-match players if necessary. So just set up and go. No more complicated interactions. That's awesome. The second and third entry points are kind of related. The second one is if Nate invites me and I get one of those notification banners and I tap it and I accept the invite, we will launch your game.
And once we launch the game, you need to put up this UI and show the matchmaking in progress. And once it connects, you're good to go. And kind of similar to that, if I hit -- if I go into Game Center and I find a game that Nate is playing, I can tap play right there and that will launch the app and start the -- it will also invite Nate, but it will start the matchmaking process and you need to go through a similar thing where you put up the UI.
So let's talk about this UI. What do we need to put it up? We make a match request. Match request contains sort of your preferences about what you want from the match, like the number of players. Is it two or is it four? We then pass that to the matchmaker view controller.
And that will interact with a singleton matchmaker under the covers and produce the GK match. GK match is this game table. It's your channel for communications. So to set up, we make the match request and specify the number of players, min and max. There's some other options which I'll talk about later. Once we have the match request, we show the view controller. You construct the view controller, pass in the master request.
And this is important. You need to set the delegate. And as with many of our APIs, or most of our APIs, if you don't set the delegate, things will just mysteriously not work. So make sure you do that. And then you present it as usual. Now... Once the user hits play or takes some other action in the UI, you need to respond to those actions. So we do that with the delegate. In this case, we're going to show what happens when we successfully find a match.
You have a new match, so you set the delegate. Now it's your code and you're ready to go. You know, just set up your match and go. Now, that's one of the delegate methods we implement, which is when the user hits play or they invite friends. The user hits cancel on the upper left.
If the match fails, like I've invited Jeff or Nate and they're on a bus going through a tunnel, they've accepted, then the bus goes in the tunnel, they lose connection, they'll get did fail with error and you need to take appropriate action. Now, on the handling invitation side, you implement an invite handler block. And this block implements the second two entry points for when you accept an invite or when you launch from Game Center. And this is important. You want to give your users good experience, don't you? So when you accept an invite, you'll launch the app.
I don't want to go through a bunch of set-up screens or menus. I want to go right into the matchmaking process and get into the game. So install that invite handler as early as possible. And we recommend you actually authenticate an application that did finish launching. And then install your event handler if you successfully authenticate. That will get called automatically. And you'll be able to go right on from there.
So how do we implement this? Well, you have one invite handler for both kinds of -- you know, both these invite entry points. And it takes two arguments. It takes a GK invite and a list of players. Only one of these will be non-nil, depending on whether it was the accept invite or the Game Center launch. So if there's an invite, we construct a matchmaker view controller and set the day we'll get a present. And we set the matchmaker view controller to the same pattern as before. If there are players, we use a different initializer, a match request, and players to invite.
And we set the delegate and we present. And that's all there is to it. So in summary, we create the match request. We present the standard UI. We handle the invites. And this same UI, by the way, works if you want to host the game yourself. The only difference is you go through a little different API that doesn't return a GK match data. Or GK match. It returns a -- it just gives you the information required to let you go on with your server. And you can read about that in the documentation.
So now let's say you want to provide your own custom look. You want to do the UI yourself. We now give you all the features to do programmatic matchmaking. So to do this, you make your match request, and this time you call the Singleton matchmaker directly, and it will return your match.
So do this. This is all the code you need. Just this little bit. You get the shared matchmaker. You call find match for request. Handle any errors if you need to. In other words, you're good to go. So if you want to get your -- if you have a single-player game and you want to try out multiplayer, this is the only code you have to write other than handling the data. You can get connected. You can start trying out your game. And you're good to go. It's that easy.
And if you want to find nearby players running your game, it's also pretty easy. You get the shared matchmaker. You call this new API, start browsing for nearby players with reachable. And if you find one, someone using a device in the same room, add them to the array. Probably a good idea to check if they're reachable or not. And when you're done looking, you call stop browsing. Now, new for iOS 6, we can send invites.
You know, programmatically. So what you do is you get your shared matchmaker. In the match request, there's a field, Players Who Invite, and you give it the players you wish to invite. These may be players that you've played with previously or players you just discovered through that local multiplayer browsing that we just did. And once you have them, you call find match requests. You get your match and you're good to go.
Now one thing you need to do is when you invite someone, you may wish to give feedback for when the players responded. You may want to go from inviting to connecting, or you may wish to show that they're actually ready to go. So we allow you to implement a response handler.
And this gets called. And at this point, you can mark your players accepted in your UI. And then there's also a good trigger for starting your game. You can ask yourself, do I have enough players yet? And if you are, you can tell the matchmaker, finish matchmaking, and we're good to go.
Now let me step back and talk about some other features on the match request. You know, player groups is a way to allow players of like minds to play the part of the game that they love the most. So let's illustrate this with a racing game. So let's say there's four kinds of tracks: oval, figure eight, curvy, and the wave with that long straightaway. And my favorite track is the figure eight. And let me tell you a secret, it's because it's the only one I'm any good at.
So I want to play with other players who love the figure-eight track. So I can just set that by setting the player group on the match request of the figure-eight track. This is a constant that you define. It's a 32-bit int. You can define as many or as few as you wish. And we'll just match them in. So other ideas for this is easy, normal, or hard.
Or game type. You might want to play Deathmatch or Capture the Flag or Team Fortress. But there's one subtlety here, which is, let's say I love to play the oval track, but the rest of you like the other three. And I'm trying to match at three in the morning.
Well, there may not be anybody else on, so I might be waiting a long time to get a match. That's not a good user experience. So what can we do? Well, we have an API to check for the activity on that player group. So you can check that, and if it's low or zero, you can say, "Hey, Christy, nobody else is playing that track right now. Do you want to go into the general pool, or do you wish to pick another track?" So that's a good feature if you wish to use player groups.
Now kind of a dual to that in a moment, yay, is player attributes. This allows you to specify the role that you wish to play in the game. This is a 32-bit unsigned integer. And what we do is I get a value, Nate gets a value. Each player who wishes to play chooses a value. And they'll be orred together.
And a match will be made if all the numbers are orred together to form a match. A pattern of all ones in the bits. So let's walk through this with an example. In chess, maybe I prefer to play black. So I'll give it the pattern FFF000. If Megan likes to play white, she gets 000FFF.
Let's say Nate is happy to play either color. So he'll just give me all Fs. And when we matchmake, we'll pick players that will match together to all Fs. Now Nate, even though he's got all Fs, will not just match with himself because we also have to meet the other requirements like minimum players. So it'll pick any other player.
So other examples of this, a role-playing game like our Dungeon Cage Match. You could pick fighter, cleric, mage, or thief. Or in a soccer game, goalie, forward, or defense. So in summary, you create the match request, use player groups or attributes as desired, you request the match, you wait for them to connect, and then you play.
So now let's talk about once you've made a match, how do you do the communications between the peers? So we're first talking about networking strategy and host selection. How to send and receive data. How to observe state changes. So on the right here, I'm showing our GK match and you implement a match delegate.
And these four things you implement are all you have to do to handle peer-to-peer communications. Let's go into this. But first, networking strategy. If I have four devices that are playing your game and they're sharing data, one way I might do this is every time I make a move, I broadcast my changes to the other four players. And if Nate makes a move, he broadcasts to all four players and so forth. Now, this is not a good idea.
It consumes unnecessary bandwidth because it's sending redundant data. And furthermore, if I'm making changes, Nate's making changes, Dan's making changes, you're going to have to implement some kind of conflict resolution coherency. And that's a lot of complexity for your code. There's a better way. Choose one of your devices as the host.
It'll be the holder of the truth of your app, of your game. The other devices can communicate their updates. My device can reconcile those changes and then broadcast it to the others. This uses less bandwidth and makes your code simpler. So that's a win all around. Now, in the past, we've told you to do this.
But it turns out, I mean, if you ever try to get, you know, yourself and three of your friends to, you know, when they're not in the same room to agree on anything, coordinate on anything, that's a difficult problem. And we kind of had you guys solving that in the past. But new in iOS 6, we give you a simple API to pick your host.
All four devices call choose best host player with completion handler. And it will pick one of the player IDs based on the device they're using, the network they're using, and so forth. And it will be consistent across all four devices. Once you call this, you've got your host picked. It is that easy.
So now let's talk about sending data. There are three choices that you need to make here. The first one is data size and frequency. And what this is about is, let's say I have my space shooter game. And I'm flying my spaceship. And I want the peer to see every movement I make as I jitter my finger across the screen. I want to make the ship move. I could do this by sending the update 60 times a second and I send all the data on the game as my ship's moving across. Well, that's obviously a bad idea.
It's inefficient. It sends unnecessary data. And it sends it too often. So you should use some techniques like dead reckoning where you not only send over the new positions, you send their velocities, their acceleration. You could even analyze the movement of my finger and generate a standard deviation and send that across.
Then the peer... can just model that and interpolate. Now you can send the information less often. Rather than 60 times a second, you send it five times a second. And this improves your latency and your user experience. So make good choices here. Now you can also choose communication styles, you know, between reliable and unreliable. You know, unreliable, you just send the packet and forget it. And this is good for clocked updates like my ship movement.
You know, because I've already implemented this interpolation logic, it's okay if one of my clocked updates is missed. You know, the peer can predict the movement and fill in the missing parts. Now, for something like, you know, my ship blows up, and so now I have two ships left, that's an event, and it's important the other side knows that. I'm not going to send it again. So I use reliable communications, and it sends the packet.
If the packet doesn't make it to Nate or whoever is receiving it, Game Center will send it again. It will retry it until it gets an acknowledgement. So it's good for events, but it's not good for sort of ongoing game activity. Now the final choice is whether you send to individual players or to all players.
And this code here shows how to send data to all players. You just make an NSData with your data, send data to all players with data mode, and there's an out parameter of an error that gets called, and you need to handle that error. The code for sending to specific players is just as easy. You make an array.
If you're hosted, it'll probably be one player, but you could send it to two or three, your choice. And it's the same kind of thing. Send data to players with data mode and error. Now receiving data is even easier. You get a callback on your delegate, did receive data, and will tell you what player sent it.
Now, the last thing you need to do is to check for state changes. When a player connects, you want to show some feedback they're connecting. You maybe put their photo on the screen or something. We checked for that state and did change state and if the player is connected, give that feedback.
If they've disconnected, You know, take appropriate action. And this is also a good time to call expected players. If your game hasn't started, The expected players will tell you how many players are still connecting. If you have no expected players, you're ready to start your game. Now, if you lose connection and it's a one-on-one game that's invite-only, You can implement should we invite player in your delegate. If you make this true, then if I invite someone, let's say Megan, and she's on a bus going through a tunnel and she loses her connection, all is not lost.
Game Center on your behalf will send her a new invite and when she comes out of that tunnel, she'll get that invite and she accepts. She's back in the action playing with me as if nothing had happened. I can also add other players to the existing game, and this follows the similar pattern closely.
Get your match request. Update the parameters as you desire. Create the view controller. And then call this API, add players to match, giving it your current match. So in summary, we've talked about the matchmaking UI and how it can quickly get players into your game. We've talked about handling invites and programmatic matchmaking if you wish to roll your own UI. And we've talked about peer-to-peer communication and some of the best practices.
And now let's move on to turn-based. So in contrast to peer-to-peer, Not everyone has to be at the table at the same time. There's no need to manage connection and disconnection. Instead, you're playing a game. In this example, we have four players or four friends in a six-player game and you and a player to be named later.
So right now it's my turn. So I have to be at the table, but the others may not be there yet. In fact, this may be a new match. They've not even been invited. And when I take my turn and I pass it to Sue, she gets an invite. When she accepts, she's now at the table. Same for Bob.
Now even the player to be named later, when we pass the turn to them, they get matched in at that point. So far the match has proceeded in sort of a natural order, but it's not restricted to that. Meg could choose to pass the turn to Sam. Now Sam, being really grateful, could pass it back to Meg.
and Meg may choose then to pass it back to you. The order is completely up to you. Now let's go into a little more detail of how the turn flow goes. So it's my turn. I've updated my game data. I pass it to the server. Sue gets a push notification.
If Sue wishes to take this turn or accept this invite, she gets the game data it's her turn. She now passes it to Bob. Now let's say Bob is going on a trip around the world. And he's one of these people who likes to, when he's on vacation, he's really on vacation, so he's off the grid.
He's left his phone at home. I know that's hard for a lot of us, but, you know, it's a good thing to do. So Bob misses his turn. Now this is a problem in iOS 5, because now this match is stuck. Bob never comes back to it. The game's dead.
But thankfully in iOS 6 we have a new API called Fallbacks and Timeouts. And with Fallbacks and Timeouts, Sue could choose not just Bob, but Meg and the others. As many players as they want. They can even repeat players or make it the player who has the current turn. The game will time out and pass it to Meg.
and she gets the data and we're good to go. We can also support multiple matches. I'm not very good at chess, but there may be some of you out there that can play 30 games of chess at a time. And that's possible with turn-based gaming. We support up to 30 simultaneous matches. We support 16 players per match. This gameplay is fully asynchronous. The game data we pass around is up to 64K bytes. The seats are filled via invitation or auto-match. The turn order is developer defined.
And missed turns are handled through a callback list. And the turn timeout which you pass in will give you a constant which defaults to two weeks. But you can also choose a different timeout. Although we recommend you don't make it like five minutes or an hour because that would make your game less fun for the users. Now the expectations of a turn-based game is that you need to be able to handle multiple simultaneous matches.
Each one will have its own state, its own player, its own outcome. And you'll need to let the player choose among the matches which one they want to view or take a turn on. Also, one player at a time. Other players will observe, but the player who has the turn can make changes.
Now, your app is not always running. A typical use pattern here is, I'm off tweeting or updating my Facebook. You know, a turn comes in. I go, okay, I'll take that turn. We'll launch your app, I'll take the turn, and then I'll exit and go back to tweeting. Now I want to write that great American tweet, so that's got to come first.
Now, I may be anywhere in your app as well. I may be taking a turn from Nate. and Megan finishes her turn and passes it to me. You should handle this notification and say, hey, Christy, Megan wants to play with you. Do you want to exit your current match or leave that current match and go to Megan's game and come back to Nate's later? You just need to give a good user experience here.
So the classes involved with turn-based gaming. We have a GK turn-based match. This is the counterpart to GK match for turn-based. It represents a single instance of the game as the list of the participants involved. It contains the current game state. It also indicates whose turn it is.
Now what are these participants? I've talked about players a lot, but now I've brought up this new term, participant. And why do we have two things that are sort of alike? And the reason is the participant is the slot at the table. You know, it's an open position, and until that player accepts the invite or joins the game, it doesn't have a player yet. So turn-based gaming thinks in terms of participants. When that participant gets filled, it gets a player ID set.
It has a status which is invited or matching and then becomes active when it's playing and then it becomes done. The outcome of the game gets filled in when the game is over or the player quits. And there are various outcomes like won, lost, tied, and so forth.
We have a GK turn-based event handler. This is a singleton for handling all your turn-based events. So this gets called when you get invited or you join a match. Or when an invite is initiated from the Game Center app. So those are the second two entry points we talked about before.
It also gets called when someone has taken their turn or when the match has ended. And finally, we have the GK Turn-Based Matchmaker View Controller. This is the focal point for the actions in your game. Now remember I told you that you have to manage up to 30 simultaneous matches? Well, it turns out that we can do most of the work for you.
We provide a UI here that contains a list of all your active matches. Your current turn, matches that have the other player's turn. If there's an invite pending, it'll show it at the top there. It'll also show matches that you've already won. The user can select these and you'll get a callback that lets your game show them. So this could act as your complete match manager. If I swipe it, I can delete it and that'll quit from the match.
If I hit the plus on the upper right, it'll take me to the matchmaking UI and let me invite players or just hit play now to auto match. So it's a complete solution. So how do we pose this? We make a match request. We construct the view controller, just like with peer-to-peer. Here's a difference, however.
There's a field on the View Control called Show Existing Matches. If you want that match manager UI, you set this to Yes. If you prefer to roll your own that's more integrated with your look or whatever, set that to No, and you'll just get the matchmaking piece but not the match manager piece. And once you're ready, you present.
Now there's some delegate actions on the ViewController that get called. So when a user creates a new match, they call didFindMatch. When a user selects a match in the UI, you also get called Turn-Based Matchmaker ViewControllerDidFindMatch. If you accept an invite, you get called did find match. If the user hits cancel on the upper left, you get turn-based matchmaker view controller was canceled. The match failed? He had called with did fail with error. If a user swipes to remove a match, you get player quit for match.
Now let's implement did find match for when a user selects one. So the first thing we need to do, and this is true of all of these events, is you need to dismiss the view controller. We don't know when to take it down, so you need to tell us.
Secondly, now an improvement we've made in iOS since iOS 5 is that we do our best to make sure the match data is up to date whenever you get the match. So if you just get it off the match, it'll have a current value. But even so, it's still good to load the latest match data.
Someone may have quit in the short time between we last got it and now. So I would load it. Now display that match to your user. And if it's your turn, Allow them to take actions in the game. Now the match data contains the current state of the match.
The contents are developer defined. It's completely up to you. It's an arbitrary NSData. It's stored online, so you must have the current turn to update it. But others can read it. It's of a limited size of 64K, so pack your data wisely. And you can get a lot of stuff in here, but if you need more room, you can point to server-stored data. Now let's talk about taking a turn.
So to take a turn, you make a move in your game. This is just up to you. It's based on the rules of your game. A player may make a move, they may resign or pass or so forth, depending on what you desire. You choose the next players and you call our API to submit the turn. So to do this, here's your update of your state. Now you choose the next participants, and I'll give you an example of how to do that soon.
Then you set a message to be shown to the other participants. So in this case, I made the Kessel run in 12 parsecs. Hooray! And now we send the new game state to the Game Center and pass the turn to the next participant. And here's where you supply the timeout. So how do we choose next participants? Well, that's up to you. You can go clockwise, counterclockwise. You can skip every other player.
You can even let the player decide. But you must choose active players. If you choose a player who's done with the game or quit, it's an error. And you should also guard against missed turns. And you do this by providing a list of multiple next participants rather than just one. And this will automatically enable the use of timeouts.
And the last participant on the list, though, they will not get a timeout because we don't know who to give the turn to afterwards. So I strongly recommend you add yourself as the last participant. Because if I just took a turn and nobody else takes a turn, Then I'm probably the most likely person to take the next turn. And you can do something like mark the player as one. So how do we do that? Let's implement a simple clockwise rotation. So we're going to ask the match for its participants and get the index of the current participant.
Now, let's loop through the participants, starting with the next one, and add them if they are still active. We add them to the array and we're going to keep looping around. Notice that my loop is post-decrement, so that'll catch me, the current participant, as the last entry. If there are participants remaining, return that list. Otherwise, return nil. The game's over at this point. There are no active participants. You should handle that accordingly.
Now, this is a new feature in iOS 6, which is saving match data. So, some games, rather than having a turn take a single step, it might consist of multiple discrete steps. For example, in a trivia game, let's say the MC is firing questions. Let's say Nate is playing. So the MC is going to fire questions one after another to Nate.
As long as he keeps answering correctly, his turn continues. You know, he doubles his money or whatnot. If he answers incorrectly, his turn ends. Now there's a few things about this. Now let's say I'm playing this game and I answer two questions correctly on my iPad. I switch to my iPhone.
Well, in iOS 5, I would start that turnover. You know, with this saved match data now, I can continue with the third question. Also, you know, Megan and Dan are watching me play. You know, they're running the game and they're watching my updates. My game can send updates to them.
And this is also good to avoid cheating situations. Like let's say I'm playing a game and I roll some dice. I don't lie, I get snake eyes. Well, now I can -- I mean, before I can go over to my iPhone and I get a do-over because I just launched the game, start my turn.
But with saving match data, when I launch that phone, I'm going to have my die rolls there. So it makes your game much more robust. So to do this, let's walk through that trivia example. So we're going to have a while loop. You ask trivia question. Update game state. Number correct plus one. And we save the current turn with match data. And to illustrate this, here I am and here's Megan and Dan. They're running your game.
When I update, I send the data to the server. I keep my own copy. I can continue with my turn. Since they have running instances of your game, they will get an event handler callback and they'll receive a new copy of the data. The other three players who are doing something else, they do not get push notifications. But if they launch the game, they'll get the same data and they'll be able to follow along.
And this leads us into the kinds of turn notifications we get. If you receive an invite, you'll get a push notification and we'll call the delegate method handleTurnEventForMatch. If it becomes your turn, the same thing. You get a push notification, you get a handle turn event for match.
If the turn is passed to someone else besides you, only the running instances of the game get handle turn event for match. There's no push notification sent in that case. And likewise for saving the data. If the match ends, you get a push notification and handleMatchEnded gets called. Now let's talk about implementing handleTurnEventForMatch. There's a couple things you should do here. If it's now my turn, inform the user.
In this example, we're just using the show banner with title, but you can show whatever UI you want and take whatever action you wish. And similarly, handle that case of if I'm playing the game, if I'm taking a turn for another match, or I'm just observing a match and somebody makes a change, we can check that and update our UI.
Now, things to remember when taking a turn is only the current participant may update the data, and they're also the only ones that can pass the turn. Other players may quit during this time, so you need to handle that. And finally, handle your turn events. Now for quitting a match, this is when a player resigns or they just decide to quit.
There's two cases here. One is when it's my turn. Quitting while I'm in turn is just like taking a turn, except I set an outcome on that participant. So you'll update your game state. You'll set my outcome to quit, and then you'll pass the turn by sending, you know, player quit in turn with completion handler.
And you can supply a participant list with fallbacks and use the timeouts. If it's not your turn, you just inform Game Center by calling an API player quit out of turn. At that point, it will just mark you as quit. Now, if the game is over and you have the turn, you can end the match. At this point, you need to set the outcomes for all participants. And we provide a number of constants, including one loss, tied, various positions, a player ran out of time, and so forth.
We can also set a -- we also provide a custom field here so you can show custom outcomes in your UI. Provide an optional message. And then inform Game Centers and the notification goes out. Now, how do we do this? Well, we set the outcome. In this case, we're kind of lucky no one lost, but we're not that lucky because no one won either. We set the final game state and we set the optional message. Yes, I really did win the Kessel Run this time. We end the match just by calling our API and that's it.
Now that the game is over, I want to play again. And this is really easy. You just put a button on your game over screen and then you call on the match. Re-match with completion handler. And when this returns, you can start your game. In turn-based gaming, this means I take the first turn, and then when I'm done, I can pass it to one of the other participants who will be invited back to play. Now if Nate also does this on his device, he'll get a match where he can take a turn. So there'll actually be two instances of the matches created. That's just the characteristic of turn-based because the invites don't happen until it becomes their turn.
Now in contrast to that, we also support this on GK Match. In the case of GK Match, All the players who were in that match who hit replay will get auto-matched into a new match. So the players who don't choose to do this will get left out, but the other ones will all get matched into a single match. But other than that, it's really easy and we recommend you add that because it adds more replayability to these games.
So with that, I've given you a quick walkthrough of multiplayer. This is a really popular feature. It adds a lot of longevity to your app and engagement for your players. I've talked about the different styles of multiplayer we support. I've gone into detail on peer-to-peer and turn-based. I've pointed you to documentation for how to do server-based.
I've talked about the Matchmaker UI and how it can make it really easy for you to connect with your friends and play or even with other people on the Internet or in the same room. I've talked about programmatic matchmaking. I've talked about peer-to-peer communication and the best practices thereof.
And then finally, I've given you a nickel tour through turn-based gaming. For more information, you can contact the incomparable Alan Schafer, our wonderful evangelist. Or you can read the documentation. There's a multiplayer section in the GameKit programming guide. Or you can, you know, go to our forums. We post and reply to your messages.
There are a number of related sessions I hope you're able to make, like what's new in Game Center, integrating your games with Game Center, or what's new in iTunes Connect. And after me, Gabe is going to show you hands-on how to port your app to OS X and broaden that customer base. So please attend that. That's awesome. And thank you very much.