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 работать в песочнице.