2013-03-25 4 views
7

Я пытаюсь реализовать многопользовательскую игру в режиме реального времени с пользовательским интерфейсом (без GKMatchMakerViewController). Я использую startBrowsingForNearbyPlayersWithReachableHandler:^(NSString * playerID, BOOL достижимый), чтобы найти локального игрока, а затем инициировать запрос на совпадение с синглтоном GKMatchmaker (который я уже начал).iOS Game Center GameKit Programmatic Invite Matchmaking

Здесь у меня проблемы. Когда я отправляю запрос, обработчик завершения запускается почти сразу, без ошибки, и возвращаемое совпадение имеет ожидаемое количество игроков, равное нулю. Между тем, другой игрок определенно не ответил на запрос

Соответствующий код:

- (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, так и в matchmaker finMatchForRequest: withCompletionHandler безрезультатно. Поведение, которое происходит, заключается в том, что свахи немедленно возвращают матч (даже до приглашения приглашенного), а matchRequest inviteeResponseHandler никогда не вызывается даже после того, как приглашенный ответит приглашение на матч.

Может кто-нибудь предложить совет по этому вопросу? Спасибо.

... Джим

+0

Как вы получили startBrowsi ngForNearbyPlayersWithReachableHandler работать? Я никогда не получаю никакого обратного вызова от него? – bobmoff

ответ

15

Я только что получил эту работает над своей игрой сегодня. Для получения настройки канала связи требуется больше переговоров. Первоначальное совпадение, возвращенное приглашающему, ждет ответа приглашенного ... Вот мой процесс с двумя игроками. Вот все шаги, которые выполняет мой раскрутка. Очевидно, что никакой реальной обработки ошибок не включены здесь:

Во-первых, Аутентифицировать плеер

Во-вторых, сразу после проверки подлинности установленной 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» со второго шага, вызывается.

В-седьмых, «inviteHandler» со второго шага получает матч за GKInvite!

В-восьмых, «inviteeResponseHandler» с четвертого шага получает название, которое закончило матч!

Девятый, создайте hasChangeState из GKMatchDelegate, чтобы обработать завершение матча.Что-то вроде этого:

- (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); 
}} 

одиннадцатых, создать didReceiveData из GKMatchDelegate что-то вроде этого:

- (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);} 

Двенадцатый ... Ну теперь вы иметь каналы связи и работать ... делать все, что вы хотите ...

+0

Хороший ответ !!!!! –

+0

@ GoRose-Hulman вы можете обновить свой ответ для iOS 7? –

+0

Знаете ли вы правильный способ сделать это в iOS9? Я просто задал аналогичный вопрос: http://stackoverflow.com/questions/36728503/gkmatchmaker-findmatchforrequest-invite-never-received – mark

Смежные вопросы