Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Game Center Finding a Match Programmatically

I just can't figure out how this works. What I am trying to do is let two players play a game if a third player joins it can instantly join the game, if the fourth and last player joins it can also instantly join the game. They can also leave the game at anytime for whatever reason, if that happens there should be a space open for another person or for the same person to reconnect. That's the idea.

Now what I got is the following. I authenticate the local player for obvious reasons. Then I search for a match like so:

if (matchRequest) [matchRequest release];
matchRequest            = [[GKMatchRequest alloc] init];
matchRequest.minPlayers = 2;
matchRequest.maxPlayers = 4;

[[GKMatchmaker sharedMatchmaker] findMatchForRequest:matchRequest withCompletionHandler:^(GKMatch *match, NSError *error) {
    if (error) {
        // An error occured
    } else {
        if (matchCurrent) [matchCurrent release];
        matchCurrent          = [match retain];
        matchCurrent.delegate = self;
    }
}];

If I execute this part on three different devices, two of them will find each other and the third is still looking. So I figured after the find match for request has found the minimum amount of players it will be executed once. So what I needed was a method that used the matchCurrent that I retained to add more players. Luckely that method existed, but how would that work? When do you call it in this case? I decided to put it under a button so I could manually execute it when a match has been found.

What I discovered is that when I pressed it on the first device, finally the third device could find the match the first and second device were in. In fact the second and third device contained the playerIDs of every device involved. Which is a good thing. But there are two problems.

  1. Which device should actually call the addPlayersToMatch method? And how can you restrict it to one device executing that method? Plus when should you call it?
  2. Why, on the device calling that method, isn't the playerIDs updated?

    [[GKMatchmaker sharedMatchmaker] addPlayersToMatch:matchCurrent matchRequest:matchRequest completionHandler:^(NSError *error) {
        //matchCurrent.playerIDs is not updated?!
    }]; 
    

    Actually they are updated. When I see the playerIDs appear on the second and third device I manually update the matchCurrent.playerIDs on device one and suddenly it does recognize the player. However even the 'didChangeState' for player is not called when the new player is discovered on device one.

like image 465
Mark Avatar asked Oct 07 '10 20:10

Mark


2 Answers

Your using the Apple iOS Game Center GKMatchmaker class. I'm assuming you are using a peer to peer connection, not hosted.

The GKMatch class gives the playerIDs array to you.

@property(nonatomic, readonly) NSArray *playerIDs

This is an ordered list, so you might be able to use it to select the first player call addPlayersToMatch.

Linked below is some documentation.

http://developer.apple.com/library/ios/#documentation/GameKit/Reference/GKMatchmaker_Ref/Reference/Reference.html

http://developer.apple.com/library/ios/#documentation/GameKit/Reference/GKMatch_Ref/Reference/Reference.html

http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/GameKit_Guide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008304

like image 186
Thomas Langston Avatar answered Oct 17 '22 19:10

Thomas Langston


Which device should actually call the addPlayersToMatch method? And how can you restrict it to one device executing that method?

You could solve this problem by having the devices "draw straws". Each device generates a random number, then sends it to the others. The device with the largest number is the leader, and it is the one that must call addPlayersToMatch. If two devices pick the same number, throw out the numbers and start over.

like image 37
benzado Avatar answered Oct 17 '22 19:10

benzado