Implementing leaderboards is an activity which many developers want to understand so that they can include them among their game features. Corona supports various services for managing leaderboards including Google Play Games Services and Apple Game Center.
This tutorial will outline one way of setting up your game to use both
This tutorial does not outline setting up your game(s) in iTunes Connect or Google Play. Please refer to the many online resources for those instructions.
For
Your license key, a very long string found within the developer console.
Your
The string that identifies your leaderboard — this looks something like CgkA8kb12jK0onOQBg
.
Keep record of all this information since you’ll need to provide it to your Corona app.
Apple Game Center also requires you to gather some information for your app code. When you create a leaderboard, you’ll be asked to give it a unique name. It’s recommended that you follow the com.yourdomain.yourgame.leaderboardname
. Make a note of this since you’ll need to specify it within your Corona app.
For each respective service, you’ll need to include the information gathered above within specific areas of your Corona project.
Details on the necessary Google Play Games Services settings can be found in the documentation, but here’s an overview on the necessary aspects:
Implement Google app licensing as outlined here and sign the .apk
with a private key as outlined here.
Ensure that you have enabled both Drive API and
Add an entry into the plugins
table of build.settings
for the
settings = { plugins = { ["plugin.gpgs.v2"] = { publisherId = "com.coronalabs", supportedPlatforms = { android=true } }, }, }
android
table of build.settings
as the googlePlayGamesAppId
key:settings = { android = { googlePlayGamesAppId = "YOUR_APPLICATION_ID", }, }
Apple Game Center is a bit easier — basically, just include the plugin within the plugins
table of build.settings
as follows:
settings = { plugins = { ["CoronaProvider.gameNetwork.apple"] = { publisherId = "com.coronalabs" }, }, }
In the Goodbye Globals! tutorial, we outlined how to use a data module to share information between scenes and modules. This technique will be used again to store the various game networking plugin handles used in this tutorial.
globalData.lua
and save it to your project directory. Inside, include the following lines:-- Pseudo-global space local M = {} return M
main.lua
file, require()
the data module and add two variables to its table, globalData.gpgs
and globalData.gameCenter
, both initially set to nil
. These will hold the plugin handles for later use.local globalData = require( "globalData" ) local json = require( "json" ) globalData.gpgs = nil globalData.gameCenter = nil
Note that we also require()
the JSON library. This is not essential for all implementations, but we’ll use JSON in this tutorial to output game network response data to the console.
Next, let’s test to see what platform the user is on. If it’s an Android device, we’ll require()
require()
globalData
handles configured above.
local globalData = require( "globalData" ) local json = require( "json" ) globalData.gpgs = nil globalData.gameCenter = nil local platform = system.getInfo( "platform" ) local env = system.getInfo( "environment" ) if ( platform == "android" and env ~= "simulator" ) then globalData.gpgs = require( "plugin.gpgs.v2" ) elseif ( platform == "ios" and env ~= "simulator" ) then globalData.gameCenter = require( "gameNetwork" ) end
Now we’re ready to initialize and log the user in to the proper game network. For this, we’ll first need to add listener functions to handle game network initialization events. Since Lua is a
This is one major point where .init()
call. You just to need to login.
-- Google Play Games Services initialization/login listener local function gpgsInitListener( event ) if not event.isError then if ( event.name == "login" ) then -- Successful login event print( json.prettify(event) ) end end end -- Apple Game Center initialization/login listener local function gcInitListener( event ) if event.data then -- Successful login event print( json.prettify(event) ) end end
You can perform additional tasks upon successful login, for instance requesting player information, but for the purpose of this tutorial, we simply output the values returned by the event.
With the listener functions in place, we can now initialize the game network depending on which platform the user is on:
-- Initialize game network based on platform if ( globalData.gpgs ) then -- Initialize Google Play Games Services globalData.gpgs.login( { userInitiated=true, listener=gpgsInitListener } ) elseif ( globalData.gameCenter ) then -- Initialize Apple Game Center globalData.gameCenter.init( "gamecenter", gcInitListener ) end
Now that we have the game network initialized and the user is logged in, we’re ready to transmit scores. Normally you would do this after the game is over, or perhaps after the player accomplishes something noteworthy. If you’re tracking the user’s high score locally, you can choose to only transmit a score that you know to be a high score, or alternatively you can send the score to
For this, similar to the initialization process, we’ll need a listener function for submitted scores:
local function submitScoreListener( event ) -- Google Play Games Services score submission if ( globalData.gpgs ) then if not event.isError then local isBest = nil if ( event.scores["daily"].isNewBest ) then isBest = "a daily" elseif ( event.scores["weekly"].isNewBest ) then isBest = "a weekly" elseif ( event.scores["all time"].isNewBest ) then isBest = "an all time" end if isBest then -- Congratulate player on a high score local message = "You set " .. isBest .. " high score!" native.showAlert( "Congratulations", message, { "OK" } ) else -- Encourage the player to do better native.showAlert( "Sorry...", "Better luck next time!", { "OK" } ) end end -- Apple Game Center score submission elseif ( globalData.gameCenter ) then if ( event.type == "setHighScore" ) then -- Congratulate player on a high score native.showAlert( "Congratulations", "You set a high score!", { "OK" } ) else -- Encourage the player to do better native.showAlert( "Sorry...", "Better luck next time!", { "OK" } ) end end end
Note that because each network returns different data, we must test for the proper network and handle returned data independently.
With the listener function in place, we can now submit a score to either of the respective services. For this task, you will need the leaderboard identifiers that you acquired from Google or created for Apple. These must exactly match what the service is expecting.
For convenience later on, let’s wrap this in a function which accepts a single score
parameter:
local function submitScore( score ) if ( globalData.gpgs ) then -- Submit a score to Google Play Games Services globalData.gpgs.leaderboards.submit( { leaderboardId = "CgkA8kb12jK0onOQBg", score = score, listener = submitScoreListener }) elseif ( globalData.gameCenter ) then -- Submit a score to Apple Game Center globalData.gameCenter.request( "setHighScore", { localPlayerScore = { category = "com.yourdomain.yourgame.leaderboard", value = score }, listener = submitScoreListener }) end end
Now, submitting a score is as easy as calling the submitScore()
function, for example:
submitScore( 10000 )
Games which include leaderboards must logically provide some way for players to view them. This might be triggered from the listener handler of a button widget or, alternatively, it could be shown after the user achieves submitScoreListener()
function we already created.
Whatever the method, showing a leaderboard can be done like this:
if ( globalData.gpgs ) then -- Show a Google Play Games Services leaderboard globalData.gpgs.leaderboards.show( "CgkA8kb12jK0onOQBg" ) elseif ( globalData.gameCenter ) then -- Show an Apple Game Center leaderboard globalData.gameCenter.show( "leaderboards", { leaderboard = { category = "com.yourdomain.yourgame.leaderboard" } }) end
While your own game networking implementation can — and probably should — extend beyond just leaderboards, hopefully this tutorial gives you a solid foundation for building