/****
* Classes
****/
var Particle = Container.expand(function (color, gravityMultiplier) {
var self = Container.call(this);
gravityMultiplier = typeof gravityMultiplier === 'undefined' ? 1 : gravityMultiplier;
self.gravityMultiplier = gravityMultiplier;
self.graphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.graphics.tint = color;
self.speedX = (Math.random() - 0.5) * 10;
self.speedY = (Math.random() - 0.5) * 10;
self.scaleX = self.scaleY = Math.random() * 0.5 + 0.5;
self.alpha = 1;
self.tick = function () {
self.x += self.speedX;
self.speedY += 0.7 * self.gravityMultiplier;
self.y += self.speedY;
self.alpha -= 0.02;
if (self.alpha <= 0) {
var index = particles.indexOf(self);
if (index > -1) {
particles.splice(index, 1);
}
self.destroy();
}
};
});
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartBackground = self.attachAsset('heartBackground', {
anchorX: 0.5,
anchorY: 0.5
});
heartBackground.blendMode = 1;
var heartGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
});
var LifeIndicator = Container.expand(function (initialLives) {
var self = Container.call(this);
LifeIndicator.prototype.triggerLifeLostParticles = function (x, y) {
var particleColors = [0xff0000, 0xff4500, 0xff6347];
for (var i = 0; i < 5; i++) {
var color = particleColors[Math.floor(Math.random() * particleColors.length)];
var particle = new Particle(color, 0);
particle.x = x;
particle.y = y;
particles.push(particle);
this.addChild(particle);
}
};
self.lives = initialLives;
self.hearts = [];
var heartWidth = 110;
var totalWidth = (self.lives - 1) * (heartWidth + 10);
var startX = -totalWidth / 2;
for (var i = 0; i < self.lives; i++) {
var heart = new Heart();
heart.x = startX + i * (heartWidth + 10);
self.hearts.push(heart);
self.addChild(heart);
}
self.updateLives = function (lives) {
lives = Math.max(0, lives);
while (self.hearts.length > lives) {
var heart = self.hearts.pop();
if (heart) {
self.triggerLifeLostParticles(heart.x, heart.y);
heart.destroy();
}
}
while (self.hearts.length < lives) {
var newHeart = new Heart();
var heartWidth = 100;
newHeart.x = startX + self.hearts.length * (heartWidth + 10);
self.hearts.push(newHeart);
self.addChild(newHeart);
}
self.lives = lives;
};
});
var Snowflake = Container.expand(function () {
var self = Container.call(this);
self.rotation = Math.random() * Math.PI * 2;
self.rotationSpeed = Math.random() * 0.05 - 0.025;
var flakeGraphics = self.attachAsset('snowflake', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 1.5 + 1;
self.direction = Math.random() * Math.PI * 2;
self.xSpeed = Math.cos(self.direction) * Math.abs(Math.random() * 1 + 0.5);
self.ySpeed = Math.abs(Math.sin(self.direction)) * self.speed;
self.tick = function () {
self.x += self.xSpeed;
self.y += self.ySpeed;
self.scale.x = self.scale.y = 0.5 + self.ySpeed / 6;
self.rotation += self.rotationSpeed;
if (self.x > 2048 || self.x < 0 || self.y > 2732) {
self.x = Math.random() * 2048;
self.y = -50;
}
};
});
var Cell = Container.expand(function (type, totalTypes) {
var self = Container.call(this);
self.targetX = 0;
self.targetY = 0;
self.isMoving = false;
self.totalTypes = totalTypes;
self.type = typeof type === 'undefined' ? Math.floor(Math.random() * self.totalTypes) : type;
var assetName = 'cellType' + self.type;
var cellBackground = self.attachAsset('cellBackground', {
anchorX: 0.5,
anchorY: 0.5
});
cellBackground.alpha = 0;
var cellGraphics = self.createAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
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 = 2;
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;
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x20497b
});
/****
* Game Code
****/
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 particles = [];
game.createParticleEffect = function (x, y, type) {
var fixedColors = [0x82d756, 0x5ecde9, 0xf8a4a0, 0x921d2a, 0x7719f9, 0xffffff, 0xefa63b, 0x7dd6a4];
var color = fixedColors[type % fixedColors.length];
for (var i = 0; i < 10; i++) {
var particle = new Particle(color);
particle.x = x + gridContainer.x;
particle.y = y + gridContainer.y;
particles.push(particle);
this.addChild(particle);
}
};
game.totalCellTypes = 2;
var score = 0;
game.hasPossibleMoves = function () {
for (var col = 0; col < gridWidth; col++) {
for (var row = 0; row < gridHeight; row++) {
var cell = grid[col][row];
if (cell) {
var neighbors = [{
x: col - 1,
y: row
}, {
x: col + 1,
y: row
}, {
x: col,
y: row - 1
}, {
x: col,
y: row + 1
}];
for (var i = 0; i < neighbors.length; i++) {
var pos = neighbors[i];
if (pos.x >= 0 && pos.x < gridWidth && pos.y >= 0 && pos.y < gridHeight) {
var neighborCell = grid[pos.x][pos.y];
if (neighborCell && neighborCell.type === cell.type) {
return true;
}
}
}
}
}
}
return false;
};
game.resetBoard = function () {
grid.forEach(function (column, colIndex) {
column.forEach(function (cell, rowIndex) {
if (cell) {
game.deleteCell(cell);
}
var newCell = new Cell(undefined, game.totalCellTypes);
var targetPos = game.calculateTargetPosition(colIndex, rowIndex);
newCell.move(targetPos.x, targetPos.y, true);
game.attachCellListeners(newCell);
newCell.y = -100;
grid[colIndex][rowIndex] = newCell;
gridContainer.addChild(newCell);
});
});
};
var background = game.attachAsset('background', {
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2;
background.y = 2732 / 2;
game.addChild(background);
var gridWidth = 8;
var gridHeight = 8;
var gridSpacing = 8;
var cellWidth = 200;
var cellHeight = 200;
var gridContainer = new Container();
var boardBackground = game.attachAsset('boardBackground', {
anchorX: 0.5,
anchorY: 0.5
});
boardBackground.alpha = 0.7;
gridContainer.addChildAt(boardBackground, 0);
game.addChild(gridContainer);
var totalGridWidth = gridWidth * (cellWidth + gridSpacing) - gridSpacing;
var totalGridHeight = gridHeight * (cellHeight + gridSpacing) - gridSpacing;
gridContainer.x = (2048 - totalGridWidth) / 2 + cellWidth / 2 + 3;
gridContainer.y = (2732 - totalGridHeight) / 2 + cellHeight / 2 + 90;
boardBackground.x = totalGridWidth / 2 - cellWidth / 2;
boardBackground.y = totalGridHeight / 2 - cellHeight / 2 + 30;
game.calculateTargetPosition = function (col, row) {
return {
x: col * (cellWidth + gridSpacing),
y: row * (cellHeight + gridSpacing)
};
};
game.findConnectedNeighbors = function (cell, connectedNeighbors) {
connectedNeighbors = connectedNeighbors || [];
if (!cell) {
return [];
}
var cellType = cell.type;
var cellColRow = game.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);
game.findConnectedNeighbors(neighborCell, connectedNeighbors);
}
}
});
}
return connectedNeighbors;
};
game.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;
};
game.deleteCell = function (cell) {
var colRow = game.findCellColRow(cell);
if (colRow) {
grid[colRow.col][colRow.row] = null;
game.createParticleEffect(cell.x, cell.y, cell.type);
cell.destroy();
}
};
game.attachCellListeners = function (cell) {
cell.on('down', function (obj) {
var connectedNeighbors = game.findConnectedNeighbors(cell);
if (connectedNeighbors.length > 0) {
score += 10 * connectedNeighbors.length + (connectedNeighbors.length - 2) * 5;
LK.setScore(LK.getScore() + score);
scoreText.setText(LK.getScore().toString());
var cellsToDestroy = [cell].concat(connectedNeighbors);
cellsToDestroy.forEach(function (cell) {
game.deleteCell(cell);
});
game.moveToEmptySpace('down', false);
game.moveToEmptySpace('left', true);
}
});
cell.on('up', function (obj) {});
cell.on('move', function (obj) {});
};
var grid = [];
var scoreText = new Text2(score.toString(), {
size: 150,
fill: "#ffffff",
weight: '800',
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
scoreText.anchor.set(.5, 0);
LK.gui.topCenter.addChild(scoreText);
var lifeIndicator = new LifeIndicator(10);
lifeIndicator.y = 260;
LK.gui.topCenter.addChild(lifeIndicator);
for (var i = 0; i < gridWidth; i++) {
grid[i] = [];
for (var j = 0; j < gridHeight; j++) {
var cell = new Cell(undefined, game.totalCellTypes);
var targetPos = game.calculateTargetPosition(i, j);
cell.move(targetPos.x, targetPos.y, true);
game.attachCellListeners(cell);
grid[i][j] = cell;
gridContainer.addChild(cell);
}
}
game.moveToEmptySpace = function (direction, rowMode) {
var moved;
do {
moved = false;
var dx = direction === 'left' ? 1 : direction === 'right' ? -1 : 0;
var dy = direction === 'up' ? 1 : direction === 'down' ? -1 : 0;
for (var col = 0; col < gridWidth; col++) {
for (var row = 0; row < gridHeight; row++) {
if (!grid[col][row]) {
var isRowOrColumnEmpty = true;
if (rowMode) {
for (var checkIndex = 0; checkIndex < (direction === 'left' || direction === 'right' ? gridHeight : gridWidth); checkIndex++) {
isRowOrColumnEmpty = isRowOrColumnEmpty && !grid[direction === 'left' || direction === 'right' ? col : checkIndex][direction === 'up' || direction === 'down' ? row : checkIndex];
}
}
if (isRowOrColumnEmpty) {
if (rowMode) {
for (var checkIndex = 0; checkIndex < (direction === 'left' || direction === 'right' ? gridHeight : gridWidth); checkIndex++) {
var targetCol = direction === 'left' || direction === 'right' ? col : checkIndex;
var targetRow = direction === 'up' || direction === 'down' ? row : checkIndex;
if (targetCol + dx >= 0 && targetCol + dx < gridWidth && targetRow + dy >= 0 && targetRow + dy < gridHeight && grid[targetCol + dx][targetRow + dy]) {
var targetCell = grid[targetCol + dx][targetRow + dy];
var targetPos = game.calculateTargetPosition(targetCol, targetRow);
targetCell.move(targetPos.x, targetPos.y);
grid[targetCol][targetRow] = targetCell;
grid[targetCol + dx][targetRow + dy] = null;
moved = true;
}
}
} else {
var targetCol = col + dx;
var targetRow = row + dy;
if (targetCol >= 0 && targetCol < gridWidth && targetRow >= 0 && targetRow < gridHeight && grid[targetCol][targetRow]) {
var targetCell = grid[targetCol][targetRow];
var targetPos = game.calculateTargetPosition(col, row);
targetCell.move(targetPos.x, targetPos.y);
grid[col][row] = targetCell;
grid[targetCol][targetRow] = null;
moved = true;
}
}
}
}
}
}
} while (moved);
};
var maxSnowflakes = 100;
var snowflakeContainer = new Container();
game.addChildAt(snowflakeContainer, 1);
var snowflakes = [];
for (var i = 0; i < maxSnowflakes; i++) {
var flake = new Snowflake();
flake.x = Math.random() * 2048;
flake.y = Math.random() * 2732;
snowflakeContainer.addChild(flake);
snowflakes.push(flake);
}
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 = 0; i < particles.length; i++) {
particles[i].tick();
}
for (var i = 0; i < snowflakes.length; i++) {
snowflakes[i].tick();
}
var cellsAreMoving = grid.some(function (column) {
return column.some(function (cell) {
return cell && cell.isMoving;
});
});
if (!cellsAreMoving && !game.hasPossibleMoves()) {
game.totalCellTypes = Math.min(8, 3 + Math.floor(score / 2000));
var tilesLeft = grid.reduce(function (acc, column) {
return acc + column.filter(function (cell) {
return cell !== null;
}).length;
}, 0);
lifeIndicator.updateLives(lifeIndicator.lives - tilesLeft);
if (lifeIndicator.lives <= 0) {
LK.showGameOver();
} else {
game.resetBoard();
}
}
});
Cartoon Christmas decoration Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas candy cane Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas stocking Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas yellow starr Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas ornament Blue Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas snow flake. Blue Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas outdoor scene. Forest, northern lights. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
White square. Narrow round corners. Background element. Flat. Vector. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas heart Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Simple Cartoon Christmas particle. White. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas ornament yellow and purple Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon Christmas snow man head. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Simple Cartoon Christmas wreath. Purple Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.