diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..7cec603
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..e44e865
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ endg-2048
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/assets/js/application.js b/assets/js/application.js
index 2c1108e..46b9d34 100644
--- a/assets/js/application.js
+++ b/assets/js/application.js
@@ -1,4 +1,6 @@
// Wait till the browser is ready to render the game (avoids glitches)
-window.requestAnimationFrame(function () {
- new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
+window.requestAnimationFrame(function (){
+ let storage = new RemoteStorageManager;
+ new GameManager(4, new KeyboardInputManager, new HTMLActuator("game1"), storage, "game1");
+ new GameManager(4, undefined, new HTMLActuator("game2"), storage, "game2");
});
diff --git a/assets/js/game_manager.js b/assets/js/game_manager.js
index 7160285..7b9a036 100644
--- a/assets/js/game_manager.js
+++ b/assets/js/game_manager.js
@@ -1,21 +1,24 @@
-function GameManager(size, InputManager, Actuator, StorageManager) {
+function GameManager(size, InputManager, Actuator, StorageManager, game){
this.size = size; // Size of the grid
- this.inputManager = new InputManager;
- this.storageManager = new StorageManager;
- this.actuator = new Actuator;
+ this.inputManager = InputManager;
+ this.storageManager = StorageManager;
+ this.actuator = Actuator;
+ this.game = game;
this.startTiles = 2;
- this.inputManager.on("move", this.move.bind(this));
- this.inputManager.on("restart", this.restart.bind(this));
- this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));
+ if(this.inputManager){
+ this.inputManager.on("move", this.move.bind(this));
+ this.inputManager.on("restart", this.restart.bind(this));
+ this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));
+ }
this.setup();
}
// Restart the game
GameManager.prototype.restart = function () {
- this.storageManager.clearGameState();
+ this.storageManager.sendAction("restart");
this.actuator.continueGame(); // Clear the game won/lost message
this.setup();
};
@@ -32,30 +35,33 @@ GameManager.prototype.isGameTerminated = function () {
};
// Set up the game
-GameManager.prototype.setup = function () {
- var previousState = this.storageManager.getGameState();
-
- // Reload the game from a previous game if present
- if (previousState) {
- this.grid = new Grid(previousState.grid.size,
- previousState.grid.cells); // Reload grid
- this.score = previousState.score;
- this.over = previousState.over;
- this.won = previousState.won;
- this.keepPlaying = previousState.keepPlaying;
- } else {
- this.grid = new Grid(this.size);
- this.score = 0;
- this.over = false;
- this.won = false;
- this.keepPlaying = false;
-
- // Add the initial tiles
- this.addStartTiles();
- }
-
- // Update the actuator
- this.actuate();
+GameManager.prototype.setup = function (){
+ this.storageManager.onData((data) => {
+ if(data.action === "state"){
+ // Reload the game from a previous game if present
+ if (data.value) {
+ var previousState = JSON.parse(data.value);
+ this.grid = new Grid(previousState.grid.size,
+ previousState.grid.cells); // Reload grid
+ this.score = previousState.score;
+ this.over = previousState.over;
+ this.won = previousState.won;
+ this.keepPlaying = previousState.keepPlaying;
+ } else {
+ this.grid = new Grid(this.size);
+ this.score = 0;
+ this.over = false;
+ this.won = false;
+ this.keepPlaying = false;
+
+ // Add the initial tiles
+ this.addStartTiles();
+ }
+
+ // Update the actuator
+ this.actuate();
+ }
+ }, this.game);
};
// Set up the initial tiles to start the game with
@@ -77,17 +83,6 @@ GameManager.prototype.addRandomTile = function () {
// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
- if (this.storageManager.getBestScore() < this.score) {
- this.storageManager.setBestScore(this.score);
- }
-
- // Clear the state when the game is over (game over only, not win)
- if (this.over) {
- console.log("over "+this.score);
- this.storageManager.clearGameState();
- } else {
- this.storageManager.setGameState(this.serialize());
- }
this.actuator.actuate(this.grid, {
score: this.score,
@@ -96,6 +91,8 @@ GameManager.prototype.actuate = function () {
bestScore: this.storageManager.getBestScore(),
terminated: this.isGameTerminated()
});
+
+ this.storageManager.sendAction("state", JSON.stringify(this.serialize()));
};
@@ -111,7 +108,7 @@ GameManager.prototype.serialize = function () {
};
// Save all tile positions and remove merger info
-GameManager.prototype.prepareTiles = function () {
+GameManager.prototype.prepareTiles = function (){
this.grid.eachCell(function (x, y, tile) {
if (tile) {
tile.mergedFrom = null;
diff --git a/assets/js/html_actuator.js b/assets/js/html_actuator.js
index 6b31f2d..f2e397c 100644
--- a/assets/js/html_actuator.js
+++ b/assets/js/html_actuator.js
@@ -1,8 +1,8 @@
-function HTMLActuator() {
- this.tileContainer = document.querySelector(".tile-container");
- this.scoreContainer = document.querySelector(".score-container");
- this.bestContainer = document.querySelector(".best-container");
- this.messageContainer = document.querySelector(".game-message");
+function HTMLActuator(id) {
+ this.tileContainer = document.querySelector(".tile-container-"+id);
+ this.scoreContainer = document.querySelector(".score-container-"+id);
+ this.bestContainer = document.querySelector(".best-container-"+id);
+ this.messageContainer = document.querySelector(".game-message-"+id);
this.score = 0;
}
diff --git a/assets/js/local_storage_manager.js b/assets/js/local_storage_manager.js
deleted file mode 100644
index 2ca9cc3..0000000
--- a/assets/js/local_storage_manager.js
+++ /dev/null
@@ -1,63 +0,0 @@
-window.fakeStorage = {
- _data: {},
-
- setItem: function (id, val) {
- 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 LocalStorageManager() {
- this.bestScoreKey = "bestScore";
- this.gameStateKey = "gameState";
-
- var supported = this.localStorageSupported();
- this.storage = supported ? window.localStorage : window.fakeStorage;
-}
-
-LocalStorageManager.prototype.localStorageSupported = function () {
- var testKey = "test";
-
- try {
- var storage = window.localStorage;
- storage.setItem(testKey, "1");
- storage.removeItem(testKey);
- return true;
- } catch (error) {
- return false;
- }
-};
-
-// Best score getters/setters
-LocalStorageManager.prototype.getBestScore = function () {
- return this.storage.getItem(this.bestScoreKey) || 0;
-};
-
-LocalStorageManager.prototype.setBestScore = function (score) {
- this.storage.setItem(this.bestScoreKey, score);
-};
-
-// Game state getters/setters and clearing
-LocalStorageManager.prototype.getGameState = function () {
- var stateJSON = this.storage.getItem(this.gameStateKey);
- return stateJSON ? JSON.parse(stateJSON) : null;
-};
-
-LocalStorageManager.prototype.setGameState = function (gameState) {
- this.storage.setItem(this.gameStateKey, JSON.stringify(gameState));
-};
-
-LocalStorageManager.prototype.clearGameState = function () {
- this.storage.removeItem(this.gameStateKey);
-};
diff --git a/assets/js/remote_storage_manager.js b/assets/js/remote_storage_manager.js
new file mode 100644
index 0000000..b1ce9b3
--- /dev/null
+++ b/assets/js/remote_storage_manager.js
@@ -0,0 +1,51 @@
+function RemoteStorageManager() {
+ this.storage = new WebSocket("ws://localhost/");
+ openListeners = [];
+ dataListeners = [];
+
+ this.bestScore = 0;
+
+ this.storage.onopen = function(){
+ this.connected = true;
+ openListeners.forEach(listener => listener());
+ }
+
+ this.storage.onmessage = function(e){
+ let data = JSON.parse(e.data);
+ let list = dataListeners[data.game];
+ if(list !== undefined) list.forEach(listener => listener(data));
+ console.log(data);
+
+ if(data.action === "bestScore"){
+ this.bestScore = data.value;
+ }
+ }
+
+ this.openListeners = openListeners;
+ this.dataListeners = dataListeners;
+}
+
+RemoteStorageManager.prototype.onConnected = function(func){
+ if(this.connected){
+ func();
+ return;
+ }
+ this.openListeners.push(func);
+}
+
+RemoteStorageManager.prototype.onData = function(func, game){
+ let listeners = this.dataListeners[game];
+ if(listeners == undefined){
+ listeners = [];
+ this.dataListeners[game] = listeners;
+ }
+ listeners.push(func);
+}
+
+RemoteStorageManager.prototype.sendAction = function(action, value){
+ this.storage.send(JSON.stringify(value === undefined ? {action:action} : {action:action,value:value}));
+}
+
+RemoteStorageManager.prototype.getBestScore = function(){
+ return this.bestScore;
+}
\ No newline at end of file
diff --git a/assets/style/main.css b/assets/style/main.css
index 0109624..3404642 100644
--- a/assets/style/main.css
+++ b/assets/style/main.css
@@ -116,8 +116,10 @@ hr {
margin-bottom: 30px; }
.container {
- width: 500px;
- margin: 0 auto; }
+ width: 40%;
+ margin: 0 auto;
+ display: inline-block;
+}
@-webkit-keyframes fade-in {
0% {
diff --git a/index.html b/index.html
index b25c4b8..9f6223a 100644
--- a/index.html
+++ b/index.html
@@ -18,12 +18,11 @@
-
+
+
+
-
- How to play: Use your arrow keys to move the tiles. When two tiles with the same number touch, they merge into one!
-
-
-
- Note: This site is the official version of 2048. You can access it on your phone via the EndStorage Hub.
-
+
@@ -87,7 +124,7 @@
-
+