extract the grid to its own class
[2048.git] / js / html_actuator.js
blob:a/js/html_actuator.js -> blob:b/js/html_actuator.js
--- a/js/html_actuator.js
+++ b/js/html_actuator.js
@@ -1,14 +1,93 @@
 function HTMLActuator() {
+  this.tileContainer  = document.getElementsByClassName("tile-container")[0];
+  this.gameContainer  = document.getElementsByClassName("game-container")[0];
+  this.scoreContainer = document.getElementsByClassName("score-container")[0];
 
+  this.score = 0;
 }
 
-HTMLActuator.prototype.actuate = function (grid) {
-  // Temporary debug visualizer
-  grid.cells.forEach(function (row) {
-    var mapped = row.map(function (tile) {
-      return tile ? tile.value : " ";
-    }).join(" | ");
-    console.log(mapped);
+HTMLActuator.prototype.actuate = function (grid, metadata) {
+  var self = this;
+
+  window.requestAnimationFrame(function () {
+    self.clearContainer(self.tileContainer);
+
+    grid.cells.forEach(function (column) {
+      column.forEach(function (cell) {
+        if (cell) {
+          self.addTile(cell);
+        }
+      });
+    });
+
+    self.updateScore(metadata.score);
+
+    if (metadata.over) self.message(false); // You lose
+    if (metadata.won) self.message(true); // You win!
   });
 };
 
+HTMLActuator.prototype.clearContainer = function (container) {
+  while (container.firstChild) {
+    container.removeChild(container.firstChild);
+  }
+};
+
+HTMLActuator.prototype.addTile = function (tile) {
+  var self = this;
+
+  var element   = document.createElement("div");
+  var position  = tile.previousPosition || { x: tile.x, y: tile.y };
+  positionClass = this.positionClass(position);
+
+  element.classList.add("tile", "tile-" + tile.value, positionClass);
+  element.textContent = tile.value;
+
+  this.tileContainer.appendChild(element);
+
+  if (tile.previousPosition) {
+    window.requestAnimationFrame(function () {
+      element.classList.remove(element.classList[2]);
+      element.classList.add(self.positionClass({ x: tile.x, y: tile.y }));
+    });
+  } else if (tile.mergedFrom) {
+    element.classList.add("tile-merged");
+    tile.mergedFrom.forEach(function (merged) {
+      self.addTile(merged);
+    });
+  } else {
+    element.classList.add("tile-new");
+  }
+};
+
+HTMLActuator.prototype.normalizePosition = function (position) {
+  return { x: position.x + 1, y: position.y + 1 };
+};
+
+HTMLActuator.prototype.positionClass = function (position) {
+  position = this.normalizePosition(position);
+  return "tile-position-" + position.x + "-" + position.y;
+};
+
+HTMLActuator.prototype.updateScore = function (score) {
+  this.clearContainer(this.scoreContainer);
+
+  var difference = score - this.score;
+  this.score = score;
+
+  this.scoreContainer.textContent = this.score;
+
+  if (difference) {
+    var addition = document.createElement("div");
+    addition.classList.add("score-addition");
+    addition.textContent = "+" + difference;
+
+    this.scoreContainer.appendChild(addition);
+  }
+};
+
+HTMLActuator.prototype.message = function (won) {
+  var type = won ? "game-won" : "game-over";
+  this.gameContainer.classList.add(type);
+};
+

comments