8

カスタムUI(GKMatchMakerViewControllerなし)を使用してリアルタイムマルチプレイヤーゲームを実装しようとしています。startBrowsingForNearbyPlayersWithReachableHandler:^(NSString * playerID、BOOL到達可能)を使用してローカルプレーヤーを検索し、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

上記のコードでは、それをどこに含めるべきかわかりません。私はそれをGKMatchRequestinviteResponseHandlerとマッチメーカーfinMatchForRequest:withCompletionHandlerの両方で試しましたが無駄になりました。発生する動作は、マッチメーカーが即座に(招待者が招待される前であっても)一致を返し、招待者が一致の招待をタップした後でも、matchRequestinviteResponseHandlerが呼び出されないことです。

誰かがこれについてアドバイスを提供できますか?ありがとうございました。

...ジム

4

1 に答える 1

16

今夜、これを自分のゲームで動作させました。通信チャネルを設定するには、さらに多くのネゴシエーションを行う必要があります。招待者に返された最初の試合は、招待者が応答するのを待っています...これが2人のプレーヤーだけでの私のプロセスです。これが私のコミュニケーションスピンアップが実行しているすべてのステップです。明らかに、ここには実際のエラー処理は含まれていません。

まず、プレーヤーを認証します

次に、認証セットの直後に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を次のように設定します...私は1人の友人だけを招待しています:

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

5番目に、リクエストを使用して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...
    }
}];

第6に、これは他のプレーヤーにリクエストを送信し、他のプレーヤーが2番目のステップから「inviteHandler」を受け入れると呼び出されます。

第7に、2番目のステップの「inviteHandler」がGKInviteに一致します。

第8に、4番目のステップの「inviteeResponseHandler」が呼び出され、試合が終了しました。

9番目に、GKMatchDelegateから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]];
    }
}}

10番目に、これが私の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);
}}

11番目に、GKMatchDelegateから次のような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);}

12番目...これで通信チャネルが稼働しました...好きなことをしてください...

于 2013-04-11T02:51:11.693 に答える