/****
* Classes
****/
var Tile = Container.expand(function (value) {
var self = Container.call(this);
self.alpha = 0;
var fadeIn = function fadeIn() {
if (self.alpha < 1) {
self.alpha = Math.min(self.alpha + 0.24, 1);
self.scale.set(self.alpha);
LK.setTimeout(fadeIn, 16.67);
} else {
self.alpha = 1;
self.scale.set(1);
}
};
fadeIn();
self.value = value || 2;
var tileGraphics = self.attachAsset('tile', {
anchorX: 0.5,
anchorY: 0.5
});
var hsvToRgb = function hsvToRgb(h, s, v) {
var r, g, b;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v, g = t, b = p;
break;
case 1:
r = q, g = v, b = p;
break;
case 2:
r = p, g = v, b = t;
break;
case 3:
r = p, g = q, b = v;
break;
case 4:
r = t, g = p, b = v;
break;
case 5:
r = v, g = p, b = q;
break;
}
return (Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255);
};
self.setTint = function () {
var hue = (Math.log2(self.value) + 6) % 20 / 20;
tileGraphics.tint = hsvToRgb(hue, 0.3, 1);
};
self.setTint();
var tileLabel = new Text2(self.value.toString(), {
size: 300,
fill: '#332d28',
font: 'Sans-Serif',
weight: '800',
strokeThickness: 0
});
tileLabel.anchor.set(0.5, 0.5);
tileLabel.x = 0;
tileLabel.y = -40;
self.addChild(tileLabel);
self.setValue = function (value) {
self.newValue = value;
};
self.updateToRealValue = function () {
if (self.newValue) {
self.value = self.newValue;
tileLabel.setText(self.value.toString());
var textScale = Math.min(1, 350 / (tileLabel.width / tileLabel.scale.x));
tileLabel.scale.set(textScale);
self.setTint();
self.newValue = null;
self.scale.set(1.2);
var scaleDown = function scaleDown() {
if (self.scale.x > 1) {
self.scale.x -= 0.02;
self.scale.y -= 0.02;
LK.setTimeout(scaleDown, 16.67);
} else {
self.scale.set(1);
}
};
scaleDown();
}
};
self.targetX = 0;
self.targetY = 0;
self.isMoving = false;
self.merged = false;
self.setPosition = function (x, y, instant) {
self.targetX = x * 500 + 250;
self.targetY = y * 500 + 250;
if (instant) {
self.x = self.targetX;
self.y = self.targetY;
}
};
self.move = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 150) {
self.isMoving = true;
self.x += dx / distance * 150;
self.y += dy / distance * 150;
return false;
}
self.isMoving = false;
self.x = self.targetX;
self.y = self.targetY;
return true;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
game.checkPossibleMoves = function () {
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
if (squares[i][j] === null) {
return true;
}
if (i < gridSize - 1 && squares[i][j] !== null && squares[i + 1][j] !== null && squares[i][j].value === squares[i + 1][j].value) {
return true;
}
if (j < gridSize - 1 && squares[i][j] !== null && squares[i][j + 1] !== null && squares[i][j].value === squares[i][j + 1].value) {
return true;
}
}
}
return false;
};
var scoreTxt = new Text2('2', {
size: 220,
fill: '#000000',
font: 'Impact',
strokeThickness: 0
});
scoreTxt.anchor.set(.5, 0);
LK.gui.topCenter.addChild(scoreTxt);
var tutorialTxt = new Text2('Swipe to merge & merge', {
size: 120,
fill: '#000000',
font: 'Impact',
strokeThickness: 0
});
tutorialTxt.anchor.set(.5, 1);
LK.gui.bottom.addChild(tutorialTxt);
tutorialTxt.y -= 30;
var toBeRemoved = [];
game.addRandomTile = function () {
var emptyPositions = [];
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
if (squares[i][j] === null) {
emptyPositions.push({
x: i,
y: j
});
}
}
}
if (emptyPositions.length > 0) {
var randomPosition = emptyPositions[Math.floor(Math.random() * emptyPositions.length)];
var square = new Tile(Math.random() < 0.5 ? 2 : 4);
square.setPosition(randomPosition.x, randomPosition.y, true);
squares[randomPosition.x][randomPosition.y] = square;
gridContainer.addChild(square);
}
};
game.mergeTiles = function (x1, y1, x2, y2) {
if (squares[x1][y1] !== null && squares[x2][y2] !== null && squares[x1][y1].value === squares[x2][y2].value && !squares[x1][y1].merged && !squares[x2][y2].merged) {
squares[x2][y2].setValue(squares[x2][y2].value * 2, true);
squares[x2][y2].merged = true;
squares[x1][y1].targetX = squares[x2][y2].targetX;
squares[x1][y1].targetY = squares[x2][y2].targetY;
toBeRemoved.push(squares[x1][y1]);
squares[x1][y1] = null;
gridContainer.removeChild(squares[x2][y2]);
gridContainer.addChild(squares[x2][y2]);
return true;
}
return false;
};
var gridSize = 4;
game.setBackgroundColor(0xD3D3D3);
var gridContainer = new Container();
gridContainer.x = 44;
gridContainer.y = 400;
game.addChild(gridContainer);
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
var gridTile = gridContainer.attachAsset('gridTile', {
anchorX: 0.5,
anchorY: 0.5
});
gridTile.x = i * 500 + 250;
gridTile.y = j * 500 + 250;
gridTile.alpha = .1;
}
}
var squares = new Array(gridSize).fill().map(function () {
return new Array(gridSize).fill(null);
});
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
squares[i][j] = null;
}
}
var initialTiles = 2;
for (var i = 0; i < initialTiles; i++) {
var x, y;
do {
x = Math.floor(Math.random() * gridSize);
y = Math.floor(Math.random() * gridSize);
} while (squares[x][y] !== null);
var square = new Tile();
square.setPosition(x, y, true);
square.alpha = 1;
square.scale.set(1);
squares[x][y] = square;
gridContainer.addChild(square);
}
var swipeStart = {
x: 0,
y: 0
};
var swipeEnd = {
x: 0,
y: 0
};
var boardChanged = false;
var winMessageShown = false;
game.moveTiles = function (direction) {
var dx = (direction === 'right') - (direction === 'left');
var dy = (direction === 'down') - (direction === 'up');
var moved = false;
do {
moved = false;
var iStart = dx > 0 ? gridSize - 1 : 0;
var iEnd = dx > 0 ? -1 : gridSize;
var iStep = dx > 0 ? -1 : 1;
var jStart = dy > 0 ? gridSize - 1 : 0;
var jEnd = dy > 0 ? -1 : gridSize;
var jStep = dy > 0 ? -1 : 1;
for (var i = iStart; i !== iEnd; i += iStep) {
for (var j = jStart; j !== jEnd; j += jStep) {
var x = i + dx;
var y = j + dy;
if (x >= 0 && x < gridSize && y >= 0 && y < gridSize && squares[i][j] !== null) {
if (squares[x][y] === null) {
squares[x][y] = squares[i][j];
squares[i][j] = null;
squares[x][y].setPosition(x, y);
moved = true;
boardChanged = true;
} else if (squares[x][y] !== null && squares[i][j] !== null && squares[x][y].value === squares[i][j].value) {
moved = game.mergeTiles(i, j, x, y);
if (moved) {
boardChanged = true;
}
}
}
}
}
} while (moved);
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
if (squares[i][j] !== null) {
squares[i][j].merged = false;
}
}
}
};
game.on('down', function (obj) {
var anyTileMoving = squares.some(function (row) {
return row.some(function (tile) {
return tile && tile.isMoving;
});
});
if (!anyTileMoving) {
var pos = obj.event.getLocalPosition(game);
swipeStart = {
x: pos.x,
y: pos.y
};
}
});
game.on('up', function (obj) {
var pos = obj.event.getLocalPosition(game);
swipeEnd = {
x: pos.x,
y: pos.y
};
var dx = swipeEnd.x - swipeStart.x;
var dy = swipeEnd.y - swipeStart.y;
var threshold = 50;
if (Math.abs(dx) > threshold || Math.abs(dy) > threshold) {
if (Math.abs(dx) > Math.abs(dy)) {
if (dx > 0) {
game.moveTiles('right');
} else {
game.moveTiles('left');
}
} else {
if (dy > 0) {
game.moveTiles('down');
} else {
game.moveTiles('up');
}
}
if (tutorialTxt) {
LK.gui.bottom.removeChild(tutorialTxt);
tutorialTxt = null;
}
}
});
LK.on('tick', function () {
var allTilesStopped = true;
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
if (squares[i][j] !== null) {
if (!squares[i][j].move()) {
allTilesStopped = false;
}
}
}
}
for (var i = 0; i < toBeRemoved.length; i++) {
if (!toBeRemoved[i].move()) {
allTilesStopped = false;
} else {
toBeRemoved[i].destroy();
toBeRemoved.splice(i, 1);
i--;
}
}
if (allTilesStopped) {
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
if (squares[i][j] !== null && squares[i][j].newValue) {
squares[i][j].updateToRealValue();
if (squares[i][j].value === 2048 && !winMessageShown) {
var winMessage = new Text2('Congratulations\n you win!', {
size: 150,
fill: '#ffffff',
font: 'Sans-Serif',
weight: '800',
stroke: '#000000',
strokeThickness: 25,
align: 'center'
});
winMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(winMessage);
winMessageShown = true;
LK.setTimeout(function () {
LK.gui.center.removeChild(winMessage);
}, 5000);
}
}
}
}
if (boardChanged) {
game.addRandomTile();
boardChanged = false;
var maxTileValue = Math.max.apply(Math, squares.map(function (row) {
return Math.max.apply(Math, row.map(function (tile) {
return tile ? tile.value : 0;
}));
}));
var newScore = maxTileValue;
LK.setScore(newScore);
scoreTxt.setText(newScore.toString());
}
if (!game.checkPossibleMoves()) {
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
if (squares[i][j] !== null) {
squares[i][j].alpha = 1;
squares[i][j].scale.set(1);
}
}
}
LK.showGameOver();
}
}
});