Slide 1

Slide 1 text

Game Center и социальные API © 2010-2011 Владимир Пузанов, Hack&Dev LLC Разработка приложений для платформы iOS

Slide 2

Slide 2 text

План занятия ✤ Введение в GameKit API ✤ Функциональные возможности Game Center ✤ Таблицы результатов ✤ Достижения ✤ Многопользовательская игра

Slide 3

Slide 3 text

GameKit API ✤ GameKit предоставляет функции для создания игр с возможностью социального взаимодействия ✤ Компоненты GameKit: ✤ Game Center – централизованный сетевой сервис (iOS 4.1) ✤ P2P-соединения – поиск и передача данных между устройствами через Wi-Fi или Bluetooth (iOS 3.0) ✤ Голосовое общение – простой API для голосового общения (iOS 3.0)

Slide 4

Slide 4 text

Game Center Авторизация Приглашения в игру Поиск игровых сессий P2P передача данных Друзья Достижения Таблицы результатов Голосовое общение

Slide 5

Slide 5 text

Game Center как платформа ✤ Самостоятельное приложение, которое предоставляет доступ ко всей социальной информации ✤ Сервис для хранения, передачи, обработки социальных данных и установки сетевых P2P-соединений ✤ Фреймворк, предоставляющий API для доступа к социальным и сетевым функциям

Slide 6

Slide 6 text

Сервисы Game Center ✤ Авторизация – Game Center предоставляет унифицированный механизм для авторизации пользователей, прозрачный для конечного приложения ✤ Таблицы результатов (leaderboards) – публикация рейтинга пользователей ✤ Достижения (achievements) – публикация достижений в игре с поддержкой скрытых достижений и прогресса по конкретным достижениям

Slide 7

Slide 7 text

Сервисы Game Center ✤ Сетевая игра – автоматический поиск подходящих игроков для сетевой игры (с поддержкой работы через серверы Game Center или собственные) ✤ Приглашения на сетевую игру позволяют приглашать друзей поиграть, при этом уведомление проходит через механизм APSN, приложение не обязательно должно быть запущено для получения приглашения ✤ P2P-соединения – API, который предоставляет возможность передавать данные между участниками созданной сетевой игры

Slide 8

Slide 8 text

Общие принципы и требования ✤ Почти все API Game Center требуют авторизированного локального пользователя. Если пользователь не авторизирован (или Game Center недоступен) – отключайте доступ к функциям Game Center. ✤ Приложение должно использовать стек UIViewController (Game Center требует отображения своих контроллеров модально) ✤ Большинство API работает асинхронно через блоки ✤ При проблеме с сетью во время отправки данных сохраняйте их для повторной отправки позже ✤ При проблеме с сетью во время получения данных Game Center может вернуть закешированные данные (вместе с кодом ошибки)

Slide 9

Slide 9 text

Общие принципы и требования ✤ Game Center должен быть сконфигурирован в iTunes Connect ✤ У приложения должен быть указан правильный Bundle ID ✤ Если приложение не может работать без Game Center – необходимо указать это в зависимостях приложения (UIRequiredDeviceCapabilities) ✤ Если приложение может работать частично без Game Center – необходимо использовать слабую линковку и проверять наличие классов Game Center на устройстве и версию iOS >=4.1

Slide 10

Slide 10 text

Тестирование приложения ✤ Тестировать приложение с Game Center можно только при наличии аккаунта в iOS Developer Program, независимо от того, тестируется оно на симуляторе, или устройстве Сборка Целевая аудитория Окружение Game Center Симулятор Разработчик Песочница Устройство (Debug) Разработчик Песочница Устройство (Ad-Hoc) Тестер Песочница Устройство (AppStore) Пользователи Основные серверы

Slide 11

Slide 11 text

Работа с пользователями ✤ Пользователь должен создать учетную запись в Game Center ✤ Данные таблиц результатов и достижений автоматически сохраняются для текущего пользователя ✤ У каждого пользователя свой уникальный список друзей ✤ Пользователь идентифицируется по playerID и alias: ✤ playerID – уникальная строка, определяющая пользователя ✤ alias – псевдоним пользователя, подходящий для отображения

Slide 12

Slide 12 text

Авторизация локального пользователя - (void)authenticateLocalPlayer { ! [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) { ! ! if(!error) { ! ! ! // обработка данных пользователя ! ! } else { ! ! ! // сообщение об ошибке, блокирование доступа к Game Center ! ! } ! }]; } ✤ Авторизация должна быть выполнена как можно раньше (в didFinishLaunchingWithOptions:) ✤ В случае недоступности локального пользователя любой доступ к функциям Game Center должен быть заблокирован

Slide 13

Slide 13 text

Деавторизация локального пользователя ✤ Локальный пользователь может быть деавторизирован во время жизни приложения (используя функции многозадачности iOS) ✤ В таком случае необходимо заблокировать доступ к Game Center и предложить повторную авторизацию [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(authenticationChanged) name:GKPlayerAuthenticationDidChangeNotificationName object:nil]; ... - (void)authenticationChanged { ! if([GKLocalPlayer localPlayer].isAuthenticated) { ! ! // локальный пользователь потенциально изменился } else { ! ! // локальный пользователь недоступен ! } }

Slide 14

Slide 14 text

- (void)retrieveFriends { ! if ([GKLocalPlayer localPlayer].authenticated) { ! ! [[GKLocalPlayer localPlayer] loadFriendsWithCompletionHandler:^(NSArray *friends, NSError *error) { ! ! ! if(!error) { ! ! ! ! // обработка списка друзей – playerID массиве friends ! ! ! } else { ! ! ! ! // обработка ошибки ! ! ! } ! ! }]; ! } } Список друзей ✤ Список друзей не загружен по умолчанию, для его получения необходимо выполнить запрос

Slide 15

Slide 15 text

- (void)loadPlayerData:(NSArray *)identifiers { ! [GKPlayer ! loadPlayersForIdentifiers:identifiers ! withCompletionHandler:^(NSArray *players, NSError *error) { ! ! if(!error) { ! ! ! // обработка массива объектов GKPlayer ! ! } else { ! ! ! // обработка ошибки ! ! } ! }]; } Список друзей ✤ Для получений объектов GKPlayer на базе списка идентификаторов необходимо выполнить еще один запрос

Slide 16

Slide 16 text

Таблицы результатов ✤ Таблицы результатов отображают «успеваемость» пользователей по какому-то критерию (набранные очки, заработанные деньги и т.д.) ✤ Параметры таблиц: ✤ Единицы измерения ✤ Порядок сортировки (по возрастанию или убыванию) ✤ Форматирование значений ✤ Вывод в общей таблице, или отдельные таблицы в зависимости от режима игры

Slide 17

Slide 17 text

Настройка таблицы результатов в iTunes Connect ✤ Leaderboard Reference Name – информационное имя для таблицы ✤ Leaderboard ID – уникальный идентификатор ✤ Score Format Type: ✤ Integer – 123456789 ✤ Fixed Point – To 1/2/3 Decimal(s) – 12345678.9 ✤ Elapsed Time – To the Minute (second, 1/100 second) – 123:45 ✤ Money – Whole Numbers – 123456789 ✤ Money – To 2 Decimals – 1234567,89

Slide 18

Slide 18 text

- (void)reportScore:(int64_t)score forCategory:(NSString *)category { ! GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease]; ! scoreReporter.value = score; ! [scoreReporter reportScoreWithCompletionHandler:^(NSError *error) { ! ! if(error) { ! ! ! // сохранение scoreReporter для повторной попытки ! ! } ! }]; } Отправка результата ✤ Результат сохраняется в объекте класса GKScore как значение int64_t (64-битное целое со знаком) ✤ В случае проблемы при отправке, объект GKScore должен быть сохранен (например с помощью протокола NSCoding) для повторной попытки отправки позднее

Slide 19

Slide 19 text

Отображение стандартного контроллера ✤ Для отображения таблицы результатов можно использовать стандартный контроллер GKLeaderboardViewController ✤ Настраиваемые свойства: ✤ category – идентификатор категории (заданный в iTunes Connect) ✤ timeScope – период отображения результатов (за день, неделю, все время)

Slide 20

Slide 20 text

- (void)showLeaderboard { ! GKLeaderboardViewController *leaderboardController = [[[GKLeaderboardViewController alloc] init] autorelease]; ! if(leaderboardController) { ! ! leaderboardController.leaderboardDelegate = self; ! ! // инициализация category, timeScope ! ! [self presentModalViewController:leaderboardController animated:YES]; ! } } - (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController { ! // сохранение category, timeScope ! [self dismissModalViewControllerAnimated:YES]; } Отображение стандартного контроллера ✤ При возможности, сохраняйте значения category и timeScope при выходе из контроллера и восстанавливайте их при последующем запуске

Slide 21

Slide 21 text

Получение данных из таблиц результатов ✤ В случае, если необходимо отобразить собственный интерфейс для таблицы результатов, Game Center API предоставляет возможность получения массива объектов GKScore по заданным критериям: ✤ playerScope – все игроки или только друзья ✤ range – диапазон возвращаемых объектов ✤ category и timeScope – аналогично, как и для стандартного контроллера ✤ Также, можно сделать запрос по конкретным идентификаторам игроков с помощью метода initWithPlayerIDs:

Slide 22

Slide 22 text

- (void)retrieveTopTenScores { ! GKLeaderboard *leaderboardRequest = [[[GKLeaderboard alloc] init] autorelease]; ! if(leaderboardRequest) { ! ! leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal; ! ! leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime; ! ! leaderboardRequest.range = NSMakeRange(1,10); ! ! [leaderboardRequest ! ! loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) { ! ! ! if(error) { ! ! ! ! // обработка ошибки ! ! ! } ! ! ! if(scores) { ! ! ! ! // обработка списка результатов ! ! ! } ! ! }]; ! } } Получение данных из таблиц результатов ✤ Массив scores может быть возвращен даже при наличии ошибки (на базе закешированных данных)

Slide 23

Slide 23 text

- (void)loadCategoryTitles { ! [GKLeaderboard loadCategoriesWithCompletionHandler:^( ! NSArray *categories, NSArray *titles, NSError *error) { ! ! if(error) { ! ! ! // обработка ошибки ! ! } ! ! if(categories) { ! ! ! // обработка ID категорий и их заголовков ! ! } ! }]; } Получение данных из таблиц результатов ✤ Не используйте свой код форматирования вместо score.formattedValue, иначе данные будут выглядеть по-разному в приложении и в Game Center ✤ Для использования данных локализации необходимо получать данные из iTunes Connect

Slide 24

Slide 24 text

Достижения ✤ Цели для игроков ✤ Мотивация для прохождения разных режимов игры на разных уровнях сложности ✤ Параметры достижений: ✤ Название достижения ✤ Описание, отображаемое пока достижение не получено ✤ Описание, отображаемое когда достижение получено ✤ Изображение (отображается только у полученых достижений) ✤ «Стоимость» достижения (до 1000 баллов на приложение) ✤ Изначальное отображение достижения

Slide 25

Slide 25 text

Обновление состояния достижения ✤ Состояние достижения – значение от 0.0 до 100.0 ✤ Если достижение было создано как скрытое по умолчанию – оно отображается (даже при изменении состояния в 0.0) ✤ Понизить состояние нельзя ✤ При достижении значения 100.0 достижение отмечается как полученное

Slide 26

Slide 26 text

- (void)reportAchievementIdentifier:(NSString *)identifier percentComplete:(float) percent { ! GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier:identifier] autorelease]; ! if(achievement) { ! ! achievement.percentComplete = percent; ! ! [achievement reportAchievementWithCompletionHandler:^(NSError *error) { ! ! ! if(error) { ! ! ! ! // сохранение achievement для повторной попытки ! ! ! } ! ! }]; ! } } Обновление состояния достижения ✤ Аналогично как и с GKScore, при проблемах с сетью объект GKAchievement необходимо сохранить и отправить еще раз позже

Slide 27

Slide 27 text

- (void)loadAchievements { ! [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) { ! ! if(error) { ! ! ! // обработка ошибки ! ! } ! ! if(achievements) { ! ! ! // обработка списка достижений ! ! } ! }]; } Обновление состояния достижения ✤ Обновлять таким образом необходимо только новые достижения, список текущих достижений необходимо получить как можно раньше (сразу после авторизации)

Slide 28

Slide 28 text

- (void)resetAchievements { ! [GKAchievement resetAchievementsWithCompletionHandler:^(NSError *error) { ! ! if(error) { ! ! ! // обработка ошибки ! ! } ! }]; } Сброс списка достижений ✤ При необходимости, список достижений можно сбросить ✤ Все скрытые по умолчанию достижения снова станут скрытыми

Slide 29

Slide 29 text

- (void)showAchievements { ! GKAchievementViewController *achievements = [[[GKAchievementViewController alloc] init] autorelease]; ! if(achievements) { ! ! achievements.achievementDelegate = self; ! ! [self presentModalViewController:achievements animated:YES]; ! } } - (void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController { ! [self dismissModalViewControllerAnimated:YES]; } Отображение стандартного контроллера ✤ Контроллер списка достижений не содержит опций для настройки отображения

Slide 30

Slide 30 text

- (void)retrieveAchievmentMetadata { ! [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:^(NSArray *descriptions, NSError *error) { ! ! if(error) { ! ! ! // обработка ошибки ! ! } ! ! if(descriptions) { ! ! ! // обработка списка объектов GKAchievementDescription ! ! } ! }]; } Отображение собственного контроллера ✤ Информацию по достижению (описание) необходимо запрашивать отдельно

Slide 31

Slide 31 text

[achievementDescription loadImageWithCompletionHandler:^(UIImage *image, NSError *error) { ! if(error) { ! ! // обработка ошибки ! } }]; Отображение собственного контроллера ✤ Так же отдельно запрашиваются изображения полученных достижений

Slide 32

Slide 32 text

Сетевая игра ✤ Стандартный интерфейс поиска матча ✤ Входящие приглашения ✤ Програмные средства поиска матчей ✤ Поддержка до четырех участников (до 16 с использованием своего сервера)

Slide 33

Slide 33 text

Использование платформы Game Center для передачи данных ✤ API предоставляет функции для передачи данных по надежному и по быстрому каналам ✤ Рекомендуемые размеры пакетов: ✤ До 87Кб при использовании надежного транспорта ✤ До 1000Кб при использовании ненадежного транспорта

Slide 34

Slide 34 text

Использование своего сервера ✤ GKMatch предоставляет только идентификаторы участников ✤ Абсолютно вся передача данных должна быть реализована самостоятельно