Welcome to the third Game Center session.
This is Game Center Techniques, Part 2 and I'm going to talk to you about adding multiplayer to your game.
I'm Nathan Taylor.
I'm a senior iPhone development engineer, the Game Center team.
And we want to talk about how the facilities for multiplayer do the hard stuff, getting people connected in terms of network gaming so that you can just easily take advantage of our APIs and get your game players playing with each other.
I'm going do a quick overview of what Game Center is and what Game Center offers and then I'm going to step into the nitty gritty of what we do for multiplayer to make it easy for you.
First of all Game Center is Apple's social gaming network.
It's comprised of three parts there's the built-in application, Game Center app, if you've installed the developer seed you've seen our icon on your home screen or page 2.
It's also a framework.
The GameKit framework is where the Game Center API lives and we have a set of online services, our Game Center services, which we host sort of in the cloud.
There are servers and they handle a lot of the storage requirements for your leaderboards and your achievements as well as all the players and then they have the Auto-Matching and invite services that hook your players up for multiplayer.
Game Center provides several of these facilities here; the friend relationships, leaderboards, achievements and the multiplayer API that's the focus of this talk.
All of these build together combined to make a social gaming network and then the multiplayer you know leverages that and that leverages the friend relationships to send friend invites and also it just helps grow the network.
If you play with somebody you'll see them on the recently played list in the Game Center app.
And then you can make them your friend and add them to your network for future invites.
So what you're going to learn in this session, I'm going to show you the overview slide, the graphic that is the block diagram that is Game Center that you've seen before if you've been here.
But we'll focus on the area that we're going to talk about.
I'm going to give you a quick look at what we provide in the Game Center services and then I'm going to go in-depth on what the multiplayer services are.
I'm going to start with Authentication because you can't do anything in Game Center unless you've authenticated the local player, about how to get connected through invites and Auto-Matching and talk about the network communications that we set up for you and you know the different types of things you can do here and how to be a good network citizen.
Finally we're going to get into how you can make it fun and engaging for users beyond how great your game is but let them talk to each other with player communications.
So this is the block diagram that is Game Center.
We have the GameKit framework in the middle in green here.
And your games and Game Center sit on top of this.
We provide the general functionality that was covered in the previous session, which is the authentication, friends list, leaderboards and achievements.
And then what we're going to cover today in this session is the multiplayer functionality.
This is our Auto-Matching service, our Game Invitations, Peer-to-Peer Networking and In-Game Voice Chat.
So the Game Center services, the servers that we offer are there to connect people.
We use these servers to route requests to devices and we use these to find devices that can communicate so that we can establish global peer-to-peer communications.
So the question that came up in the overview, and yes we do establish wide-area network peer-to-peer communication between devices.
These services are available over WiFi and over the various cellular networks and you know being able to connect people and get together in the same game provides a great opportunity for social gaming and allows a lot of people to discover your games because as was shown in the overview if one person invites their friend to play a game and that friend does not have the game yet the invitation notice will give them an opportunity to buy the game immediately in the game store, in the app store.
And ultimately there are things you need to keep in mind; these are mobile devices.
These are phones.
People move around, phone calls come in, connections come and go and there are some considerations you need to take into account in handling these off-line situations.
So as I said players will come and go in the middle of your game.
Now we're going to try and notify you if you have a connection that goes away but you need to be prepared for the game player to take phone calls and if they lose and regain their connection.
So we have facilities where you can detect a disconnect and then potentially add another player into it or your game can just go on without that player or you can handle it whatever way you need to.
And you also need to be aware in iOS 4 of multitasking.
Your game might get switched to the background for some other reason in which case you might want to Pause.
And if you're in multiplayer you might want to communicate that to the other players so that they Pause as well.
And ultimately it's important for game play to be able to continue for the others in one form or another.
If they want to continue and let this person be dropped, you know without this person, then they should be able to do so.
So the service also there are some considerations that need to be taken in setting up your game.
We currently provide compatibility between different versions and this comes into play with matchmaking.
In iTunes Connect you set up your game through its bundle identifier and you register it to be a game center application and then you set up the versions that are going to be compatible to play with each other.
So if you add the Game Center services multiplayer in version 1.0 and then you know, or actually you add it in 2.0 and you have it in 2.1 and then you know you broke it in 2.3, so maybe you want to leave that out, and then maybe 3.0 is now totally different.
It's no longer compatible.
You need to kind of report these in iTunes Connect so that we know that you know basically if 3.0 comes in it's compatible with 2.0 and 2.1 but it's not compatible with 1.0 anymore.
And this is done with Invites on the recipient's device and the invite will come in and we'll tell them what version it was for and if they don't have that version, but they do have the game, they can at least go to the store and upgrade to the appropriate version.
Actually, they'll get to go to the latest version.
So that's one thing to keep in mind.
Before we can get started with multiplayer and Game Center in general you need to take the GKLocalPlayer, which is the user of the device and you need to authenticate it.
So authentication is done with the LocalPlayer and it also provides the friend list so that you can now dive into the social network, get the friends of this player and display them and use them however you want to.
The LocalPlayer provides an invariant playerID persistent the lifetime of that account.
You should use this for referencing saved games so that if because one device might be used for multiple local players at different times.
You'd like them to have different sets of saved game data.
You also want to use this for cash data as mentioned in the previous session if you want to submit a leaderboard score or achievement and the network is offline at the time, you want to archive that achievement or score.
It will be saved with the playerID and you will want to resend that.
So the key thing to keep in mind with authentication is you want to do it as early as possible.
We recommend that you do it as soon as you can after an application is launching.
The only thing to keep in mind is its probably best that your game UI is up in some form because Game Center will show additional UI.
If the user is not logged in we're going to show an alert allowing them to log in or create a new account.
If they have gone through and logged in somewhere else we have a single sign-on and then we will automatically authenticate and we will at least show the UI to welcome them back to Game Center and your game.
If you have not authenticated and start using other Game Center APIs these will return immediately with errors.
So make sure to authenticate as soon as possible.
Here is a quick review of the code.
It is a single method on LocalPlayer.
The first thing you want to do is get the LocalPlayer through the GKLocalPlayer Singleton method, and then call authenticateWithCompletionHandler and this is using the block syntax.
You will receive a callback with an error or not.
If you receive an error you should disable your Game Center features but make sure that the user can still play your game in some form.
You know you may have to restrict them to Single-Player mode, but at least leave some of your game functionality.
Because it would be terrible if your game was not usable when they're on an airplane.
Otherwise go ahead and enable the Game Center functionality and provide the full Game Center experience.
So the first multiplayer experience that I want to talk about is Auto-Matching.
This is where we allow people with similar configurations that want to play multiplayer without any encumbrance just to jump in and be matched with people that are like-minded.
There is a few classes we use to do this in the API.
They are the GKMatchRequest, which defines the parameters of the match, the GKMatchmaker that can do this, the matchmaking, you know it takes the match request and gets the match back without any UI and then if you want to, provide standard UI for the matchmaking and if you do this you need to handle invitations as well, which will be the next section.
You can use the GKmatchmakerViewController.
I'm going to walk through the Auto-Matching flow a little bit here and show you how things were communicating with the servers.
If you were at the overview session you've probably seen this before but I'm going to go into a little bit more detail about the parts of this matchmaking.
So we're starting up here with Onward, which is one of our test games and ThunderZeus has just signed in.
We're going to set up Auto-Matching and then add two more players to play.
So here the game is allowing 2 to 4 players.
ThunderZeus has chosen to play with 4 players and when I hit the Play Now, the match request will be sent to by the Matchmaker to our Auto-Matching services.
Now if you've written a great game, it's popular.
You'll have a lot of people out there and the probability is there are going to people for this person to play with.
Everybody's going to want to play the game.
The services are going to look at all the requests, find the most appropriate, the best suited requests, and we'll return a match to those games.
The Matchmaking class GKMatchmaker or the View Controller will return a match object at which point you can begin your game.
So here's a rundown of the matchmaking process.
The first thing you need to do is create a match request.
This is where you define the parameters of the match.
You then send the match request to the server either through the Matchmaker or the standard UI.
The server then applies the Matchmaking logic and takes into account parameters of the match request, information about all the devices that are requesting similar parameters in their connection capabilities and looks at particular into two parameters that you can choose, which is the Player Group and the player attributes.
These are properties on the match request that allow you to control how the match is grouped, you know how we segregate the pools of the people that want to play and also the type of players that can come together.
I'm going to give more details and in-depth analysis of this later.
Once the server has found the best match the match is returned to all the devices that are participating in that match.
Then it's up to you to basically start listening on that match for all players to connect.
Once everything is ready to go, begin the game and let everybody have fun.
So let's take a look at what the match request is.
It's a really simple object.
It's the parameters for the match.
You get to set a few properties here.
The first two are the minimum and maximum players.
If you want to allow the user to choose between a certain set of players you can set a range, 2 to 4 for example.
If you only wanted to allow a 3-player game you could set both equal to 3.
Ultimately the only requirements here are that minimum players be less than or equal to maximum players, it wouldn't make sense otherwise.
Now keep in mind depending on what type of match you want, whether you're going to go with a peer-to-peer match or client-hosted or server-hosted, sorry or server-hosted match, there may be other limitations to what type or the number of players that we can support.
Then you're going to assign a Player Group.
A Player Group is some parameters based on your application, the version of the application, the level they've chosen.
The player attributes are more specific attributes about what the player's chosen, their class you know in an RPG, their position in a sport and I'll take a look at those later.
Let's look at Player Groups right now.
I've got 4 tracks.
We've got the standard oval, the figure eight, and some that are a bit more interesting.
Now, when we go to the matchmaking services we want to split the people up into which racetrack they want to play on right.
They're going to pick this before you go into Auto-Matching and you know when that happens the match requests are all sent to the server.
The server groups these by the Player Group and will only match players that are in the same Player Group.
Now as you can see there's one side of it that can happen in this case and that is that there's a racetrack that's unpopular or a level that's unpopular and ultimately just a Player Group that nobody is playing in.
We provide an API for you to query the activity of this Player Group, which you can then use to either present UI to the user to show them that hey, there's not been many people on that racetrack.
It's not very popular now.
Maybe you don't want to play that one or you can even use it to automatically redirect them to a different Player Group after they've chosen it and I demonstrate that here.
You know you query the Player Group and you switch them to this other racetrack.
Then when the match request goes in that person is not going to be sitting there for a long time.
They will be immediately matched with everybody that wants to play that particular track.
So what exactly is a Player Group?
You know, it's hard to define.
It really depends on your game, but it's an arbitrary grouping based on in-game settings.
You know we've called it internally a bucket or if you want to think of a hash table, its like has you know.
It's some combination of what the user has chosen and the configuration of your game.
You know if you have download content, you know inapt purchase content and you have someone who wants to play a new track, well that track should have you know new content of another Player Group.
Ultimately you're going to use this to match players with compatible in-game settings and our services will not match people between Player Groups.
So only in the same Player Group will be matched.
Ideas for Player Group assignment are difficulty setting.
That's pretty easy.
You know you've got people that like to play easy that are probably not good at the game so you can kind of keep those people together.
Normal and Hard applies, well as I showed with the racetracks the game level or map if you're in first-person shooter.
You may want to combine this with game mode, so you may want to kind of hash the two together and combine you know, capture the flag and deathmatch so they'll be a different Player Group for level 1 capture the flag and deathmatch.
You know each of those would be a different Player Group as well as level 1 deathmatch.
If you have a global game that's very popular and you want to keep people playing that are local to each other, you may want to use Player Groups based on region or even realm such as the multi-mass multiplayer on-line games where you have to remember realms.
One thing to do is as showed, query activity in the Player Group to make sure that there are people there to play with.
And let me show you how we can do that.
It's basically one a synchronous API.
It's on the GKMatchmaker class and it's called queryPlayerGroupActivity withCompletionHandler.
The input parameter is the Player Group you wish to use.
In this graphic here each of the colored arrows represents a player attribute based on the key here.
And what's going to happen is they're going to communicate.
They're all in the same Player Group and the services are going to find the best players that fit the set of player attributes.
So it's going to return a match to one of each of the different colored arrows.
So I've got here a thief, a fighter, a mage and a cleric.
Now let's see more specifically what an attribute is and how it works.
Now we were sort of analyzing the used cases here and try to find the simplest way we could represent something to achieve these results.
And basically what we've come up with here and its optional is a 32-bit integer value that you use sort of as flags to represent the attributes of your player in this match request.
We sort of do a logical OR operation on this when performing a match to group these together.
And if you think about this as the OR the Player Group is the AND, and if you're outside of the Player Group its not going to match anything.
You want to choose these based on player characteristics.
I gave an example previously of a role-playing game where we have a fighter, cleric, mage and a thief but if you're writing a musical game, a band, you might have a guitar, bass, drums and vocals or a sports game where you need a goalie, a couple forwards and defenders.
Ultimately what happens in the server is we try to combine these flags to match you know the maxent bit pattern 0xFFFFFFFF.
You know you don't need me to read that but it's there.
You know we're going to combine these and when the server finds the combination of player attributes within the same Player Group that matches it is what's going to use to send the match back to.
So let's take a more in-depth example of how you can configure a match request and we'll look at it in code here.
So I've kind of broken things in part here, so we have the basic match request up top where I'm setting up a 4-player dungeon crawl.
They're going to play my level 4 dungeon.
I have a minimum of 4 players and a maximum of 4 players; you need a 4-player party for this game.
One of the players would set their attributes to the fighter attributes.
Another one on another device would be the mage, cleric and thief and then through the Matchmaker we'll send up this match request.
Once the match is made the players need to get connected and this where a lot of the heavy lifting is done for you by Game Center.
We will establish by default a peer-to-peer connection and this is where we establish connections directly between player's devices and we analyze what the connectivity abilities are, you know to pick the correct players for a match.
And essentially what this establishes is a mesh where each device is connected to all other devices that are played.
If you choose to go with a peer-to-peer match, you have Send and Receive data APIs in the GKMatch object.
The other option we provide with our services is to go with a server-hosted match.
There are fewer limitations to the number of players but you have to host a separate server yourself to host the game.
But this has a benefit.
It allows you to improve these abilities, get more players and provide more options.
The one down side is that to go this way you need to establish custom network communications.
You need to set up the links between each device and your server.
We will give the devices enough information so that you can figure out who should be playing each other when they connect to your server.
We will do the invites and the Auto-Matching but it's up to you to connect to your server and get everybody communicating through your service.
So let's just take a quick look at how these look like.
It's pretty straightforward.
Once you've communicated with the Auto-Matching services and had the matches returned to the devices either a peer-to-peer network, here a little mesh will be set up where each device talks to the other or you could go with the hosted approach where every device talks to your run, the central server you run.
So let's look at what we need to do Matchmaking.
These are two devices representing two different players that want to be connected through our services.
And we're going to replace one of these with the classes you need to do this.
Here we have two classes that I went through before.
The match request and the Matchmaker, the match request is pretty straightforward as I showed you earlier.
We set up a match request with the player counts and the minimum players and maximum players.
The Player Group and the player attributes are defined, how this person, this local person, should be matched with other players.
This match request is passed as the Matchmaker and with this code here we initialize the shared Matchmaker.
Then we call create match or request withCompletionHandler.
This takes the match request that you just created as input and will return to you on success a GKMatch object that represents the peer-to-peer network and it will contain information for you to find out when players connect, disconnect and also to send and receive data.
If we are unable to create a match an error will be returned and you need to handle that error and report the situation to the user.
On success though you need to set somebody to be the delegate of this match to start receiving connections and receiving data, here I set the delegate to self.
The other way you could set the match is server-hosted.
If you go the server-hosted route you're going to want to use a different API.
This API is findPlayersforRequest withCompletionHandler.
Instead of us returning a GKMatch object that contains all the connections for the peer-to-peer network retain an array of GKPlayers.
Each GKPlayer has a playerID that is invariant which you can communicate to the server to help connect these people.
Similarly as the other API an error will be returned if we are unable to connect and create the match.
Now in summary of Matchmaking it's pretty straightforward.
It's simple to set up Matchmaking without UI or with UI.
The first step is to create a match request.
Think about the Player Groups you need for your game.
How do you want to separate how people play in your game?
That's kind of the first step you need to think about.
And then think about if you're going to need attributes at all and if you do, you now make sure that the sign goes to the match request.
Then you're going to request the match.
You're going to take this match request you built, hand it off to the Matchmaker or stand it off to the standard UI through the MatchmakerViewController.
When you get the match back you need to handle player state changes and wait for players to connect.
After everybody is connected the game is ready to go on.
So that wraps up Auto-Matching.
The next thing I want to talk about are invitations.
Invitations are handled by some of the same classes and a couple other classes.
Again we have the match request.
We also have the Matchmaker and the new classes are the GKInvite and the MatchmakerViewController again.
So we use the match request the same way but the rest is going to be a little bit different.
So let's take a look at an invite flow in a demo game that we created and I've got a few screen shots to walk you through here.
I've got two devices, inviter and an invitee.
The inviter has already launched the game and been authenticated.
The player is going to select to invite their friends to play and up comes the standard UI.
To do this you're going to need to implement that button and initialize and show the standard UI.
Then the player can Select To Invite a Friend, which will bring up their friend list.
They can choose their friend and essentially even choose multiple friends from this list at the same time.
Once they've got people they want to play with they'll click Next where they can compose an optional message that will show up on the device when the invitation is received and once Send is pressed the view controller sends the match request and the players up to the service where we compose a notification, find the players device and send the notification on to the device and when the recipients device receives the notification up pops the alert.
If they have the game and its compatible they can choose to Accept or Decline the invitation, we always hope that they Accept.
So here the invitee is going to accept the game.
The game launches and will automatically display the Matchmaker UI.
At this point now everybody is connected and ready to go and we're just waiting on ThunderZeus, the inviter, to start the game.
They pick PlayNow.
At this point the match object is returned, the players are connected and the game starts.
So what do we use invitations for and how do they work?
Well, generally they're to invite friends to play games.
And they are two ways that this can happen, and they only happen involving Game Center UI.
One is through the standard in-game UI provided by the GKMatchmakerViewController and the other way is through is Game Center.
As was discussed in the overview if the user browses to their friend's page in the Game Center application and then views one of the games that their friend is playing there is a Play button available on that screen.
If they click that Play button we're going to launch your game and request that you invite that player to play the game with the player of your device.
What happens is we send push notifications.
All the invites goes through the push notification mechanism.
It's sent directly to your friend's device and there are pretty much options that they'll get to choose from.
The primary one is to Accept the invite and Play the game.
If they're busy and don't want to play they can Decline.
If they don't have the game or don't have a compatible version they can go to the apps store and buy your game or upgrade to your latest version.
Once the invite is accepted and they have the latest game we're going to automatically launch the game and that's where you come into play.
The flow to creating, to inviting friends to play is pretty much like creating a MatchmakerViewController.
You're going to create a match request, use the same set of properties min players and max players, Player Groups and player attributes.
You will initialize the MatchmakerViewController with this request.
This MatchmakerViewController uses underneath a GKMatchmaker object that I discussed with Auto-Matching and shows our standard UI.
So you're going to show the MatchmakerViewController object you created where the user is now in control.
And if you have a range of players they are able to change the number of players they wish to play and then select from their friends list the players that they wish to play with.
It's also possible that they you know you have a 4-player game they may invite one or two players and then choose to Auto-Match the remaining players.
So if they don't invite everybody to fill in all the game slots, all the available players, Auto-Matching as I discussed before will fill in the rest, automatically behind the scenes.
When the user is done with this UI you're either going to get a match or you're not.
And so hopefully we'll get a match and you can start the game.
So again we're going to start with two devices, one to communicate through the Game Center services and we have essentially one device that represents the inviter and one the invitee.
So I take away the inviters device here and show you the classes that you're going to use at the top level for setting up game invitations.
It's really simple the two you need to worry about.
Again we start with the match request.
We're going to start pretty much the same parameters, 2 to 4 players in our level 4 dungeon.
We're going to initialize the match request.
We initialize the MatchmakerViewController with our match request.
We want to be the delegate of the MatchmakerViewController because through a delegate method that the match is returned and then we will show the MatchmakerViewController to present the UI to the user.
Now at this point we need to be the delegator and implement these delegate methods.
So let's look at what the delegate does.
The first and primary one, the one we hope always gets called is MatchmakerViewController did create match.
This is the delegate method that is called when the user has completed the ViewController, the Game Center services have found the best people to play with and/or the invitations have been accepted and you will get a return to match.
Again you want to set yourself to be the delegator of the match or somebody else and then wait for everybody to connect.
Now optionally you can do just like with Auto-Matching, you can choose to do the ViewController with a hosted match in which case you will get the MatchmakerViewControllerDidFindPlayer delegate method called and similar to Auto-Matching this returns an array of players.
There are a few other delegate methods that handle cancellation, MatchmakerViewController was canceled.
This happens when the user clicks the Cancel button.
Errors MatchmakerViewController did fail with error.
This is that the server's, based on the match request was unable to make a valid match.
If you have an error in your match request something went wrong in communicating with the servers.
You may get this call.
We've gone through how you send an invite but there is work you need to do to be able to handle the invite once it's received.
Game Center will show the invite alert.
When the user accepts your game will be launched.
But for you to know that you were launched with an invite we needed to implement these two methods and when you get these you need to show the ViewController.
These are both basically properties that are blocks on GKMatchmaker.
The first is the InviteHandler block.
This block is called when your game is launched or when an invite has been accepted by the user on behalf of your game.
And basically the block will be called and pass the invite.
There are some things worth knowing, this is one.
You should keep this thing set at all times.
You may be called immediately after setting this block to the GKMatchmaker.
Because if your game was launched in response to an invite, you know, the invite is waiting, so as soon as you send this CompletionHandler it's going to get called and the invite is going to passed to it so be ready to handle it when you send it.
It also may get called at any point during your game flow.
If you're just playing the game, playing your game, and they receive another invite from one of their friends to play their game, the alert comes up, and they can choose to accept or decline that invite.
If they want to play with this other person that invited them, you know they like them better than who they're playing with, you need to respect their wishes and make sure that you clean up your game state and get them set up into this new game.
So you are going to be called and you are going to be given a GKInvite object and all you really need to do is initialize the MatchmakerViewController with this invite and show it.
The other method, which is not in the API that you've seen in the seeds, but will be coming soon is the playerstoInviteHandler.
This handles a special case of your game being launched from Game Center from a friend's game details page.
And it has basically the same sort of conditions as the InviteHandler.
It can be called immediately.
With multitasking it can potentially be called at any time.
And you know do the same thing, initialize the MatchmakerViewController.
It's a little bit different.
Instead of being the recipient of an invite you're actually going to be sending an invite on behalf of the user.
Transparently you're going to set up the UI.
So to do this you want to initialize the ViewController with the match request and the array of players that this block has given.
So we're going to take a look at the code for these and how these come together right now.
So I've moved to the other side and we're implementing the invitee recipient code and we have two blocks that we're dealing with again, the GKMatchmaker and the GKMatchmakerViewController.
Let's implement the InviteHandler that's going to pass the invite, the GKInvite to the matchmaker ViewController.
It's the InviteHandler block on the shared Matchmaker and it's a block that takes as a parameter one single parameter, the GKInvite.
This is a pretty simple object.
You don't actually need to pull anything out of it.
You're just going to pass it along.
You're going to pass it and initialize the MatchmakerViewController with it.
Again you need to become the delegate of the ViewController and you need to show the ViewController.
Now I'm going to take a little liberty with the next slide because it's actually the invite tour side but I'm going to show it here because it fits.
This is the playerstoInviteHandler, which works pretty much the same way.
You're going to set up your players InviteHandler block and instead of a GKInvite object it's an array of players.
And instead of initializing the ViewController with an invite you'll mate it with a match request, which we'll make based on the properties the player chooses perhaps before this step you actually want to show some UI so that it will let the player pick the level that they want to play on.
Because remember this is a little bit different, essentially you're going to send the invite out so you can let them pick the level, pick their class whatever and playerstoInvite and the same thing, set up the delegate and show the ViewController.
So in summary, invitations are pretty easy.
A couple things you need to do.
One, remember to create the match request.
You know present the standard UIs because all invitation flow goes through the standard UI whether sending one out, you're handling or receiving an invite or you're going to prepare an invite response to someone launching an app from Game Center.
The few things to remember is you can be called at any time.
Make sure that you can clean up your game state, and you need to respect the user's wishes.
You know, if they've accepted an invite and they're called it's because they want to play that invite and you need to abandon what they're currently doing, and remember that it may be called immediately.
So let's take a look at the hard stuff, the networking that we do for you.
Basically all of the networking is done under the GKMatch object.
And this networking, this peer-to-peer networking that we do for you is actually shares a lot of the infrastructure that makes FaceTime work.
FaceTime is established as a peer-to-peer connection and it uses a lot of the same stuff that we do.
So the match represents the game communications between the players.
It's got an array of players.
It lets you know when players are connecting.
It gives you an API so that you can send data.
If you've seen the previous versions of the GameKit framework, a lot of this is similar.
We have two ways of sending data.
You can send data unreliably you know.
This is data, you know that if it didn't go through it's going to be stale anyway and you can just send new data and replace it.
You know position information of a player moving around a map or it can be sent reliably and what we do with reliable data is we will wait for acknowledgement and attempt to resend the data if it doesn't go through.
Now in general a lot of the stuff we need to do unreliable is probably satisfactory.
It also provides a delegate method so that you can receive data on all the other players in the match.
And finally there's a PlayerStateChange delegate method that allows you to wait and watch for player's state changes.
It will tell when you players connect and when players disconnect.
And you use this first off to wait for all players to connect before you start sending any of your game data and also to be able to notice when players drop or disconnect mid game.
You know, if someone takes a phone call, goes into a tunnel, you know you need to be able to handle this.
We're on mobile devices.
So let's take a look at what we need to do to wait for players to connect.
It's a GKMatch delegate method called MatchPlayersDidChangeState.
The operative objects are the player and the state that they changed to.
I highlight the two states that we care about here, the connected state.
This is when they initially connect and a disconnected state when they disconnect.
And we will try, when you get this disconnect, they are really disconnected.
We have tried through our connections to reconnect them and have been unable to.
So at this point they're gone and you need to be able to handle that.
There are ways you can do this with a match and the Matchmaker.
You can choose to add players to the Auto-Match but we'll take a look at that later.
So when you're using this call and waiting for players to connect, we have a property that can help you to do that.
This is property on the match called expectedPlayers and you can watch for that to decrement.
We'll decrement how the players connect that we expect.
So we'll start off you now you've got a 4-player game.
We're going to be expecting 3 players and as each player connects this will decrement.
When this gets to 0, if you haven't already started your game because remember this player state can happen at any time, it's time to start your game.
A couple of ways to send data once the connection is established and you want to start a multiplayer game that means communicating the game state between devices.
So two APIs, we have a GKMatch, sendDatatwoPlayers with data mode allows you to send your data to a subset of the players that are in the match.
And again you can send it reliably or unreliably.
Here I use reliable as my example.
Worth noting is that this method will return a bouillon and it would be false if for some reason we were unable to send the data and in that case the error property will be populated.
Similarly we have a method basically to broadcast data to all the players in the match.
This is SendDatatoAllPlayers again with a data mode and again this property will turn a bouillon and an error on failure.
To receive data there a single development method that you need to implement that is matched, DidReceiveDatafromPlayer and you know I really can't tell you what to do here because it all depends on your game code but you want to take that data you got and run it through your game engine and it's pretty much as easy as that.
So some things to keep in mind when using our Matchmaking services, we want everybody here to write games that are good network citizens.
This means that games that will work with multiple instances running on the same network.
Cooperate and play nice when there are other games running on the same network.
So here are a couple of things we recommend that you do.
First, keep your network traffic to a minimum.
By minimum I mean make it small, so minimize the size of the data packets and send as few packets as possible.
So some things not to do don't send data for every game frame if you can avoid it.
If you're game is running at 60 frames per second do you really need to send location players for every frame.
Think hard about that, because that's an awful lot of data to be sending.
You also don't want to broadcast data to all players all the time.
It's usually the case that the data only needs to go to a subset of the players and not to everybody.
To help with this we also recommend that you try adopting some common networking strategies.
Some of these are to set up a client-host network topology.
This is where you're going to choose one of the peers to be a host and all other devices will communicate through that host.
Or you can set up a ring network where the device is communicated along the ring and with the array of players in the match and the disconnect notices you can also re-establish that ring so it's a little more robust than some other ring networks.
Or you can host your own servers and use our server-based networking.
So let's take a quick look at what it kind of takes to do a client-host because this is what a lot of you are probably going to want to do.
This is what we've done in most of our demo games.
The first thing you need to do is to nominate the host.
And common ways to do this are to set up a voting or a coin-toss algorithm where random numbers are generated, sent to all the devices, collated and the host is chosen from that or we found that there is kind of an easy way that you can do things, too.
You can compare the playerIDs.
Now the playerIDs are strings, but you still use string collation to compare them.
And while it's not truly random, you will be able to reliably and very cheaply find either the lowest sort order or the highest order playerID and make that one the host without having to communicate excess packets.
Ultimately then you want to communicate all data to the host that involves the game state where the host then maintains the truth and then chooses who it needs to send data out to.
So the host will then pass that data to the necessary clients.
We take at look at how this affects the networking.
Here's a peer-to-peer mesh where we've got you know bidirectional connections between all the devices.
There basically are 6 bidirectional connections here.
If we move to a client-host topology we basically reduce the communication down to, let me go back real quick, 3 bidirectional caches.
The green arrows represent the subset that are used for the client host so the device up front has become the host.
Now everybody communicates through it.
Alternatively as I mentioned you know you may want to think about using a ring network that is suitable for your game.
One of the graphics is wrong, but there should be another arrow on that short link in red, but basically we established used 4 of the connections as basically unidirectional links and we can send data around the ring.
So that handles what we do for peer-to-peer.
If you were going the other route and you want to host your own server, some considerations you need to take into account is one, when using the GKMatchmaker and Auto-Matching or the MatchmakerViewController you want to make sure you choose the correct API to use.
It is essentially a separate set of APIs and parameters for peer-to-peer networking, which is the default and hosted networking, which is for a client, when you host the server yourself.
You can still use our invitations in Auto-Matchmaking flow.
That's why it's there.
We want to do that part for you.
And you can even use the playerID to track players.
You know we only give you an array of playerIDs for the match.
You can use those to find the unique matches on your server.
The multiple ways you want to do this is communicate these matched players to your server and then implement your networking and set up communications.
So let's take a look at the Auto-Matching API that we use for this.
I think you've seen it once before in the slides but we'll just review it here.
This is findPlayersforRequest withCompletionHandler.
It's a method on the GKMatchmaker and it returns an array of players or an error you now for a server-hosted match.
Now if you want to use a standard UI or handle invitations you do this with a match request and you set up the standard GKMatchmakerViewController but in addition to setting yourself as the delegate you want to set the hosted property to YES.
That's telling us you intend for this to be a hosted game where you're going to host it on your own servers.
You'll show the UI and then you'll get back a different delegate call.
I'll show you the delegate.
It's the MatchmakerViewController, didfindPlayers delegate and you'll get an array of players for this match.
So for peer-to-peer networking GKMatch provides all the API you need to do the communications.
We've got Send.
We've have Receive and we've got player state change APIs.
It's important that you handle the player state changes.
Remember these are mobile devices.
They can take phone calls.
They now multitask.
They can lose their connection to the network so be able to handle that.
Be a good network citizen.
You don't want to overwhelm the networks that games are being played on you know.
Use our APIs appropriately and, you know, make sure that you're not over-saturating the network.
And if you need to handle, you want to handle a lot of players, you have some other functionality you want to handle, seriously consider hosting on your own servers.
So the last thing I want to talk about is In-Game Voice Chat.
We made this very easy for you to establish voice communications between the players in your match.
Now this only applies to peer-to-peer matches as it uses the GKMatch class and the GKVoiceChat class, which represents a distinct chat.
So In-Game Voice Chat allows your players to communicate with each other.
All the iPhones even the iPod touches.
They all have microphone.
You know if you connect the microphone headset to the iPod touch, it's great for players to communicate.
It's a new thing to be able to do this and it's a new thing on the phones.
You know it's almost kind of expected to be able to do this.
It really keeps players involved.
If players can talk to each other, you know get some more into the game, they can do things like trash talk.
They can encourage the others.
They can strategize among their own team.
It really enhances the competition.
We make it very easy for you to integrate.
It's basically you know we do all the networking for you to send the voice packets between devices.
All you have to do are create the Voice Chats and then manipulate them for which one is active.
So let's take a look at what Voice Chats offer.
We have multiple named Voice Chats that are accessible from the GKMatch.
You can use properties on the Voice Chats or methods to start and stop them so you can hear selected chats.
You can have multiple chats going.
The microphone is always routed to only a single chat.
And you can increase or decrease the volume of a given chat.
And if you need to it's possible for you to allow the player to mute another player in any given chat.
And then just like in Matchmaking it's useful to watch for the state changes so we have a handler implemented by a block.
The players update the handler, so you can find out when players connect, disconnect, start and stop speaking.
So before you set up the Voice Chats you need to set up the audio on the device.
It's a little pre-set up you need to do.
You want to set your audio session to play and record and make it the active audio session.
Take a quick look at this code.
There are a couple of ways to do this.
I'm showing you the AVAudioSession.
You basically set up its shared instance.
You set its category to Play and Record category and you make it active.
It's pretty straightforward.
Once you've got the audio session set up you need to get the Voice Chats.
Before you can actually do this you need to get the match.
So from the match, you're self-match, I'm going to create two chats.
The main chat or the lobby, which is where everybody will be able to talk to everybody else and the team chat for the red team, where only the people on the red team after that is connected can talk.
Here I show where we can stop the main chat so it's not going to play through this user's device so they won't hear the audio from the main chat and start the team chat.
And then I will make the team chat active to the route the microphone to the team chat.
And one important thing to note is when you make the microphone active for this it's generally important for you to give some indication to the user.
And an audible and a visual indicator are usually called for.
So it's just when you activate a chat and get the microphone active indicate it please.
Handling player state changes is pretty straightforward.
It's a block, the playerStateUpdateHandler.
There are 4 states that you may care about connected, if a player connects you may want to show their icon, show their name in lobby whatever.
If a disconnect, remove them from that list.
And when they start speaking you may want to show an icon you know a speaker icon, a little dot next to the name and remove it when they go silent.
So a lot of this functionality for multiplayer can only be tested on devices.
So its' very important that you test this on devices in particular like invitations or Voice Chat do not work you know you'll want to test with multiple devices and multiple accounts.
Testing on the simulator is limited.
You can test mostly other Game Center features like leaderboards and achievements but invitations are not available due to limitations and In-Game Voice Chat is also disabled.
There is only one little side effect that you probably won't notice but our preemptive cache invalidation is also disabled in the simulator, which you will only notice in the Game Center application probably, if at all.
So thank you for listening to me.
A couple of things I want to say before I leave the stage here is remind you that the first thing you need to do before you use Game Center is authenticate the local player.
Nothing will work unless you do that.
Then think about for your app how you want to divide the players that are going to play multiplayer.
You know come up with some good Player Groups and player attributes so that you can get the right sets of people together.
To handle invites make sure you implement both the InviteHandler and the playersToInviteHandler.
Use GKmatchmakerViewController to present the standard invitation UI and standard Matchmaking UI.
Once you have a match, wait for all players to connect before you start sending packets otherwise they're not going to go through.
It's a lot easier if you just wait before you start sending them.
Integrate Voice Chat because it gets your players more involved and we make it easy for you to do so.
And remember the Game Center is currently a preview on iPhone, sorry iOS 4 and will be available later this year.
For more information contact the Graphics and Game Technologies Evangelist, Allan Schaffer.