refactor grid, gamemanager, tile
[2048.git] / js / html_actuator.js
Gabriele Cirulli
Grégory HOULLIER

Gabriele Cirulli
Grégory HOULLIER
Gabriele Cirulli

Gabriele Cirulli

Gabriele Cirulli
Gabriele Cirulli

Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli






Gabriele Cirulli
Gabriele Cirulli

Tim Petricola
Gabriele Cirulli
Gabriele Cirulli





Laurent Margirier

Gabriele Cirulli

Gabriele Cirulli
Gabriele Cirulli

Laurent Margirier
Gabriele Cirulli
Laurent Margirier
Gabriele Cirulli


Gabriele Cirulli



Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli

Gabriele Cirulli
Laurent Margirier
Gabriele Cirulli
Gabriele Cirulli

Gabriele Cirulli

Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli

Gabriele Cirulli

Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli

Gabriele Cirulli


Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli


Gabriele Cirulli
Gabriele Cirulli
Gabriele Cirulli



Gabriele Cirulli








Gabriele Cirulli
Gabriele Cirulli

Gabriele Cirulli







Gabriele Cirulli





Gabriele Cirulli

Tim Petricola
Tim Petricola
Tim Petricola

Gabriele Cirulli
Gabriele Cirulli
Tim Petricola
Gabriele Cirulli





Dave Risney


Gabriele Cirulli

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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");
 
  this.score = 0;
}
 
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);
    self.updateBestScore(metadata.bestScore);
 
    if (metadata.terminated) {
      if (metadata.over) {
        self.message(false); // You lose
      } else if (metadata.won) {
        self.message(true); // You win!
      }
    }
 
  });
};
 
// Continues the game (both restart and keep playing)
HTMLActuator.prototype.continue = function () {
  this.clearMessage();
};
 
HTMLActuator.prototype.clearContainer = function (container) {
  while (container.firstChild) {
    container.removeChild(container.firstChild);
  }
};
 
HTMLActuator.prototype.addTile = function (tile) {
  var self = this;
 
  var wrapper   = document.createElement("div");
  var inner     = document.createElement("div");
  var position  = tile.previousPosition || { x: tile.x, y: tile.y };
  var positionClass = this.positionClass(position);
 
  // We can't use classlist because it somehow glitches when replacing classes
  var classes = ["tile", "tile-" + tile.value, positionClass];
 
  if (tile.value > 2048) classes.push("tile-super");
 
  this.applyClasses(wrapper, classes);
 
  inner.classList.add("tile-inner");
  inner.textContent = tile.value;
 
  if (tile.previousPosition) {
    // Make sure that the tile gets rendered in the previous position first
    window.requestAnimationFrame(function () {
      classes[2] = self.positionClass({ x: tile.x, y: tile.y });
      self.applyClasses(wrapper, classes); // Update the position
    });
  } else if (tile.mergedFrom) {
    classes.push("tile-merged");
    this.applyClasses(wrapper, classes);
 
    // Render the tiles that merged
    tile.mergedFrom.forEach(function (merged) {
      self.addTile(merged);
    });
  } else {
    classes.push("tile-new");
    this.applyClasses(wrapper, classes);
  }
 
  // Add the inner part of the tile to the wrapper
  wrapper.appendChild(inner);
 
  // Put the tile on the board
  this.tileContainer.appendChild(wrapper);
};
 
HTMLActuator.prototype.applyClasses = function (element, classes) {
  element.setAttribute("class", classes.join(" "));
};
 
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 > 0) {
    var addition = document.createElement("div");
    addition.classList.add("score-addition");
    addition.textContent = "+" + difference;
 
    this.scoreContainer.appendChild(addition);
  }
};
 
HTMLActuator.prototype.updateBestScore = function (bestScore) {
  this.bestContainer.textContent = bestScore;
};
 
HTMLActuator.prototype.message = function (won) {
  var type    = won ? "game-won" : "game-over";
  var message = won ? "You win!" : "Game over!";
 
  this.messageContainer.classList.add(type);
  this.messageContainer.getElementsByTagName("p")[0].textContent = message;
};
 
HTMLActuator.prototype.clearMessage = function () {
  // IE only takes one value to remove at a time.
  this.messageContainer.classList.remove("game-won");
  this.messageContainer.classList.remove("game-over");
};
 
comments