29/10/2014

Google Play Leaderboards Integration in Haxeflixel

The easiest way to integrate leaderboards from Google Play Games in your Haxeflixel project is using the openfl extension developed by Sergey Miryanov, linden-google-play. The extension allows you to set up other services such as Achievement and states, but in this tutorial I’ll focus on leaderboards (although the logic is very similar).
There’s an extensive example on how to use those extensions published by Sergey himself, and if you want you can download it from the Play Store straight on your phone to test it.
This is not a beginner’s tutorial. I assume you have already tested your game on Android - which means you set up lime for android and have the Android SDK installed. If you know your way around the Google Play Developer Console and / or have already published an Android app, even better - If not, don’t worry - I will go through that part step by step.

Installing Extensions

The linden-google-play extension is not currently available on the haxelib repositories, but you can install the extension anyway by opening a terminal and running
haxelib git linden-google-play https://github.com/sergey-miryanov/linden-google-play
This will install the extension in your HaxeToolkit/lib folder by downloading it straight from github, as explained here.
There are several steps to follow to implement leaderboards in your game: first is setting up your project in the Google Developer Console and linking the game to a .APK with the proper certificates, then creating the leaderboards and finally implementing the leaderboard access from your project. Let’s start!

Setting up your project in the Google Developer Console

Export your game to the Android target by running
lime build android
From the command line. Make sure the application is signed with your personal developer Keystore - you can do this by adding the line
<certificate path="[Path to your Keystore]" alias="[Your Alias]" if="android" unless="debug"/>
To your Project.xml - You’ll be prompted the password during compilation.
When it’s done, navigate to [Your Project]\export\android\bin\bin and grab the file [Your Game Name]-release.apk - Move it somewhere or simply keep an eye on it as we’ll need it shortly.
Next, log on to your Google Developer Console and Click on the “All Applications” icon on the left, add a new application and upload the previously mentioned [Your Game Name]-release.apk. That’s all we need to do for now, you can fill in your app details later. Note down the 12 digits number next to your game name - that’s your Application ID - we’ll need that later.
Click on the Game Services icon on the left, and add a new game. Fill up the requested information, and then go to Linked Apps. Here you will be able to link the game to the appopriate app and submit a security certificate. THIS IS IMPORTANT: You will need to link two apps, both using the same package name (the app created when you uploaded your game .apk) but each with a different certificate - one with the RELEASE certificate, and the other with the DEBUG certificate.
To find your Debug Certificate, open a terminal and run one of those lines:
If you’re on Windows:
keytool -list -v -keystore %USERPROFILE%\.android\debug.keystore -alias androiddebugkey -storepass android -keypass android
If you’re on Mac / Linux:*
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
Your certificate is the long string after SHA1 under Certificate Fingerprints .
To find your Release Certificate, open a terminal and run:
keytool -list -v -keystore [Path to your .keystore] file -alias [Your Alias]
After you’re done, it should look like this:
console_screen

Creating the Leaderboards

Move on to the Leaderboards section and create some leaderboards. Note down the 18 characters string next to the leaderboard name - That’s the leaderboard ID, and we will need it when accessing leaderboards from Haxeflixel.
Go to the Testing section and make sure that your Google Account’s mail figures in the Testing Access list - this way you will be able to test your game even if it has not been published. After this, we are done with the developer console - Let’s move onto Haxeflixel!

Setting up your Haxeflixel Project

We need to replace the original AndroidManifest.xml that lime-tools generates when targetting android with a slightly modified one that will tell our app how to connect to Google Play. Be sure to have compiled to Android at least once, and then go to [Your Project]\export\android and copy the AndroidManifest.xml file. Go back to your project root folder and create a new folder called “libs” - paste thed AndroidManifest.xml in here. Open it, and right under
<application android:debuggable="false" android:icon="@drawable/icon" android:label="[Your Game Name]">
paste this code:
<!-- for linden-google-play -->
    <meta-data
      android:name="com.google.android.gms.version"
      android:value="@integer/google_play_services_version" />
    <meta-data
      android:name="com.google.android.gms.games.APP_ID"
      android:value="@string/app_id" />
    <meta-data
      android:name="com.google.android.gms.appstate.APP_ID"
      android:value="@string/app_id" />
<!-- / -->
In this same folder, create a file called ids.xml and paste this code inside it:
<resources>
<string name="app_id">(Your Game Application ID)</string>
</resources>
That’s the Application ID - The 12 digits number that was listed next to your game name in the Google Developer Console, remember?
Now we’ll tell Haxeflixel to use those newly created files - Go to your Project.xml and paste this code before the Window Settings:
<template path="libs/AndroidManifest.xml" rename="AndroidManifest.xml" if="android"/>
<template path="libs/ids.xml" rename="res/values/ids.xml" if="android" />
This way they’ll both be included in the Android compilation.
Now let’s move onto some actual coding! Create a new file in your project and call it GooglePlayHandler.hx, then paste this code in it:
import ru.zzzzzzerg.linden.GooglePlay;
import ru.zzzzzzerg.linden.play.Achievement;
import ru.zzzzzzerg.linden.play.AppState;

class GooglePlayHandler extends ru.zzzzzzerg.linden.play.ConnectionHandler
{
var _m : Main;

public function new(m : Main)
{
super();
_m = m;
}

override public function onConnectionEstablished(what : String)
{
if(what == "GAMES_CLIENT")
{
trace("GAMES_CLIENT Connected");
}
else if(what == "APP_STATE_CLIENT")
{
trace("APP_STATE_CLIENT Connected");
}
}

override public function onSignedOut(what : String)
{
if(what == "GAMES_CLIENT")
{
trace("GAMES_CLIENT Signed Out");
}
else if(what == "APP_STATE_CLIENT")
{
trace("APP_STATE_CLIENT Signed Out");
}
}

override public function onWarning(msg : String, where : String)
{
trace(["Warning", msg, where]);
}

override public function onError(what : String, code : Int, where : String)
{
trace(["Error", what, code, where]);
}

override public function onException(msg : String, where : String)
{
trace(["Exception", msg, where]);
}
}
We will use this handler class to connect to the Google Play Services: it’s useful to have a class in your project which extends it as we’ll be able to override its connections methods to print customized messages (useful for debugging) and / or deactivate object based on the connection status.
Go to your Reg.hx, and add those imports:
import ru.zzzzzzerg.linden.GooglePlay;
import ru.zzzzzzerg.linden.play.Achievement;
import ru.zzzzzzerg.linden.play.AppState;
Create a new google play object inside the class:
static public var googlePlay : GooglePlay;
We are defining it as a static public variable in the Reg class, so I can access it quickly from any class using Reg.googlePlay. Feel free to change this, I personally like to create an helper class and call it from there.
Go to Main.hx, and paste this code under initialize();
#if android
Reg.googlePlay = new GooglePlay(new GooglePlayHandler(this));
#end
This will initialize the handler object defined before. We are doing this in Main.hx as GooglePlayHandler needs a Main class passed to its constructor.
To connect to Google Play Games, just call:
#if android
if (GooglePlayHelper.googlePlay.games.isSignedIn())
{
GooglePlayHelper.googlePlay.games.connect();
}
#end
You can paste this right after the previous line if you want your game to try and connect as soon as it’s opened. If you want to test it straight away, at this point you should get the Play Games welcome screen asking you to sign up to the game with your email address. Neat!
Note how those two functions are wrapped in Haxeflixel conditionals, and therefore executed only when the game is running on an Android platform.

Accessing Leaderboards from Haxeflixel

To save your score to a leaderboard:
Reg.googlePlay.games.submitScore("[Leaderboard ID]", [Score]);
Where [Leaderboard ID] is the 18 characters string displayed next to your leaderboard name in the Google Play Developer console. The value of [Score] should changed based on the type of your leaderboard - quoting the official Android Documentation:
The meaning of the score value depends on the formatting of the leaderboard established in the developer console. Leaderboards support the following score formats:
  • Fixed-point: score represents a raw value, and will be formatted based on the number of decimal places configured. A score of 1000 would be formatted as 1000, 100.0, or 10.00 for 0, 1, or 2 decimal places.
  • Time: score represents an elapsed time in milliseconds. The value will be formatted as an appropriate time value.
  • Currency: score represents a value in micro units. For example, in USD, a score of 100 would display as $0.0001, while a score of 1000000 would display as $1.00
For more details, please see Leaderboard Concepts.”
To display a leaderboard’s scores using the Google Games APIs:
Reg.googlePlay.games.showLeaderboard("[Leaderboard ID]");
To be noted that all the scores submitted during the testing stage will be deleted once the application is published - so feel free to load it up with tests.
That’s all for now! I haven’t personally implemented any IAP or achievement systems in my games yet, so I feel like I’m not competent to write a tutorials about those - they shouldn’t work too differently from the leaderboards - but again, Sergey Miryanov published and extensive example that features all the functionality - It might not guide you step by step, but it’s definitely worth a look.

3 comments:

  1. Man, I love you, thank you very much,I will put your name in the credits!

    ReplyDelete
  2. Hey there, I just published my first game in the Google Play Store, I put your name in the credits as promissed :) The game is paid so I understand if you don't have interest in buying it, if you want the .apk development build I can send to you see the final work. Play Store link: https://play.google.com/store/apps/details?id=com.Beardfish.RedBlockAttack or mail me at beardfishstudio@gmail.com. Thanks again!

    ReplyDelete