Введение
Статья написана на примере игры Clear Sky 2
Многие разработчики игр хотят использовать сервис Google Play Game Services в своих играх. Я не был исключением, но знаний и навыков как быстро добавить поддержку GPGS в свою libgdx игру не было. В данной статье опишу процесс подключения таблицы рекордов и достижений. Исходные данные: Eclipse, настроенная консоль разработчика для работы с игровыми сервисами, android-проект, корневой проект.
Настройка
Не буду рассказывать, как настроить консоль разработчика для работы сGPGS , скажу лишь, что оттуда нам понадобятся ресурсы вида:
games-ids.xml
, где app_id – идентификатор вашего приложения, строки вида leaderboard_xxx и achievement_xxx указывают на конкретную таблицу рекордов и достижение соответственно. Следует создать ресурсный xml-файл с именем games-ids.xml в android-проекте своей игры и поместить туда ресурсы выше.
Для работы GPGS нужен проект-библиотека google-play-services_lib. Его путь:
<android-sdk>\extras\google\google_play_services\libproject\google-play-services_lib
По умолчанию игровые сервисы не устанавливаются вместе с Android SDK , поэтому по этому пути ничего не будет. Чтобы это исправить нужно в Android SDK Manager установить два пакета: Google Repository и Google Play services.
Проект-библиотеку google-play-services_lib нужно импортировать в Eclipse. После чего установить в свойствах импортированного проекта галочку «Is library».
Теперь нужно связать между собой ваш android-проект и библиотеку google-play-services_lib . Для этого добавляем библиотеку враздел Required projects on the build path. (Properties -> Java Build Path -> Projects ).
На данном этапе можно было бы закончить настройку, но официальная документация Google настоятельно рекомендует использовать класс-помощник GameHelper. Этот класс сильно облегчает жизнь при работе с игровыми сервисами. Его установка аналогична установке google-play-services_lib (импортировать проект как библиотеку, связать проект-библиотеку с android-проектом). Скачать BaseGameUtils.
В AndroidManifest.xml добавляем два разрешения и мета-данные:
<uses-permissionandroid:name="android.permission.INTERNET" />
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE" />
Мета-данные добавляются внутри тегаapplication :
<meta-data
android:name="com.google.android.gms.games.APP_ID"
android:value="@string/app_id" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
Настройка закончена.
Код
Вглавной Activity реализуем два интерфейса GameHelperListener, ActionResolver :
public
class MainActivity extends AndroidApplication implements GameHelperListener, ActionResolver
Интерфейс GameHelperListene r выглядит следующим образом:
publicinterface GameHelperListener {
/**
* Вызывается при неудачной попытке входа. В этом методе можно показать
* пользователю кнопку «Sign-in» для ручного входа
*/
void
onSignInFailed();
/** Вызывается при удачной попытке входа */
void
onSignInSucceeded();
}
Интерфейс ActionResolver создаем сами. Он нужен для вызова платформо-зависимого кода. Эта техника описана в официальной wiki libgdx . Пример интерфейса:
publicinterfaceActionResolver {
/** Узнать статус входа пользователя */
public
boolean
getSignedInGPGS();
/** Вход */
public
void
loginGPGS();
/** Отправить результат в таблицу рекордов */
public
void
submitScoreGPGS(
intscore);
/**
* Разблокировать достижение
*
* @param achievementId
* ID достижения. Берется из файла games-ids.xml
*/
public
void
unlockAchievementGPGS(String achievementId);
/** Показать Activity с таблицей рекордов */
public
void
getLeaderboardGPGS();
/** Показать Activity сдостижениями */
public
void
getAchievementsGPGS();
}
Пример кода главной Activity:
public
class MainActivity extends AndroidApplication implements
GameHelperListener, ActionResolver {
// помощник для работы с игровыми сервисами
private
GameHelper gameHelper;
// класснашейигры
private
TestGame game;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
// CLIENT_ALL указыветнаиспользование API всехклиентов
gameHelper =
newGameHelper(
this, GameHelper.CLIENT_ALL);
// выключить автоматический вход при запуске игры
gameHelper.setConnectOnStart(
false);
gameHelper.enableDebugLog(
true);
// запретить отключение экрана без использования дополнительных
// разрешений (меньше разрешений – больше доверие к приложению)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Входной параметр this является ActionResolver. Позволяет вызывать из
// игрового цикла платформо-зависимые методы GPGS
game =
newTestGame(
this);
AndroidApplicationConfiguration config =
newAndroidApplicationConfiguration();
initialize(game, config);
gameHelper.setup(
this);
}
// методы gameHelper’а: onStart(), onStop() вызываются для корректной работы
// GPGS в жизненном цикле android-приложения
@Override
protected
void
onStart() {
super
.onStart();
gameHelper.onStart(
this);
}
@Override
protected
void
onStop() {
super
.onStop();
gameHelper.onStop();
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
}
@Override
protected
void
onActivityResult(
intrequestCode,
intresultCode, Intent data) {
super
.onActivityResult(requestCode, resultCode, data);
// здесь gameHelper принимает решение о подключении, переподключении или
// отключении от игровых сервисов, в зависимости от кода результата
// Activity
gameHelper.onActivityResult(requestCode, resultCode, data);
}
@Override
public
boolean
getSignedInGPGS() {
// статусподключения
return
gameHelper.isSignedIn();
}
@Override
public
void
loginGPGS() {
try
{
runOnUiThread(
newRunnable() {
@Override
public
void
run() {
// инициировать вход пользователя. Может быть вызван диалог
// входа. Выполняется в UI-потоке
gameHelper.beginUserInitiatedSignIn();
}
});
}
catch(Exception e) {
e.printStackTrace();
}
}
@Override
public
void
submitScoreGPGS(
intscore) {
// отправить игровые очки в конкретную таблицу рекордов с ID
// “HgkIr62KmoQJEAIQAQ”
Games.Leaderboards.submitScore(gameHelper.getApiClient(),
"HgkIr62KmoQJEAIQAQ"
, score);
}
@Override
public
void
unlockAchievementGPGS(String achievementId) {
// открытьдостижениес ID achievementId
Games.Achievements.unlock(gameHelper.getApiClient(), achievementId);
}
@Override
public
void
getLeaderboardGPGS() {
// вызвать Activity для всех зарегистрированных таблиц рекордов. Так же
// можно вызывать Activity под конкретную таблицу
startActivityForResult(
Games.Leaderboards.getAllLeaderboardsIntent(gameHelper
.getApiClient()),
100);
}
@Override
public
void
getAchievementsGPGS() {
// вызвать Activity сдостижениями
startActivityForResult(
Games.Achievements.getAchievementsIntent(gameHelper
.getApiClient()),
101);
}
@Override
public
void
onSignInSucceeded() {
}
@Override
public
void
onSignInFailed() {
}
}
Допустим, у нас в игре предусмотрено достижение – набрать 1 млн. игровых очков, то код реализующий это будет выглядеть так:
publicstatic
void
checkTotalPoints(
intpoints) {
ActionResolver res = getActionResolver();
if
(!res.getSignedInGPGS()) {
return
;
}
if
(points >=
1000000) {
res.unlockAchievementGPGS(“HgkIr62KmoQJEAIQGA”);
}
}
То же самое и с таблицей рекордов, только еще легче: нужно просто вызвать метод submitScoreGPGS(int score ) интерфейса ActionResolver.
P. S. Для тестирования игровых сервисов нужно экспортировать apk-файл с тем же сертификатом, что и в консоли разработчика. Так же нужно добавить аккаунты тестировщиков в консоли. Изменения в игровых сервисах вступают в силу через некоторое время.
Использованные источники:
developers.google.com/games/services/android/quickstart
developer.android.com/intl/ru/google/play-services/setup.html
github.com/libgdx/libgdx/wiki