So you created a little game and published it to the marketplace pretty pleased just for getting something out there. Soon users through reviews are asking for an online leaderboard. That’s what happened to me and my “tetris” game, Metro Blocks. First you think of building one yourself, thinking it can’t be that difficult. But then you think about hosting, scaling, security and domain and you start thinking that it might be better to check out what people have done. A colleague of mine pointed me to the http://www.mogade.com who provides a free service to casual game developers. And the rest of my post is dedicated to using mogade as leaderboard.
Step 1: REGISTER
Go to https://www.mogade.com/manage/accounts/register to register an account. NB the confirmation is LUIGI for those not familiar with the Nintendo classic.
Step 2: SETUP GAME INFO
Log in to mogade and Create your game first and then your leaderboard. Should be straightforward. Notice that your game has an id and a secret key assigned. We will use them later when we setup the code.
Step 3: DOWNLOAD LIBRARY
Now you have your account setup, you’ll need to get the library/sdk to integrate it into your solution. Go to https://github.com/mogade/mogade-windowsphone to download the latest version. If you are not familiar with git just download the latest zip file with the solution. Then it’s just a plain old Visual studio solution. Remember to unblock the zip file before unpacking it if you have Windows 7.
After unzipping, open the solution and compile. In you bin/debug or release you will find 3 dlls that you are going to reference in your solution. So open your game and add references to:
– Mogade.Windows.Phone.Core.dll
– Mogade.Windows.Phone.dll
– Newtonsoft.Json.Silverlight.dll (Used for serializing json)
Step 4: INTEGRATE CODE
The nice thing about Mogade library is that it does the heavy lifting for you. No need for xmlserialzing, calling webservices or such. We will just use the api provided for us. All the code samples are taken from a demo game I made called Armageddon which full source code is attached.
First I wrap the Client/Provider in a custom class called MogadeCommunicator. It basicly just acts as a singleton to be used by my scoreservice.
public class MogadeCommunicator { private const string GameKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Replace with your game key private const string Secret = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Replace with your secret private static IMogadeClient _client;</code> public static IMogadeClient Client { get { if (_client == null) { _client = CreateClient(); } return _client; } } private static IMogadeClient CreateClient() { // Initialized the configuration our client should use to uniqly identify the user. // We'll choose the recommended combination of Phone's unique Id + username. MogadeConfiguration.Configuration(c => c.UsingUniqueIdStrategy(UniqueIdStrategy.DeviceId)); _client = MogadeClient.Initialize(GameKey, Secret); if (NetworkInterface.GetIsNetworkAvailable()) { _client.Update(null); _client.LogApplicationStart(); // This is only needed if you want reporting on usage. } return _client; }
With our client setup, let’s move over to our leaderboardservice. It pretty simple and provides 3 methods : GettingLeaderboards, GetUserRanking and SaveScore which basicly all you need for a leaderboard. Worth noting is it that I use another great framework MVVM Light to act as a publish/subscribe messeging system. That means that the responses from Mogade are wrapped into my custom events and published. That means you can subscribe to when leaderboards are recieved and put the result out to the user.
Another thing to be aware of is that I use the Deployment.Current.Dispatcher.BeginInvoke() to marshall the data back to the gui thread. That is because my game is in Silverlight.
public static class LeaderboardService { private const string LeaderBoardKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Replace with your leaderboard key private static readonly IMogadeClient Client = MogadeCommunicator.Client; /// <summary> /// Retrives the ranking of user and raises UserRankingRetrievedEvent when retrieved /// </summary> public static void GetLeaderBoards() { // Doing it easy, get all leaderboards since we aim to display them. Client.GetLeaderboard(LeaderBoardKey, LeaderboardScope.Overall, 1, OverallScoresRetrieved); Client.GetLeaderboard(LeaderBoardKey, LeaderboardScope.Weekly, 1, WeeklyScoresRetrieved); Client.GetLeaderboard(LeaderBoardKey, LeaderboardScope.Daily, 1, DailyScoresRetrieved); } /// <summary> /// Retrives the ranking of user and raises UserRankingRetrievedEvent when retrieved /// </summary> /// public static void GetUserRanking(string userName) { if (string.IsNullOrEmpty(userName)) return; Client.GetLeaderboard(LeaderBoardKey, LeaderboardScope.Overall, 1, userName, UserRankingRetrieved); } /// <summary> /// Saves a Highscore to Mogade, and raises ScoreSavedStatusEvent when completed (successfully / or not) /// </summary> /// public static void SaveScore(Highscore highScore) { var score = new Score { UserName = highScore.UserName, Points = highScore.Score, Data = highScore.GetScoreData() }; Client.SaveScore(LeaderBoardKey, score, ScoreSaved); } private static void UserRankingRetrieved(Response e) { if (e.Error != null) return; if (e.Data.User == null) return; Deployment.Current.Dispatcher.BeginInvoke(() => { var payLoad = new UserRankingRetrievedEvent { ScoreWithRank = e.Data.User }; Messenger.Default.Send(payLoad); }); } private static void ScoreSaved(Response e) { Deployment.Current.Dispatcher.BeginInvoke(() => { var payLoad = new ScoreSavedStatusEvent { Success = e.Success, Ranks = e.Data }; Messenger.Default.Send(payLoad); }); } private static void OverallScoresRetrieved(Response e) { if (e.Error != null) return; RaiseLeaderBoardEvent(e.Data.Scores, LeaderboardScope.Overall); } private static void WeeklyScoresRetrieved(Response e) { if (e.Error != null) return; RaiseLeaderBoardEvent(e.Data.Scores, LeaderboardScope.Weekly); } private static void DailyScoresRetrieved(Response e) { if (e.Error != null) return; RaiseLeaderBoardEvent(e.Data.Scores, LeaderboardScope.Daily); } private static void RaiseLeaderBoardEvent(IEnumerable scores, LeaderboardScope scope) { if (scores == null) return; // Make sure we invoke the response onto the GUI Thread Deployment.Current.Dispatcher.BeginInvoke(() => { var highscores = new List(); int rank = 1; foreach (var item in scores) { var highscore = new Highscore(); highscore.Ranking = rank; highscore.Score = item.Points; highscore.UserName = item.UserName; highscore.UpdateWithScoreData(item.Data); rank++; highscores.Add(highscore); } // Setup and publish leaderboard event var payLoad = new LeaderboardRetrievedEvent { Scores = highscores, Scope = scope }; Messenger.Default.Send(payLoad); }); } }
So that is basicly the 2 classes needed to get started. To see the full interaction download the source code. It’s a very basic game and I think the code shouldn’t be to complex. It’s created for demo purposes but published to the Markeplace (with some deservedly bad reviews :)) . For other Silverlight coders I think there is some Helper classes that can be useful.
Quick Summary:
Mogade – http://www.mogade.com – Excellent Free leaderboardservice brought to you by Karl Seguin. Also make sure to read his ebook “Foundations of Programming”.
MVVM Light – Laurent Buignon’s lightweight MVVM framework. http://mvvmlight.codeplex.com/
MVVM Light – Laurent Buignon’s lightweight MVVM framework. http://mvvmlight.codeplex.com/
Myself
Just an average developer, more graft than craft. Trying to give something back to the community after spending my career picking up snippets from the web. Feel free to ask me anything:
Here is the solution, remember to rename file extension to .zip (It’s a bit big ca 20mb)
Great Article, been thinking about tackling this myself but this service is perfect.
Hey,
I’ve tried running the example from Mogade.
JsonSerializationException was unhandled.
Error getting value from ‘username’ on ‘f__AnonymousType0`4[System.String,System.Int32,System.String,System.String]’.
Drilling down into View Detail, inner exception message it says
“Attempt to access the method failed: .f__AnonymousType0`4.get_username()”
Have you had any problems like this ?
I just tried the example from Mogade and it works from me. The error seem related to a JsonSerializing. You could try downloading the latest version of Json.net from http://json.codeplex.com/
The mogade uses the previous version which is a Silverlight assembly. The latest version of Json.Net supports WP7 and could be worth trying to switch.
Thanks for the suggestion, I download the latest version and tried the switch to the Windows Phone but still got the same error for both
I got a reply back from Karl on GitHub saying it may be a problem with VS Express for WP which I’m using because when i load the solutions in I get an error saying “solution folders are not allowed” and whatever is in folder stuff is not loaded. This occurs for both the Mogade DLL builder project and the mini game.
thanks a ton.. i am going to start on a game today… hopefully its going to be a small game. so this will be very helpful for second version.
Reblogged this on Invoke IT Limited and commented:
I think i will need one of these soon.
Hey, real good articel. I only can say THANKS!
It’s really a great and helpful piece of info. I’m happy that you shared this helpful information with us. Please stay us up to date like this. Thanks for sharing.
hi, am new to window phone developing and c#. I am searching for leaderboard and achievement integration. Will appreciate if u can help me to solve problem.
1> how to add reference in MS VisualStudio 10?
2> do i need to use keyword using “libName” or any namespace?
3> Also, my compiler complain about line number 24 of ur first part of code. how to fix it?
Hi Nitesh,
Please send me your email and I’ll send you a sample project that is easy to understand for a beginner. My mail is brian@solli.net
Hi Software graftsman. my apology for replying this late. I am able to get the project compile and run successfully. But right now am looking for something that similar to gamecenter of ios platform which allow user to have their own account and can login from anywhere. also each user will have their unique record of score and achievement. this project is working fine, but it look like it don’t support user account and also user score can be overridden by another user if they both use same name. my client have objection to this . i am trying to use microsoft’s xboxlive also. but i have been told that microsoft won’t allow all game to use their xbox live services. please tell me what modification should i do so that each user can have unique account.
Thank you very much for taking interest in replying me 🙂
Was about to try to build my own using google app engine but this looks a lot easier. Thanks.
Having a bit of trouble getting the example to compile. It seems mogade library may have changed a fair bit. For example I can’t find the ScoreWithRank Object anywhere in the current mogade library.
Hi, The example is pretty old so I will try to update it with latest version of Mogade and publish it. Will try to get to it tonight.
In the meantime you can take a look at:
https://github.com/mogade/mogade-examples-windowsphone
I’ve looked at the latests bits from Mogade and I see there are several things that needs updating. I will try to update the code and the blog post this week.
They stopped supporting it, unfortunately 😦