Please have a look, download it for free and consider buying some extra lives and unlock the multiplayer feature to play against people from all over the world! Play agains me => my nickname is “GABEHOE” or against my co-worker Adrian => “ADIMAN84” 😀
We’d love to hear suggestions and receive feedbacks from you… and compete with you! Hahahah…

On this blog post I am going to show you how to use Game Center (Game Kit Framework) to make an amazing Multiplayer Game like SNOWGRE… well, not the whole game, but at least I will show you how to code the multiplayer stuff! 😉

Advertisement:

The first iPhone App ever that finds out who’s calling you before you answer the phone.

First, we have to diferentiate what happens in the frontend (all the stuff you “see” with your eyes) and in the backend (all the connection stuff and data that is being exchanged between the players).

Present the Game Center ViewController to find oponents or invite a friend – matchmaking!

Once Game Center has found enough players for a match, we present the game scene

let’s enable Game Center for our App:

Preparations

Login into iTunes Connect

Click on “Manage Your Apps”

Click on the App Icon

Follow the steps described on the screenshot below:

Game Center Activation – iTunes Connect

Now we have enabled and activated Game Center for our Game. Let’s go to XCode…

Add the GameKit Framework into your project => select the Project (top left of Groups & Files), select the “Build Phases” Tab on the right, expand the “Link Binary with Libraries” section and press the “+”-button. Then, select the “GameKit.framework” and click “add”.

Add GameKit.framework to your project

Authenticate the player

We have now everything preparated to begin with the implementation. First we must know first a few things about authentication. Basically whenever your App starts up, we have to authenticate (or check) the player in Game Center. If the user is already authenticated, there appears a welcome message like “Welcome back!”. If the user is not authenticated, a ViewController will show up asking for a username & password. But that’s not everything… what if the user logs out and your App is running? Fortunately there is an “authentication changed” notification so that we can immediately react and invite the user to log in again.

Let’s dig into some codeezzzz…

We need a GameCenterManager singleton, that will be responsible for all Game Center action throughout our game. Make a new class, a subclass of NSObject and name it “GameCenterManager”:

So this is our GameCenterManager. I used basically the same code from as Apple suggests here: GameCenterManager. But removed a few methods like “submitAchievements”, “resetAchievements”, etc. since this is not need here for the scope of this blog post. The most important method for us is “findMatchWithMinPlayers”. This method is responsible for finding an oponent player in the same network or somewhere else in the Game Center network.

Since we define a delegate (our “RootViewController” – more about this one later on this post), our GameCenterManager sends the data to him whenever he receives data from a player (playerID). Like this we always know when a player changes position or shoots from his gun, etc… got it?

Our delegate: RootViewController

This ViewController (can be any other ViewController that you decide to be the delegate of our GameCenterManager) decides what to do with the information we get from our oponent(s). The GameCenterManager tells our RootViewController following…

We found an oponent (or more)! His name is “player2”

We are ready to start the match!

Stay tuned, I will send you his positions and his states!

If the player2 (or other players) loose connection or abort the game, or win the game, I will notify you!

OK… now we need to handle the data we get from our GameCenterManager as following: create (if not yet existing) a ViewController (subclass of UIViewController in our case – not mandatory! We have additional code in our RootViewController… that’s why) that will be the delegate of the GameCenterManager:

[self setGameState:kGameStateWaitingForOponentToStart];
[self startGame];
}
- (void)matchEnded {
NSLog(@"Match ended because of disconnection or anything else... check above our GameCenterManager... handle!");
}
// this method receives data from all players, in our game only from one oponent
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
// Imagine we have a multiplayer game with 4 players... somehow you have to differentiate
// the data you receive... are we getting new positions from player2 or player3 or player4?
// so the three following lines we don't need in OUR example, but I let it there as a hint
// for you if you plan to make a multiplayer game with more than 2 players in total.
if (oponentPlayerID == nil) {
oponentPlayerID = [playerID retain];
}
// there are other ways to check if we receive a game status message or a hero position
// message... but this works :)
if ([data length] == sizeof(HeroInfo) * HERO_INFO_PACKAGESIZE) {
// in our game we have to simulate the oponent and all his actions... in our case it
// is the Hero2 object. So we send the info to that object, so that we can put the
// Hero2 into the right position on the screen and into the right state (stunned,
// hitting, burping, etc.)
HeroInfo *messageHero = (HeroInfo *)[data bytes];
[[Hero2 sharedInstance] setHeroInfo:messageHero];
}
else {
// we received a game state message... something happened
HeroMessage *myMessage = (HeroMessage *) [data bytes];
if (myMessage->messageType == kMessageTypeGameHasBegun) {
[self setGameState:kGameStateIsReadyToStartGame];
[self reallyStartMultiplayerSession];
}
else if (myMessage->messageType == kMessageTypeDisconnection) {
// our GameCenterManager just told us that our oponent was disconnected fro
// from the match... maybe he got a phone call, or his phone ran out of batteries,
// or whatever... react! You can close the match or tell the user that he has
// won or just call [self setupMultiplayerGame] again...
}
else if (myMessage->messageType == kMessageTypeGameIsOver) {
if (myMessage->oponentHasWon) {
// we received the message from the oponent, that he has won the match!
}
else {
// we received the message from the oponent, that he has lost the game
// due to an unknown (yet) reason.
}
}
}
}
-(void)reallyStartMultiplayerSession {
// YOUR_GAME is responsible to show the game
[YOUR_GAME startMultiplayerSession];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (NSUInteger) supportedInterfaceOrientations {
//Because your app is only landscape, your view controller for the view in your
// popover needs to support only landscape
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
-(BOOL)shouldAutorotate {
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
+(RootViewController *)sharedInstance {
return staticRootVC;
}
@end

HANG ON! We’re almost finished… there is another headerfile where we define our message-structures called Constants.h. Before I show you that, let me explain some functions in RootViewController first. The method – (void)setupMultiplayerGame; tells our GameCenterManager that we want to play a multiplayer game with a friend or somebody in the world. The GameCenterManager presents then a GKMatchmakerViewController modally where the user can choose between looking for an oponent nearby or worldwide. Once Game Center has found an oponent, it tells our RootViewController that we are ready to play.

OK, let’s see what we need in Constants.h…

Constants.h

// This here defines the multiplyer of size of package we send each time to our oponent...
// For example in a game, you define 60fps or sometimes 30fps... so it's not wise to send
// 30 or 60 times a second a Package to the oponent!!! Obviously, right...? So don't forget
// to build up a buffer or some sort of technology to cope with this problem, otherwise the
// hero2 will not update smoothly on your screen...
#define HERO_INFO_PACKAGESIZE 3

I’m pretty sure that I’ll be able to manage sending/receive and updating the UI with the data received, but one thing I’m not quite able to determine is when to actually start the match : when a player Connects or when didFindMatch ?