Hi,
Looking through this forum’s posts I noticed a lot of issues with people who have developed a super simple game and want to provide an online scores facility so their players can see how they match up against the competition.
The first thing many people do is turn to GPGS: then spend the next week or so trying to get it to work.
I also looked at GPGS to provide a Leaderboard for a simple game I had developed but found it would take more work to fill in the GPGS forms and integrate it than it took me to develop the game in the first place!!! So I didn’t bother.
Anyway, when they say “it’s free to use”, you just know it ain’t: they are data mining you, your game, and most worryingly of all, the people who innocently play your game.
And what if I wanted to develop the game on a platform that GPGS doesn’t support? You are right back at square one again, looking for another service that can handle that platform. Then you have a delta on your game project and you now have to manage two development streams!
All I want is an online leaderboard…
Fortunately, my background is in developing business services, and I’ve written one or two RESTful APIs in that time, so, I took this experience and wrote my own online Leaderboard.
It uses a simple RESTful API. That means it is platform agnostic. It doesn’t matter if you wrote it for Android, iOS or a game console, as long as you can perform a POST call, you can use it.
With my service I can upload a score and download a JSON data-set of scores (filtered by date, and choose how many rows/scores to return).
The data-set includes:
- the high-score
- the gamer-handle of the person who uploaded the score
- the scores position in the list, and if the call is from a gamer who’s high-score isn’t in the “top-xx” list, then an extra row is provided just for them with their score and position
- a Boolean flag on each score row so you know when the row belongs to the current gamer, that way you can uniquely format that row to make it “pop” in the table.
- Several date columns of increasing scope providing a score’s upload date’s:
- Year
- Year/Month
- Year/Month/Day
- and, Year/Month/Day/Time
- So I can format my Leaderboard to show the “All Time Top-10” scores as well as “This Months Top-10” scores.
The service also provides a means to upload and verify a gamer’s handle (short-name). The service also checks the validity of a gamer’s handle each time they submit a score.
Finally, the service also has an API call that returns a real Globally Unique Identifier (GUID).
But why, you may ask???
When I was developing business apps, I needed a unique ID for each device. Normally, you would assume that the “DeviceId” reported by the mobile operating system would be the value to use? Wrong. That value can change with a major update of the operating system (e.g. iOS). Therefore, the “DeviceId” cannot be trusted.
So instead I choose to use a Globally Unique Identifier.
After looking at several methods of generating a GUID on the device itself, I decided to write a simple API call to do just that. Now when my game is installed a newly minted GUID (I call it an “Instance ID”) is stored against it that I trust, and can use to uniquely identify the device on the service.
Example code:
local function recordNewInstallationListener( event ) if ( event.isError ) then print("-----------------------------------------------------------------------------------------") print( "Network error: ", event.response ) else print("-----------------------------------------------------------------------------------------") print ( event.response ) end end local function recordNewInstallation() local headers = {} headers["Content-Type"] = "application/json" headers["Accept-Language"] = "en-GB" local body = {} body.gameId = gameId body.api\_key = api\_key local params = {} params.headers = headers params.body = json.encode(body) network.request( fgs\_url .. "RecordNewInstallation", "POST", recordNewInstallationListener, params ) end -- Call function recordNewInstallation()
Response:
{"status":0,"errMsg":"","instanceId":"0ab1cd01-01a0-0a0a-01ab-a01a5abc0123","gamerHandle":"PLAYER74"}
After I wrote this service for myself, I thought it could be used by other game developers, so over several weeks I developed a web-site to allow other developers to sign up to consume my API, and I loaded it with coding examples to help my fellow developers get up to speed with it quickly.
[Personal note: This service and web-site took me a lot longer than it took to develop my simple Corona game - it felt like I had gone down the rabbit hole on this one! All I wanted was to give my players the opportunity to see how they compare to the other gamers! If somebody had told me in January that by the February I would have developed an Online Leaderboard with it’s own web-site for a game platform I had only started to use a few months earlier - I would have dismissed it out of hand. But you know, having an online Leaderboard in a game should be really, really simple to implement, and when I saw it wasn’t and you also lose your privacy in the process, I took it upon myself to put this right.]
The service is hosted, and that costs, especially if there’s a lot of traffic, so I charge a nominal fee (and it’s volume priced, so the more calls made, the lower the price).
You only pay for what you use, and it’s free to develop and integrate it; you only pay when you put your game into production, so if you develop it but decide not to use it, that’s OK, it wouldn’t have cost you anything, and I don’t ask for any personal or financial info (In fact, I use PayPal, so I do not store any personal or financial data at all).
So in summary:
- Online leaderboard
- Gamer-handles - what’s the point in uploading a score if no-one knows IT’S YOU?
- Super simple RESTful API calls returning JSON formatted data
- Cross-platform: games running on Android, iOS, Windows, Mac, can all access the same service and data through the same API
- I don’t data-mine and I don’t collect personal or financial data on you, or your players.
- A Globally Unique Identifier (GUID) generator!
And, finally…
The web-site gives coding examples showing how to issue POST calls using LUA (and C#, Jquery, etc…).
I’m thinking of writing an article (or series of articles) on how I consume this service in a Corona game, particularly the generating and storing a games GUID, managing the online high-scores and uploading new ones, formatting the scores table, and capturing, validating and storing a gamer’s handle.
Let me know if this maybe useful to you.
My service can be found here: