var Particle = Container.expand(function (tint) { var self = Container.call(this); self.tint = tint; var particleGraphics = self.createAsset('particle', 'Particle Graphics', 0.5, 0.5); particleGraphics.rotation = Math.random() * Math.PI * 2; particleGraphics.tint = self.tint; self.vx = Math.random() * 4 - 2; self.vy = Math.random() * 4 - 2; self.alpha = 1; self.lifetime = 60; self.tick = function () { self.x += self.vx; self.y += self.vy; self.alpha -= 1 / self.lifetime; if (self.alpha <= 0) self.destroy(); }; }); var Cell = Container.expand(function (type) { var self = Container.call(this); var cellGraphics = self.createAsset('cell', 'Grid Cell', .5, .5); self.targetX = 0; self.targetY = 0; self.isMoving = false; self.totalTypes = 5; self.type = type || Math.floor(Math.random() * self.totalTypes); var hue = self.type / self.totalTypes; var color = hsvToRgb(hue, 0.6, 1); cellGraphics.tint = color; self.move = function (x, y, instant) { self.targetX = x; self.targetY = y; if (instant) { self.x = x; self.y = y; } }; self.tick = function () { var acceleration = 1; self.speedX = self.speedX || 0; self.speedY = self.speedY || 0; var threshold = 1; var dx = self.targetX - self.x; var dy = self.targetY - self.y; if (Math.abs(dx) < threshold && Math.abs(dy) < threshold) { self.x = self.targetX; self.y = self.targetY; self.isMoving = false; self.speedX = 0; self.speedY = 0; } else { if (dx !== 0) { self.speedX += dx > 0 ? acceleration : -acceleration; } if (dy !== 0) { self.speedY += dy > 0 ? acceleration : -acceleration; } var nextX = self.x + self.speedX; var nextY = self.y + self.speedY; if (self.speedX > 0 && nextX > self.targetX || self.speedX < 0 && nextX < self.targetX) { nextX = self.targetX; self.speedX = 0; } if (self.speedY > 0 && nextY > self.targetY || self.speedY < 0 && nextY < self.targetY) { nextY = self.targetY; self.speedY = 0; } self.x = nextX; self.y = nextY; self.isMoving = self.x !== self.targetX || self.y !== self.targetY; } }; }); function hsvToRgb(h, s, v) { var i = Math.floor(h * 6), f = h * 6 - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s), mod = i % 6, r = [v, q, p, p, t, v][mod], g = [t, v, v, q, p, p][mod], b = [p, p, t, v, v, q][mod]; return (r * 255 << 16) + (g * 255 << 8) + b * 255; } var Game = Container.expand(function () { var self = Container.call(this); var background = self.createAsset('background', 'Background Asset', 0, 0); background.width = LK.stage.width; background.height = LK.stage.height; self.addChildAt(background, 0); var score = 0; var selectedCells = []; self.particles = []; var scoreTxt = new Text2('0', { size: 150, fill: "#ffffff", font: "'Fredoka One', cursive", dropShadow: false, dropShadowColor: '#000000' }); LK.gui.topCenter.addChild(scoreTxt); scoreTxt.x -= 80; scoreTxt.y += 100; self.spawnParticles = function (x, y, color) { for (var i = 0; i < 10; i++) { var particle = new Particle(color); particle.x = gridContainer.x + x; particle.y = gridContainer.y + y; var hue = color / 0xFFFFFF; particle.tint = hsvToRgb(hue, 0.6, 1); self.particles.push(particle); self.addChild(particle); } }; self.checkMovesAllowed = function () { for (var i = 0; i < gridWidth; i++) { for (var j = 0; j < gridHeight; j++) { var cell = grid[i][j]; if (cell) { var neighbors = self.findConnectedNeighbors(cell); if (neighbors.length > 1) { return true; } } } } return false; }; var gridWidth = 4; var gridHeight = 4; var gridSpacing = 8; var tempCell = new Cell(); var cellWidth = tempCell.width; var cellHeight = tempCell.height; tempCell.destroy(); var gridContainer = new Container(); self.addChild(gridContainer); var totalGridWidth = gridWidth * (cellWidth + gridSpacing) - gridSpacing; var totalGridHeight = gridHeight * (cellHeight + gridSpacing) - gridSpacing; gridContainer.x = (2048 - totalGridWidth) / 2 + cellWidth / 2 + 5; gridContainer.y = (2732 - totalGridHeight) / 2 + cellHeight / 2; self.calculateTargetPosition = function (col, row) { return { x: col * (cellWidth + gridSpacing), y: row * (cellHeight + gridSpacing) }; }; self.findConnectedNeighbors = function (cell, connectedNeighbors) { connectedNeighbors = connectedNeighbors || []; if (!cell) return []; var cellType = cell.type; var cellColRow = self.findCellColRow(cell); if (cellColRow) { var directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; directions.forEach(function (dir) { var newRow = cellColRow.row + dir[0]; var newCol = cellColRow.col + dir[1]; if (newRow >= 0 && newRow < gridHeight && newCol >= 0 && newCol < gridWidth) { var neighborCell = grid[newCol][newRow]; if (neighborCell && neighborCell.type === cellType && connectedNeighbors.indexOf(neighborCell) === -1) { connectedNeighbors.push(neighborCell); self.findConnectedNeighbors(neighborCell, connectedNeighbors); } } }); } return connectedNeighbors; }; self.findCellColRow = function (cell) { for (var col = 0; col < gridWidth; col++) { for (var row = 0; row < gridHeight; row++) { if (grid[col][row] === cell) { return { col: col, row: row }; } } } return null; }; self.deleteCell = function (cell) { var colRow = self.findCellColRow(cell); if (colRow) { grid[colRow.col][colRow.row] = null; var hue = cell.type / cell.totalTypes; var color = hsvToRgb(hue, 0.6, 1); self.spawnParticles(cell.x, cell.y, color); cell.destroy(); score += Math.pow(2, selectedCells.length); LK.setScore(score); scoreTxt.setText('Score: ' + score); self.moveToEmptySpace(); } }; self.attachCellListeners = function (cell) { var dragStartCell = null; self.resetSelectedCells = function () { selectedCells.forEach(function (cell) { cell.alpha = 1; }); self.resetSelectedCells = function () { selectedCells.forEach(function (cell) { cell.alpha = 1; }); selectedCells = []; }; selectedCells = []; }; cell.on('down', function (obj) { dragStartCell = cell; selectedCells.push(cell); cell.alpha = 0.5; }); cell.on('move', function (obj) { if (dragStartCell) { var pos = obj.event.getLocalPosition(gridContainer); var col = Math.floor((pos.x + cellWidth / 2) / (cellWidth + gridSpacing)); var row = Math.floor((pos.y + cellHeight / 2) / (cellHeight + gridSpacing)); if (col >= 0 && col < gridWidth && row >= 0 && row < gridHeight) { var targetCell = grid[col][row]; if (targetCell && selectedCells.indexOf(targetCell) === -1) { if (targetCell.type === dragStartCell.type) { targetCell.alpha = 0.5; selectedCells.push(targetCell); } else { self.resetSelectedCells(); dragStartCell = null; } } } } }); cell.on('up', function (obj) { if (selectedCells.length >= 4) { for (var col = 0; col < gridWidth; col++) { for (var row = 0; row < gridHeight; row++) { var cell = grid[col][row]; if (cell && dragStartCell && cell.type === dragStartCell.type) { self.deleteCell(cell); } } } } else if (selectedCells.length > 1) { for (var i = 0; i < selectedCells.length; i++) { self.deleteCell(selectedCells[i]); } } selectedCells.forEach(function (cell) { cell.alpha = 1; }); selectedCells = []; dragStartCell = null; }); }; var grid = []; for (var i = 0; i < gridWidth; i++) { grid[i] = []; for (var j = 0; j < gridHeight; j++) { var cell = new Cell(); var targetPos = self.calculateTargetPosition(i, j); cell.move(targetPos.x, targetPos.y, true); self.attachCellListeners(cell); grid[i][j] = cell; gridContainer.addChild(cell); } } self.moveToEmptySpace = function () { var moved; do { moved = false; for (var col = 0; col < gridWidth; col++) { for (var row = gridHeight - 2; row >= 0; row--) { if (grid[col][row] && !grid[col][row + 1]) { var targetCell = grid[col][row]; var targetPos = self.calculateTargetPosition(col, row + 1); targetCell.move(targetPos.x, targetPos.y); grid[col][row + 1] = targetCell; grid[col][row] = null; moved = true; } } } } while (moved); for (var col = 0; col < gridWidth; col++) { if (!grid[col][0]) { var newCell = new Cell(); var targetPos = self.calculateTargetPosition(col, 0); newCell.x = targetPos.x; newCell.y = targetPos.y - cellHeight - 200; newCell.move(targetPos.x, targetPos.y); self.attachCellListeners(newCell); grid[col][0] = newCell; gridContainer.addChildAt(newCell, 0); self.moveToEmptySpace(); } } }; LK.on('tick', function () { for (var i = 0; i < gridWidth; i++) { for (var j = 0; j < gridHeight; j++) { if (grid[i][j]) grid[i][j].tick(); } } for (var i = self.particles.length - 1; i >= 0; i--) { var particle = self.particles[i]; particle.tick(); if (particle.lifeSpan <= 0) { particle.destroy(); self.particles.splice(i, 1); } } scoreTxt.setText(score); if (!self.checkMovesAllowed()) { if (!self.gameOverTimeout) { self.gameOverTimeout = LK.setTimeout(function () { LK.showGameOver(); }, 2000); } } else { if (self.gameOverTimeout) { LK.clearTimeout(self.gameOverTimeout); self.gameOverTimeout = null; } } }); });
var Particle = Container.expand(function (tint) {
var self = Container.call(this);
self.tint = tint;
var particleGraphics = self.createAsset('particle', 'Particle Graphics', 0.5, 0.5);
particleGraphics.rotation = Math.random() * Math.PI * 2;
particleGraphics.tint = self.tint;
self.vx = Math.random() * 4 - 2;
self.vy = Math.random() * 4 - 2;
self.alpha = 1;
self.lifetime = 60;
self.tick = function () {
self.x += self.vx;
self.y += self.vy;
self.alpha -= 1 / self.lifetime;
if (self.alpha <= 0) self.destroy();
};
});
var Cell = Container.expand(function (type) {
var self = Container.call(this);
var cellGraphics = self.createAsset('cell', 'Grid Cell', .5, .5);
self.targetX = 0;
self.targetY = 0;
self.isMoving = false;
self.totalTypes = 5;
self.type = type || Math.floor(Math.random() * self.totalTypes);
var hue = self.type / self.totalTypes;
var color = hsvToRgb(hue, 0.6, 1);
cellGraphics.tint = color;
self.move = function (x, y, instant) {
self.targetX = x;
self.targetY = y;
if (instant) {
self.x = x;
self.y = y;
}
};
self.tick = function () {
var acceleration = 1;
self.speedX = self.speedX || 0;
self.speedY = self.speedY || 0;
var threshold = 1;
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
if (Math.abs(dx) < threshold && Math.abs(dy) < threshold) {
self.x = self.targetX;
self.y = self.targetY;
self.isMoving = false;
self.speedX = 0;
self.speedY = 0;
} else {
if (dx !== 0) {
self.speedX += dx > 0 ? acceleration : -acceleration;
}
if (dy !== 0) {
self.speedY += dy > 0 ? acceleration : -acceleration;
}
var nextX = self.x + self.speedX;
var nextY = self.y + self.speedY;
if (self.speedX > 0 && nextX > self.targetX || self.speedX < 0 && nextX < self.targetX) {
nextX = self.targetX;
self.speedX = 0;
}
if (self.speedY > 0 && nextY > self.targetY || self.speedY < 0 && nextY < self.targetY) {
nextY = self.targetY;
self.speedY = 0;
}
self.x = nextX;
self.y = nextY;
self.isMoving = self.x !== self.targetX || self.y !== self.targetY;
}
};
});
function hsvToRgb(h, s, v) {
var i = Math.floor(h * 6), f = h * 6 - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s), mod = i % 6, r = [v, q, p, p, t, v][mod], g = [t, v, v, q, p, p][mod], b = [p, p, t, v, v, q][mod];
return (r * 255 << 16) + (g * 255 << 8) + b * 255;
}
var Game = Container.expand(function () {
var self = Container.call(this);
var background = self.createAsset('background', 'Background Asset', 0, 0);
background.width = LK.stage.width;
background.height = LK.stage.height;
self.addChildAt(background, 0);
var score = 0;
var selectedCells = [];
self.particles = [];
var scoreTxt = new Text2('0', {
size: 150,
fill: "#ffffff",
font: "'Fredoka One', cursive",
dropShadow: false,
dropShadowColor: '#000000'
});
LK.gui.topCenter.addChild(scoreTxt);
scoreTxt.x -= 80;
scoreTxt.y += 100;
self.spawnParticles = function (x, y, color) {
for (var i = 0; i < 10; i++) {
var particle = new Particle(color);
particle.x = gridContainer.x + x;
particle.y = gridContainer.y + y;
var hue = color / 0xFFFFFF;
particle.tint = hsvToRgb(hue, 0.6, 1);
self.particles.push(particle);
self.addChild(particle);
}
};
self.checkMovesAllowed = function () {
for (var i = 0; i < gridWidth; i++) {
for (var j = 0; j < gridHeight; j++) {
var cell = grid[i][j];
if (cell) {
var neighbors = self.findConnectedNeighbors(cell);
if (neighbors.length > 1) {
return true;
}
}
}
}
return false;
};
var gridWidth = 4;
var gridHeight = 4;
var gridSpacing = 8;
var tempCell = new Cell();
var cellWidth = tempCell.width;
var cellHeight = tempCell.height;
tempCell.destroy();
var gridContainer = new Container();
self.addChild(gridContainer);
var totalGridWidth = gridWidth * (cellWidth + gridSpacing) - gridSpacing;
var totalGridHeight = gridHeight * (cellHeight + gridSpacing) - gridSpacing;
gridContainer.x = (2048 - totalGridWidth) / 2 + cellWidth / 2 + 5;
gridContainer.y = (2732 - totalGridHeight) / 2 + cellHeight / 2;
self.calculateTargetPosition = function (col, row) {
return {
x: col * (cellWidth + gridSpacing),
y: row * (cellHeight + gridSpacing)
};
};
self.findConnectedNeighbors = function (cell, connectedNeighbors) {
connectedNeighbors = connectedNeighbors || [];
if (!cell) return [];
var cellType = cell.type;
var cellColRow = self.findCellColRow(cell);
if (cellColRow) {
var directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
directions.forEach(function (dir) {
var newRow = cellColRow.row + dir[0];
var newCol = cellColRow.col + dir[1];
if (newRow >= 0 && newRow < gridHeight && newCol >= 0 && newCol < gridWidth) {
var neighborCell = grid[newCol][newRow];
if (neighborCell && neighborCell.type === cellType && connectedNeighbors.indexOf(neighborCell) === -1) {
connectedNeighbors.push(neighborCell);
self.findConnectedNeighbors(neighborCell, connectedNeighbors);
}
}
});
}
return connectedNeighbors;
};
self.findCellColRow = function (cell) {
for (var col = 0; col < gridWidth; col++) {
for (var row = 0; row < gridHeight; row++) {
if (grid[col][row] === cell) {
return {
col: col,
row: row
};
}
}
}
return null;
};
self.deleteCell = function (cell) {
var colRow = self.findCellColRow(cell);
if (colRow) {
grid[colRow.col][colRow.row] = null;
var hue = cell.type / cell.totalTypes;
var color = hsvToRgb(hue, 0.6, 1);
self.spawnParticles(cell.x, cell.y, color);
cell.destroy();
score += Math.pow(2, selectedCells.length);
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
self.moveToEmptySpace();
}
};
self.attachCellListeners = function (cell) {
var dragStartCell = null;
self.resetSelectedCells = function () {
selectedCells.forEach(function (cell) {
cell.alpha = 1;
});
self.resetSelectedCells = function () {
selectedCells.forEach(function (cell) {
cell.alpha = 1;
});
selectedCells = [];
};
selectedCells = [];
};
cell.on('down', function (obj) {
dragStartCell = cell;
selectedCells.push(cell);
cell.alpha = 0.5;
});
cell.on('move', function (obj) {
if (dragStartCell) {
var pos = obj.event.getLocalPosition(gridContainer);
var col = Math.floor((pos.x + cellWidth / 2) / (cellWidth + gridSpacing));
var row = Math.floor((pos.y + cellHeight / 2) / (cellHeight + gridSpacing));
if (col >= 0 && col < gridWidth && row >= 0 && row < gridHeight) {
var targetCell = grid[col][row];
if (targetCell && selectedCells.indexOf(targetCell) === -1) {
if (targetCell.type === dragStartCell.type) {
targetCell.alpha = 0.5;
selectedCells.push(targetCell);
} else {
self.resetSelectedCells();
dragStartCell = null;
}
}
}
}
});
cell.on('up', function (obj) {
if (selectedCells.length >= 4) {
for (var col = 0; col < gridWidth; col++) {
for (var row = 0; row < gridHeight; row++) {
var cell = grid[col][row];
if (cell && dragStartCell && cell.type === dragStartCell.type) {
self.deleteCell(cell);
}
}
}
} else if (selectedCells.length > 1) {
for (var i = 0; i < selectedCells.length; i++) {
self.deleteCell(selectedCells[i]);
}
}
selectedCells.forEach(function (cell) {
cell.alpha = 1;
});
selectedCells = [];
dragStartCell = null;
});
};
var grid = [];
for (var i = 0; i < gridWidth; i++) {
grid[i] = [];
for (var j = 0; j < gridHeight; j++) {
var cell = new Cell();
var targetPos = self.calculateTargetPosition(i, j);
cell.move(targetPos.x, targetPos.y, true);
self.attachCellListeners(cell);
grid[i][j] = cell;
gridContainer.addChild(cell);
}
}
self.moveToEmptySpace = function () {
var moved;
do {
moved = false;
for (var col = 0; col < gridWidth; col++) {
for (var row = gridHeight - 2; row >= 0; row--) {
if (grid[col][row] && !grid[col][row + 1]) {
var targetCell = grid[col][row];
var targetPos = self.calculateTargetPosition(col, row + 1);
targetCell.move(targetPos.x, targetPos.y);
grid[col][row + 1] = targetCell;
grid[col][row] = null;
moved = true;
}
}
}
} while (moved);
for (var col = 0; col < gridWidth; col++) {
if (!grid[col][0]) {
var newCell = new Cell();
var targetPos = self.calculateTargetPosition(col, 0);
newCell.x = targetPos.x;
newCell.y = targetPos.y - cellHeight - 200;
newCell.move(targetPos.x, targetPos.y);
self.attachCellListeners(newCell);
grid[col][0] = newCell;
gridContainer.addChildAt(newCell, 0);
self.moveToEmptySpace();
}
}
};
LK.on('tick', function () {
for (var i = 0; i < gridWidth; i++) {
for (var j = 0; j < gridHeight; j++) {
if (grid[i][j]) grid[i][j].tick();
}
}
for (var i = self.particles.length - 1; i >= 0; i--) {
var particle = self.particles[i];
particle.tick();
if (particle.lifeSpan <= 0) {
particle.destroy();
self.particles.splice(i, 1);
}
}
scoreTxt.setText(score);
if (!self.checkMovesAllowed()) {
if (!self.gameOverTimeout) {
self.gameOverTimeout = LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
}
} else {
if (self.gameOverTimeout) {
LK.clearTimeout(self.gameOverTimeout);
self.gameOverTimeout = null;
}
}
});
});