Remembering best times and adding some final styling
The game is now pretty playable as it stands. We can shuffle the pieces, only allow them to be dragged according to the rules, and the game will detect when the puzzle has been solved. Using a simple timer we can tell the player how long it took for them to solve it, but then what? What is the player supposed to do, just remember his/her best score?
Of course, we now need a way to save the player's best time. It would also be handy if we could display an additional message if they beat their stored best time. We'll use the JavaScript localStorage API to store the best time.
We can also add a little extra styling to finish the appearance of the game and lay out the different elements a little better.
Prepare for Lift Off
The steps that we'll cover in this task are as follows:
Checking whether a best time has been saved
Checking whether the current best time is better than the saved best time
Updating the saved best time when the current best time is better than it
Displaying an additional message when the saved best time is beaten
Tidying up the presentation of the game with CSS
Engage Thrusters
Everything we need to do in this task can be done in the if
statement that is executed once the pieces are back in the correct order. Directly after where we displayed the congratulatory message in the last task add the following code:
var totalSeconds = (currentTime.hours * 60 * 60) + (currentTime.minutes * 60) + currentTime.seconds; if (localStorage.getItem("puzzleBestTime")) { var bestTime = localStorage.getItem("puzzleBestTime"); if (totalSeconds < bestTime) { localStorage.setItem("puzzleBestTime", totalSeconds); $("<p/>", { text: "You got a new best time!" }).appendTo("#ui"); } } else { localStorage.setItem("puzzleBestTime", totalSeconds); $("<p/>", { text: "You got a new best time!" }).appendTo("#ui"); }
We already created the style sheet that we'll use for this – sliding-puzzle.css
, so we just need to add the following selectors and style rules to this file:
#puzzle { width:730px; padding:5px; margin:auto; border:1px solid #aaa; border-radius:5px; background-color:#eee; } #puzzle figure { width:510px; height:676px; border:1px solid #aaa; position:relative; float:left; background-color:#fff; } #ui { padding:10px 0 0 10px; float:left; } #ui button { margin-bottom: 2em; } #ui p { font-size:1.7em; } #start { width:204px; height:50px; font-size:1.75em; }
Objective Complete - Mini Debriefing
First of all we convert the current time into seconds so that we have only a single value to work with and store. The seconds are calculated using the hours
, minutes
, and seconds
properties of the currentTime
object used to update the visible timer on the page.
The hours
property is multiplied by 60
to convert to minutes, and then by 60
again to convert to seconds. The minutes
property is multiplied by 60
a single time, then these two values are added to the seconds remaining in the seconds
property to give the final total, which we store in the totalSeconds
variable.
Next we check the localStorage to see if a key exists with the name puzzleBestTime
. If it does, we store the value held in localStorage
in the bestTime
variable. If the value of our totalSeconds
variable is less than the bestTime
variable, we have a new high score, which we save in localStorage with the puzzleBestTime
name in order to overwrite the old best time. We then display a second congratulatory message to say a new high score has been achieved.
If localStorage doesn't contain a key with this name, this must be the first time the game has been played in this browser, so we set the name of the key and store the value of the currentTime
variable as the new best time, and again display the second congratulatory message.
There's nothing really crucial in the CSS that we added; it was just a little bit of light styling to tidy up the various elements we've used and present the game in a cleaner style.
Classified Intel
The localStorage API is one of the more stable JavaScript APIs that fall within the general umbrella term of HTML5, and enjoys wide support by all of the latest versions of all common browsers.
Old browsers, which we may still need to support, such as IE7 or Firefox 2, do not support localStorage. Luckily there are plenty of polyfills and workarounds that exist to add a basic level of support in these legacy browsers.
See https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills for a wide range of polyfills and patches that add support for modern APIs to legacy browsers.