iPhone - многопользовательская онлайн-игра с пониманием механики

Я разрабатываю многопользовательскую онлайн-игру, но у меня проблемы с документацией Apple. (Я пробовал эти руководства Рэя Вендерлихса Часть 1 и part 2, но они не работают (совпадение никогда не начинается, потому что приглашающее устройство никогда не получает подтверждение совпадения).

Поскольку эта тема обширна, я создам один вопрос, а затем при необходимости перейду к созданию еще одного вопроса по SO.

Я хочу создать многопользовательскую онлайн-игру, в которой пользователь сможет пригласить от 1 до 3 человек. Таким образом, это будет матч от 2 до 4 человек. Игра не пошаговая. Он живой, и объем данных, передаваемых между пользователями, минимален.

Начнем с основных вещей.

1) первое, что я делаю, это создаю уведомление

if (self.gameCenterAvailable) {
    NSNotificationCenter *nc = 
    [NSNotificationCenter defaultCenter];
    [nc addObserver:self 
           selector:@selector(authenticationChanged) 
               name:GKPlayerAuthenticationDidChangeNotificationName 
             object:nil];

}

чтобы сообщить мне, когда уведомление изменится. Когда это произойдет, сработает метод authenticationChanged ... вот он

- (void)authenticationChanged {    

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;
        [self 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;
        [self presentModalViewController:mmvc animated:YES];
    }
};

}

Я взял этот код у Apple. Мой вопрос вот в чем. Если Apple говорит запустить этот код после аутентификации пользователя, почему он проверяет наличие приглашения или пользователей для приглашения? Насколько я понимаю, пользователей еще не пригласили. Если в это время код не выполняется, верно? Он просто будет сидеть в памяти в ожидании вызова, КОГДА приглашение сделано, верно?

Если это так, я сейчас создаю приглашение на матч, выполняя

[self dismissModalViewControllerAnimated:NO];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
request.minPlayers = minPlayers;     
request.maxPlayers = maxPlayers;
request.playersToInvite = self.pendingPlayersToInvite;

GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];    
mmvc.matchmakerDelegate = self;

[self presentModalViewController:mmvc animated:YES];

Окно будет представлено всем пользователям, которых я выберу пригласить. Предположим, первый нажимает ПРИНЯТЬ на приглашении. Какой метод будет запущен в моем приложении, как мне узнать личность пользователя и как узнать, все ли пользователи приняли?

благодаря.


person Duck    schedule 23.02.2012    source источник


Ответы (1)


Прежде всего, имейте в виду, что приглашения в среде Sandbox, как правило, работают хаотично, поэтому я предлагаю вам начать с того, что все игроки будут искать доступный матч. Код будет примерно таким:

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

[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request
                               withCompletionHandler:^(GKMatch *match, NSError *error) {
                                     if (error || !match) {
                                       // handle the error
                                     }
                                     else if (match != nil){
                                       // match found
                                     }}];
  }

Затем вам нужно реализовать протокол GKMatchDelegate. Там есть метод, который будет вызываться для каждого игрока, который присоединяется к матчу, и для каждого игрока, который отключается от него (с помощью этого метода вы можете узнать личность пользователя с его playerID):

- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
    switch (state){
      case GKPlayerStateConnected: 
        if (match.expectedPlayerCount == 0) {
          // start the match
        }
        break;
      case GKPlayerStateDisconnected:
        // remove the player from the match, notify other players, etc
        break;
    } 
}

Что касается вашего первого вопроса, код на authenticationChanged регистрирует только обработчики для этих методов, то есть код, который будет вызываться при получении уведомлений.

РЕДАКТИРОВАТЬ: Что касается вопроса к вашему комментарию, если матч был начат с приглашения, пользователь, который начал матч, должен дождаться, пока все приглашения будут приняты, или отменить некоторые из них, а затем нажать Start Match (или что-то в этом роде) на Экран приглашения. В этом сценарии условие match.expectedPlayerCount == 0 будет выполнено, когда все игроки, принявшие приглашения, подключатся к матчу. Если матч был запущен с помощью AutoMatch, Game Center выполняет следующие действия: как только он находит minPlayers, ожидающих начала матча, он присваивает им совпадение, а затем ждет еще несколько секунд, чтобы увидеть, сможет ли он заполнить оставшиеся слоты. В какой-то момент он начнет матч с определенным количеством игроков между minPlayers и maxPlayers. Тогда условие match.expectedPlayerCount == 0 будет выполнено только после того, как все игроки фактически присоединятся к матчу, но обратите внимание, что когда было принято решение начать матч, количество игроков, ожидаемых для этого матча, уже определено Game Center.

person elibud    schedule 23.02.2012
comment
спасибо за ответ, но это вопрос по этой строке if (match.expectedPlayerCount == 0). Если я даю пользователю возможность создать матч, приглашающий от 1 до 3 человек, когда именно это условие сработает? Я имею в виду, что если в матче может быть любое количество игроков от 2 до 4, он будет удовлетворять это каждый раз. Итак, после того, как первый пользователь примет приглашение, матч начнется. Вот как все начинает разваливаться в моем видении того, как эта штука работает. - person Duck; 23.02.2012
comment
См. Мою правку выше. Просто дайте мне знать, если у вас есть еще вопросы, я по собственному опыту знаю, что Game Center может сбивать с толку вначале, но как только все будет сделано правильно, он работает как шарм. - person elibud; 23.02.2012
comment
Хорошо, теперь я понимаю это, но предположим, что игрок (назовем его игроком ONE) отправляет 3 приглашения, два приглашения принимаются, но до того, как последнее ответит, игрок ONE нажимает PLAY NOW. Какой метод будет работать? матч: player: didChangeState :? Спасибо за вашу помощь. - person Duck; 23.02.2012
comment
Нет, match: player: didChangeState: не будет выполняться, поскольку третий игрок никогда не был подключен к матчу в первую очередь. Также я не уверен, что вы можете нажать «Играть сейчас» (у меня сейчас нет среды разработки, которую можно было бы проверить), если только все приглашенные игроки не приняли или вы не отменили приглашение. - person elibud; 24.02.2012