Как принять приглашение в Game Center

Я пытаюсь реализовать приглашения с Game Center, и есть одна вещь, которую я не понимаю. Хорошо, я отправил приглашение с одного устройства на другое. Затем у меня есть UIAlertView на приемнике, который просит меня принять или отклонить приглашение. когда я принимаю его, он обрабатывается следующим образом:

[GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) 
                 {
                     // Insert application-specific code here to clean up any games in progress.
                     if (acceptedInvite)
                     {
                         GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
                         mmvc.matchmakerDelegate = self;
                         [presentingViewController presentModalViewController:mmvc animated:YES];
                     }
                     else if (playersToInvite)
                     {
                         GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
                         request.minPlayers = 2;
                         request.maxPlayers = 4;
                         request.playersToInvite = playersToInvite;

                         GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
                         mmvc.matchmakerDelegate = self;
                         [presentingViewController presentModalViewController:mmvc animated:YES];

                     }
                 };

Ну, это здорово, но что дальше? устройство отправителя, очевидно, ждет какого-то стандартного типа ответа, потому что оно также показывает предупреждение, сообщающее мне, что есть некоторые приглашения, на которые еще не ответили, если я нажму "играть сейчас".

Итак, как я могу принять приглашение? Какие данные (и как) я должен отправить обратно? И что именно я должен делать со стороны приемника? Должна ли игра начинаться сразу после нажатия " принять "или я должен сначала закрыть AlertView, а затем нажать"Играть сейчас"?

Рэй Вендерлих это говорит, что я должен выбрать второй способ, но когда отклонить предупреждение и нажмите "Играть сейчас", оказывается, отправитель устройство все еще ждет ответа и не знает, что я уже принял приглашение. если я нажму "играть сейчас" в этот момент, то, как я сказал выше, он показывает предупреждение, которое говорит, что приложение ждет ответа. Так что если вы когда-нибудь делали это, пожалуйста, объясните мне, что я должен делать. Спасибо!

3 ответов


  1. я регистрируюсь для инвайтов, как только игра загружается и вызываю делегировать при получении приглашения
  2. так inviteReceived называет матч мейкера для увольнения игры центральный контроллер и создание матча
  3. и, наконец, когда соответствие найдено, метод connectionStatusChanged заботится о том, чтобы представить все игры просмотры, игроки и прочее

вот код:

я регистрируюсь для приглашений как как только игра будет загружена и позвоните делегату, когда будет получено приглашение:

- (void)registerInvites {
    [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
        self.pendingInvite = acceptedInvite;
        self.pendingPlayersToInvite = playersToInvite;
        [delegate inviteReceived];
    };
}

таким образом, inviteReceived вызывает match maker для увольнения контроллера game center и создания матча:

- (void)inviteReceived {
    [[GCMultiplayerHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController:(UIViewController*)[self.superview nextResponder] delegate:self];
}


- (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(id<GCMultiplayerHelperDelegate>)theDelegate {
    if (!gameCenterAvailable) return;

    matchStarted = NO;
    self.match = nil;
    self.presentingViewController = viewController;
    delegate = theDelegate;

    [presentingViewController dismissModalViewControllerAnimated:YES];
    GKMatchmakerViewController *mmvc;

    if (pendingInvite != nil) {

        mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:pendingInvite] autorelease];

    } else {

        GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
        request.minPlayers = minPlayers;     
        request.maxPlayers = maxPlayers;
        request.playersToInvite = pendingPlayersToInvite;

        mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];    

    }

    mmvc.matchmakerDelegate = self;
    [presentingViewController presentModalViewController:mmvc animated:YES];

    self.pendingInvite = nil;
    self.pendingPlayersToInvite = nil;
}

и, наконец, когда матч был найден, метод connectionStatusChanged заботится о представлении всех взглядов игры, игроков и начале матча:

- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch
{
    self.match = theMatch;
    match.delegate = self;
    if (!matchStarted && match.expectedPlayerCount == 0) {
        NSLog(@"Ready to start match! - didFindMatch");
        [presentingViewController dismissModalViewControllerAnimated:YES];

        [self.delegate connectionStatusChanged:CONNECTIONSUCCESS];
    }
}

я успешно реализовал онлайн-матч game center после учебных пособий Рэя. Ответ на ваш вопрос: вам не нужно ничего отправлять на приглашающее устройство. При вызове строки:GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];, matchMakerVController обрабатывает соединение . Однако вы должны написать обработчик приглашений как можно скорее, предпочтительно в методе проверки подлинности. Смотрите мой:

-(void) authenticationChanged {

if ([GKLocalPlayer localPlayer].isAuthenticated && !userAuthenticated) {
    NSLog(@"Authentication changed: player authenticated.");
    userAuthenticated = TRUE;

    [self sendUnsentScores];

    [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite){

        NSLog(@"Invite");

        if([AppDelegate mainMenuController].presentedViewController!=nil) {
            [[AppDelegate mainMenuController] dismissViewControllerAnimated:NO completion:^{

            }];
        } // if we're not on the main menu, or another game is going on.
          // this would be easier to do if you were using a navigation controller
          // where you'd just push the multiplayer menu etc.


        self.pendingInvite = acceptedInvite;
        self.pendingPlayersToInvite = playersToInvite;

        [[AppDelegate mainMenuController] presentViewController:[AppDelegate mainMenuController].multiGameMenu animated:NO completion:^{ // push the multiplayer menu

            [[AppDelegate mainMenuController].multiGameMenu duel:nil];
        }];

    };

}

и вот метод дуэли, если вам интересно. Очень грязный код, но разберитесь с ним :)

- (IBAction)duel:(id)sender {
NSLog(@"duel");

if (presentingMenu.multiGameController==nil || presentingMenu.multiGame.gameInProgress==NO) {

    presentingMenu.multiGame=nil;
    presentingMenu.multiGameController=nil;

    MultiViewController *mvc = [[MultiViewController alloc] init]; //create game VC

    presentingMenu.multiGameController = mvc; //presenting menu is just the main menu VC
                                              // it holds this menu, and the game
                                              // objects.
}

if (presentingMenu.multiGame == nil) {

    presentingMenu.multiGame = [[MultiGame alloc] // similarly create the game object

    initWithViewController:presentingMenu.multiGameController];
    //they both have pointers to each other (A loose, bad MVC).                        

    presentingMenu.multiGameController.game = presentingMenu.multiGame;

    [presentingMenu.multiGame startGame];

}

if (presentingMenu.multiGameController.gameState==0) { //new game

    presentingMenu.multiGameController.game = presentingMenu.multiGame;

    [[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController:self delegate:presentingMenu.multiGame]; // the GC magic happens here - it know about the invite.

} else {

    [self presentViewController:presentingMenu.multiGameController animated:YES completion:^{

    }];

}

}

inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) устарел. См. новый способ регистрации уведомлений о приглашениях.

обработчик приглашений gkmatchmaker устарел