首页 文章

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

提问于
浏览
7

我正在尝试使用自定义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

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

有人可以就此提出建议吗?谢谢 .

...吉姆

1 回答

  • 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”被召唤完成比赛!

    第九,从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]];
        }
    }}
    

    第十,这是我的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创建一个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);}
    

    第十二......好了,现在你已经开始运行了沟通渠道......做你想做的事......

相关问题