From 664546ef9a44a3cf99a7fd4ae491a98695d16693 Mon Sep 17 00:00:00 2001 From: Tim Petricola Date: Mon, 10 Mar 2014 16:02:16 -0400 Subject: [PATCH 1/3] Store best score in localStorage Dependency injection and hide best score for incompatible browsers --- index.html | 6 +++++- js/application.js | 2 +- js/game_manager.js | 17 ++++++++++++----- js/html_actuator.js | 15 ++++++++++++++- js/local_score_manager.js | 24 ++++++++++++++++++++++++ style/main.css | 21 +++++++++++++++------ style/main.scss | 18 +++++++++++++++--- 7 files changed, 86 insertions(+), 17 deletions(-) create mode 100644 js/local_score_manager.js diff --git a/index.html b/index.html index acb945b..cf017fc 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,7 @@ + @@ -22,7 +23,10 @@

2048

-
0
+
+
0
+
0
+

Join the numbers and get to the 2048 tile!

diff --git a/js/application.js b/js/application.js index 656a88d..036ca3a 100644 --- a/js/application.js +++ b/js/application.js @@ -1,6 +1,6 @@ document.addEventListener("DOMContentLoaded", function () { // Wait till the browser is ready to render the game (avoids glitches) window.requestAnimationFrame(function () { - var manager = new GameManager(4, KeyboardInputManager, HTMLActuator); + new GameManager(4, KeyboardInputManager, HTMLActuator, LocalScoreManager); }); }); diff --git a/js/game_manager.js b/js/game_manager.js index 1880d48..11974c1 100644 --- a/js/game_manager.js +++ b/js/game_manager.js @@ -1,7 +1,8 @@ -function GameManager(size, InputManager, Actuator) { +function GameManager(size, InputManager, Actuator, ScoreManager) { this.size = size; // Size of the grid this.inputManager = new InputManager; - this.actuator = new Actuator; + this.scoreManager = new ScoreManager; + this.actuator = new Actuator(this.scoreManager.isSupported()); this.startTiles = 2; @@ -51,11 +52,17 @@ GameManager.prototype.addRandomTile = function () { // Sends the updated grid to the actuator GameManager.prototype.actuate = function () { + if (this.scoreManager.get() < this.score) { + this.scoreManager.set(this.score); + } + this.actuator.actuate(this.grid, { - score: this.score, - over: this.over, - won: this.won + score: this.score, + over: this.over, + won: this.won, + bestScore: this.scoreManager.get() }); + }; // Save all tile positions and remove merger info diff --git a/js/html_actuator.js b/js/html_actuator.js index f1c3308..b6aec40 100644 --- a/js/html_actuator.js +++ b/js/html_actuator.js @@ -1,9 +1,15 @@ -function HTMLActuator() { +function HTMLActuator(bestScoreSupported) { this.tileContainer = document.getElementsByClassName("tile-container")[0]; this.scoreContainer = document.getElementsByClassName("score-container")[0]; + this.bestContainer = document.getElementsByClassName("best-container")[0]; this.messageContainer = document.getElementsByClassName("game-message")[0]; this.score = 0; + this.bestScoreSupported = bestScoreSupported; + + if (!this.bestScoreSupported) { + this.bestContainer.style.display = "none"; + } } HTMLActuator.prototype.actuate = function (grid, metadata) { @@ -21,6 +27,7 @@ HTMLActuator.prototype.actuate = function (grid, metadata) { }); self.updateScore(metadata.score); + self.updateBestScore(metadata.bestScore); if (metadata.over) self.message(false); // You lose if (metadata.won) self.message(true); // You win! @@ -103,6 +110,12 @@ HTMLActuator.prototype.updateScore = function (score) { } }; +HTMLActuator.prototype.updateBestScore = function (bestScore) { + if (this.bestScoreSupported) { + this.bestContainer.textContent = bestScore; + } +}; + HTMLActuator.prototype.message = function (won) { var type = won ? "game-won" : "game-over"; var message = won ? "You win!" : "Game over!" diff --git a/js/local_score_manager.js b/js/local_score_manager.js new file mode 100644 index 0000000..400633b --- /dev/null +++ b/js/local_score_manager.js @@ -0,0 +1,24 @@ +function LocalScoreManager() { + this.key = 'bestScore'; +} + +LocalScoreManager.prototype.get = function () { + if (!this.isSupported()) { + return 0; + } + + return localStorage.getItem(this.key); +}; + +LocalScoreManager.prototype.set = function (score) { + if (!this.isSupported()) { + return false; + } + + localStorage.setItem(this.key, score); +}; + +LocalScoreManager.prototype.isSupported = function () { + return !!window.localStorage; +}; + diff --git a/style/main.css b/style/main.css index f5760a4..784aeb5 100644 --- a/style/main.css +++ b/style/main.css @@ -49,9 +49,12 @@ h1.title { top: -50px; opacity: 0; } } -.score-container { +.scores-container { + float: right; } + +.score-container, .best-container { position: relative; - float: right; + display: inline-block; background: #bbada0; padding: 15px 25px; font-size: 25px; @@ -60,19 +63,19 @@ h1.title { font-weight: bold; border-radius: 3px; color: white; - margin-top: 8px; } - .score-container:after { + margin-top: 8px; + text-align: center; } + .score-container:after, .best-container:after { position: absolute; width: 100%; top: 10px; left: 0; - content: "Score"; text-transform: uppercase; font-size: 13px; line-height: 13px; text-align: center; color: #eee4da; } - .score-container .score-addition { + .score-container .score-addition, .best-container .score-addition { position: absolute; right: 30px; color: red; @@ -86,6 +89,12 @@ h1.title { -webkit-animation-fill-mode: both; -moz-animation-fill-mode: both; } +.score-container:after { + content: "Score"; } + +.best-container:after { + content: "Best"; } + p { margin-top: 0; margin-bottom: 10px; diff --git a/style/main.scss b/style/main.scss index 5343c6d..96cdc7b 100644 --- a/style/main.scss +++ b/style/main.scss @@ -58,11 +58,15 @@ h1.title { } } -.score-container { +.scores-container { + float: right; +} + +.score-container, .best-container { $height: 25px; position: relative; - float: right; + display: inline-block; background: $game-container-background; padding: 15px 25px; font-size: $height; @@ -72,13 +76,13 @@ h1.title { border-radius: 3px; color: white; margin-top: 8px; + text-align: center; &:after { position: absolute; width: 100%; top: 10px; left: 0; - content: "Score"; text-transform: uppercase; font-size: 13px; line-height: 13px; @@ -100,6 +104,14 @@ h1.title { } } +.score-container:after { + content: "Score"; +} + +.best-container:after { + content: "Best" +} + p { margin-top: 0; margin-bottom: 10px; From fda0e8405fbc912241279fafda59cb03c98f4a48 Mon Sep 17 00:00:00 2001 From: Tim Petricola Date: Mon, 10 Mar 2014 17:18:54 -0400 Subject: [PATCH 2/3] Fix win/over in local --- js/html_actuator.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/html_actuator.js b/js/html_actuator.js index b6aec40..3e51195 100644 --- a/js/html_actuator.js +++ b/js/html_actuator.js @@ -118,9 +118,11 @@ HTMLActuator.prototype.updateBestScore = function (bestScore) { HTMLActuator.prototype.message = function (won) { var type = won ? "game-won" : "game-over"; - var message = won ? "You win!" : "Game over!" + var message = won ? "You win!" : "Game over!"; - if (ga) ga("send", "event", "game", "end", type, this.score); + if (typeof ga !== "undefined") { + ga("send", "event", "game", "end", type, this.score); + } this.messageContainer.classList.add(type); this.messageContainer.getElementsByTagName("p")[0].textContent = message; From d6da8d99251266445beaead0da79f0085756c054 Mon Sep 17 00:00:00 2001 From: Tim Petricola Date: Tue, 11 Mar 2014 11:52:02 -0400 Subject: [PATCH 3/3] localStorage fallback --- js/game_manager.js | 2 +- js/html_actuator.js | 11 ++--------- js/local_score_manager.js | 33 ++++++++++++++++++++------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/js/game_manager.js b/js/game_manager.js index 11974c1..91c0390 100644 --- a/js/game_manager.js +++ b/js/game_manager.js @@ -2,7 +2,7 @@ function GameManager(size, InputManager, Actuator, ScoreManager) { this.size = size; // Size of the grid this.inputManager = new InputManager; this.scoreManager = new ScoreManager; - this.actuator = new Actuator(this.scoreManager.isSupported()); + this.actuator = new Actuator; this.startTiles = 2; diff --git a/js/html_actuator.js b/js/html_actuator.js index 3e51195..36e1d75 100644 --- a/js/html_actuator.js +++ b/js/html_actuator.js @@ -1,15 +1,10 @@ -function HTMLActuator(bestScoreSupported) { +function HTMLActuator() { this.tileContainer = document.getElementsByClassName("tile-container")[0]; this.scoreContainer = document.getElementsByClassName("score-container")[0]; this.bestContainer = document.getElementsByClassName("best-container")[0]; this.messageContainer = document.getElementsByClassName("game-message")[0]; this.score = 0; - this.bestScoreSupported = bestScoreSupported; - - if (!this.bestScoreSupported) { - this.bestContainer.style.display = "none"; - } } HTMLActuator.prototype.actuate = function (grid, metadata) { @@ -111,9 +106,7 @@ HTMLActuator.prototype.updateScore = function (score) { }; HTMLActuator.prototype.updateBestScore = function (bestScore) { - if (this.bestScoreSupported) { - this.bestContainer.textContent = bestScore; - } + this.bestContainer.textContent = bestScore; }; HTMLActuator.prototype.message = function (won) { diff --git a/js/local_score_manager.js b/js/local_score_manager.js index 400633b..95c6966 100644 --- a/js/local_score_manager.js +++ b/js/local_score_manager.js @@ -1,24 +1,31 @@ +window.fakeStorage = { + _data : {}, + setItem : function (id, val) { + console.log('set'); + return this._data[id] = String(val); + }, + getItem : function (id) { + return this._data.hasOwnProperty(id) ? this._data[id] : undefined; + }, + removeItem : function (id) { return delete this._data[id]; }, + clear : function () { return this._data = {}; } +}; + function LocalScoreManager() { + var localSupported = !!window.localStorage; this.key = 'bestScore'; + this.storage = localSupported ? window.localStorage : window.fakeStorage; } LocalScoreManager.prototype.get = function () { - if (!this.isSupported()) { - return 0; + var score = this.storage.getItem(this.key); + if (typeof score === "undefined" || score === null) { + score = 0; } - - return localStorage.getItem(this.key); + return score; }; LocalScoreManager.prototype.set = function (score) { - if (!this.isSupported()) { - return false; - } - - localStorage.setItem(this.key, score); -}; - -LocalScoreManager.prototype.isSupported = function () { - return !!window.localStorage; + this.storage.setItem(this.key, score); };