提交 bd7f8963 编写于 作者: G Gabriele Cirulli

Merge branch 'resume-game' of github.com:mfrederiksen/2048 into mfrederiksen-resume-game

......@@ -23,7 +23,7 @@
</div>
</div>
<p class="game-intro">Join the numbers and get to the <strong>2048 tile!</strong></p>
<a class="restart-button">New Game</a>
<div class="game-container">
<div class="game-message">
<p></p>
......
function GameManager(size, InputManager, Actuator, ScoreManager) {
function GameManager(size, InputManager, Actuator, StorageManager) {
this.size = size; // Size of the grid
this.inputManager = new InputManager;
this.scoreManager = new ScoreManager;
this.storageManager = new StorageManager;
this.actuator = new Actuator;
this.startTiles = 2;
......@@ -15,6 +15,7 @@ function GameManager(size, InputManager, Actuator, ScoreManager) {
// Restart the game
GameManager.prototype.restart = function () {
this.storageManager.clearGameState();
this.actuator.continue();
this.setup();
};
......@@ -35,15 +36,24 @@ GameManager.prototype.isGameTerminated = function () {
// Set up the game
GameManager.prototype.setup = function () {
this.grid = new Grid(this.size);
this.score = 0;
this.over = false;
this.won = false;
this.keepPlaying = false;
// Add the initial tiles
this.addStartTiles();
var previousGameState = this.storageManager.getGameState();
if (previousGameState) {
this.grid = new Grid(previousGameState.grid.size, previousGameState.grid.cells);
this.score = previousGameState.score;
this.over = previousGameState.over;
this.won = previousGameState.won;
this.keepPlaying = previousGameState.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();
......@@ -68,20 +78,33 @@ 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);
if (this.storageManager.getBestScore() < this.score) {
this.storageManager.setBestScore(this.score);
}
this.storageManager.setGameState(this.serializeGameState());
this.actuator.actuate(this.grid, {
score: this.score,
over: this.over,
won: this.won,
bestScore: this.scoreManager.get(),
bestScore: this.storageManager.getBestScore(),
terminated: this.isGameTerminated()
});
};
GameManager.prototype.serializeGameState = function () {
return {
size: this.size,
grid: this.grid.gridState(),
score: this.score,
over: this.over,
won: this.won,
keepPlaying: this.keepPlaying
};
}
// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
this.grid.eachCell(function (x, y, tile) {
......
function Grid(size) {
function Grid(size, previousCellState) {
this.size = size;
this.cells = [];
this.build();
this.cells = previousCellState ? this.buildFromPreviousState(previousCellState) : this.buildNew();
}
// Build a grid of the specified size
Grid.prototype.build = function () {
Grid.prototype.buildNew = function () {
var cells = [];
for (var x = 0; x < this.size; x++) {
var row = this.cells[x] = [];
var row = cells[x] = [];
for (var y = 0; y < this.size; y++) {
row.push(null);
}
}
return cells;
};
Grid.prototype.buildFromPreviousState = function (state) {
var cells = [];
for (var x = 0; x < this.size; x++) {
var row = cells[x] = [];
for (var y = 0; y < this.size; y++) {
var tileState = state[x][y];
row.push(tileState ? new Tile(tileState.position, tileState.value) : null);
}
}
return cells;
};
// Find the first available random position
......@@ -82,3 +94,19 @@ Grid.prototype.withinBounds = function (position) {
return position.x >= 0 && position.x < this.size &&
position.y >= 0 && position.y < this.size;
};
Grid.prototype.gridState = function () {
var cellState = [];
for (var x = 0; x < this.size; x++) {
var row = cellState[x] = [];
for (var y = 0; y < this.size; y++) {
row.push(this.cells[x][y] ? this.cells[x][y].tileState() : null);
}
}
return {
size: this.size,
cells: cellState
}
};
......@@ -68,6 +68,10 @@ KeyboardInputManager.prototype.listen = function () {
retry.addEventListener("click", this.restart.bind(this));
retry.addEventListener(this.eventTouchend, this.restart.bind(this));
var restart = document.querySelector(".restart-button");
restart.addEventListener("click", this.restart.bind(this));
restart.addEventListener("touchend", this.restart.bind(this));
var keepPlaying = document.querySelector(".keep-playing-button");
keepPlaying.addEventListener("click", this.keepPlaying.bind(this));
keepPlaying.addEventListener("touchend", this.keepPlaying.bind(this));
......
......@@ -19,7 +19,8 @@ window.fakeStorage = {
};
function LocalScoreManager() {
this.key = "bestScore";
this.bestScoreKey = "bestScore";
this.gameStateKey = "gameState";
var supported = this.localStorageSupported();
this.storage = supported ? window.localStorage : window.fakeStorage;
......@@ -38,11 +39,23 @@ LocalScoreManager.prototype.localStorageSupported = function () {
}
};
LocalScoreManager.prototype.get = function () {
return this.storage.getItem(this.key) || 0;
LocalScoreManager.prototype.getBestScore = function () {
return this.storage.getItem(this.bestScoreKey) || 0;
};
LocalScoreManager.prototype.set = function (score) {
this.storage.setItem(this.key, score);
LocalScoreManager.prototype.setBestScore = function (score) {
this.storage.setItem(this.bestScoreKey, score);
};
LocalScoreManager.prototype.getGameState = function () {
var stateJSON = this.storage.getItem(this.gameStateKey);
return stateJSON ? JSON.parse(stateJSON) : null;
};
LocalScoreManager.prototype.setGameState = function (gameState) {
this.storage.setItem(this.gameStateKey, JSON.stringify(gameState));
};
LocalScoreManager.prototype.clearGameState = function () {
this.storage.removeItem(this.gameStateKey);
};
......@@ -15,3 +15,13 @@ Tile.prototype.updatePosition = function (position) {
this.x = position.x;
this.y = position.y;
};
Tile.prototype.tileState = function () {
return {
position: {
x: this.x,
y: this.y
},
value: this.value
};
}
\ No newline at end of file
......@@ -143,8 +143,21 @@ hr {
100% {
opacity: 1; } }
.restart-button {
display: inline-block;
background: #8f7a66;
border-radius: 3px;
padding: 0 20px;
text-decoration: none;
color: #f9f6f2;
height: 40px;
line-height: 42px;
display: block;
width: 100px;
margin: 10px auto 10px auto;
text-align: center; }
.game-container {
margin-top: 40px;
position: relative;
padding: 15px;
cursor: default;
......@@ -516,7 +529,6 @@ hr {
margin-bottom: 10px; }
.game-container {
margin-top: 40px;
position: relative;
padding: 10px;
cursor: default;
......
......@@ -168,10 +168,17 @@ hr {
line-height: 42px;
}
.restart-button {
@include button;
display: block;
width: 100px;
margin: 10px auto 10px auto;
text-align: center;
}
// Game field mixin used to render CSS at different width
@mixin game-field {
.game-container {
margin-top: 40px;
position: relative;
padding: $grid-spacing;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册