2013-03-25 30 views
7

Tôi đang cố gắng triển khai trò chơi nhiều người chơi trong thời gian thực với giao diện người dùng tùy chỉnh (không có GKMatchMakerViewController). Tôi đang sử dụng startBrowsingForNearbyPlayersWithReachableHandler:^(NSString * playerID, BOOL reachable) để tìm một trình phát nội bộ, và sau đó bắt đầu một yêu cầu kết hợp với singleton GKMatchmaker (mà tôi đã bắt đầu).Trung tâm trò chơi iOS GameKit Lập trình Mời mai mối

Đây là nơi tôi đang gặp sự cố. Khi tôi gửi yêu cầu, trình xử lý hoàn thành sẽ kích hoạt gần như ngay lập tức, mà không có lỗi và kết quả khớp sẽ trả về có số người chơi dự kiến ​​là 0. Trong khi đó, các cầu thủ khác chắc chắn đã không đáp ứng với yêu cầu

Mã liên quan:

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

Tôi biết từ một câu hỏi trước (iOS Gamecenter Programmatic Matchmaking) mà tôi cần phải bao gồm này:

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

trong đoạn mã trên nhưng tôi không biết nó nên được bao gồm ở đâu. Tôi đã thử nó cả lời mời GKMatchRequest inviteeResponseHandler, và trong finMatchForRequest mai mối: withCompletionHandler không có kết quả. Hành vi xảy ra là người mai mối trả về một trận đấu ngay lập tức (ngay cả trước khi người được mời đã được mời) và người được mờiResponseHandler matchRequest không bao giờ được gọi ngay cả sau khi người được mời nhấn vào lời mời kết hợp.

Ai đó có thể đưa ra lời khuyên về điều này? Cảm ơn bạn.

... Jim

+0

Làm thế nào bạn có được startBrowsingForNearbyPla yersWithReachableHandler có thể hoạt động không? Tôi không bao giờ nhận được bất kỳ cuộc gọi lại từ nó ?? – bobmoff

Trả lời

15

Tôi vừa làm việc này tối nay. Có nhiều thương lượng bạn cần làm để thiết lập kênh liên lạc. Trận đấu đầu tiên được trả lại cho người mời đang đợi người được mời trả lời ... Đây là quá trình của tôi chỉ với hai người chơi. Dưới đây là tất cả các bước mà hoạt động truyền thông của tôi đang thực hiện. Rõ ràng, không xử lý lỗi thực sự bao gồm ở đây:

Đầu tiên, Xác thực trình phát của bạn

Thứ hai, ngay sau khi bộ xác thực mờiHandler. Một cái gì đó như thế này:

[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..."); 
      } 
     }]; 
    } 
}; 

Thứ ba, Nhận danh sách người chơi bạn của bạn (không phải bí danh).

Thứ tư, cài đặt một cái gì đó GKMatchRequest bạn như thế này ... Tôi chỉ mời một người bạn:

// 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]; 
    } 
}; 

Thứ năm, Sử dụng các yêu cầu để gọi findMatchForRequest: withCompletionHandler: một cái gì đó như thế này ...

[[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... 
    } 
}]; 

Thứ sáu, điều này sẽ gửi yêu cầu đến người chơi khác và nếu họ chấp nhận "inviteHandler" từ bước thứ hai được gọi.

Thứ bảy, "inviteHandler" từ bước thứ hai nhận được kết quả phù hợp cho GKInvite!

Thứ tám, "inviteeResponseHandler" từ bước thứ tư được gọi là kết thúc trận đấu!

Thứ chín, tạo một didChangeState từ GKMatchDelegate để xử lý kết thúc trận đấu.Một cái gì đó như thế này:

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

thứ mười, đây là SendMessage của tôi:

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

thứ mười, tạo một didReceiveData từ GKMatchDelegate một cái gì đó như thế này:

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

thứ mười hai ... Vâng bây giờ bạn có các kênh truyền thông và chạy ... làm bất cứ điều gì bạn muốn ...

+0

Câu trả lời hay !!!!! –

+0

@ GoRose-Hulman bạn có thể cập nhật câu trả lời cho iOS 7 không? –

+0

Bạn có biết cách chính xác để thực hiện việc này trong iOS9 không? Tôi vừa hỏi một câu hỏi tương tự: http://stackoverflow.com/questions/36728503/gkmatchmaker-findmatchforrequest-invite-never-received – mark

Các vấn đề liên quan