iOS游戏中心GameKit程序化邀请配对

我正在尝试实现一个实时的多人游戏与自定义用户界面(没有GKMatchMakerViewController)。 我使用的是startBrowsingForNearbyPlayersWithReachableHandler:^(NSString * playerID,BOOL可达)find一个本地播放器,然后用GKMatchmaker单例(我已经发起)发起一个匹配请求。

这是我遇到麻烦的地方。 当我发送请求时,完成处理程序几乎立即触发,没有错误,并且它返回的匹配具有预期的玩家数为零。 同时,另外一个玩家肯定没有回应这个要求

相关编码:

- (void) findMatch { GKMatchRequest *request = [[GKMatchRequest alloc] init]; request.minPlayers = NUM_PLAYERS_PER_MATCH; //2 request.maxPlayers = NUM_PLAYERS_PER_MATCH; //2 if (nil != self.playersToInvite) { // we always successfully get in this if-statement request.playersToInvite = self.playersToInvite; request.inviteeResponseHandler = ^(NSString *playerID, GKInviteeResponse response) { [self.delegate updateUIForPlayer: playerID accepted: (response == GKInviteeResponseAccepted)]; }; } request.inviteMessage = @"Let's Play!"; [self.matchmaker findMatchForRequest:request withCompletionHandler:^(GKMatch *match, NSError *error) { if (error) { // Print the error NSLog(@"%@", error.localizedDescription); } else if (match != nil) { self.currentMatch = match; self.currentMatch.delegate = self; // All players are connected if (match.expectedPlayerCount == 0) { // start match [self startMatch]; } [self stopLookingForPlayers]; } }]; } 

从以前的问题( iOS Gamecenter Programmatic Matchmaking )我知道我需要包含这个:

 - (void)matchForInvite:(GKInvite *)invite completionHandler:(void (^)(GKMatch *match, NSError *error))completionHandler 

在上面的代码,但我不知道应该包括在哪里。 我已经尝试了这两个GKMatchRequest inviteeResponseHandler,并在媒人finMatchForRequest:withCompletionHandler无济于事。 发生的行为是匹配器立即返回一个匹配(甚至在受邀者被邀请之前),并且即使在被邀请者点击匹配邀请之后也不会调用matchRequest inviteeResponseHandler。

有人可以就此提供build议吗? 谢谢。

…吉姆

今天晚上我刚刚开始了这个游戏。 您需要做更多的谈判来获得沟通渠道的设置。 返回邀请者的初始比赛正在等待被邀请者回复…这是我的过程只有两名球员。 以下是我的联络活动正在进行的所有步骤。 显然,这里没有包含真正的error handling:

首先,validation你的玩家

其次,在validation后设置inviteHandler。 像这样的东西:

 [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite* acceptedInvite, NSArray *playersToInvite) { if(acceptedInvite != nil) { // Get a match for the invite we obtained... [[GKMatchmaker sharedMatchmaker] matchForInvite:acceptedInvite completionHandler:^(GKMatch *match, NSError *error) { if(match != nil) { [self disconnectMatch]; // Record the new match... self.MM_gameCenterCurrentMatch = match; self.MM_gameCenterCurrentMatch.delegate = self; } else if(error != nil) { NSLog(@"ERROR: From matchForInvite: %@", [error description]); } else { NSLog(@"ERROR: Unexpected return from matchForInvite..."); } }]; } }; 

第三,获取你的朋友playerIds(不别名)的列表。

第四,设置你的GKMatchRequest像这样…我只邀请一个朋友:

 // Initialize the match request - Just targeting iOS 6 for now... GKMatchRequest* request = [[GKMatchRequest alloc] init]; request.minPlayers = 2; request.maxPlayers = 2; request.playersToInvite = [NSArray arrayWithObject:player.playerID]; request.inviteMessage = @"Let's play!"; // This gets called when somebody accepts request.inviteeResponseHandler = ^(NSString *playerID, GKInviteeResponse response) { if (response == GKInviteeResponseAccepted) { //NSLog(@"DEBUG: Player Accepted: %@", playerID); // Tell the infrastructure we are don matching and will start using the match [[GKMatchmaker sharedMatchmaker] finishMatchmakingForMatch:self.MM_gameCenterCurrentMatch]; } }; 

第五,使用请求调用findMatchForRequest:withCompletionHandler:这样的事情…

  [[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch* match, NSError *error) { if (error) { NSLog(@"ERROR: Error makeMatch: %@", [error description] ); [self disconnectMatch]; } else if (match != nil) { // Record the new match and set me up as the delegate... self.MM_gameCenterCurrentMatch = match; self.MM_gameCenterCurrentMatch.delegate = self; // There will be no players until the players accept... } }]; 

第六,这将请求发送给其他玩家,如果他们接受来自第二步的“inviteHandler”被调用。

第七,从第二步“邀请处理者”得到GKInvite的比赛!

第八,来自第四步的“inviteeResponseHandler”被称为完成比赛!

第九,从GKMatchDelegate创build一个didChangeState来处理匹配的最终化。 像这样的东西:

 - (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state{ switch (state) { case GKPlayerStateConnected: // Handle a new player connection. break; case GKPlayerStateDisconnected: // A player just disconnected. break; } if (!self.matchStarted && match.expectedPlayerCount == 0) { self.matchStarted = YES; // Handle initial match negotiation. if (self.iAmHost && !self.sentInitialResponse) { self.sentInitialResponse = true; // Send a hello log entry [self sendMessage: [NSString stringWithFormat:@"Message from friend, 'Hello, thanks for accepting, you have connected with %@'", self.MM_gameCenterLocalPlayer.alias] toPlayersInMatch: [NSArray arrayWithObject:playerID]]; } }} 

第十,这里是我的sendMessage:

 - (void) sendMessage:(NSString*)action toPlayersInMatch:(NSArray*) playerIds{ NSError* err = nil; if (![self.MM_gameCenterCurrentMatch sendData:[action dataUsingEncoding:NSUTF8StringEncoding] toPlayers:playerIds withDataMode:GKMatchSendDataReliable error:&err]) { if (err != nil) { NSLog(@"ERROR: Could not send action to players (%@): %@ (%d) - '%@'" ,[playersInMatch componentsJoinedByString:@","],[err localizedDescription],[err code], action); } else { NSLog(@"ERROR: Could not send action to players (%@): null error - '%@'",[playersInMatch componentsJoinedByString:@","], action); } } else { NSLog(@"DEBUG: Message sent to players (%@) - '%@'",[playersInMatch componentsJoinedByString:@","], action); }} 

第十一,从GKMatchDelegate创build一个didReceiveData,如下所示:

 - (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID{ NSString* actionString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; // Send the initial response after we got the initial send from the // invitee... if (!self.iAmHost &&!self.sentInitialResponse) { self.sentInitialResponse = true; // Send a hello log entry [self sendMessage: [NSString stringWithFormat:@"Message from friend, 'Hello, thanks for inviting, you have connected with %@'", self.MM_gameCenterLocalPlayer.alias] toPlayersInMatch: [NSArray arrayWithObject:playerID]]; } // Execute the action we were sent... NSLog(actionString);} 

第十二…那么现在你有沟通渠道和运行…做任何你想要的…