We know how to store data in an array and dictionary and how to show them onscreen, great! However, there's one thing to keep in mind when working with arrays and dictionaries: they will lose their values when the game is closed. The players might close the web browser window. Whenever they do this, they close the game, and the game will not remember the last value you put inside the array or the dictionary.
In most cases, this is not what we want. If we want to keep a score and then compare it to create a leaderboard, we want the game to remember it even after the game is closed. To do this, we need to store the data in the player's computer. So, when we start the game next time, our game can still remember the player's score. How do we do this? Using a WebStorage
object.
WebStorage
does not store data in the browser cache, so if the user wants to clear the browser cache, their data is not lost. However, the WebStorage
data will be lost if they clear the cookies or offline website data. However, on platforms that are not web browsers with an address bar (the Windows 8 app), there's no way for players to delete the WebStorage
data.
Remember that the WebStorage
object associates data with the domain. For example, all games that are hosted on myGamesSites.com
share the same data, but games hosted on facebook.com have different data and can't access data from myGamesSites.com
.
There are two places where a WebStorage
object stores data:
Now, let's use the WebStorage
object to store our data. Insert WebStorage
into your project; we'll add the scores
value to WebStorage
when the player is destroyed, just like the array and dictionary. So, first disable the two events that add a new value to the array and dictionary object, and we'll create a new playerShip On destroyed
event to insert new data to WebStorage
. The way to add a new value to WebStorage
is the same as the way in which we added a dictionary, where it associates a key to a value. So let's create a playerScore
key to store the scores, like this:
This is easy enough, but in order to make a leaderboard, we need to show not only the scores from the latest play session, but also from the previous ones. We will later show all this data to the player by making a leaderboard table. So, for example, if we have 5 game sessions, we want the data in WebStorage
to be like this (the left part is the key, and the right part is the value):
"playerScore1": 50 "playerScore2": 100 "playerScore3": 70 "playerScore4": 20 "playerScore5": 60
The players might play for more than five game sessions, and we want our code to be able to handle this kind of situation. If we use the previous code, the value of the playerScore
key of our WebStorage
object will be changed every time the player dies, because storing another value to a key that already exists will overwrite it. So, what should we do?
First, we'll create a new key on the WebStorage
object; let's call it gameSession
to make it clear that this key will record how many game sessions have been played. We'll create it every time the layout starts to mark the beginning of a new game session. There's a special thing when we create this key; we'll only create it if it isn't created earlier. This way, we won't overwrite the last value of the gameSession
key. We do this using the is local key exists
action of our WebStorage
object and then invert the condition.
After that, let's make a new global variable to add the gameSession
number to the key when we save the value to WebStorage
; we'll call this variable sessionNumber
and make it a string. Why a string; isn't the value that is stored to the gameSession
key a number? Well, it's because unlike a dictionary where you can retrieve text or numbers, all the values you retrieve from WebStorage
are always text.
Now, we have what we need to make our code remember several game sessions, so let's do this. However, first, delete the action when we set the playerScore
local key to our WebStorage
object, because we're going to replace this with a different set of code snippets. When the player is destroyed, we want to retrieve the gameSession
key and store the value in our sessionNumber
global variable. We can retrieve a value using a localValue()
expression and passing the key to it:
After that, we will increment the gameSession
value by one and store it back to WebStorage
so that we can store the score for the upcoming game sessions. We will do this by changing the sessionNumber
variable to a number, incrementing it by one, and storing it to WebStorage
.
The previous code does not change the value of the sessionNumber
variable; we only use its value to change the gameSession
key. Now, we'll store the score to WebStorage
using a key with a sessionNumber
variable added at the end.
The game now stores different scores for different game sessions, and that's great! What is left now is to actually show them in a leaderboard. So now, create a new layout where we'll create the leaderboard and give it the same background as the first layout. We'll add two text objects that we'll use for the leaderboard on this layout; name them highscoreNameText
and highscoreText
to show the key and the score, respectively, in the leaderboard.
At the start of the layout, we'll look at the WebStorage
object and see how many elements it has. For each element, we'll create new text objects to show the key and the score to the screen. Here, we're using another concept in programming that I haven't explained yet: loop
.
What is looping? I explained in Chapter 1, Downloading and Understanding Construct 2, that the code in Construct 2, like in any other language, is executed from top to bottom. So, the code in Construct 2 is run from the first event to the last event without stopping, that is, unless it encounters a loop.
A loop is a block of code that is always executed as long as its conditions are still true. At the end of a loop block, the program will check whether the conditions have been met or not. If not, the execution starts again from the beginning of the loop; if the conditions have been met, the loop ends, and the execution continues to the next code.
I'm sure it's going to be easier to understand when we put this knowledge into practice. We'll do this using one kind of loop: a for
loop. A for
loop is a loop that goes on for a specified number of time; this is specified by its start and end indexes. What we want to do is loop for the total count of members of our WebStorage
object, and then, we will create the two texts to show our leaderboard. A for
loop is used when we know exactly how many times to loop; in this instance, we're looping for the total count of members of our WebStorage
object.
There are three things we need for a for
loop:
The for
loop will increment the loop index by one at the end of the loop and then start the code from the top again. The loop ends when the loop index has reached the end index.
We'll use two WebStorage
expressions in this loop: localAt
and localKeyAt
. The localAt
expression is used to retrieve the value at an index; we can retrieve the value stored in WebStorage
by its index number or by the key. Just like an array, WebStorage
is a zero-based index, so the first member is at index 0, the second one is at index 1, and so on. A localKeyAt
expression will give us the key at a certain index.
Remember that at the beginning of Layout 1
, we created a key called gameSession
in our WebStorage
object. This key will be at index 0, and our playerScore
set of keys will be at index 1, 2, 3, and so on. So, our for
loop will loop from index 1 to the end of WebStorage
.
To define end of WebStorage, we will count the number of local keys stored in WebStorage
and deduct it by one. Why do we deduct it? Because WebStorage
is a zero-based index, but if we count it, we will get the total number of local keys stored, which is not a zero-based index. We will name our loop leaderboard
and use the following code along with it:
Then, we will create the two text strings and put them in the appropriate places. We want the y position of the text strings to increase every time the loop index increases so that the position of the new text is below the last one. After that, we'll change the value of the text strings. One will show the key; we will do this using a WebStorage
expression, localKeyAt
, and we'll supply the loop index to get the key at an index. The other text will show the score; we will do this with the localAt
expression that will give us the value that's stored in an index.
We are now ready to test our leaderboard, but first, we must make the game switch to Layout 2
after the player is destroyed. So, let's go back to the event sheet in Layout 1
and add two more actions. The first one will wait for 1 second before changing the layout, and the second action will change the layout.
Now, test your game. Make sure that you're testing from Layout 1
and not Layout 2
. After the player ship is destroyed, the game will take you to the second layout where you can see a leaderboard similar to the one shown in the following screenshot:
Congratulations! You have made your own basic leaderboard. Other games that use leaderboards also follow similar techniques but use online storage instead of local data like us.