├── README.md
├── doge1.jpeg
├── favicon.png
├── img
├── 144
│ ├── doge-fat-114.gif
│ ├── doge-hat-114.gif
│ ├── doge-derp-114.gif
│ ├── doge-prizza-114.gif
│ ├── doge-shake-114.gif
│ ├── doge-wink-114.gif
│ ├── background-lo-res.png
│ ├── doge-gradient-114.gif
│ ├── doge-peepers-114.gif
│ ├── doge-rainbow-114.gif
│ ├── doge-shake-space-114.gif
│ └── doge-sunglasses-114.gif
└── 212
│ ├── doge-fat-212.gif
│ ├── doge-hat-212.gif
│ ├── doge-derp-212.gif
│ ├── doge-prizza-212.gif
│ ├── doge-shake-212.gif
│ ├── doge-wink-212.gif
│ ├── doge-gradient-212.gif
│ ├── doge-peepers-212.gif
│ ├── doge-rainbow-212.gif
│ ├── doge-shake-space-212.gif
│ └── doge-sunglasses-212.gif
├── meta
└── apple-touch-icon.png
├── style
├── fonts
│ ├── comic_sans.woff
│ └── comic-sans.css
└── main.css
├── rate.js
├── js
├── tile.js
├── animframe_polyfill.js
├── local_score_manager.js
├── application.js
├── grid.js
├── keyboard_input_manager.js
├── html_actuator.js
└── game_manager.js
└── index.html
/README.md:
--------------------------------------------------------------------------------
1 | # doge-2048.github.io
--------------------------------------------------------------------------------
/doge1.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/doge1.jpeg
--------------------------------------------------------------------------------
/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/favicon.png
--------------------------------------------------------------------------------
/img/144/doge-fat-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-fat-114.gif
--------------------------------------------------------------------------------
/img/144/doge-hat-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-hat-114.gif
--------------------------------------------------------------------------------
/img/212/doge-fat-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-fat-212.gif
--------------------------------------------------------------------------------
/img/212/doge-hat-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-hat-212.gif
--------------------------------------------------------------------------------
/img/144/doge-derp-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-derp-114.gif
--------------------------------------------------------------------------------
/img/144/doge-prizza-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-prizza-114.gif
--------------------------------------------------------------------------------
/img/144/doge-shake-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-shake-114.gif
--------------------------------------------------------------------------------
/img/144/doge-wink-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-wink-114.gif
--------------------------------------------------------------------------------
/img/212/doge-derp-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-derp-212.gif
--------------------------------------------------------------------------------
/img/212/doge-prizza-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-prizza-212.gif
--------------------------------------------------------------------------------
/img/212/doge-shake-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-shake-212.gif
--------------------------------------------------------------------------------
/img/212/doge-wink-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-wink-212.gif
--------------------------------------------------------------------------------
/meta/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/meta/apple-touch-icon.png
--------------------------------------------------------------------------------
/style/fonts/comic_sans.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/style/fonts/comic_sans.woff
--------------------------------------------------------------------------------
/img/144/background-lo-res.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/background-lo-res.png
--------------------------------------------------------------------------------
/img/144/doge-gradient-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-gradient-114.gif
--------------------------------------------------------------------------------
/img/144/doge-peepers-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-peepers-114.gif
--------------------------------------------------------------------------------
/img/144/doge-rainbow-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-rainbow-114.gif
--------------------------------------------------------------------------------
/img/212/doge-gradient-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-gradient-212.gif
--------------------------------------------------------------------------------
/img/212/doge-peepers-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-peepers-212.gif
--------------------------------------------------------------------------------
/img/212/doge-rainbow-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-rainbow-212.gif
--------------------------------------------------------------------------------
/rate.js:
--------------------------------------------------------------------------------
1 | document.querySelector('#rate').href = `https://chrome.google.com/webstore/detail/${chrome.runtime.id}/reviews`;
--------------------------------------------------------------------------------
/img/144/doge-shake-space-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-shake-space-114.gif
--------------------------------------------------------------------------------
/img/144/doge-sunglasses-114.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/144/doge-sunglasses-114.gif
--------------------------------------------------------------------------------
/img/212/doge-shake-space-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-shake-space-212.gif
--------------------------------------------------------------------------------
/img/212/doge-sunglasses-212.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2Cmo/doge-2048.github.io/doge2048/img/212/doge-sunglasses-212.gif
--------------------------------------------------------------------------------
/style/fonts/comic-sans.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "Comic Sans";
3 | src: url("comic_sans.eot");
4 | src: url("comic_sans.eot?#iefix") format("embedded-opentype"),
5 | url("comic_sans.woff") format("woff");
6 | font-weight: normal;
7 | font-style: normal;
8 | }
9 |
--------------------------------------------------------------------------------
/js/tile.js:
--------------------------------------------------------------------------------
1 | function Tile(position, value) {
2 | this.x = position.x;
3 | this.y = position.y;
4 | this.value = value || 2;
5 |
6 | this.previousPosition = null;
7 | this.mergedFrom = null; // Tracks tiles that merged together
8 | }
9 |
10 | Tile.prototype.savePosition = function () {
11 | this.previousPosition = { x: this.x, y: this.y };
12 | };
13 |
14 | Tile.prototype.updatePosition = function (position) {
15 | this.x = position.x;
16 | this.y = position.y;
17 | };
18 |
--------------------------------------------------------------------------------
/js/animframe_polyfill.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var lastTime = 0;
3 | var vendors = ['webkit', 'moz'];
4 | for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
5 | window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
6 | window.cancelAnimationFrame =
7 | window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
8 | }
9 |
10 | if (!window.requestAnimationFrame) {
11 | window.requestAnimationFrame = function(callback, element) {
12 | var currTime = new Date().getTime();
13 | var timeToCall = Math.max(0, 16 - (currTime - lastTime));
14 | var id = window.setTimeout(function() { callback(currTime + timeToCall); },
15 | timeToCall);
16 | lastTime = currTime + timeToCall;
17 | return id;
18 | };
19 | }
20 |
21 | if (!window.cancelAnimationFrame) {
22 | window.cancelAnimationFrame = function(id) {
23 | clearTimeout(id);
24 | };
25 | }
26 | }());
27 |
--------------------------------------------------------------------------------
/js/local_score_manager.js:
--------------------------------------------------------------------------------
1 | window.fakeStorage = {
2 | _data: {},
3 |
4 | setItem: function (id, val) {
5 | return this._data[id] = String(val);
6 | },
7 |
8 | getItem: function (id) {
9 | return this._data.hasOwnProperty(id) ? this._data[id] : undefined;
10 | },
11 |
12 | removeItem: function (id) {
13 | return delete this._data[id];
14 | },
15 |
16 | clear: function () {
17 | return this._data = {};
18 | }
19 | };
20 |
21 | function LocalScoreManager() {
22 | this.key = "bestScore";
23 |
24 | var supported = this.localStorageSupported();
25 | this.storage = supported ? window.localStorage : window.fakeStorage;
26 | }
27 |
28 | LocalScoreManager.prototype.localStorageSupported = function () {
29 | var testKey = "test";
30 | var storage = window.localStorage;
31 |
32 | try {
33 | storage.setItem(testKey, "1");
34 | storage.removeItem(testKey);
35 | return true;
36 | } catch (error) {
37 | return false;
38 | }
39 | };
40 |
41 | LocalScoreManager.prototype.get = function () {
42 | return this.storage.getItem(this.key) || 0;
43 | };
44 |
45 | LocalScoreManager.prototype.set = function (score) {
46 | this.storage.setItem(this.key, score);
47 | };
48 |
--------------------------------------------------------------------------------
/js/application.js:
--------------------------------------------------------------------------------
1 | // Wait till the browser is ready to render the game (avoids glitches)
2 | window.requestAnimationFrame(function () {
3 | new GameManager(4, KeyboardInputManager, HTMLActuator, LocalScoreManager);
4 | });
5 |
6 |
7 | var imageList = [
8 | "img/212/doge-derp-212.gif",
9 | "img/212/doge-fat-212.gif",
10 | "img/212/doge-gradient-212.gif",
11 | "img/212/doge-hat-212.gif",
12 | "img/212/doge-peepers-212.gif",
13 | "img/212/doge-prizza-212.gif",
14 | "img/212/doge-rainbow-212.gif",
15 | "img/212/doge-shake-space-212.gif",
16 | "img/212/doge-sunglasses-212.gif",
17 | "img/212/doge-shake-212.gif",
18 | "img/212/doge-wink-212.gif",
19 | "img/114/doge-derp-114.gif",
20 | "img/114/doge-fat-114.gif",
21 | "img/114/doge-gradient-114.gif",
22 | "img/114/doge-hat-114.gif",
23 | "img/114/doge-peepers-114.gif",
24 | "img/114/doge-prizza-114.gif",
25 | "img/114/doge-rainbow-114.gif",
26 | "img/114/doge-shake-space-114.gif",
27 | "img/114/doge-sunglasses-114.gif",
28 | "img/114/doge-shake-114.gif",
29 | "img/114/doge-wink-114.gif",
30 | ];
31 | for(var i = 0; i < imageList.length; i++ )
32 | {
33 | var imageObject = new Image();
34 | imageObject.src = imageList[i];
35 | }
36 |
--------------------------------------------------------------------------------
/js/grid.js:
--------------------------------------------------------------------------------
1 | function Grid(size) {
2 | this.size = size;
3 |
4 | this.cells = [];
5 |
6 | this.build();
7 | }
8 |
9 | // Build a grid of the specified size
10 | Grid.prototype.build = function () {
11 | for (var x = 0; x < this.size; x++) {
12 | var row = this.cells[x] = [];
13 |
14 | for (var y = 0; y < this.size; y++) {
15 | row.push(null);
16 | }
17 | }
18 | };
19 |
20 | // Find the first available random position
21 | Grid.prototype.randomAvailableCell = function () {
22 | var cells = this.availableCells();
23 |
24 | if (cells.length) {
25 | return cells[Math.floor(Math.random() * cells.length)];
26 | }
27 | };
28 |
29 | Grid.prototype.availableCells = function () {
30 | var cells = [];
31 |
32 | this.eachCell(function (x, y, tile) {
33 | if (!tile) {
34 | cells.push({ x: x, y: y });
35 | }
36 | });
37 |
38 | return cells;
39 | };
40 |
41 | // Call callback for every cell
42 | Grid.prototype.eachCell = function (callback) {
43 | for (var x = 0; x < this.size; x++) {
44 | for (var y = 0; y < this.size; y++) {
45 | callback(x, y, this.cells[x][y]);
46 | }
47 | }
48 | };
49 |
50 | // Check if there are any cells available
51 | Grid.prototype.cellsAvailable = function () {
52 | return !!this.availableCells().length;
53 | };
54 |
55 | // Check if the specified cell is taken
56 | Grid.prototype.cellAvailable = function (cell) {
57 | return !this.cellOccupied(cell);
58 | };
59 |
60 | Grid.prototype.cellOccupied = function (cell) {
61 | return !!this.cellContent(cell);
62 | };
63 |
64 | Grid.prototype.cellContent = function (cell) {
65 | if (this.withinBounds(cell)) {
66 | return this.cells[cell.x][cell.y];
67 | } else {
68 | return null;
69 | }
70 | };
71 |
72 | // Inserts a tile at its position
73 | Grid.prototype.insertTile = function (tile) {
74 | this.cells[tile.x][tile.y] = tile;
75 | };
76 |
77 | Grid.prototype.removeTile = function (tile) {
78 | this.cells[tile.x][tile.y] = null;
79 | };
80 |
81 | Grid.prototype.withinBounds = function (position) {
82 | return position.x >= 0 && position.x < this.size &&
83 | position.y >= 0 && position.y < this.size;
84 | };
85 |
--------------------------------------------------------------------------------
/js/keyboard_input_manager.js:
--------------------------------------------------------------------------------
1 | function KeyboardInputManager() {
2 | this.events = {};
3 |
4 | this.listen();
5 | }
6 |
7 | KeyboardInputManager.prototype.on = function (event, callback) {
8 | if (!this.events[event]) {
9 | this.events[event] = [];
10 | }
11 | this.events[event].push(callback);
12 | };
13 |
14 | KeyboardInputManager.prototype.emit = function (event, data) {
15 | var callbacks = this.events[event];
16 | if (callbacks) {
17 | callbacks.forEach(function (callback) {
18 | callback(data);
19 | });
20 | }
21 | };
22 |
23 | KeyboardInputManager.prototype.listen = function () {
24 | var self = this;
25 |
26 | var map = {
27 | 38: 0, // Up
28 | 39: 1, // Right
29 | 40: 2, // Down
30 | 37: 3, // Left
31 | 75: 0, // vim keybindings
32 | 76: 1,
33 | 74: 2,
34 | 72: 3,
35 | 87: 0, // W
36 | 68: 1, // D
37 | 83: 2, // S
38 | 65: 3 // A
39 | };
40 |
41 | document.addEventListener("keydown", function (event) {
42 | var modifiers = event.altKey || event.ctrlKey || event.metaKey ||
43 | event.shiftKey;
44 | var mapped = map[event.which];
45 |
46 | if (!modifiers) {
47 | if (mapped !== undefined) {
48 | event.preventDefault();
49 | self.emit("move", mapped);
50 | }
51 |
52 | if (event.which === 32) self.restart.bind(self)(event);
53 | }
54 | });
55 |
56 | var retry = document.querySelector(".retry-button");
57 | retry.addEventListener("click", this.restart.bind(this));
58 | retry.addEventListener("touchend", this.restart.bind(this));
59 |
60 | var keepPlaying = document.querySelector(".keep-playing-button");
61 | keepPlaying.addEventListener("click", this.keepPlaying.bind(this));
62 | keepPlaying.addEventListener("touchend", this.keepPlaying.bind(this));
63 |
64 | var showInfo = document.querySelector(".info-container");
65 | showInfo.addEventListener("click", this.showInfo.bind(this));
66 | showInfo.addEventListener("touchend", this.showInfo.bind(this));
67 |
68 | // var hideInfo = document.querySelector(".hide-info");
69 | // hideInfo.addEventListener("click", this.hideInfo.bind(this));
70 | // hideInfo.addEventListener("touchend", this.hideInfo.bind(this));
71 |
72 |
73 | // Listen to swipe events
74 | var touchStartClientX, touchStartClientY;
75 | var gameContainer = document.getElementsByClassName("game-container")[0];
76 |
77 | gameContainer.addEventListener("touchstart", function (event) {
78 | if (event.touches.length > 1) return;
79 |
80 | touchStartClientX = event.touches[0].clientX;
81 | touchStartClientY = event.touches[0].clientY;
82 | event.preventDefault();
83 | });
84 |
85 | gameContainer.addEventListener("touchmove", function (event) {
86 | event.preventDefault();
87 | });
88 |
89 | gameContainer.addEventListener("touchend", function (event) {
90 | if (event.touches.length > 0) return;
91 | var dx = event.changedTouches[0].clientX - touchStartClientX;
92 | var absDx = Math.abs(dx);
93 | var dy = event.changedTouches[0].clientY - touchStartClientY;
94 | var absDy = Math.abs(dy);
95 | if (Math.max(absDx, absDy) > 10) {
96 | // (right : left) : (down : up)
97 | self.emit("move", absDx > absDy ? (dx > 0 ? 1 : 3) : (dy > 0 ? 2 : 0));
98 | }
99 | });
100 | };
101 | KeyboardInputManager.prototype.restart = function (event) {
102 | event.preventDefault();
103 | this.emit("restart");
104 | };
105 | KeyboardInputManager.prototype.keepPlaying = function (event) {
106 | event.preventDefault();
107 | this.emit("keepPlaying");
108 | };
109 | KeyboardInputManager.prototype.showInfo = function (event) {
110 | event.preventDefault();
111 | this.emit("showInfo");
112 | };
113 | KeyboardInputManager.prototype.hideInfo = function (event) {
114 | event.preventDefault();
115 | this.emit("hideInfo");
116 | };
117 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DOGE 2048 | ubg247
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
DOGE2048
28 |
29 |
36 |
37 |
38 |
39 |
42 |
51 |
58 |
59 |
85 |
86 |
87 |
88 |
89 |
Use your arrow keys or swipe to combine similar Doges and score points!
90 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/js/html_actuator.js:
--------------------------------------------------------------------------------
1 | function HTMLActuator() {
2 | this.tileContainer = document.querySelector(".tile-container");
3 | this.scoreContainer = document.querySelector(".score-container");
4 | this.bestContainer = document.querySelector(".best-container");
5 | this.messageContainer = document.querySelector(".game-message");
6 | this.info = document.querySelector(".info");
7 | this.dogeSays = document.querySelector(".doge-says");
8 | this.adSpace = document.querySelector(".shout-out");
9 |
10 | this.score = 0;
11 | }
12 |
13 | var dogeSayings = ['such good', 'so amaze', 'many points', 'very unstoppable', 'great jorb', 'such playing', 'very good', 'points', 'very gaming', 'such player', 'concern' ,'bewildered', 'pro gamer', 'many game', 'so good', 'very scores', 'so scoring', 'so hot right now', 'such playing', 'such matching', 'so matched', 'very matched', 'very neat' ,'such natural',]
14 |
15 | HTMLActuator.prototype.actuate = function (grid, metadata) {
16 | var self = this;
17 |
18 | window.requestAnimationFrame(function () {
19 | self.clearContainer(self.tileContainer);
20 |
21 | grid.cells.forEach(function (column) {
22 | column.forEach(function (cell) {
23 | if (cell) {
24 | self.addTile(cell);
25 | }
26 | });
27 | });
28 |
29 | self.updateScore(metadata.score);
30 | self.updateBestScore(metadata.bestScore);
31 |
32 | if (metadata.terminated) {
33 | if (metadata.over) {
34 | self.message(false); // You lose
35 | } else if (metadata.won) {
36 | self.message(true); // You win!
37 | }
38 | }
39 |
40 | });
41 | };
42 |
43 | // Continues the game (both restart and keep playing)
44 | HTMLActuator.prototype.continue = function () {
45 | this.clearMessage();
46 | };
47 |
48 | HTMLActuator.prototype.clearContainer = function (container) {
49 | while (container.firstChild) {
50 | container.removeChild(container.firstChild);
51 | }
52 | };
53 |
54 | HTMLActuator.prototype.addTile = function (tile) {
55 | var self = this;
56 |
57 | var wrapper = document.createElement("div");
58 | var inner = document.createElement("div");
59 | var position = tile.previousPosition || { x: tile.x, y: tile.y };
60 | var positionClass = this.positionClass(position);
61 |
62 | // We can't use classlist because it somehow glitches when replacing classes
63 | var classes = ["tile", "tile-" + tile.value, positionClass];
64 |
65 | if (tile.value > 2048) classes.push("tile-super");
66 |
67 | this.applyClasses(wrapper, classes);
68 |
69 | inner.classList.add("tile-inner");
70 | inner.textContent = tile.value;
71 |
72 | if (tile.previousPosition) {
73 | // Make sure that the tile gets rendered in the previous position first
74 | window.requestAnimationFrame(function () {
75 | classes[2] = self.positionClass({ x: tile.x, y: tile.y });
76 | self.applyClasses(wrapper, classes); // Update the position
77 | });
78 | } else if (tile.mergedFrom) {
79 | classes.push("tile-merged");
80 | this.applyClasses(wrapper, classes);
81 |
82 | // Render the tiles that merged
83 | tile.mergedFrom.forEach(function (merged) {
84 | self.addTile(merged);
85 | });
86 | } else {
87 | classes.push("tile-new");
88 | this.applyClasses(wrapper, classes);
89 | }
90 |
91 | // Add the inner part of the tile to the wrapper
92 | wrapper.appendChild(inner);
93 |
94 | // Put the tile on the board
95 | this.tileContainer.appendChild(wrapper);
96 | };
97 |
98 | HTMLActuator.prototype.applyClasses = function (element, classes) {
99 | element.setAttribute("class", classes.join(" "));
100 | };
101 |
102 | HTMLActuator.prototype.normalizePosition = function (position) {
103 | return { x: position.x + 1, y: position.y + 1 };
104 | };
105 |
106 | HTMLActuator.prototype.positionClass = function (position) {
107 | position = this.normalizePosition(position);
108 | return "tile-position-" + position.x + "-" + position.y;
109 | };
110 |
111 | HTMLActuator.prototype.updateScore = function (score) {
112 | this.clearContainer(this.scoreContainer);
113 | this.clearContainer(this.dogeSays)
114 |
115 | var difference = score - this.score;
116 | this.score = score;
117 |
118 | this.scoreContainer.textContent = this.score;
119 |
120 | if (difference > 0) {
121 | var addition = document.createElement("div");
122 | addition.classList.add("score-addition");
123 | addition.textContent = "+" + difference;
124 | this.scoreContainer.appendChild(addition);
125 |
126 | var message = dogeSayings[Math.floor(Math.random() * dogeSayings.length)]
127 | var messageElement = document.createElement("p");
128 | messageElement.textContent = message
129 | var left = 'left:' + Math.round(Math.random() * 80) + '%;'
130 | var top = 'top:' + Math.round(Math.random() * 80) + '%;'
131 | var color = 'color: rgb(' + Math.round(Math.random() * 255) + ', ' + Math.round(Math.random() * 255) + ', ' + Math.round(Math.random() * 255) + ');'
132 | var styleString = left + top + color
133 | messageElement.setAttribute('style', styleString);
134 | this.dogeSays.appendChild(messageElement);
135 | if (difference > 4) {
136 | this.adSpace.innerHTML = ads[Math.floor(Math.random() * ads.length)]
137 | }
138 |
139 | }
140 | };
141 |
142 | HTMLActuator.prototype.updateBestScore = function (bestScore) {
143 | this.bestContainer.textContent = bestScore;
144 | };
145 |
146 | HTMLActuator.prototype.message = function (won) {
147 | var type = won ? "game-won" : "game-over";
148 | var message = won ? "You win!" : "Game over!";
149 |
150 | this.messageContainer.classList.add(type);
151 | this.messageContainer.getElementsByTagName("p")[0].textContent = message;
152 | };
153 |
154 | HTMLActuator.prototype.clearMessage = function () {
155 | // IE only takes one value to remove at a time.
156 | this.messageContainer.classList.remove("game-won");
157 | this.messageContainer.classList.remove("game-over");
158 | };
159 |
160 |
161 | HTMLActuator.prototype.showInfo = function () {
162 | if ( this.info.getAttribute('style') === "display:block;"){
163 | this.info.setAttribute('style','display:none;')
164 | document.querySelector('.show-info').innerHTML = 'INFO';
165 | } else {
166 | this.info.setAttribute('style','display:block;')
167 | document.querySelector('.show-info').innerHTML = 'CLOSE';
168 | }
169 | }
170 |
171 | HTMLActuator.prototype.hideInfo = function () {
172 | this.info.setAttribute('style','display:none;')
173 | }
174 |
--------------------------------------------------------------------------------
/js/game_manager.js:
--------------------------------------------------------------------------------
1 | function GameManager(size, InputManager, Actuator, ScoreManager) {
2 | this.size = size; // Size of the grid
3 | this.inputManager = new InputManager;
4 | this.scoreManager = new ScoreManager;
5 | this.actuator = new Actuator;
6 |
7 | this.startTiles = 2;
8 |
9 | this.inputManager.on("move", this.move.bind(this));
10 | this.inputManager.on("restart", this.restart.bind(this));
11 | this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));
12 | this.inputManager.on("showInfo", this.showInfo.bind(this));
13 | this.inputManager.on("hideInfo", this.hideInfo.bind(this));
14 |
15 | this.setup();
16 | }
17 |
18 | // Restart the game
19 | GameManager.prototype.restart = function () {
20 | this.actuator.continue();
21 | this.setup();
22 | };
23 |
24 | // Keep playing after winning
25 | GameManager.prototype.keepPlaying = function () {
26 | this.keepPlaying = true;
27 | this.actuator.continue();
28 | };
29 |
30 | GameManager.prototype.showInfo = function () {
31 | this.actuator.showInfo();
32 | };
33 |
34 |
35 | GameManager.prototype.hideInfo = function () {
36 | this.actuator.hideInfo();
37 | };
38 |
39 | GameManager.prototype.isGameTerminated = function () {
40 | if (this.over || (this.won && !this.keepPlaying)) {
41 | return true;
42 | } else {
43 | return false;
44 | }
45 | };
46 |
47 | // Set up the game
48 | GameManager.prototype.setup = function () {
49 | this.grid = new Grid(this.size);
50 |
51 | this.score = 0;
52 | this.over = false;
53 | this.won = false;
54 | this.keepPlaying = false;
55 |
56 | // Add the initial tiles
57 | this.addStartTiles();
58 |
59 | // Update the actuator
60 | this.actuate();
61 | };
62 |
63 | // Set up the initial tiles to start the game with
64 | GameManager.prototype.addStartTiles = function () {
65 | for (var i = 0; i < this.startTiles; i++) {
66 | this.addRandomTile();
67 | }
68 | };
69 |
70 | // Adds a tile in a random position
71 | GameManager.prototype.addRandomTile = function () {
72 | if (this.grid.cellsAvailable()) {
73 | var value = Math.random() < 0.9 ? 2 : 4;
74 | var tile = new Tile(this.grid.randomAvailableCell(), value);
75 |
76 | this.grid.insertTile(tile);
77 | }
78 | };
79 |
80 | // Sends the updated grid to the actuator
81 | GameManager.prototype.actuate = function () {
82 | if (this.scoreManager.get() < this.score) {
83 | this.scoreManager.set(this.score);
84 | }
85 |
86 | this.actuator.actuate(this.grid, {
87 | score: this.score,
88 | over: this.over,
89 | won: this.won,
90 | bestScore: this.scoreManager.get(),
91 | terminated: this.isGameTerminated()
92 | });
93 |
94 | };
95 |
96 | // Save all tile positions and remove merger info
97 | GameManager.prototype.prepareTiles = function () {
98 | this.grid.eachCell(function (x, y, tile) {
99 | if (tile) {
100 | tile.mergedFrom = null;
101 | tile.savePosition();
102 | }
103 | });
104 | };
105 |
106 | // Move a tile and its representation
107 | GameManager.prototype.moveTile = function (tile, cell) {
108 | this.grid.cells[tile.x][tile.y] = null;
109 | this.grid.cells[cell.x][cell.y] = tile;
110 | tile.updatePosition(cell);
111 | };
112 |
113 | // Move tiles on the grid in the specified direction
114 | GameManager.prototype.move = function (direction) {
115 | // 0: up, 1: right, 2:down, 3: left
116 | var self = this;
117 |
118 | if (this.isGameTerminated()) return; // Don't do anything if the game's over
119 |
120 | var cell, tile;
121 |
122 | var vector = this.getVector(direction);
123 | var traversals = this.buildTraversals(vector);
124 | var moved = false;
125 |
126 | // Save the current tile positions and remove merger information
127 | this.prepareTiles();
128 |
129 | // Traverse the grid in the right direction and move tiles
130 | traversals.x.forEach(function (x) {
131 | traversals.y.forEach(function (y) {
132 | cell = { x: x, y: y };
133 | tile = self.grid.cellContent(cell);
134 |
135 | if (tile) {
136 | var positions = self.findFarthestPosition(cell, vector);
137 | var next = self.grid.cellContent(positions.next);
138 |
139 | // Only one merger per row traversal?
140 | if (next && next.value === tile.value && !next.mergedFrom) {
141 | var merged = new Tile(positions.next, tile.value * 2);
142 | merged.mergedFrom = [tile, next];
143 |
144 | self.grid.insertTile(merged);
145 | self.grid.removeTile(tile);
146 |
147 | // Converge the two tiles' positions
148 | tile.updatePosition(positions.next);
149 |
150 | // Update the score
151 | self.score += merged.value;
152 |
153 | // The mighty 2048 tile
154 | if (merged.value === 2048) self.won = true;
155 | } else {
156 | self.moveTile(tile, positions.farthest);
157 | }
158 |
159 | if (!self.positionsEqual(cell, tile)) {
160 | moved = true; // The tile moved from its original cell!
161 | }
162 | }
163 | });
164 | });
165 |
166 | if (moved) {
167 | this.addRandomTile();
168 |
169 | if (!this.movesAvailable()) {
170 | this.over = true; // Game over!
171 | }
172 |
173 | this.actuate();
174 | }
175 | };
176 |
177 | // Get the vector representing the chosen direction
178 | GameManager.prototype.getVector = function (direction) {
179 | // Vectors representing tile movement
180 | var map = {
181 | 0: { x: 0, y: -1 }, // up
182 | 1: { x: 1, y: 0 }, // right
183 | 2: { x: 0, y: 1 }, // down
184 | 3: { x: -1, y: 0 } // left
185 | };
186 |
187 | return map[direction];
188 | };
189 |
190 | // Build a list of positions to traverse in the right order
191 | GameManager.prototype.buildTraversals = function (vector) {
192 | var traversals = { x: [], y: [] };
193 |
194 | for (var pos = 0; pos < this.size; pos++) {
195 | traversals.x.push(pos);
196 | traversals.y.push(pos);
197 | }
198 |
199 | // Always traverse from the farthest cell in the chosen direction
200 | if (vector.x === 1) traversals.x = traversals.x.reverse();
201 | if (vector.y === 1) traversals.y = traversals.y.reverse();
202 |
203 | return traversals;
204 | };
205 |
206 | GameManager.prototype.findFarthestPosition = function (cell, vector) {
207 | var previous;
208 |
209 | // Progress towards the vector direction until an obstacle is found
210 | do {
211 | previous = cell;
212 | cell = { x: previous.x + vector.x, y: previous.y + vector.y };
213 | } while (this.grid.withinBounds(cell) &&
214 | this.grid.cellAvailable(cell));
215 |
216 | return {
217 | farthest: previous,
218 | next: cell // Used to check if a merge is required
219 | };
220 | };
221 |
222 | GameManager.prototype.movesAvailable = function () {
223 | return this.grid.cellsAvailable() || this.tileMatchesAvailable();
224 | };
225 |
226 | // Check for available matches between tiles (more expensive check)
227 | GameManager.prototype.tileMatchesAvailable = function () {
228 | var self = this;
229 |
230 | var tile;
231 |
232 | for (var x = 0; x < this.size; x++) {
233 | for (var y = 0; y < this.size; y++) {
234 | tile = this.grid.cellContent({ x: x, y: y });
235 |
236 | if (tile) {
237 | for (var direction = 0; direction < 4; direction++) {
238 | var vector = self.getVector(direction);
239 | var cell = { x: x + vector.x, y: y + vector.y };
240 |
241 | var other = self.grid.cellContent(cell);
242 |
243 | if (other && other.value === tile.value) {
244 | return true; // These two tiles can be merged
245 | }
246 | }
247 | }
248 | }
249 | }
250 |
251 | return false;
252 | };
253 |
254 | GameManager.prototype.positionsEqual = function (first, second) {
255 | return first.x === second.x && first.y === second.y;
256 | };
257 |
--------------------------------------------------------------------------------
/style/main.css:
--------------------------------------------------------------------------------
1 | @import url(fonts/comic-sans.css);
2 | html, body {
3 | margin: 0;
4 | padding: 0;
5 | background: #fff;
6 | color: #000;
7 | /* font-family: "Clear Sans", "Helvetica Neue", Arial, sans-serif;*/
8 | font-family: 'Comic Sans', 'Comic Sans', Chalkboard, Helvetica, Arial, sans-serif;
9 | font-size: 18px;
10 | -webkit-animation: background-gradient-change linear 6s infinite alternate;
11 | -moz-animation: background-gradient-change linear 6s infinite alternate;
12 | -moz-animation: background-gradient-change linear 6s infinite alternate; }
13 |
14 | body {
15 | margin: 20px 0 0 0; }
16 |
17 | .overlay{
18 | height: 100%;
19 | width: 100%;
20 | position:fixed;
21 | top:0;
22 | left:0;
23 | overflow:auto;
24 | background: rgba(255,255,255,0.8);
25 | z-index: 1000;
26 | }
27 |
28 | .modal{
29 | background: #f0f;
30 | border-radius: 3px;
31 | width:300px;
32 | margin-top:100px;
33 | margin-left: auto;
34 | margin-right: auto;
35 | }
36 | .appstore{
37 | text-align: center;
38 | }
39 |
40 | .appstore-icon{
41 | margin-top:20px;
42 | margin-left:auto;
43 | margin-right:auto;
44 | height: 212px;
45 | width: 212px;
46 | background: #f0f url('../img/212/doge-sunglasses-212.gif');
47 | }
48 | .close-modal{
49 | margin-top:20px;
50 | cursor: pointer;
51 | }
52 |
53 | .close-modal:hover{
54 | -webkit-animation: hover-change linear 0.1s infinite;
55 | -moz-animation: hover-change linear 0.1s infinite;
56 | animation: hover-change linear 0.1s infinite;
57 | }
58 |
59 | .heading:after {
60 | content: "";
61 | display: block;
62 | clear: both; }
63 |
64 | h1.title {
65 | color:#333;
66 | font-size: 27px;
67 | font-weight: bold;
68 | margin: 0;
69 | display: block;
70 | float: left; }
71 |
72 | #twitter-widget-0 {
73 | width: 100px !important;
74 | position: relative;
75 | }
76 |
77 | .COINWIDGETCOM_CONTAINER {
78 | position: relative;
79 | bottom: 5px;
80 | }
81 |
82 | .footer > div{
83 | display:inline-block !important;
84 | width: auto !important;
85 | overflow:hidden;
86 | }
87 |
88 | .footer{
89 | /* width:188px;*/
90 | width:265px;
91 | margin-left: auto;
92 | margin-right: auto;
93 | text-align:center;}
94 |
95 | @-webkit-keyframes move-up {
96 | 0% {
97 | top: 25px;
98 | opacity: 1; }
99 |
100 | 100% {
101 | top: -50px;
102 | opacity: 0; } }
103 |
104 | @-moz-keyframes move-up {
105 | 0% {
106 | top: 25px;
107 | opacity: 1; }
108 |
109 | 100% {
110 | top: -50px;
111 | opacity: 0; } }
112 |
113 | @keyframes move-up {
114 | 0% {
115 | top: 25px;
116 | opacity: 1; }
117 |
118 | 100% {
119 | top: -50px;
120 | opacity: 0; } }
121 |
122 | @-webkit-keyframes fade-in-out {
123 | 0% {
124 | opacity: 0; }
125 |
126 | 50% {
127 | opacity: 1; }
128 |
129 | 100% {
130 | opacity: 0; } }
131 |
132 | @-moz-keyframes fade-in-out {
133 | 0% {
134 | opacity: 0; }
135 |
136 | 50% {
137 | opacity: 1; }
138 |
139 | 100% {
140 | opacity: 0; } }
141 |
142 | @keyframes fade-in-out {
143 | 0% {
144 | opacity: 0; }
145 |
146 | 50% {
147 | opacity: 1; }
148 |
149 | 100% {
150 | opacity: 0; } }
151 |
152 | @-webkit-keyframes hover-change {
153 | 0% {color: cyan;}
154 | 25% {color: magenta;}
155 | 50% {color: yellow;}
156 | 100% {color: white;} }
157 |
158 | @-moz-keyframes hover-change {
159 | 0% {color: cyan;}
160 | 25% {color: magenta;}
161 | 50% {color: yellow;}
162 | 100% {color: white;} }
163 |
164 | @keyframes hover-change {
165 | 0% {color: cyan;}
166 | 25% {color: magenta;}
167 | 50% {color: yellow;}
168 | 100% {color: white;} }
169 |
170 | @-webkit-keyframes background-gradient-change {
171 | 0% {background: #cff;}
172 | 33% {background: #fcf;}
173 | 66% {background: #ffc;}
174 | 100% {background: #cff;}}
175 |
176 | @-moz-keyframes background-gradient-change {
177 | 0% {background: #dff;}
178 | 33% {background: #fdf;}
179 | 66% {background: #ffd;}
180 | 100% {background: #dff;}}
181 |
182 | @keyframes background-gradient-change {
183 | 0% {background: #dff;}
184 | 33% {background: #fdf;}
185 | 66% {background: #ffd;}
186 | 100% {background: #dff;}}
187 |
188 | a:hover {
189 | -webkit-animation: hover-change linear 0.1s infinite;
190 | -moz-animation: hover-change linear 0.1s infinite;
191 | animation: hover-change linear 0.1s infinite;
192 | }
193 |
194 | .scores-container {
195 | float: right;
196 | text-align: right; }
197 |
198 | .game-container .doge-says {
199 | position: fixed;
200 | top: 0;
201 | left: 0;
202 | z-index: 100;}
203 | .game-container .doge-says p {
204 | position:fixed;
205 | font-size: 60px;
206 | font-weight: bold;
207 | height: 60px;
208 | line-height: 60px;
209 | -webkit-animation: fade-in-out 600ms ease-in;
210 | -moz-animation: fade-in-out 600ms ease-in;
211 | animation: fade-in-out 600ms ease-in;
212 | -webkit-animation-fill-mode: both;
213 | -moz-animation-fill-mode: both;
214 | animation-fill-mode: both; }
215 |
216 |
217 | .info-container {
218 | position: relative;
219 | cursor:pointer;
220 | left:50%;
221 | margin-left:-32px;
222 | margin-bottom:10px;}
223 |
224 | .shout-out-container{
225 | text-align:center;
226 | }
227 | .shout-out{
228 | height:10px;
229 | line-height: 10px;
230 | background: #f0f;
231 | padding: 10px 10px;
232 | border-radius: 3px;
233 | display:inline-block;
234 | }
235 |
236 | .shout-out a{
237 | font-weight: normal;
238 | height:10px;
239 | width:auto;
240 | text-decoration:none;
241 | color:#fff;
242 | }
243 |
244 | .info-container, .hide-info {
245 | display: inline-block;
246 | background: #f0f;
247 | padding: 10px 15px;
248 | height: 10px;
249 | line-height: 10px;
250 | font-size:10px;
251 | font-weight: bold;
252 | border-radius: 3px;
253 | color: white;
254 | margin-top: 8px;
255 | width: 36px;
256 | text-align: center; }
257 | .info-container a, .hide-info a{
258 | color:#fff;
259 | text-decoration:none;}
260 |
261 | .game-container .info {
262 | display: none;
263 | position: absolute;
264 | overflow: scroll;
265 | top: 0;
266 | right: 0;
267 | bottom: 0;
268 | left: 0;
269 | background: rgba(255,255,255,0.9);
270 | z-index: 100;
271 | border-radius: 6px;
272 | text-align: center;
273 | /* -webkit-animation: fade-in 800ms ease;
274 | -moz-animation: fade-in 800ms ease;
275 | animation: fade-in 800ms ease;*/
276 | -webkit-animation-fill-mode: both;
277 | -moz-animation-fill-mode: both;
278 | animation-fill-mode: both; }
279 | .game-container .info p {
280 | position:relative;
281 | font-size: 16px;
282 | padding:10px 20px 10px 20px;
283 | font-weight: bold;}
284 |
285 | .score-container, .best-container {
286 | position: relative;
287 | display: inline-block;
288 | background: #f0f;
289 | padding: 15px 25px;
290 | /* font-size: 25px;*/
291 | height: 9px;
292 | line-height: 27px;
293 | font-weight: bold;
294 | border-radius: 3px;
295 | color: white;
296 | margin-top: 8px;
297 | text-align: center; }
298 | .score-container:after, .best-container:after {
299 | position: absolute;
300 | width: 100%;
301 | top: 10px;
302 | left: 0;
303 | text-transform: uppercase;
304 | font-size: 12px;
305 | line-height: 13px;
306 | text-align: center;
307 | color: #000; }
308 | .score-container .score-addition, .best-container .score-addition {
309 | position: absolute;
310 | right: 30px;
311 | font-size: 20px;
312 | line-height: 20px;
313 | color: rgba(119, 110, 101, 0.9);
314 | z-index: 100;
315 | -webkit-animation: move-up 600ms ease-in;
316 | -moz-animation: move-up 600ms ease-in;
317 | animation: move-up 600ms ease-in;
318 | -webkit-animation-fill-mode: both;
319 | -moz-animation-fill-mode: both;
320 | animation-fill-mode: both; }
321 |
322 | .score-container:after {
323 | content: "Score"; }
324 |
325 | .best-container:after {
326 | content: "Best"; }
327 |
328 | p {
329 | margin-top: 0;
330 | margin-bottom: 10px;
331 | line-height: 1.65; }
332 |
333 | a {
334 | color: #f0f;
335 | font-weight: bold;
336 | text-decoration: underline;
337 | cursor: pointer; }
338 |
339 | strong.important {
340 | text-transform: uppercase; }
341 |
342 | hr {
343 | border: none;
344 | border-bottom: 1px solid #d8d4d0;
345 | margin-top: 20px;
346 | margin-bottom: 30px; }
347 |
348 | .container {
349 | width: 500px;
350 | margin: 0 auto; }
351 |
352 | @-webkit-keyframes fade-in {
353 | 0% {
354 | opacity: 0; }
355 |
356 | 100% {
357 | opacity: 1; } }
358 |
359 | @-moz-keyframes fade-in {
360 | 0% {
361 | opacity: 0; }
362 |
363 | 100% {
364 | opacity: 1; } }
365 |
366 | @keyframes fade-in {
367 | 0% {
368 | opacity: 0; }
369 |
370 | 100% {
371 | opacity: 1; } }
372 |
373 | .game-container {
374 | margin-top: 10px;
375 | position: relative;
376 | padding: 15px;
377 | cursor: default;
378 | -webkit-touch-callout: none;
379 | -webkit-user-select: none;
380 | -moz-user-select: none;
381 | background: rgba(0,0,0,0.05);
382 | /* background: #a0a0a0;*/
383 | border-radius: 6px;
384 | width: 500px;
385 | height: 500px;
386 | -webkit-box-sizing: border-box;
387 | -moz-box-sizing: border-box;
388 | box-sizing: border-box; }
389 | .game-container .game-message{
390 | display: none;
391 | position: absolute;
392 | top: 0;
393 | right: 0;
394 | bottom: 0;
395 | left: 0;
396 | background: rgba(255,255,255,0.9);
397 | z-index: 100;
398 | text-align: center;
399 | -webkit-animation: fade-in 800ms ease 1200ms;
400 | -moz-animation: fade-in 800ms ease 1200ms;
401 | animation: fade-in 800ms ease 1200ms;
402 | -webkit-animation-fill-mode: both;
403 | -moz-animation-fill-mode: both;
404 | animation-fill-mode: both; }
405 | .game-container .game-message p {
406 | font-size: 60px;
407 | font-weight: bold;
408 | height: 60px;
409 | line-height: 60px;
410 | margin-top: 222px; }
411 | .game-container .game-message .lower {
412 | display: block;
413 | margin-top: 59px; }
414 | .game-container .game-message a {
415 | display: inline-block;
416 | background: #f0f;
417 | border-radius: 3px;
418 | padding: 0 20px;
419 | text-decoration: none;
420 | color: #f9f6f2;
421 | height: 40px;
422 | line-height: 42px;
423 | margin-left: 9px; }
424 | .game-container .game-message a.keep-playing-button {
425 | display: none; }
426 | .game-container .game-message.game-won {
427 | background: rgba(237, 194, 46, 0.5);
428 | color: #f9f6f2; }
429 | .game-container .game-message.game-won a.keep-playing-button {
430 | display: inline-block; }
431 | .game-container .game-message.game-won, .game-container .game-message.game-over {
432 | display: block; }
433 |
434 | .grid-container {
435 | position: absolute;
436 | z-index: 1; }
437 |
438 | .grid-row {
439 | margin-bottom: 15px; }
440 | .grid-row:last-child {
441 | margin-bottom: 0; }
442 | .grid-row:after {
443 | content: "";
444 | display: block;
445 | clear: both; }
446 |
447 | .grid-cell {
448 | width: 106.25px;
449 | height: 106.25px;
450 | margin-right: 15px;
451 | float: left;
452 | border-radius: 3px;
453 | background: rgba(255,255,255,0.8);
454 | /* background: rgba(238, 228, 218, 0.35);*/
455 | }
456 | .grid-cell:last-child {
457 | margin-right: 0; }
458 |
459 | .tile-container {
460 | position: absolute;
461 | z-index: 2; }
462 |
463 | .tile, .tile .tile-inner {
464 | width: 107px;
465 | height: 107px;
466 | -webkit-transform: translate3d(0, 0, 0);
467 | line-height: 116.25px; }
468 | .tile.tile-position-1-1 {
469 | -webkit-transform: translate(0px, 0px);
470 | -moz-transform: translate(0px, 0px);
471 | transform: translate(0px, 0px); }
472 | .tile.tile-position-1-2 {
473 | -webkit-transform: translate(0px, 121px);
474 | -moz-transform: translate(0px, 121px);
475 | transform: translate(0px, 121px); }
476 | .tile.tile-position-1-3 {
477 | -webkit-transform: translate(0px, 242px);
478 | -moz-transform: translate(0px, 242px);
479 | transform: translate(0px, 242px); }
480 | .tile.tile-position-1-4 {
481 | -webkit-transform: translate(0px, 363px);
482 | -moz-transform: translate(0px, 363px);
483 | transform: translate(0px, 363px); }
484 | .tile.tile-position-2-1 {
485 | -webkit-transform: translate(121px, 0px);
486 | -moz-transform: translate(121px, 0px);
487 | transform: translate(121px, 0px); }
488 | .tile.tile-position-2-2 {
489 | -webkit-transform: translate(121px, 121px);
490 | -moz-transform: translate(121px, 121px);
491 | transform: translate(121px, 121px); }
492 | .tile.tile-position-2-3 {
493 | -webkit-transform: translate(121px, 242px);
494 | -moz-transform: translate(121px, 242px);
495 | transform: translate(121px, 242px); }
496 | .tile.tile-position-2-4 {
497 | -webkit-transform: translate(121px, 363px);
498 | -moz-transform: translate(121px, 363px);
499 | transform: translate(121px, 363px); }
500 | .tile.tile-position-3-1 {
501 | -webkit-transform: translate(242px, 0px);
502 | -moz-transform: translate(242px, 0px);
503 | transform: translate(242px, 0px); }
504 | .tile.tile-position-3-2 {
505 | -webkit-transform: translate(242px, 121px);
506 | -moz-transform: translate(242px, 121px);
507 | transform: translate(242px, 121px); }
508 | .tile.tile-position-3-3 {
509 | -webkit-transform: translate(242px, 242px);
510 | -moz-transform: translate(242px, 242px);
511 | transform: translate(242px, 242px); }
512 | .tile.tile-position-3-4 {
513 | -webkit-transform: translate(242px, 363px);
514 | -moz-transform: translate(242px, 363px);
515 | transform: translate(242px, 363px); }
516 | .tile.tile-position-4-1 {
517 | -webkit-transform: translate(363px, 0px);
518 | -moz-transform: translate(363px, 0px);
519 | transform: translate(363px, 0px); }
520 | .tile.tile-position-4-2 {
521 | -webkit-transform: translate(363px, 121px);
522 | -moz-transform: translate(363px, 121px);
523 | transform: translate(363px, 121px); }
524 | .tile.tile-position-4-3 {
525 | -webkit-transform: translate(363px, 242px);
526 | -moz-transform: translate(363px, 242px);
527 | transform: translate(363px, 242px); }
528 | .tile.tile-position-4-4 {
529 | -webkit-transform: translate(363px, 363px);
530 | -moz-transform: translate(363px, 363px);
531 | transform: translate(363px, 363px); }
532 |
533 | .tile {
534 | color: rgba(0,0,0,0);
535 | position: absolute;
536 | -webkit-transition: 100ms ease-in-out;
537 | -moz-transition: 100ms ease-in-out;
538 | transition: 100ms ease-in-out;
539 | -webkit-transition-property: -webkit-transform;
540 | -moz-transition-property: -moz-transform;
541 | transition-property: transform; }
542 | .tile .tile-inner {
543 | border-radius: 3px;
544 | background: #eee4da;
545 | text-align: center;
546 | font-weight: bold;
547 | z-index: 10;
548 | font-size: 55px; }
549 | .tile.tile-2 .tile-inner {
550 | background: #f0f url('../img/212/doge-wink-212.gif');
551 | background-size: cover;
552 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
553 |
554 | .tile.tile-4 .tile-inner {
555 | background: #f0f url('../img/212/doge-shake-space-212.gif');
556 | background-size: cover;
557 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
558 |
559 | .tile.tile-8 .tile-inner {
560 | background: #f0f url('../img/212/doge-peepers-212.gif');
561 | background-size: cover;}
562 |
563 | .tile.tile-16 .tile-inner {
564 | background: #f0f url('../img/212/doge-prizza-212.gif');
565 | background-size: cover;}
566 |
567 | .tile.tile-32 .tile-inner {
568 | background: #f0f url('../img/212/doge-hat-212.gif');
569 | background-size: cover;}
570 |
571 | .tile.tile-64 .tile-inner {
572 | background: #f0f url('../img/212/doge-gradient-212.gif');
573 | background-size: cover;}
574 |
575 | .tile.tile-128 .tile-inner {
576 | background: #f0f url('../img/212/doge-fat-212.gif');
577 | background-size: cover;
578 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.2381), inset 0 0 0 1px rgba(255, 255, 255, 0.14286);
579 | font-size: 45px; }
580 | @media screen and (max-width: 480px) {
581 | .tile.tile-128 .tile-inner {
582 | font-size: 25px; } }
583 | .tile.tile-256 .tile-inner {
584 |
585 | background: #f0f url('../img/212/doge-rainbow-212.gif');
586 | background-size: cover;
587 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.31746), inset 0 0 0 1px rgba(255, 255, 255, 0.19048);
588 | font-size: 45px; }
589 | @media screen and (max-width: 480px) {
590 | .tile.tile-256 .tile-inner {
591 | font-size: 25px; } }
592 | .tile.tile-512 .tile-inner {
593 |
594 | background: #f0f url('../img/212/doge-sunglasses-212.gif');
595 | background-size: cover;
596 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.39683), inset 0 0 0 1px rgba(255, 255, 255, 0.2381);
597 | font-size: 45px; }
598 | @media screen and (max-width: 480px) {
599 | .tile.tile-512 .tile-inner {
600 | font-size: 25px; } }
601 | .tile.tile-1024 .tile-inner {
602 | background: #f0f url('../img/212/doge-derp-212.gif');
603 | background-size: cover;
604 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.47619), inset 0 0 0 1px rgba(255, 255, 255, 0.28571);
605 | font-size: 35px; }
606 | @media screen and (max-width: 480px) {
607 | .tile.tile-1024 .tile-inner {
608 | font-size: 15px; } }
609 | .tile.tile-2048 .tile-inner {
610 |
611 | background: #f0f url('../img/212/doge-shake-212.gif');
612 | background-size: cover;
613 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.55556), inset 0 0 0 1px rgba(255, 255, 255, 0.33333);
614 | font-size: 35px; }
615 | @media screen and (max-width: 480px) {
616 | .tile.tile-2048 .tile-inner {
617 | font-size: 15px; } }
618 | .tile.tile-super .tile-inner {
619 |
620 | background: #f0f url('../img/212/doge-derp-212.gif');
621 | background-size: cover;
622 | font-size: 30px; }
623 | @media screen and (max-width: 480px) {
624 | .tile.tile-super .tile-inner {
625 | font-size: 10px; } }
626 |
627 | @-webkit-keyframes appear {
628 | 0% {
629 | opacity: 0;
630 | -webkit-transform: scale(0);
631 | -moz-transform: scale(0);
632 | transform: scale(0); }
633 |
634 | 100% {
635 | opacity: 1;
636 | -webkit-transform: scale(1);
637 | -moz-transform: scale(1);
638 | transform: scale(1); } }
639 |
640 | @-moz-keyframes appear {
641 | 0% {
642 | opacity: 0;
643 | -webkit-transform: scale(0);
644 | -moz-transform: scale(0);
645 | transform: scale(0); }
646 |
647 | 100% {
648 | opacity: 1;
649 | -webkit-transform: scale(1);
650 | -moz-transform: scale(1);
651 | transform: scale(1); } }
652 |
653 | @keyframes appear {
654 | 0% {
655 | opacity: 0;
656 | -webkit-transform: scale(0);
657 | -moz-transform: scale(0);
658 | transform: scale(0); }
659 |
660 | 100% {
661 | opacity: 1;
662 | -webkit-transform: scale(1);
663 | -moz-transform: scale(1);
664 | transform: scale(1); } }
665 |
666 | .tile-new .tile-inner {
667 | -webkit-animation: appear 200ms ease 100ms;
668 | -moz-animation: appear 200ms ease 100ms;
669 | animation: appear 200ms ease 100ms;
670 | -webkit-animation-fill-mode: backwards;
671 | -moz-animation-fill-mode: backwards;
672 | animation-fill-mode: backwards; }
673 |
674 | @-webkit-keyframes pop {
675 | 0% {
676 | -webkit-transform: scale(0);
677 | -moz-transform: scale(0);
678 | transform: scale(0); }
679 |
680 | 50% {
681 | -webkit-transform: scale(1.2);
682 | -moz-transform: scale(1.2);
683 | transform: scale(1.2); }
684 |
685 | 100% {
686 | -webkit-transform: scale(1);
687 | -moz-transform: scale(1);
688 | transform: scale(1); } }
689 |
690 | @-moz-keyframes pop {
691 | 0% {
692 | -webkit-transform: scale(0);
693 | -moz-transform: scale(0);
694 | transform: scale(0); }
695 |
696 | 50% {
697 | -webkit-transform: scale(1.2);
698 | -moz-transform: scale(1.2);
699 | transform: scale(1.2); }
700 |
701 | 100% {
702 | -webkit-transform: scale(1);
703 | -moz-transform: scale(1);
704 | transform: scale(1); } }
705 |
706 | @keyframes pop {
707 | 0% {
708 | -webkit-transform: scale(0);
709 | -moz-transform: scale(0);
710 | transform: scale(0); }
711 |
712 | 50% {
713 | -webkit-transform: scale(1.2);
714 | -moz-transform: scale(1.2);
715 | transform: scale(1.2); }
716 |
717 | 100% {
718 | -webkit-transform: scale(1);
719 | -moz-transform: scale(1);
720 | transform: scale(1); } }
721 |
722 | .tile-merged .tile-inner {
723 | z-index: 20;
724 | -webkit-animation: pop 200ms ease 100ms;
725 | -moz-animation: pop 200ms ease 100ms;
726 | animation: pop 200ms ease 100ms;
727 | -webkit-animation-fill-mode: backwards;
728 | -moz-animation-fill-mode: backwards;
729 | animation-fill-mode: backwards; }
730 |
731 | .game-intro {
732 | margin-bottom: 0; }
733 |
734 | .game-explanation, .shout-out {
735 | margin-top: 0px;
736 | text-align: center;
737 | font-size: 14px;}
738 |
739 |
740 |
741 | @media screen and (max-width: 480px) {
742 | html, body {
743 | font-size: 15px; }
744 |
745 | body {
746 | margin: 20px 0;
747 | padding: 0 20px; }
748 |
749 | .modal{
750 | width:280px;}
751 |
752 | h1.title {
753 | font-size: 25px;
754 | margin-top: 15px; }
755 |
756 | .container {
757 | width: 280px;
758 | margin: 0 auto; }
759 |
760 | .score-container, .best-container {
761 | margin-top: 0;
762 | padding: 15px 10px;
763 | min-width: 40px; }
764 |
765 | .heading {
766 | margin-bottom: 10px; }
767 |
768 | .game-explanation {
769 | display:none;}
770 |
771 | .shout-out, .game-explanation{
772 | margin-top:10px;
773 | height:0;
774 | padding-top:10px;
775 | padding-bottom:20px;
776 | /* font-size:12px;*/
777 | }
778 |
779 | .game-container {
780 | margin-top: 40px;
781 | position: relative;
782 | padding: 10px;
783 | cursor: default;
784 | -webkit-touch-callout: none;
785 | -webkit-user-select: none;
786 | -moz-user-select: none;
787 | border-radius: 6px;
788 | width: 280px;
789 | height: 280px;
790 | -webkit-box-sizing: border-box;
791 | -moz-box-sizing: border-box;
792 | box-sizing: border-box; }
793 | .game-container .game-message {
794 | display: none;
795 | position: absolute;
796 | top: 0;
797 | right: 0;
798 | bottom: 0;
799 | left: 0;
800 | z-index: 100;
801 | text-align: center;
802 | -webkit-animation: fade-in 800ms ease;
803 | -moz-animation: fade-in 800ms ease;
804 | animation: fade-in 800ms ease;
805 | -webkit-animation-fill-mode: both;
806 | -moz-animation-fill-mode: both;
807 | animation-fill-mode: both; }
808 | .game-container .game-message p {
809 | font-size: 60px;
810 | font-weight: bold;
811 | height: 60px;
812 | line-height: 60px;
813 | margin-top: 222px; }
814 | .game-container .game-message .lower {
815 | display: block;
816 | margin-top: 59px; }
817 | .game-container .game-message a {
818 | display: inline-block;
819 | border-radius: 3px;
820 | padding: 0 20px;
821 | text-decoration: none;
822 | height: 40px;
823 | line-height: 42px;
824 | margin-left: 9px; }
825 | .game-container .game-message a.keep-playing-button {
826 | display: none; }
827 | .game-container .game-message.game-won {
828 | background: rgba(237, 194, 46, 0.5);}
829 | .game-container .game-message.game-won a.keep-playing-button {
830 | display: inline-block; }
831 | .game-container .game-message.game-won, .game-container .game-message.game-over {
832 | display: block; }
833 |
834 | .grid-container {
835 | position: absolute;
836 | z-index: 1; }
837 |
838 | .grid-row {
839 | margin-bottom: 10px; }
840 | .grid-row:last-child {
841 | margin-bottom: 0; }
842 | .grid-row:after {
843 | content: "";
844 | display: block;
845 | clear: both; }
846 |
847 | .grid-cell {
848 | width: 57.5px;
849 | height: 57.5px;
850 | margin-right: 10px;
851 | float: left;
852 | border-radius: 3px;}
853 | .grid-cell:last-child {
854 | margin-right: 0; }
855 |
856 | .tile-container {
857 | position: absolute;
858 | z-index: 2; }
859 |
860 | .tile, .tile .tile-inner {
861 | width: 58px;
862 | height: 58px;
863 | line-height: 67.5px; }
864 | .tile.tile-position-1-1 {
865 | -webkit-transform: translate(0px, 0px);
866 | -moz-transform: translate(0px, 0px);
867 | transform: translate(0px, 0px); }
868 | .tile.tile-position-1-2 {
869 | -webkit-transform: translate(0px, 67px);
870 | -moz-transform: translate(0px, 67px);
871 | transform: translate(0px, 67px); }
872 | .tile.tile-position-1-3 {
873 | -webkit-transform: translate(0px, 135px);
874 | -moz-transform: translate(0px, 135px);
875 | transform: translate(0px, 135px); }
876 | .tile.tile-position-1-4 {
877 | -webkit-transform: translate(0px, 202px);
878 | -moz-transform: translate(0px, 202px);
879 | transform: translate(0px, 202px); }
880 | .tile.tile-position-2-1 {
881 | -webkit-transform: translate(67px, 0px);
882 | -moz-transform: translate(67px, 0px);
883 | transform: translate(67px, 0px); }
884 | .tile.tile-position-2-2 {
885 | -webkit-transform: translate(67px, 67px);
886 | -moz-transform: translate(67px, 67px);
887 | transform: translate(67px, 67px); }
888 | .tile.tile-position-2-3 {
889 | -webkit-transform: translate(67px, 135px);
890 | -moz-transform: translate(67px, 135px);
891 | transform: translate(67px, 135px); }
892 | .tile.tile-position-2-4 {
893 | -webkit-transform: translate(67px, 202px);
894 | -moz-transform: translate(67px, 202px);
895 | transform: translate(67px, 202px); }
896 | .tile.tile-position-3-1 {
897 | -webkit-transform: translate(135px, 0px);
898 | -moz-transform: translate(135px, 0px);
899 | transform: translate(135px, 0px); }
900 | .tile.tile-position-3-2 {
901 | -webkit-transform: translate(135px, 67px);
902 | -moz-transform: translate(135px, 67px);
903 | transform: translate(135px, 67px); }
904 | .tile.tile-position-3-3 {
905 | -webkit-transform: translate(135px, 135px);
906 | -moz-transform: translate(135px, 135px);
907 | transform: translate(135px, 135px); }
908 | .tile.tile-position-3-4 {
909 | -webkit-transform: translate(135px, 202px);
910 | -moz-transform: translate(135px, 202px);
911 | transform: translate(135px, 202px); }
912 | .tile.tile-position-4-1 {
913 | -webkit-transform: translate(202px, 0px);
914 | -moz-transform: translate(202px, 0px);
915 | transform: translate(202px, 0px); }
916 | .tile.tile-position-4-2 {
917 | -webkit-transform: translate(202px, 67px);
918 | -moz-transform: translate(202px, 67px);
919 | transform: translate(202px, 67px); }
920 | .tile.tile-position-4-3 {
921 | -webkit-transform: translate(202px, 135px);
922 | -moz-transform: translate(202px, 135px);
923 | transform: translate(202px, 135px); }
924 | .tile.tile-position-4-4 {
925 | -webkit-transform: translate(202px, 202px);
926 | -moz-transform: translate(202px, 202px);
927 | transform: translate(202px, 202px); }
928 |
929 | .tile.tile-2 .tile-inner {
930 | background: #f0f url('../img/114/doge-wink-114.gif');
931 | background-size: cover;
932 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
933 |
934 | .tile.tile-4 .tile-inner {
935 | background: #f0f url('../img/114/doge-shake-space-114.gif');
936 | background-size: cover;
937 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
938 |
939 | .tile.tile-8 .tile-inner {
940 | background: #f0f url('../img/114/doge-peepers-114.gif');
941 | background-size: cover;}
942 |
943 | .tile.tile-16 .tile-inner {
944 | background: #f0f url('../img/114/doge-prizza-114.gif');
945 | background-size: cover;}
946 |
947 | .tile.tile-32 .tile-inner {
948 | background: #f0f url('../img/114/doge-hat-114.gif');
949 | background-size: cover;}
950 |
951 | .tile.tile-64 .tile-inner {
952 | background: #f0f url('../img/114/doge-gradient-114.gif');
953 | background-size: cover;}
954 |
955 | .tile.tile-128 .tile-inner {
956 | background: #f0f url('../img/114/doge-fat-114.gif');
957 | background-size: cover;
958 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.2381), inset 0 0 0 1px rgba(255, 255, 255, 0.14286);
959 | font-size: 45px; }
960 | @media screen and (max-width: 480px) {
961 | .tile.tile-128 .tile-inner {
962 | font-size: 25px; } }
963 | .tile.tile-256 .tile-inner {
964 |
965 | background: #f0f url('../img/114/doge-rainbow-114.gif');
966 | background-size: cover;
967 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.31746), inset 0 0 0 1px rgba(255, 255, 255, 0.19048);
968 | font-size: 45px; }
969 | @media screen and (max-width: 480px) {
970 | .tile.tile-256 .tile-inner {
971 | font-size: 25px; } }
972 | .tile.tile-512 .tile-inner {
973 |
974 | background: #f0f url('../img/114/doge-sunglasses-114.gif');
975 | background-size: cover;
976 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.39683), inset 0 0 0 1px rgba(255, 255, 255, 0.2381);
977 | font-size: 45px; }
978 | @media screen and (max-width: 480px) {
979 | .tile.tile-512 .tile-inner {
980 | font-size: 25px; } }
981 | .tile.tile-1024 .tile-inner {
982 | background: #f0f url('../img/114/doge-derp-114.gif');
983 | background-size: cover;
984 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.47619), inset 0 0 0 1px rgba(255, 255, 255, 0.28571);
985 | font-size: 35px; }
986 | @media screen and (max-width: 480px) {
987 | .tile.tile-1024 .tile-inner {
988 | font-size: 15px; } }
989 | .tile.tile-2048 .tile-inner {
990 |
991 | background: #f0f url('../img/114/doge-shake-114.gif');
992 | background-size: cover;
993 | box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.55556), inset 0 0 0 1px rgba(255, 255, 255, 0.33333);
994 | font-size: 35px; }
995 | @media screen and (max-width: 480px) {
996 | .tile.tile-2048 .tile-inner {
997 | font-size: 15px; } }
998 | .tile.tile-super .tile-inner {
999 |
1000 | background: #f0f url('../img/114/doge-derp-114.gif');
1001 | background-size: cover;
1002 | font-size: 30px; }
1003 | @media screen and (max-width: 480px) {
1004 | .tile.tile-super .tile-inner {
1005 | font-size: 10px; } }
1006 |
1007 |
1008 | .footer{
1009 | width:188px;}
1010 |
1011 | #twitter-widget-0 {
1012 | position: relative;
1013 | top:5px;
1014 | }
1015 |
1016 | .COINWIDGETCOM_CONTAINER {
1017 | display:none !important;
1018 | }
1019 |
1020 | .game-container .info p {
1021 | font-size: 12px;
1022 | padding:5px 10px 5px 10px;
1023 | }
1024 |
1025 | .game-container {
1026 | margin-top: 20px; }
1027 |
1028 | .tile .tile-inner {
1029 | font-size: 35px; }
1030 |
1031 | .doge-says p {
1032 | font-size: 30px !important;
1033 | height: 30px !important;
1034 | line-height: 30px !important;}
1035 |
1036 | .game-message p {
1037 | font-size: 30px !important;
1038 | height: 30px !important;
1039 | line-height: 30px !important;
1040 | margin-top: 90px !important; }
1041 | .game-message .lower {
1042 | margin-top: 30px !important; } }
1043 |
--------------------------------------------------------------------------------