Auto-match и endTurnWithNextParticipant Game Center

Я разрабатываю пошаговую игру с двумя игроками Game Center и хочу разрешить автоматическое сопоставление.

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

- (void)endTurnWithNextParticipants:(NSArray *)nextParticipants turnTimeout:(NSTimeInterval)timeout matchData:(NSData *)matchData completionHandler:(void (^)(NSError *error))completionHandler

Теперь то, что я не понимаю, это значение массива "nextParticipants" в случае, если сопоставление начинается в режиме автоматического сопоставления, что, как я прочитал, выполняется путем установки для участников значения nil, например:

 GKMatchRequest *request = [[GKMatchRequest alloc] init];
 request.minPlayers = 2;
 request.maxPlayers = 2;
 request.playersToInvite = nil;
 request.inviteMessage = @"Let’s play";
 [GKTurnBasedMatch findMatchForRequest: request
                 withCompletionHandler: ^(GKTurnBasedMatch *match,
                                          NSError *error) {
                     NSLog(@"%@", match);
                 }];

Если массив равен нулю, и я не знаю, кто присоединится к матчу, как я могу передать ход следующему игроку? Если я использую nil в аргументе nextParticipants, конечно, я получаю ошибку "неверный список nextParticipants".

Док Apple, кажется, об этом молчит.

Итак, я также не понимаю, как на самом деле работает автоматическое сопоставление. Будет ли он совпадать с любыми двумя игроками, которые начали новый матч с автоподбора, безоговорочно? Разве я не могу каким-то образом выбрать, с какими совпадениями я хочу автоматически сопоставлять? (Предположим, например, что игра допускает несколько уровней сложности, и я не хочу, чтобы кто-то играл на более низком уровне, чтобы автоматически совпадать).

РЕДАКТИРОВАТЬ (согласно комментарию xcodegirl):

Чтобы решить эту последнюю проблему, достаточно расширить приведенный выше код, добавив что-то, что кодирует желаемый тип соответствия, в свойстве playerGroup запроса:

request.playerGroup = [Utils myEncodingAsNSUIntegerOfGameTypeGivenSomeParameters:...];

Плохо, однако, то, что playerGroup не является доступным свойством GKTurnBasedMatch. Таким образом, если вы перечисляете свои матчи, включая ожидающие автоматические матчи, и хотите отобразить информацию о том, в какую игру вы хотите играть, вы должны сохранить эту информацию другим способом.

2 ответа

Решение

После некоторых попыток кажется, что ответ на первую часть этого вопроса заключается в следующем. Как только начинается матч, даже если никто не совпал с приглашением на автоматическое совпадение, массив участников заполняется таким количеством игроков, сколько требуется (один из которых является приглашающим игроком), и каждый пропавший игрок является участником GKTurnBasedParticipant, чей статус GKTurnBasedParticipantStatusMatching. Таким образом, приглашающий игрок может сыграть первый ход, даже не дожидаясь принятия приглашенных (автоматически совпадающих) игроков, просто создав массив следующих участников, в котором приглашающий игрок размещается в конце массива.

NSMutableArray *nextParticipants = [NSMutableArray new];
for (GKTurnBasedParticipant *participant in match.participants) {
    if ([participant.playerID isEqualToString:[GKLocalPlayer localPlayer].playerID]) {
        [nextParticipants addObject:participant];
    } else {
        [nextParticipants insertObject:participant atIndex:0];
    }
}

NSData *matchData = [@"some data" dataUsingEncoding:NSUTF8StringEncoding];

// Send new game state to Game Center & pass turn to next participant
[self.invitation.match endTurnWithNextParticipants: nextParticipants
                                       turnTimeout: GKTurnTimeoutDefault
                                         matchData: matchData
                                 completionHandler: ^(NSError *error) {
                                       // do something like refreshing UI
                                 } ];

Тем не менее, вторая часть моего вопроса все еще стоит. Мне непонятно, как сделать автоматическое сопоставление условным (например: я готов автоматически сопоставить кого-то, кто хочет участвовать в гонках с машинами Формулы 1, но не с машинами Rally).

Что касается второй (неотвеченной) части, я думаю, что цель GKMatchRequest.playerAttributes это добиться того, что вы хотите. Вы устанавливаете некоторое значение, идентифицирующее свойства выбранного матча, и игровой центр гарантирует, что подходящие участники заинтересованы в одних и тех же параметрах игры. Итак, если у вас была гоночная игра, в которой вы можете участвовать в гонках на автомобилях, мотоциклах и лодках в разных погодных условиях, вы можете получить следующее:

typedef enum GameType {
    GameTypeRaceCars = 0;
    GameTypeMotorbikes = 1;
    GameTypeBoats = 2;
};
typedef enum GameOptionWeather {
    GameOptionWeatherSunny = 0;
    GameOptionWeatherRainy = 1;
};
GKMatchRequest *request = /* boilerplate */
// bit 0-1 = GameType.
// bit 3   = Weather option.
request.playerAttributes = (uint32_t)GameTypeBoats;
request.playerAttributes |= (uint32_t)(GameOptionWeatherRainy) << 2;

/* boilerplate to create the match with the request */

Это гарантировало бы, что любой подобный игрок также хочет гонять на лодках под дождем (а кто нет?).

По крайней мере, я думаю, что так и должно быть. Хотя, честно говоря, мне пока не удалось заставить пошаговую организацию игр Game Center работать в песочнице.

Другие вопросы по тегам