This is part of an ELC Tech Network

iPhone Coding Tutorial – Creating an Online Leaderboard For Your Games

As you may have seen, there are quite a few services out there offering free leaderboards.  These are great and all, but sometimes you want to have complete control over your data.  I have put together a complete tutorial detailing step by step how you can create your own online leaderboard for use in your iPhone games. For those of you who don’t know, a leaderboard is essentially a high scores list. This tutorial will also give you a very simple introduction to interfacing with web services.

The first part of this tutorial will discuss how to build the server.  We will be doing this using PHP and MYSQL.  I will also assume you have some working knowledge of PHP and MYSQL (if not, use the Google machine to get up to speed).

Since this tutorial is so long, I have decided to split it up into pages. You will notice the page number at the bottom. Please use them to navigate between parts of this post. I feel that I have to make this explicit as I will undoubtably get some dude in the comments saying “Where is the rest of the tutorial”.

Skill level: Advanced

Creating The Database

When creating a leaderboard, you will need some way of storing the data.  We will be using MYSQL for our storage.  You can also be lame and simply use flat files.  This would add quite a bit of code in the long run as you would have to write all of the sorting and pagination functionality yourself. Don’t do it.

One thing to note about my php server files. I know they could be cleaned up a little and optimized (you could create a config.php that contains all the db interface code), but the goal of this tutorial is not to show you how to code killer PHP. It’s to show you how to create code that you can connect your iPhone apps to.

I like to create one file that does a complete flash of the database.  That way, when I’m testing or switch from staging to production, it is a very simple process.  So, with that being said, here is my code for create_db.php.

Advertisement

<?php
        // create_db.php
	/** MySQL database name */
	define('DB_NAME', '');
	/** MySQL database username */
	define('DB_USER', '');
	/** MySQL database password */
	define('DB_PASSWORD', '');
	/** MySQL hostname */
	define('DB_HOST', $_ENV{DATABASE_SERVER});
 
	$table = "highscores";
 
	// Initialization
	$conn = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD);
	mysql_select_db(DB_NAME, $conn);
 
	// Error checking
	if(!$conn) {
		die('Could not connect ' . mysql_error());
	}
 
	// Drop existing table if exists
	mysql_query("DROP TABLE $table", $conn);
 
	$retval = mysql_query("CREATE TABLE $table(
		id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
		udid VARCHAR(45),
		name VARCHAR(25),
		score FLOAT(10,2),
		date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
	)",$conn);
 
	if($retval) {
		echo "Database created...";
	} else {
		echo "Could not create database " . mysql_error();
	}
 
	mysql_close($conn);
?>

I’m not going to go into too much detail about this code, however I will give a high level description of what’s going on. One thing to note about this code is it assumes you already have the database created.

First, we are defining variables that contain our database information. Make sure you replace my empty strings with your database info. After we connect to the database, we drop the table if it already exists. This is useful if you want to wipe out your test data. Finally, we create the scores table. Navigate to this file in your browser to run it and create the scores table. Pretty easy right?

You will want to make sure to remove this file from your server after running it to avoid people resetting your database.

Now that our database table has been created, it’s time to implement the web service code to publish new scores to our leaderboard.

This entry was posted in iPhone Game Programming, iPhone Programming Tutorials and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

35 Comments

  1. RoberRM
    Posted October 29, 2009 at 10:57 am | Permalink

    No, thank YOU very much! :)
    I was thinking on implementing something like this in my game and you just made my work easier. ;)

  2. Shane
    Posted October 29, 2009 at 3:02 pm | Permalink

    Thanks, excellent, I’m sure I’ll use it at some point.

  3. Posted October 30, 2009 at 1:01 am | Permalink

    Hi! Thanks very much for the tutorial!
    I have one question about getting highscrores. How I can get the scrores from the php page to the iphone sdk labels and textboxes e.t.c? I don’t want to use UIWebView.

    Please answer to the mail :)

  4. Posted October 30, 2009 at 7:26 am | Permalink

    Very well done ! Love your tuts and I always wonder how to you find time to build them, cz I know how much efforts it takes :)

    For the MySQL,based on my experience I never use FLOAT column type, because I had huge problems with float math on it, I always use DOUBLE instead, which seems to work better.

    Also, wouldn’t it be better if the password was sent trough a POST request? Or it was too much code overhead for the simple tutorial ?

    Anyhow, I’m always waiting for the new post on your blog, and congrats once more

    Marin

  5. Posted October 30, 2009 at 8:53 am | Permalink

    @Mikko – You need to make your PHP output XML instead of a table. Then parse this XML in your application into an NSDictionary. From there, you can populate whatever you want with this data.

    @Marin – I have never had any issues with FLOAT. But I’m sure you could easily switch it out with DOUBLE. As far as teh POST goes, there are many ways security could be improved. HTTP Basic AUTH would be another way to prevent attacks. I didn’t really want to go too much into it in this tutorial as I wanted to keep things simple and show users how to get a leaderboard up with very little code. Thanks for the suggestion.

  6. Posted November 11, 2009 at 4:50 am | Permalink

    Thanks for the code. I was wondering about how to make sure the person can reach the website. It seems that Apple has a framework for checking called SCNetworkReachability and some demo code in the SDK. I’m just adding that here to save people the extra google search.

  7. Posted November 11, 2009 at 6:31 pm | Permalink

    I cant seem to set up the creat_db.php page I get this error: Could not connect Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2) and also I am getting confused in xcode. Do you think you could post source code to a sample project that would do everything you described in the tutorial?

  8. Posted November 19, 2009 at 12:15 am | Permalink

    Great post. Thanks for this really. I am not a blog reglar blog reader but this blog is truly amazing indeed.

  9. jeroen
    Posted November 26, 2009 at 3:21 pm | Permalink

    Hi, tnx for this great post. Could you pls place or mail me een .zip with al the files’s?

    I build the tutorial but it doesn’t work.

    Tnx in advance.

  10. Posted December 1, 2009 at 6:32 pm | Permalink

    To check for an internet connection, you should use Apple’s Reachability class. Just download it and copy Reachability.h/m to your project. Also, you have to add the SystemConfiguration framework to your project.

    https://developer.apple.com/iphone/library/samplecode/Reachability/index.html

    Usage:

    Reachability* reachability = [Reachability sharedReachability];
    [reachability setHostName:@"www.example.com"]; // set your host name here
    NetworkStatus remoteHostStatus = [reachability remoteHostStatus];

    if(remoteHostStatus == NotReachable) { }
    else if (remoteHostStatus == ReachableViaWiFiNetwork) { }
    else if (remoteHostStatus == ReachableViaCarrierDataNetwork) { }

  11. Posted January 2, 2010 at 5:26 pm | Permalink

    Hi, should the submit score method’s return type be NSString *?

    Also, if I want to limit the maximum number of entries in the table, how should I modify the code?

    Thanks a lot!

  12. Posted January 11, 2010 at 2:35 pm | Permalink

    I ran into an error when trying to add this to my app:

    HighScoresView * hsv = [[HighScoresView alloc] initWithNibName:@”HighScoresView”
    bundle:[NSBundle mainBundle]];
    [self presentModalViewController:hsv animated:YES];
    [hsv release];

    The error would say that HighScoresView was undeclared, after a while I got the error to go away. Then I was getting hsv is undeclared and fixed that by adding Controller to the end of each HighScoresView. I was then getting a bad execution error. It seems (I traced through the debugger) that it is not taking the string from my textBox.text (Debugger says it is not a valid CFString. Then when it goes to encode the username it does the same thing and crashes. Do you have any suggestions on how I can fix this? I’ve been puzzle by it for hours now.

    -Chris

    • Geo
      Posted April 22, 2010 at 4:03 pm | Permalink

      Did you manage to fix this I am getting hsv undeclared and HighScoresViewController undeclared as well…

      Thanks in advance
      Geo

    • Gima
      Posted April 22, 2010 at 4:12 pm | Permalink

      Hi there, I think this is a great tutorial, I have done the PHP. I am just having problems with the xcode side of things, I am getting HighScoresViewController and hsv undeclared. I have added it into a an IBAction on button click, do you have any ideas?

      I have tried adding a property and synthesising it, but still isn’t working…

      One other thing is

      [self submitScore:score username:usernameTextbox.text];

      I don’t know where to put this and ma having problems with knowing how to sort out the username and password..

      I understand I am asking for a lot, but is there anything that you could possibly help me with? I am using this great tutorial to make an application for my final project at uni, and the deadline is comin up, so you can imagine….

      Thanks in advance
      Gima

  13. Posted January 21, 2010 at 2:04 pm | Permalink

    What if two people enter the same user name? Is there any way to detect if the user name has already been taken? and If so can you explain how one might go about this?

    Thanks

  14. Posted January 22, 2010 at 11:21 am | Permalink

    Hello,

    First I have to say this tutorial has been very helpful, Thanks

    I have a few questions though.

    I have the leaderboard up and running, and I have it also displaying in my app just fine. A few things that Im running into is when the user clicks the leaderboard button in my app I would like to have them enter there username to submit there high score then have the high scores view controller slides up from the bottom and displays on top of the current view.

    Im using your Inserting A UITextField In A UIAlertView, to prompt the user to enter there username. Im not sure how to modify this code, so when the user enters there username and clicks the “OK!” button that it then submits the username and highscore to the leaderbord and closes the UIAlertView and opens the high scores view. And in turn if the user clicks the “Dismiss” button it closes the UIAlertView and opens the high scores view without submitting a score or name.

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Enter A Username Here” message:@”this gets covered!” delegate:self cancelButtonTitle:@”Dismiss” otherButtonTitles:@”OK!”, nil];

    UITextField *myTextField = [[UITextField alloc] initWithFrame:CGRectMake(12, 45, 260, 25)];

    CGAffineTransform myTransform = CGAffineTransformMakeTranslation(0, 60);

    [alert setTransform:myTransform];

    [myTextField setBackgroundColor:[UIColor whiteColor]];

    [alert addSubview:myTextField];

    [alert show];

    [alert release];

    [myTextField release];

    The other issue I noticed, is there is nothing stopping someone from submitting multiple high scores, and flooding the leaderboard with just there name and scoe ten times. Is there another “possible simple” PHP script that when submitting a score it does some sort of check, such as checking if the users UDID and username match, and if there score was greater than the one currently on/or in the database then allow them to post it, if not display an alert, or just “Dismiss” the submission and display the high score view.

    I know this is asking allot, any help would be great.

    Thanks again.

  15. Posted February 5, 2010 at 2:06 pm | Permalink

    Good Article!

    Where is the rest of the tutorial? :P

  16. Rodney
    Posted February 6, 2010 at 10:28 am | Permalink

    I have an online work order system running on MySQL with PHP pages. I want to make an app to retrieve data and post data to the site. I used this tut to create a couple of test pages and can post data and retrieve via Safari. I am a real newbie on iPhone development and could use some help. A tut on posting and retrieving data would be greatly helpful. If there is one somewhere on the web, I can’t find it.

  17. brent
    Posted February 16, 2010 at 3:29 pm | Permalink

    any help on how to identify a user by username/pword instead of udid?

  18. Posted February 19, 2010 at 2:31 pm | Permalink

    Very Interesting Read! Looking forward to more on this subject Bookmarked this site. Was also curious if anybody could point me to some related material. Thanks in advance.

  19. Posted March 10, 2010 at 7:23 pm | Permalink

    Great article, I have just got the mysql db up and running and can post from my browser now! Next step to do an iPhone app to test. Thanks again.

    PS. you have a spam comment above that slipped in… might wanna delete it :P

  20. Dave
    Posted April 4, 2010 at 12:52 pm | Permalink

    As-is, the ‘secret’ really doesn’t help at all. Anyone that wants to submit a fake score can simply copy the URL passed, change the score, and re-submit the URL.

    A quick work-around to prevent this type of attack is to hash the ‘secret’ along with the data being passed. Then you just send the hashed value rather than the actual ‘secret’. On the server side, you compute the same MD5 hash to make sure the data is legit.

    Pseudo code example:

    hash = MD5( "secret" + username + score)

    NSString *urlString = [NSString stringWithFormat:@"http://icodeblog.com/ws/put_score.php?secret=%@&udid=%@&name=%@&score=%f",
    hash,udid,username,theScore];

    Note, the secret itself is never sent in plain text this way. In fact, the secret is never sent at all!

    Main benefits: (A) No one else knows your secret password, and (B) if someone changes the Score or the Username, the MD5 hash will not match.

    Quick and easy!

    HTH

    Dave

    • Jens Kappe
      Posted April 9, 2010 at 2:47 pm | Permalink

      Thx for the tutorial!

      For all people with db-Initialisation problems try to add DB_NAME when connecting to the database like in the following line:
      $conn = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD, DB_NAME);

      Best

      Jens

  21. Gima
    Posted April 22, 2010 at 4:25 pm | Permalink

    Hi there, I think this is a great tutorial, I have done the PHP. I am just having problems with the xcode side of things, I am getting HighScoresViewController and hsv undeclared. I have added it into a an IBAction on button click, do you have any ideas?

    I have tried adding a property and synthesising it, but still isn’t working…

    One other thing is

    [self submitScore:score username:usernameTextbox.text];

    I don’t know where to put this and ma having problems with knowing how to sort out the username and password..

    I understand I am asking for a lot, but is there anything that you could possibly help me with? I am using this great tutorial to make an application for my final project at uni, and the deadline is comin up, so you can imagine….

    Thanks in advance
    Gima

  22. Posted May 17, 2010 at 12:05 pm | Permalink

    Hello,

    Thanks a lot for the hard work you put into these great tutorials. I managed to create a game thanks only to all your tutorials including an online leader board. A big thank you again and keep up the good work!

    Kind regards,
    Shaheel

  23. Alejandro Alcantara
    Posted June 13, 2010 at 10:43 am | Permalink

    Hey man can you please send me a simple app build project that displays the leaderboard. i cant seem to get it to work, even that i have all the tables and everything done right and it works, but i cant show it. Plz man. Thanxs

  24. lincomatic
    Posted June 14, 2010 at 5:52 pm | Permalink

    To those who find that HighScoresViewController crashes when you try to display it, I also spent hours trying to figure out the problem. It turns out that you need to just add this line to the HighScoresViewController.m:

    @synthesize webview;

  25. Chaosal
    Posted June 16, 2010 at 1:58 pm | Permalink

    Just wanna say thanks for the great series of tutorials Brandon, they’ve been a great help in getting me up and running with programming on the iPhone =]

    To all those people sending barrages of requests for sample code and asking simple questions in an advanced tutorial: these tutorials are meant as a guide to help you out, you need to spend your own time doing research and gaining experience with the tools instead of expecting Brandon to spend his time holding your hand and writing the code for you. Copying some example code without actually understanding what it does or how it works doesn’t help you learn how to actually program.

    Thanks again dude!

  26. Dan Zimmerman
    Posted June 27, 2010 at 8:46 pm | Permalink

    Thanks a bunch guys! This is EXACTLY what i needed =D

  27. Alex Blundell
    Posted July 10, 2010 at 3:51 pm | Permalink

    Great tutorial! I’ve used it my app (and edited the html table so it fits in nicely!). I’ve noticed I can use things such as get_scores.php?offset=30&count=200 etc, etc, to edit the amount shown, and the location it’s shown in (I can also reverse it via ?sort=score+ASC to change the direction it’s shown in (reverses it) ). That’s all great, but only if you can see the position numbers! Is there a way to show the position number next to the users’ name?

    Example, now it’s:
    Name Score
    Test 30
    Test 22
    Test 18
    Test 9

    Whereas, it would be better as:
    Name Score
    1 Test 30
    2 Test 22
    3 Test 18
    4 Test 9

    Any Suggestions?

  28. Posted August 4, 2010 at 7:12 am | Permalink

    this Is Much Interesting..

    But one Question?
    Is there is any Memory Leak problem In The Above application ?

    regards

    safil sunny
    Kerala Tourism

  29. AD
    Posted August 11, 2010 at 11:50 pm | Permalink

    I have a question; I’ve noticed some apps have a code which you can share with other players, or online; this code is then entered into a textbox. The best example I can find is the Mafia Wars iphone app where users usually post “add me XXX XXX” on forums and you can enter this information on your game — I’m not sure exactly what the process is, or what this accomplishes, and I’m wondering if you could go over what this concept is and how best to use it. Thanks.

  30. Andrew
    Posted August 12, 2010 at 9:13 pm | Permalink

    Very bad security….. someone could easily sniff all wifi packets, see that the “$_GET["secret"]” value and spam the leaderboard with 9999999999

    • Alex Blundell
      Posted August 14, 2010 at 9:01 am | Permalink

      That’s why some people (like me) have implemented MD5 hashing into the mix of things sent, and taken out the “secret” key part being sent (so that it only gets sent hashed with other strings)

  31. Posted August 28, 2010 at 12:05 pm | Permalink

    Good stuff!! Thank you sir!!

One Trackback

  1. By Web Services voor de iPhone on December 9, 2009 at 12:56 pm

    [...] In deze stap schrijft men data naar de database. Meestal wordt deze stap niet beschreven. Er staat hooguit: “…en schrijven gaat precies andersom.” Hier vind je een uitstekend voorbeeld hoe dat wel kan met XML. [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">