Creating a Highscore Board


There will be two major sections to our highscore board system. The client-side scripts in our Flash application are the first section. The second section contains the server-side scripts (Perl scripts), which will process, store, and retrieve data on the server.

The highscore system has two primary operations. The first is the ability of Flash to ask for and then be served the current highscore list. This allows the user to view the current highscore board to see who is on top and what that top score is. The second operation happens when the user ends his game. His score must be submitted to the server in case his score qualifies for the highscore board.

To make things easy to follow, I will be referring to the get scores script when I'm talking about the retrieval of the current highscore information from the server. I'll also be referring to the submit scores script when I'm talking about the process of submitting a recently obtained score to see if it qualifies for a spot on the boards .

We'll begin by looking at the Flash scripts for both get and submit . Afterward, we'll look at the pair of Perl scripts that will execute the get and submit routines on the server.

All the sample .fla files, .swf files, Perl scripts, and text files we need for the highscore boards are available in the Chapter 12 directory in a subdirectory called highscoreBoards.

Setting Up Flash for Highscore Boards

To make things as simple as possible, I've created two separate .fla files ”one for each operation we must perform. The first is called getScores.fla, and it contains the highscore listing with a button that requests the list of highscores from the server. The second .fla file is called submitScore.fla, and it contains some text fields where you can enter a name and score. When you click a certain button, it submits the new name and score to the server. You will have the functionality of both .fla files in the same game, but they will likely be separate inside your game. I've chosen to break them into two .fla files for this example to make things as crisp and clear as possible.

The getScores.fla Example

The two key elements in getScores.fla are the large text field and the getButton , shown in Figure 12.8.

click to expand
Figure 12.8: The highscore board has a button that retrieves the scores and a text field that displays them.

When the user clicks the button, it triggers a small piece of code that calls a Perl script residing on the server. The Perl script responds with the highscore data that is automatically assigned to some variables in Flash. The thing to note at this point is that the text field is tied to the variable _root.highScores . Later, our Perl script will use this variable name in its response to assign the highscore data right into the text field for us.

In addition, we need a bit of script to call the Perl script. It's short, so I'm going to show you first and then explain:

 getButton.myText.text = "Get Scores"; getButton.onRelease = function(){      _root.loadVariables("getScores.pl"); } 

As you can see, the first line gives the button some text. Then we define the onRelease handler for the button. Inside the handler is a single line of code that calls loadVariables . Let's look closely at this line of code because it's where all the action happens:

 _root.loadVariables("getScores.pl"); 

In this case, I'm using "getScores.pl" as the URL; getScores.pl is the name of the Perl script we'll be writing later. The Perl script's job is to send Flash the highscore data. Also note that I'm using a relative path here, meaning that the getScores.pl file must be in the same directory as the getScores.swf file for this to work. If you attempt to test this on a Web server, you will likely need to put your Perl scripts in the cgi-bin directory and change the URL in Flash to something like "/cgi-bin/getScores.pl".

Note  

The conventional extension for a Perl script is .pl. This is not a requirement, but a convention so that you can easily identify that Perl is the interpreter required to execute the script.

Tip  

You might have the Perl script sitting on a different domain, in which case you would want to use an absolute path name for the URL, such as "http://www.mydomain.com/cgi-bin/getScores.pl".

That's all there is to this part of the development. You might be thinking, "I thought there would be more to it than that." There is more, but now it's our Perl script that will be doing most of the real work. Before we look at the server-side part, we need to develop a second .fla file to do our score submission.

The submitScore.fla Example

I've created a dynamic text field for you to input a new name for the submitScore.fla. A second dynamic text field is available for you to enter a score. (There is no game to play, so I'm letting you input a new score by hand instead of playing a game to achieve it.) Finally, there is a button that will submit the new name and score. The dynamic text fields are linked to the _root.name and _root.score variables, respectively. The contents of submitScore.fla are shown in Figure 12.9.


Figure 12.9: There are dynamic text fields for a name and score, as well as a Submit button to call the Perl script with the new name and score.

Notice in Figure 12.9 that I have entered some preliminary data into the dynamic fields. This is just to make them easy to see and to allow you to submit a score without entering data. The Name field contains Joe Smith, and the Score field contains 456332.

The code to execute this is going to be similar to what we saw in getScores.fla, but with a few additions. The first thing we need to discuss is the way we send data from Flash to the server, which is something I've been avoiding until now.

When we send data from Flash to the server, the easiest way to do it is with a call to loadVariables . It works like this: You call loadVariables on a movie clip. Then, any variables you have attached to the clip are sent automatically to the server. That means if you call loadVariables on _root , every variable you've attached to the _root timeline will be sent to the Perl script. That is generally not what you want. For one thing, you'll be forced to sort through all that data to find what you're looking for using Perl. In addition, you'll be sending data that the Perl script doesn't need, which wastes bandwidth.

Note  

Only variables that you have attached to the clip will be sent to the server. Built-in properties such as _x and _y will not be sent.

To make sure we're only sending the data needed in the Perl script, my habit is to create a temporary movie clip and attach variables containing the relevant data to that temporary clip. Then I call loadVariables on the temporary clip, and only variables I've attached are sent to the script. This allows me to easily pick and choose which data to send. If I need something sent, I attach a copy to my temporary clip (which I call submitClip ) and then call loadVariables on submitClip . Let's see this in code, beginning with the button setup:

 submitButton.myText.text = "Submit"; submitButton.onRelease = function(){ 

As you can see, I've given the button text and then opened the onRelease handler for that button. Now we need to create the submission movie clip, as follows :

 createEmptyMovieClip("submitClip", 1); 

Recall that our dynamic text fields were tied to the variables _root.name and _root.score . These both need to be copied into the submitClip , as follows:

 submitClip.name = _root.name;      submitClip.score = _root.score; 

Finally, we're ready to send the data. We do this with a call to loadVariables , as I've mentioned. (I'm closing the onRelease handler as well because this completes the function.)

 submitClip.loadVariables("submitScore.pl", "GET"); } 

The important thing in this loadVariables call is that for the first time, we're using a second argument. In this case, the argument is "GET" . The other option would have been "POST" , which is unnecessary in this case. (We'll look at exactly what "GET" and "POST" do in a moment.)

Tip  

You can use a getURL call to send variables to the server as well. The key difference between the two is what happens to the response from the server. loadVariables lets Flash interpret the results; getURL sends the results to the browser window for it to display.

Also notice that this time I'm calling submitScore.pl as the URL because that is the Perl script we're going to write to handle the score submission.

From here, it's all up to the Perl scripts; everything needed on the Flash side is done.

The Difference Between GET and POST

When you're sending data from Flash to the server with loadVariables or getURL , you can use either the word "GET" or "POST" to indicate the method of data transmission. Using "GET" is a little faster, but there is a limit of 256 KB of data that you can send this way. If you have only a couple of variables to send, use "GET" . If you'll be sending a lot of data, use "POST" . The data in a "POST" has no space limitation.

If, as we did in all our early examples, you omit the "GET" or "POST" , no data is sent to the server from Flash. If you have nothing at all to send, as we did in getScores.fla, omit the argument and you'll use up no extra time or bandwidth sending data to the server. This, of course, still allows you to receive data from the server, as we did in getScores.fla.

The Server-Side Scripts

All our Flash is up and ready to go. All we have to do is write a pair of Perl scripts to do the work on the server. This should be largely painless. We'll begin with the easier of the two scripts ”the getScores.pl script ”which is responsible for gathering the highscore data and sending it back to Flash.

The getScores.pl Perl Script

As I said before, we don't have time to get into the specifics of Perl programming, so all I can do is give you a sample script and tell you what is going on line by line. From there, it's up to you.

We begin every Perl program with a line telling the server where to look for the Perl interpreter. In the case of my Web host, the line is as follows:

 #!perl 

It is likely that your Web host will use the more common path of #!/usr/bin/perl . Consult your host to figure out the path to that server's Perl interpreter.

Next , we tell Flash that this data is to immediately expire, so no caching is done:

 print "Expires: -1\n"; 

The following line is necessary in a server-to-client transmission because it tells the client the format of the data. In nearly every case, you will have the following line in your CGI program:

 print "Content-type: text/html\n\n"; 

Our Perl script is going to store the highscore data in a text file on the server. I've chosen to name this file highscores.txt, but you could call yours anything you like. Generally, this file will be placed in the root directory of your Web page, even though the Perl script is going in the cgi-bin directory:

 $filename = "highscores.txt"; 

Now we open the file:

 open(DATABASE, $filename); 

Create an array from the data from the open file:

 @scores = <DATABASE>; 

Now that our array has been created, we can close the file:

 close DATABASE; 

We're ready to tell Flash where this data that we've just retrieved from the text file is going to go. If you recall, we set up a text field with the variable highScores to hold this data:

 print "highScores="; 
Note  

Remember when we loaded a raw text file with loadVariables ? Calling a Perl program is the same except that the Perl program generates the text file on-the-fly . That means the Perl script we write needs to print output in the same format we used for text files for load variables. This was the format of variable names and values separated by an equal sign. Each variable and value was separated from the next by the ampersand character. If you don't remember this format, reread the earlier section on loading text files with Flash.

Now we need to loop through our array and pick apart the data. Later, when we look at the submitScores.pl script, you'll see that we're organizing our highscores.txt file with each score on its own line. The score is followed by a dash (-), which is then followed by the player's name. I have provided a sample highscores.txt file with three scores in it on the CD. Refer to this file if you have any questions about the format of the text file that stores our data on the server.

We open a loop to iterate the array:

 foreach (@scores){ 

We must pick apart the line that contains the score and name separated by a dash:

 @score_entry = split('-',$_); 

We need to get rid of the newline characters that are attached to either the name or the score. (Actually, only the names will have them, but it never hurts to be safe.)

 chomp @score_entry[0];      chomp @score_entry[1]; 

Now we print the number of this score. (Our highscore boards are going to store at most the top 10 scores.)

 print ++$couner . ". "; 

We print the player's name, left justified in a nine-space field:

 printf "%-9s", @score_entry[1]; 

We print the score, right justified in a nine-space field:

 printf "%9i\r", @score_entry[0]; 

We close the array iteration loop and exit the Perl script:

 } exit; 

It's as easy as that! Admittedly, I didn't really explain how the Perl was working, but as you can see, Perl is a concise language. It can be a bit hard to learn Perl, but after you do, you can perform what seem to be incredibly complex tasks in just a line or two of script.

As you can see in Figure 12.10, when the Perl script is used on the same highscores.txt file, we get a listing of the top players.


Figure 12.10: The getScores.fla now works by calling our getScores.pl Perl script.

If you want to test this but have nowhere to place the Perl script (such as a Perl interpreter on your computer or a Web host), you can change the URL in your getScores.fla program to be "http://www.ifinitumdesign.com/cgi-bin/getScores.pl", and a copy of that Perl script will run on my Web server.

Tip  

You can install the Perl interpreter on your computer to test CGI scripts yourself. All major OS platforms have Perl interpreters. http://www.perl.org and http://www.perl.com can get you started.

The submitScore.pl Perl Script

The Perl script for submitting a score is a bit more complex. We have to open the same highscore.txt file that we did in getScores.pl, but we also have to take in the submission data from Flash and see if it qualifies for a new highscore. If it does, we need to add it into highscores.txt at the appropriate place. Finally, if more than 10 scores are listed, we need to remove the last one.

We begin submitScore.pl like we did our previous Perl script, with a path:

 #!perl 

Now we give the same expiration and formatting that we did in our previous Perl script:

 print "Expires: -1\n"; print "Content-type: text/html\n\n"; 

The following line grabs the incoming data and puts it in a variable:

 $data = $ENV{'QUERY_STRING'}; 

We need a couple lines of what will most likely look like gibberish. When text is sent from Flash to the server and back again, Flash has to encode the data in a special way. Flash automatically removes this encoding when it receives data from the server, but Perl does not. We manually decode the incoming text:

 $data =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("C",hex())/eg; $data =~ tr/\+/ /; 

Now we need to break the data into each variable and value pair. (Flash will have combined them with ampersands in between.)

 @pdata = split("&",$data); 

We need to break apart each variable value pair by its equal sign separator and store it for later use:

 foreach(@pdata){      ($k, $v) = split "=",$_;      $i{$k} = $v; } 

At this point, we've converted the incoming data into exactly what we need. We're ready to open the highscores.txt file and read in the current highscore data. We did the same thing in the previous Perl script:

 $filename = "highscores.txt"; open DATABASE, $filename; @scores = <DATABASE>; close DATABASE; 

Now we have an array called scores that contains all the data from the highscores.txt file. From here, we will add the incoming highscore (from client) to the end of this array:

 push @scores, $i{'score'} . '-' . $i{'name'} . "\n"; 

We need to sort this array in Perl with the following line:

 @scores = sort {$b <=> $a} @scores; 

At this point, we've added the newly submitted score to our database of scores and sorted it such that it will be in the correct place in the order of highest to lowest scores. We're ready to reopen our highscores.txt file so that we can update it with the new data:

 open DATABASE, ">" . $filename ; 

Now we want to write out the scores. At the most, we want to write out the top 10 scores. This gives us the following for loop:

 for($index=0;$index< 10;++$index){      print DATABASE @scores[$index]; } 

That completes the necessary work, so we close and exit Perl script:

 exit; 

Again, I know my explanation was brief, but with a little tenacity and some good reference materials, you can develop your own Perl scripts to do whatever you need done.

For space considerations, I'm not going to list these Perl scripts in a big code dump. Both scripts are available on the CD in the Chapter 12 directory (highscoreBoard subdirectory) if you need to look at the code in context or if you want to alter them for your own needs.

Despite the fact that one Perl script receives data from the client and a separate Perl script sends data to the client, you can use one script to do both if that is most convenient for you. That was not the case for these particular highscore boards, but often it will be. Don't be afraid to write a Perl script that receives data from the client, processes, and then responds to the client with some data.

Final Tips on Highscore Boards

When you are developing and implementing your own highscore boards, you need to keep a few things in mind. To start, Flash cannot be secured. That means that no matter what you do, it is possible for someone to call your CGI script by hand and feed in a fake highscore. You can do some things to make it harder on the potential cheater, but nothing can completely protect you. The first task can be to protect your project from import in the publish settings. This makes it harder for the cheater to figure out where your Perl script lives and what its name is.

Consider, too, how many slots you want to use in the highscore board. In this chapter, we used a maximum of 10, but you could have an unlimited highscore board if you wanted to, letting the user flip through pages of scores with Next and Previous buttons you provide.

Also, you'll need to be careful to build your submission routines so that the user cannot double-click the Submit button and double-submit a score. You can do this pretty easily.

As cool as a highscore board can be, you'll get many people who use poor taste in a username on your boards. You can fix this problem by building in censorship. It would actually be quite easy for someone proficient to do this in Perl. I would suggest a separate Perl script to validate a username that is called when the user enters his name. Using Perl's regular expressions (which we did to break apart our user data in submitScore.pl), you could build a file of unacceptable words (which you could find on the Internet) and then search for them as substrings in the username.

In any event, the key is to develop good CGI scripts so that you don't have to do maintenance to the highscore.txt files after the boards go up on your site.




Macromedia Flash MX 2004 Game Programming
Macromedia Flash MX 2004 Game Programming (Premier Press Game Development)
ISBN: 1592000363
EAN: 2147483647
Year: 2004
Pages: 161

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net