Tuesday 18 October 2011

Game Development - High Score Leader Boards in Flash

One way of increasing the repeat appeal of a game, particularly for 1 player games, is to include a leader board of high scores. This gives the player an additional goal of beating their previous best score, allowing them to compete with themselves, and other players, even if the game has only 1 player mode.

As long as your game stores the player's score under the variable "score" this example should provide a good starting point for your own leader board or high score board.

In this example I am using ActionScript 2.0 in Flash.

The Code

The code for this is split into 3 parts. First we create a multidimensional array for keeping the scores and player signatures. Second, we store the score from the game, third we create the leader board that transfers data in and out of the array.

Part 1 - Create a Multidimensional Array

In my game the leader board only shows the top 10 scorers. For each one it displays the score and a 3 character signature from the player.

Before we can store data we need to create the place to store it. In this case I am using a multidimensional array. Multidimensional because I want to store 10 elements (1 for each of the top 10) with 2 data elements (score and signature) per player. Doing it this way allows me to sort them later based on score so I can display them from highest scorer to lowest scorer.

My approach was as follows:

/*NEW ARRAY*/
/*Make a new array object*/
var leaderboard_array:Array = new Array ();
/*'Push' data elements onto the array*/
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});

This code must run only once, run it again and you will add to the end of your array, eventually making it huge.

In effect we create an array of 10 elements, that each contain an array of 2 elements. An array within an array. Using the approach I have, where I have named each 'sub'-element "initials" and "score" means that later I can refer to these directly by name - which makes coding a bit easier to do and debug.

My new array includes pre-coded default values, this means something will display the first time and we don't get a blank leader board.

Part 2 - The Game

Your game is your own. The important thing is that you store the players "score" at the end of the game.

Because the my_array.sort(Array.NUMERIC)in Flash does not work correctly (see here), we cannot use strict datatyping  when we define our variables. So, when you first define the "score" variable, all you need to do is:

var score = 0;

Don't do:

var score:Number = 0;

Or the code won't work later, when we have to treat "score" as a string for sorting.

When the game is over, just make sure you store the player's score in the "score" variable, e.g.:

score = endgamescore;

Part 3 - The Leaderboard

At this point we have an array, and a "score". In this part of the program we need to do the following as essential elements.

a. Test whether the player's latest "score" is greater than the lowest score on the current leader board.
b. If it is, allow the player to input a 3 character signature and store it, along with the "score" in the array replacing the previous lowest score.
c. Sort the array by score so each one is listed in order of greatness.
d. Display the contents of the array in text box to show the leader board to the player.

There is more to it than that, especially since sorting numerically in Flash is not actually possible by direct means - I have gone into detail on that on another post - so much of the code is required to solve that problem.

The following code relies on the stage containing:

1. A text input box with the instance name "initials_txt"
2. A button with the instance name "button_btn"
3. A dynamic text box with the instance name "lb_txt"

The code is then as follows:

/* vars */
/* strict datatyping is off for score and sortscore in order to sort it due to restriction in Flash */
var sortscore = 0;
var initials:String = "";
/*set character limit on input text*/
_root.initials_txt.maxChars = 3;
/*PRE-POPULATE LEADERBOARD WITH CURRENT DATA FROM ARRAY*/
for (var i = 0; i < leaderboard_array.length; i++) {
    _root.lb_txt.text += leaderboard_array[i].initials + " " + leaderboard_array[i].score + "\n";
}
/*ADD NEW SCORE ON SUBMIT*/
_root.button_btn.onPress = function () {
    /* get player name value*/
    initials = _root.initials_txt.text;
    /*convert score to decimals ready for correct sorting*/
    sortscore = score / 10000;
    /*convert score values in array to decimals ready for correct sorting*/
    for (var i = 0; i < leaderboard_array.length; i++) {
        leaderboard_array[i].score = leaderboard_array[i].score / 10000;
    }

    /*sort current board by score - low to high*/
    leaderboard_array.sortOn ("score");
    /*if player score is higher than lowest score on board, replace it with player score and name*/
    if (sortscore > leaderboard_array[0].score) {
        _root.leaderboard_array[0].initials = initials;
        _root.leaderboard_array[0].score = sortscore;
    }
    /*sort again to position the new score and initials correctly in order compared to other scores in array*/
    leaderboard_array.sortOn ("score");
    /*convert all the 'decimaled' scores back again to real scores*/
    for (var i = 0; i < leaderboard_array.length; i++) {
        leaderboard_array[i].score = leaderboard_array[i].score * 10000;
    }
    /*reverse the order of the array to show scores from high to low*/
    leaderboard_array.reverse ();
    /*clear existing text from the leader board text box*/
    _root.lb_txt.text = "";
    /*print new array content to the leader board text box*/
    for (var i = 0; i < leaderboard_array.length; i++) {
        _root.lb_txt.text += leaderboard_array[i].initials + " " + leaderboard_array[i].score + "\n";
    }
};

That's the main thrust of it - read the comments in the code to see what each lump of code is doing. Of course there is scope to develop on this yourself, but I hope this helps. Happy leader board-ing.