.: Introduction :.
An increasingly popular feature in the Click community at the moment is to get away from exclusively single-player games and to provide some way to compete with other players. One of the easiest ways to do this is to keep an online high score board so that players from anywhere can compare their results with others.

The main thing that puts people off about setting up an online high score system themselves is the amount of stages involved - the game has to send information to a web page somewhere on the Internet that in turn passes information in to an online database. Then the database has to pass data back to a page and (usually) the game itself again. (It's possible to communicate directly with some databases from within an MMF application, but the majority of webspace providers don't allow connections to the database from outside the same server.) It can also be quite daunting for beginners as it involves venturing outside MMF and getting it to communicate with small scripts written in another language. However, even if you haven't got any experience with PHP or SQL before, they are both fairly easy to explain and pick up for the purposes used in this tutorial.
A rudimentary knowledge of HTML would probably be an advantage, though - not necessarily how to write entire sites, but certainly an understanding of the general layout of it would help when we come to write the script for displaying the online high score board. It will also be easier for you if you have at least some idea of the general layout and concept of databases.
Even if you don't have experience in those two areas, we'll be walking through setting up all three sections for the online high score table in this example, and then exploring what else we can do with similar setups.
.: Contents :.
Setting up the game
Finding webspace
Setting up the database
Writing a page to display the scores
Writing a page to store scores in the database
Getting the game to send a score
Timeouts
Adding security
Coping with spaces
Displaying the scores in-game
Conclusion
.: Setting up the game :.
To start off in familiar territory, it's best to begin with staying in MMF for now and writing the game or application that is going to produce the data that we want to store in our online database. To get this section over with quickly and let us get on with the real part of the tutorial, I'm going to set up what is perhaps the simplest of all games - Hold the Button. If you already have a game that produces a score at the end, feel free to use that instead.
Start a new application and go into the first frame. I'm not going to do anything spectacular here - just something quick so that we have a score to send. Create a new active object, give it the appearance of a button however you like, and add a counter to the frame as well.

Then add these events:
This is simple enough to understand - the counter will start rising when you click on the button, and the application moves to the next frame when the mouse button is released again.
Now make a new frame after the first one, and add a counter, Edit box and Button object. Go into the counter's properties and check "Global Object" under Memory Options, then click "Yes" on the dialog that appears - this will make the counter take its properties and values from one frame to another. In the screenshot, I've also put a couple of String objects in to make it a little clearer what's going on.

As you can see, this frame is going to be used to submit data out of the application. What we need to set up next is where the data is going to go and what we do with it once it gets there. This involves venturing out of MMF and into PHP and MySQL.
.: Finding Webspace :.
Before getting into making the code for the online section, though, you're going to need webspace so that you have an online space to store the data. If you already have a webhost (most Internet service providers give you a small amount of webspace for free), check to see if PHP and MySQL are supported by them - the majority of decent ones will have support for them, though on the most basic free accounts, Freewebs and so on, they're likely to be missing.
If you need to set up a new webspace account, one good one to use is Byethost. Even their free packages are extremely competent, and any of them go well above the requirements for this tutorial. I'm going to be using one of their accounts to set up the example, but all web providers should have similar interfaces.
Sign up for your webspace and log in to your admin page or control panel however you're instructed to by the provider.
.: Setting up the database :.
SQL is a type of database engine, very similar to what you might have already seen in things like Microsoft Access. Data is arranged in tables that can have any number of columns. Each row of the table represents one data item, and the individual properties of this item of data are stored in the individual columns. For example, a table for the members of a bank (which is the example given in most SQL tutorials) would contain columns with space for storing a member's name, account number and amount of money in their account.
Unlike the friendlier database applications, however, SQL is a command driven language - additions and changes are made to the database by using text-based commands known as queries. This is useful because it means we can pass a command to the database in the form of a line of text (and this is what we're going to be doing later). For the purposes of manipulating the database manually, though, most hosts provide a graphical frontend such as phpMyAdmin, which is much easier to navigate around than having to remember the syntax of hundreds of SQL commands.
The first step is to prepare the MySQL database we're going to use to store the data uploaded by your application. Most providers will allow you to do this from the control panel of your account - there should be a link named "Manage SQL" or something similar.

If there isn't a database in your account already, create a new database with a fairly generic name - we don't want the actual database to be named anything specific because it's possible you'll want to add multiple tables to it for very different purposes later. For example, the tables in my own site's database contain information about news posts for my project sites, comments left on those news posts, and lyrics and download information for my music as well as the score tables for the games I've written. It's simply called "wong".
Now open up the database you've just created (click "Admin" on Byethost). You'll be looking at the opening page for phpMyAdmin, or a similar SQL management tool.

The first stage is simple enough if you've used any kind of database before - we need to start a new table, give it a name and set up its fields (the columns that it will contain). Navigate to the "new table" page if you have to, then enter the name "buttonscores" or similar and tell it we want to add four fields.

You'll now be at the page that allows you to set up the table. Don't panic.

This page can appear pretty insurmountable if you haven't used SQL before (and particularly if you're new to the concept of databases in general), but despite some of the terminology that may be unfamiliar to you, setting up the table isn't going to be a difficult task.
Name the four fields so that you have some idea of what we're going to do with them - from top to bottom, enter the names id, name, score, and dateuploaded. Keeping them all in lowercase isn't strictly necessary, but it does help to keep things tidier later on. id is going to be used as a unique identifier for each entry. name and score are pretty self-explanatory - they'll be used to store the name entered in the game and the score that was reported. datesubmitted will store the date and time that the score was entered into the database.
We now need to set up the types of each of the fields.
- The id field requires the most setup because we don't want to worry about controlling it ourselves when we get the game to interact with the database. Set it to be a "SMALLINT" - a small integer value. Despite the name "SMALL", this type can hold any one of 65536 possible values (and having that number of entries in the table for this tutorial is pretty unlikely). However, by default the range of it goes from -32768 to 32767 instead of 0 to 65535 as we want it to - to correct this, pull down the "Attributes" box and select "UNSIGNED". Additionally, set the "Null" field to "null" and the "Extra" field to "auto_increment". Having these two properties on means that instead of having to give the database a value each time when we add a row to the table, it will detect the next unused ID and fill it in automatically. Finally, click the radio button on this row underneath the icon that looks like a table with a key - this will tell the database that we want this row to be the primary key, a unique identifier for rows in the table.
- Set the type of name to be a VARCHAR, and type "20" in the Length/Values field. A VARCHAR is like a string in MMF that is limited to the number of characters you specify - you can change it up or down, but 20 is usually sufficient for name entry fields.
- Set score to a "MEDIUMINT", and make it unsigned in the same way as we did for the ID field. This will allow values of up to 16777215 to be stored, and if anyone holds the button for longer than that, they really need to be doing something else with their time anyway. (If you're using your own game and need scores above this for any reason, remember to make this a field that can cope with the scores you need.)
- Set datesubmitted to a "TIMESTAMP", and check CURRENT_TIMESTAMP in the Default column. This property will make this field contain the time that the score was submitted rather than make us have to look it up every time.
Even though it seems like it doesn't matter just now, there's a reason why SQL doesn't just have "value" and "string" types of data like in MMF. The difference between all the many INT and VARCHAR types is that they limit themselves to a certain amount of storage space each. As a table may contain any number of rows, a small difference in the storage space required for one row may multiply up to give a huge difference in storage space for an entire table. The table for this tutorial isn't likely to grow so large that it makes any real difference, but nevertheless, thinking about data sizes is a good habit to get into.
Now we're going to try putting an entry into this database. phpMyAdmin provides a graphical user interface for doing this under the "Insert" tab, but SQL is a command-driven language underneath, and getting familiar with the way it's written will help later on. Go into the "SQL" tab and you'll be given a text area to type a command into. Enter this line:
INSERT INTO buttonscores VALUES (null, 'Tim Sweeney', '172', CURRENT_TIMESTAMP)
The "null" value at the beginning signifies that we're not putting a value into the id column, as it's going to autonumber for us. The other items are the values for name, score and datesubmitted.
This line of SQL is fairly self-explanatory - it inserts a new row into the table called 'buttonscores' and gives the fields of that row the values you specify, in the order you give them. (Therefore it's important to remember the structure of your table while writing commands for it). Hit OK and a new row will be inserted into the table with the values that you've given - click on the "Browse" tab to see it. Go back to the "SQL" or "Insert" tab and add as many more as you like - we need a couple in the table to test out the system when we write the page to display these scores.

.: Writing a page to display the scores :.
This section may also introduce a new concept, and it's one that you may well be using MMF to avoid - a code-based language. However, I don't think that there is as much of a jump as it may seem between MMF and more 'traditional' programming languages - many of the concepts behind them are the same. The main difference is that you don't have a handy list of conditions and actions, and instead commands (which are much the same as MMF actions) are just carried out in the order you give them unless you specify otherwise.
Of course, another difficulty is that you have to remember a list of commands and the correct way to use them. Fortunately, I found PHP to be one of the easier languages to pick up - one of its main design features was that it made it easy to interact with SQL databases, and that makes it ideal for our purposes. PHP files can have a combination of HTML and PHP code in them - the code is run by the server when you load the page, so that a complete HTML document is written from a combination of the HTML that you write and the HTML written by the program.
What we're going to do here is write a PHP page to display the scores that are currently in the database. You're going to need a decent text editor for this, and while Windows' default "Notepad" will work, it isn't really much more than an Edit box with some menus around it. More sophisticated editors will have features such as syntax highlighting to assist you when writing code. I've been using "Notepad2" for a while, which can be found using a Google search, but there are many text editors that have been written to suit code editing, and choosing one is largely down to your own preference.
Whatever text editor you're using, create a new text file and rename it to "displayscores.php". Now, this guide isn't going to contain an extensive PHP tutorial, but rather than putting a huge amount of code up and telling you to throw it into your own file, I think it's better to explain it in small sections as I go along. First of all, open up the document and copy and paste this into it.
<html> <head> <title>Online Scoreboard Tutorial - Scores</title> </head> <body>
This section is just plain HTML that describes the page. The text between the opening and closing "title" tags is what will appear in the title bar of a browser when the page is opened. The section ends with the opening of the "body" tag, which will contain the actual contents of the page. But the contents of this page are mostly going to come from the database, so we need to start writing PHP code here to retrieve it.
Add these lines to the file:
<? $service = "yourservice"; $username = "yourusername"; $password = "yourpassword"; $database = "yourdatabase"; mysql_connect($service, $username, $password); @mysql_select_db($database) or die( "Unable to select database");
This section requires a bit more explanation. To start off with, the "<?" tag tells the server that a section of PHP code is beginning here, rather than have it try to interpret it as HTML. The code then begins below that. Note that each line of PHP code is ended with a semicolon.
We start off with setting up some variables, which are the roughly the same idea as Counters or Strings in MMF in that they're an item of data with a name and an assigned value, string or object. The four lines to begin with set up four variables (variable names begin with $ characters in PHP) and give them the values on the right hand side of the equals sign.
In place of yourservice, yourusername, yourpassword and yourdatabase, you'll need to enter your own information. This can usually be found somewhere on your host's control panel or in the email that you received when you signed up for the service - look for a subsection with SQL information. The username and password are pretty self-explanatory, the service is the address that's often given as the "SQL hostname" or similar name (for example, my Byethost account's address is sql1.byethost9.com) and the database is the name of the database that you set up in the step before this one. (Note that it's the name of the database, and not the table - we select that later.)
The next two lines get ready to make requests to the database, using the values of the variables we set up. The actual meaning of them isn't something we need to go into too far at the moment - the last section is a safeguard message to display if for any reason the page can't connect to the database.
$query = "SELECT * FROM buttonscores"; $result = mysql_query($query); $num = mysql_numrows($result);
Now we're ready to get information from the database. As I said before, SQL is command driven, so we can get data from it by sending a string of text to the server (the actual query is the string we give to $query, and you should replace "buttonscores" with the name of the table you set up in the database if it's different). The query selects all the columns of all rows from the table and returns them in a form that our page can use.
The next two lines store the result given by the database, and the number of rows that are in that result. We'll use these variables to display the data on the page.
Here's the next section of the code:
?> <table> <tr class="header"><td>Pos</td><td>Name</td><td>Score</td><td>Date Submitted</td></tr>
The closing "?>" tag at the beginning of this section indicates that we're stopping writing PHP and putting in some plain HTML again. This time, it's the tags that set up the table. We only write out the titles for the table columns here, because the actual data is going to come from the database - and that's what we're going to put in next.
This last section is the most important part of the page:
<?
$loopindex = 0;
while ($loopindex < $num) {
$thisname = mysql_result($result, $loopindex, "name");
$thisscore = mysql_result($result, $loopindex, "score");
$thisdate = mysql_result($result, $loopindex, "datesubmitted");
$thispos = $loopindex+1;
echo ("<tr><td align=left><p>$thispos</p></td>
<td align=center><p>$thisname</p></td>
<td align=center><p>$thisscore</p></td>
<td align=center><p>$thisdate</p></td></tr>\n");
$loopindex++;
}
?>
</table>
</body>
</html>
This is the section that retrieves the data from the result that we got earlier and lays it out in the HTML table that we started above. It does this by using a "while" loop, which will continue executing the code between the { and } braces until the condition we specify is no longer true. In this case, we set up a loop counter that is added to on each pass of the loop (that's what the "$loopindex++" line does - it's a shorthand way of saying "Add 1 to "$loopindex") and only stop when the counter is above the number of rows that were returned by the SQL query - the value that we're storing in $num. On each loop, one row of the results table is examined.
The first section of code within the loop assigns the values of the row with the number $loopindex into new variables (to make things easier when we write out the HTML to display them). The $thispos variable is one more than the number of loops we've made so far. After that, the "echo" command writes out its contents to the page, creating a table row with the data we got from the database. After the loop has run the number of times we need it to, we finish off the page.
Take the completed file and upload it to your webspace however you need to - either through an FTP program or the web-based file manager provided by your host. (Remember to check any requirements on your host - for example, pages on Byethost need to be uploaded to the htdocs/ folder for them to appear). Then navigate to the page in a browser, and view the results. It should look something like this (taken from the example at http://clicktutorial.byethost9.com/displayscores.php):

If you get a PHP error message, make sure you've copy and pasted correctly, closed your brackets and quotes, and so on - PHP can provide some quite misleading error messages. There's a complete page example provided in the "code" folder with this tutorial if you want to make sure you've got the code right.
Also have a look at the source of the page (View/Source in most browsers). None of the actual code we've written is displayed at all - instead, what you get is the HTML that our program was set up to write.
The page now reads data from the database, arranges it and displays it on a page. (Of course, you'd probably want to put some extra styling into your page if this were to be part of a website). However, one of the obvious features of a high score board is that it arranges the data in order starting with the highest score at the top. To arrange the data in this way, you need to modify the query that you make to the database. Find the line that starts with $query and change it to look like this:
$query = "SELECT * FROM buttonscores ORDER BY score DESC";
This addition to the query string will sort the results by score, in descending order (so that the highest is at the top). Save and reupload the file, and your scoreboard will be in the correct order.
.: Writing a page to store scores in the database :.
We can now get information out of the database, so the next step is to also be able to put something in without going into the database. Because we can't access the database directly from an MMF application, we have to write another PHP page to take the data and pass it on to it. This time, we don't need to output anything to the HTML document until after we've decided the outcome of the program, so it starts like this:
<? $name = $_GET['name']; $score = $_GET['score']; $service = "yourservice"; $username = "yourusername"; $password = "yourpassword"; $database = "yourdatabase"; mysql_connect($service, $username, $password); @mysql_select_db($database) or die( "Unable to select database");
This section is much the same database connection code as we had before (remember to change the strings to your own service, username, and so on again). The part of the code that's new is at the top - we get the contents of $_GET['name'] and $_GET['score'], and put them into variables. These lines make it possible for our page to use data that has been passed to the browser via the URL in the address bar - I'll explain details of how later.
if ($score > 0) {
$query="INSERT INTO buttonscores
VALUES ('null', '$name', '$score', CURRENT_TIMESTAMP)";
$result=mysql_query($query);
echo("Score submitted! Name: $name, Score: $score");
}
else {
echo("No score was submitted");
}
?>
This is our query to the database. It should look familiar from a couple of sections ago - it's virtually the same as the query that we used while setting up the initial rows in the database, with the actual values replaced with the $variable placeholders. The echo line after this just prints out a confirmation, so that we aren't just looking at a white screen when we test this in the browser.
The whole thing is encased in an "if" block - this only lets the query perform if score is greater than 0. If the score isn't greater than 0, the code in the "else" block will be interpreted instead, and in this case, an error message will be displayed instead.
Save this file under a name like "submitscore.php" and upload this page to your host. It's best to test it from outside the application first so that we know it'll work, and we can do this using your normal Internet browser. Navigate to the address you uploaded the page to and make sure you get the "No score was submitted" error message - this will appear because we haven't given the page the two items of data that it was expecting at the start of the PHP code.
We're going to use a GET string to pass the data we want into the page. Doing this is quite simple, and you'll have seen it done on many sites before - a question mark character is added to the end of the page address, followed by a list of variable names and their values, separated with equals signs and with ampersands between them. For example, this is what appears in the address bar of my site if you're looking at the scores for the Computer Centre level of Special Agent in Alt Mode:
http://www.davidnewton.co.nr/agent/displayscores.php?level=Comp&type=1
The page that I have at this address looks for the shortened name of a level under "level" and the type of game under "type" so that it can tell which scores to display (like the page we just wrote, the $level variable is used as part of the query string). In this case, level is "Comp" and type is 1.
So in our situation, we want to give the variables "name" and "score" values (as those are the ones that we retrieve with the $_GET['$name'] and $_GET['$score'] expressions in the code). Go to your page again, and this time, add the following to the end of the address (or use your own values!):
?name=David+Newton&score=99999
This time, you'll get the confirmation message that your given values were put into the database. Go back to the "displayscores.php" page and you'll see that it's been added to the list.
Again, if you can't get this to work, a sample file is provided in the "Code" folder under the name "submitscore.php".
.: Getting the game to send a score :.
Now that we have the script that accepts and stores data from an outside source, we can finally set up the MMF application we created to pass data to that script and submit a score to the database. We're going to do this using the MooSock object, which comes with MMF2 and is one of the most common ways to get Internet communication working with Click software.
Open up the game we started earlier, and add a new MooSock object. Click OK to the setup dialog and place it anywhere in the frame. It's also helpful if you add another String somewhere so that we can show the state of the connection - I'll call this the Status string. Finally, add one more Edit box to the frame so that we can see the response from the page. Make this a little bigger, check "Multiline" and "Vertical scrollbar", and call it "Response".

Now go into the Event Editor.
If you haven't seen it before, use Compare Two General Values to make the second condition. The Len() expression is used to get the length of a string, and we check that its length is above 0 because we don't want the player to be able to send a blank name.
Port 80 is the HTTP port, so using this number means that we can send and receive data in the same way as a webpage would. Remember to replace "youraddresshere" with the address of your host, before any folders or filenames. It's also important to miss out the "http://" at the beginning of the address. For the example that I've been making, the address to put here is:
clicktutorial.byethost9.com
That's the address of the site, without any folders at the end or protocol information at the start. And the reason to disable the button after clicking it is to prevent the user from submitting the same score twice.
Once the connection has been made, we need to send data to the page we wrote.
That's quite a lot to digest, so I'll go through it - we send data to the page in the form of a number of lines of text - the first for the actual sending and the others to describe the data that we're sending so that it can be interpreted correctly. The first line builds up a GET string in exactly the same way as we were doing in the browser earlier - the value for "name" is the contents of the Edit box, and the value for "score" is the value of the Counter (turned into a string with Str$() here).
The other lines provide additional information to the page about the nature of the request that we're sending. The "From:" line can contain pretty much anything - as it's an HTTP request, most hosts shouldn't restrict this.
Now that we're listening for a response on port 80, we need to deal with the response.
After that, disconnecting is much easier:
Run the whole application and you'll be able to submit a score to your database - enter a name and click Submit, and after a few seconds pause, the Edit box will show the output received from the page you pointed it to. (If it's a large HTTP error that you get instead of the expected response, try using POST instead of GET in the first text line you send from the MooSock object - some servers are picky about this. Also, make sure that the address you've pointed the object to is the correct one.) If you want to see the results, look at your displayscores page online again and you'll see the added row.
In a finished application, you'd probably want to hide the Response box from the user's view and only use it for testing, or as somewhere to store a result that you can read elsewhere. We'll be using the data from the box in another example later on.
This is all you need in order to send and receive data from an online database, though in the end you'd probably want the score display code to be incorporated into part of a larger page on a site. For details on how to do this, it's best to read some PHP, HTML and SQL tutorials and learn how to perform more complex queries and displays.
Frame 2 of the example MFA shows the above simple submission frame. Code for displaying and receiving the scores is provided in the code/ folder.
.: Timeouts :.
Depending on your Internet connection, it might not be immediately obvious to test this, but you might have noticed that if for any reason the application can't make a connection to the website, it will keep trying indefinitely, effectively sticking your application (though it doesn't hang it, as MooSock only prevents the application from receiving other inputs when it's actually got a connection). It's often a good idea to put some sort of limit on the time that it will attempt to connect, so that you can prompt the user for what to do about it. We can do this entirely from within the application.
We need to keep track of how long the MooSock object has been attempting to connect, and display an error message if it takes too long. I'm using a time limit of ten seconds (500 game frames) here, and as the Button object has alterable values available it seems an ideal place to use as a counter. Create a new alterable value on the Button object called "Timeout", then do this to your first event:
This gives us a flag that we can use to detect to begin the timeout test. Now we need to add two more events:
Now, the application will detect when it hasn't got a connection after 500 frames (ten seconds at frame rate 50), and cancel the connection attempt if that happens. There's one more thing we need to do here:
Adding that action to the disconnection event will signal that there's no longer a need to keep a count of how long we've been waiting to connect.
And that's all that's needed - the MooSock object will now be signalled to give up if it can't find a connection within ten seconds, and will give the user the opportunity to re-submit.
These events are demonstrated on frame 3 of the example MFA.
.: Adding security :.
This section requires a full version of MMF2 with the Bonus Packs installed as it uses the String Parser object.
At the moment, the page that we set up can be accessed by anyone who knows its address. While anyone who accesses the site directly from a browser would also need to know the names of the variables we were expecting to come in to the page, those aren't very difficult to find out if you're determined enough. Now that we know the page that adds scores works, we can add some security to the page to avoid the possibility of people entering scores directly from a browser like we were doing earlier.
We're going to do this by passing an MD5 hash to the page along with our data. An MD5 hash is a 32-character hexadecimal number that is computed from another set of characters - in this case, our input is going to be the combination of the name and score provided, along with a password. Once the page receives all three of the inputs - the name, score and the generated MD5 code - it's going to encode the name and score in the same way and make sure that the code that it works out from them matches the one that was received.
Modify the top of your "submitscore.php" file:
<? $name = $_GET['name']; $score = $_GET['score']; $receivedmdfive = $_GET['mdfive']; $computedmdfive = md5($name . $score . "spuds");
The first added line should be obvious - it puts the value of the "mdfive" from the GET string into a variable. The second line calculates another MD5 hash from ($name . $score . "spuds"), which is PHP's way of writing "The text of 'name' with the text of 'score' added on to the end, and the words "spuds" added on to that". The "." symbol is used in much the same way as you would use "+" to concatenate strings together in MMF. For example, with our "David Newton" and "99999" sample, the resultant string would be "David Newton99999spuds". The reason for adding the password "spuds" to the hash is that it's something else that someone trying to get past the security needs to work out, rather than simply performing an MD5 hash on his name and score. Replace it with a password of your own.
Now we need to check that the two MD5s match before allowing the score into the database. All that needs to be done here is adding it as a condition to the "if" block:
if (($score > 0) && (strcmp($receivedmdfive, $computedmdfive) == 0)) {
$query="INSERT INTO buttonscores
VALUES ('null', '$name', '$score', CURRENT_TIMESTAMP)";
$result=mysql_query($query);
echo("Score submitted! Name: $name, Score: $score");
}
else {
echo("No score was submitted");
}
?>
I've placed brackets around each of the two separate conditions we're testing to make things clearer, though they're not strictly necessary. The strcmp() function compares two strings and returns 0 if they're equal, so we're checking for its result being zero here. Upload the new file to your webspace.
Now we need to modify the game to submit the score in the manner that our page expects. For this, we need to use the String Parser object to compute an MD5 within the program, so add one to your frame and go into the Event Editor.
The procedure for submitting a score is now a little different:
With these small changes - looking for a generated password in the PHP page and allowing the MMF application to provide one - you've made the page a lot more secure. If you navigate to your new score submission page in a browser and try the same trick as before (adding ?name=myname&score=100000 to the end) then it should refuse to add it. This security isn't infallible - it's just a matter of using a known algorithm to generate a code - but it certainly makes it more difficult to cheat at your high score board.
Frame 4 of the example MFA is a submission frame that uses the secure method of posting scores. The PHP file is in the code folder as "submitsecurescore.php".
.: Coping with spaces :.
One problem with the security method I described above is that strings with non-alphanumeric characters in them might not be sent as a URL entirely as you see them. For example, space characters may become "%20" when URL-encoded, meaning that the names on each side of the process (the site and the application) will be slightly different - and this will make the MD5 hash also different, causing it to fail.
A way to get around this is to examine the string before it's sent and to convert all space characters to underscores (_). These will be the same when converted to a URL. In order to do this, we need to cycle through the string before we send it, and the easiest way to do this is with a fastloop. If you aren't familiar with them, this isn't going to be an incredibly involved one - all you need to know here is that they allow you to repeat events rapidly with a loop counter increasing each time. It's almost exactly the same as the "while" loops that we wrote in PHP earlier.
When the Submit button is pressed, we need to loop through the string entered in the Edit box and replace spaces when we find them. The number of loops is equal to the length of the string, so we have one for each character. The comparison is done by using a combination of the Mid$(), Left$() and Right$() expressions to break the string down into smaller strings.
First of all, Mid$() will give us the string of a specified size starting from a certain character. When the string starting at a certain character and going on for 1 character is equal to " " (a space), we want to replace it. The loop index at this point will be equal to the position of the string that holds the character that we're examining.
To replace this space character, we need to replace the whole string with everything before the space, then "_", then everything after the space. Left$ and Right$ help us here by getting a specified number of characters from the beginning and end of the string. To get everything before the space is simple - it's the number of characters equal to the loop index we're on just now. After is slightly more difficult - it's the total length of the string minus the number of characters we've looped over already (and subtracting 1 from this, as we don't want to include the character we've just replaced).
This is the complete event.
It really isn't as bad as it looks, it's just the syntax and repetition of "loopindex" that make it look that way - a diagram may help.

With this event, spaces will be replaced with underscores before the name is sent to the scoreboard.
Frame 4 of the example MFA performs this string conversion.
.: Displaying the scores in-game :.
We're now going to make more use of the idea that the PHP page can return data to your application, rather than just printing a confirmation or error message. This time, we want to use it to display the current contents of the high score table inside the application itself.
First we need to set up the PHP page to do this. Copy and paste the code that we used for "displayscores.php", as we want to do virtually the same thing here but send back a string that the application can understand rather than display it on a page. Call the new file "returnscores.php", remove all the HTML tags around the PHP section and change it to look like this:
<?
$service = "yourservice";
$username = "yourusername";
$password = "yourpassword";
$database = "yourdatabase";
mysql_connect($service, $username, $password);
@mysql_select_db($database) or die( "Unable to select database");
$query = "SELECT * FROM buttonscores ORDER BY score DESC";
$result = mysql_query($query);
$num = mysql_numrows($result);
$loopindex = 0;
while ($loopindex < $num && $loopindex < 10) {
$thisname = mysql_result($result, $loopindex, name);
$thisscore = mysql_result($result, $loopindex, score);
$thisdate = mysql_result($result, $loopindex, datesubmitted);
echo ("$thisname|||$thisscore|||$thisdate|||");
$loopindex++;
}
?>
That's pretty much the same as the original file, though with a different "echo" line that puts the values into a continuous string separated by three pipes (|||). We want to limit the returned results to ten entries, so a new condition has been added to the while loop. We also no longer need to keep track of "$thispos", so all references to that have been deleted.
Upload this page to your webspace and navigate to its address, and you'll see the output that would usually be put into the table in "displayscores" as one continuous string. This string is what we want our application to pick up - then we'll do the actual parsing and display of it within the application.
Now create a new frame in the application - this will be our scoreboard display page. Admittedly I've boxed myself into a corner a bit here by making my application window so small, and it's difficult to get ten scores, names and dates on the page without squashing everything in, but a decent layout would be something like this.

The headers for each part of the table, the contents of each column and the list of position numbers on the left are all separate String objects. The most important ones are the non-bolded contents of the table. As you'd expect, I've called them "Names", "Scores" and "Dates". Then you just need an Edit Object to store the returned string (called Response again), a status string to let us know what's going on, and a Moosock object.
First of all, we need to set up this page to receive the string generated by the PHP page that we just wrote. This is done in a very similar way to score submission, as it's the same idea of sending a request for a webpage and receiving the data that comes back from it. No parameters are needed, so the line to send with the MooSock object is much simpler.
Run the application from this frame and see what it does. If all goes well, you'll see the string generated by our PHP page dumped into the Edit box. The next stage is to actually interpret it, and for that, we need the String Parser again. Put one into the frame and modify the events to get ready to display the scores:
What we're doing here is setting up the string parser to examine the string that was sent back from the page, and getting it to expect that all items of data will be separated by three pipes as we wrote in the page ("|||"). As you can see, we're going to go through the string using a fastloop.
Now, I should explain this next event before I write it out. By adding the delimiter to our string parser, we've created a continuous string of different data items. Our data items - name, score and date - come in groups of three, and we want to add these in order into the Names, Scores and Dates strings. So we need to add three to our "current" position, and look at (our current position+1) and (our current position+2), putting them all into the right columns, each time.

To complicate things further, the String Parser starts counting its elements from 1, but loops begin from 0. So instead of using (loopindex*3), (loopindex*3)+1, (loopindex*3)+2 as I have in the diagram, we have to add 1 to each of them to take account of that.
If all that's meaningless, just put these into your events.
They may look complex but actually perform quite simple actions - to add the right element of the String Parser object to the columns in turn by looking at it in the same way as I've put in the diagram above, then adding a new line character to the end of the string so that the next data item begins at the right place.

Frame 5 of the example MFA retrieves, parses and displays the top ten scores from the online database.
.: Conclusion :.
That's the end of this tutorial - you now have the means to send and receive scores from an online database from within an MMF application. You can make the mini-game we've just built complete by sending the player to the high score board frame we've just made after a score has been submitted, and providing a "Try again" button or something similar.
This technique isn't limited to only scores - you can send and receive any form of data between an application and site, giving the possibility of keeping track of player accounts, running totals, or just getting your game to use any kind of information from a website. If you want to take it further, read up on some PHP and SQL tutorials to see what the possibilities are.
The database and example pages that I used for this tutorial are going to stay up at http://clicktutorial.byethost9.com for as long as my account there exists - the link to the score-displaying page can be found on the section for this tutorial.