/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Candy = Container.expand(function (type) { var self = Container.call(this); self.candyType = type; self.gridX = 0; self.gridY = 0; self.isMatched = false; self.isMoving = false; var faceAssets = ['redFace', 'blueFace', 'greenFace', 'yellowFace', 'purpleFace', 'orangeFace']; var faceGraphics = self.attachAsset(faceAssets[type], { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); // Create facial features based on candy type // Define face expressions for each color: 0=red(happy), 1=blue(sad), 2=green(happy), 3=yellow(sad), 4=purple(happy), 5=orange(sad) var faceExpressions = [true, false, true, false, true, false]; // true=happy, false=sad var isHappy = faceExpressions[type] || false; // Eyes var leftEye = self.attachAsset(isHappy ? 'happyEye' : 'sadEye', { anchorX: 0.5, anchorY: 0.5 }); leftEye.x = -30; leftEye.y = -20; var rightEye = self.attachAsset(isHappy ? 'happyEye' : 'sadEye', { anchorX: 0.5, anchorY: 0.5 }); rightEye.x = 30; rightEye.y = -20; // Mouth var mouth = self.attachAsset(isHappy ? 'happyMouth' : 'sadMouth', { anchorX: 0.5, anchorY: 0.5 }); mouth.x = 0; mouth.y = 30; mouth.scaleY = isHappy ? 1 : -1; // Flip sad mouth upside down self.faceGraphics = faceGraphics; self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2; self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2; }; self.animateToPosition = function (targetX, targetY, duration, callback) { self.isMoving = true; tween(self, { x: targetX, y: targetY }, { duration: duration || 300, easing: tween.easeOut, onFinish: function onFinish() { self.isMoving = false; if (callback) callback(); } }); }; self.markMatched = function () { self.isMatched = true; // Create explosion effect with scale bounce and color flash tween(self, { scaleX: 1.5, scaleY: 1.5 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { // Flash the face bright white tween(self.faceGraphics, { tint: 0xFFFFFF }, { duration: 50, onFinish: function onFinish() { // Scale down and fade out tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { self.destroy(); } }); } }); } }); }; return self; }); var GridCell = Container.expand(function (gridX, gridY) { var self = Container.call(this); self.gridX = gridX; self.gridY = gridY; var cellBackground = self.attachAsset('gridBackground', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2; self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2a1810 }); /**** * Game Code ****/ var GRID_SIZE = 8; var CELL_SIZE = 250; var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2; var GRID_START_Y = 400; var grid = []; var candies = []; var selectedCandy = null; var isProcessing = false; var movesLeft = 30; var targetScore = 1000; var currentScore = 0; var currentLevel = 1; var maxLevel = 10; // Level configurations var levelConfigs = [{ moves: 30, target: 1000, colors: 4 }, // Level 1 { moves: 25, target: 1500, colors: 4 }, // Level 2 { moves: 25, target: 2000, colors: 5 }, // Level 3 { moves: 20, target: 2500, colors: 5 }, // Level 4 { moves: 20, target: 3000, colors: 5 }, // Level 5 { moves: 18, target: 3500, colors: 6 }, // Level 6 { moves: 18, target: 4000, colors: 6 }, // Level 7 { moves: 15, target: 4500, colors: 6 }, // Level 8 { moves: 15, target: 5000, colors: 6 }, // Level 9 { moves: 12, target: 6000, colors: 6 } // Level 10 ]; // Initialize UI var scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 150; var movesText = new Text2('Moves: 30', { size: 80, fill: 0xFFFFFF }); movesText.anchor.set(0.5, 0); LK.gui.top.addChild(movesText); movesText.y = 250; var targetText = new Text2('Target: 1000', { size: 60, fill: 0xFFFF00 }); targetText.anchor.set(0.5, 0); LK.gui.top.addChild(targetText); targetText.y = 350; var levelText = new Text2('Level: 1', { size: 80, fill: 0x00FFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); levelText.y = 50; // Initialize grid function initializeGrid() { // Create grid cells for (var x = 0; x < GRID_SIZE; x++) { grid[x] = []; for (var y = 0; y < GRID_SIZE; y++) { var cell = new GridCell(x, y); game.addChild(cell); grid[x][y] = null; } } // Fill grid with candies fillGrid(); } function fillGrid() { var numColors = levelConfigs[currentLevel - 1].colors; for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] === null) { var candyType = Math.floor(Math.random() * numColors); var candy = new Candy(candyType); candy.setGridPosition(x, y); grid[x][y] = candy; candies.push(candy); game.addChild(candy); } } } } function getCandyAt(x, y) { if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) return null; return grid[x][y]; } function isValidSwap(candy1, candy2) { var dx = Math.abs(candy1.gridX - candy2.gridX); var dy = Math.abs(candy1.gridY - candy2.gridY); return dx === 1 && dy === 0 || dx === 0 && dy === 1; } function swapCandies(candy1, candy2) { if (!candy1 || !candy2 || !isValidSwap(candy1, candy2)) return false; var tempX = candy1.gridX; var tempY = candy1.gridY; grid[candy1.gridX][candy1.gridY] = candy2; grid[candy2.gridX][candy2.gridY] = candy1; candy1.gridX = candy2.gridX; candy1.gridY = candy2.gridY; candy2.gridX = tempX; candy2.gridY = tempY; var targetX1 = GRID_START_X + candy1.gridX * CELL_SIZE + CELL_SIZE / 2; var targetY1 = GRID_START_Y + candy1.gridY * CELL_SIZE + CELL_SIZE / 2; var targetX2 = GRID_START_X + candy2.gridX * CELL_SIZE + CELL_SIZE / 2; var targetY2 = GRID_START_Y + candy2.gridY * CELL_SIZE + CELL_SIZE / 2; candy1.animateToPosition(targetX1, targetY1, 300); candy2.animateToPosition(targetX2, targetY2, 300); LK.getSound('swap').play(); return true; } function findMatches() { var matches = []; // Check horizontal matches for (var y = 0; y < GRID_SIZE; y++) { var count = 1; var currentType = grid[0][y] ? grid[0][y].candyType : -1; for (var x = 1; x < GRID_SIZE; x++) { var candy = grid[x][y]; if (candy && candy.candyType === currentType) { count++; } else { if (count >= 3) { for (var i = x - count; i < x; i++) { matches.push(grid[i][y]); } } count = 1; currentType = candy ? candy.candyType : -1; } } if (count >= 3) { for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) { matches.push(grid[i][y]); } } } // Check vertical matches for (var x = 0; x < GRID_SIZE; x++) { var count = 1; var currentType = grid[x][0] ? grid[x][0].candyType : -1; for (var y = 1; y < GRID_SIZE; y++) { var candy = grid[x][y]; if (candy && candy.candyType === currentType) { count++; } else { if (count >= 3) { for (var i = y - count; i < y; i++) { matches.push(grid[x][i]); } } count = 1; currentType = candy ? candy.candyType : -1; } } if (count >= 3) { for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) { matches.push(grid[x][i]); } } } return matches; } function removeMatches(matches) { if (matches.length === 0) return; LK.getSound('match').play(); for (var i = 0; i < matches.length; i++) { var candy = matches[i]; if (candy && !candy.isMatched) { candy.markMatched(); grid[candy.gridX][candy.gridY] = null; // Remove from candies array var candyIndex = candies.indexOf(candy); if (candyIndex !== -1) { candies.splice(candyIndex, 1); } // Add to score currentScore += 10; } } updateUI(); } function applyGravity() { var moved = false; for (var x = 0; x < GRID_SIZE; x++) { for (var y = GRID_SIZE - 1; y >= 0; y--) { if (grid[x][y] === null) { // Find candy above to fall down for (var checkY = y - 1; checkY >= 0; checkY--) { if (grid[x][checkY] !== null) { var candy = grid[x][checkY]; grid[x][y] = candy; grid[x][checkY] = null; candy.gridY = y; var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2; candy.animateToPosition(candy.x, targetY, 300); moved = true; break; } } } } } return moved; } function addNewCandies() { var added = false; var numColors = levelConfigs[currentLevel - 1].colors; for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] === null) { var candyType = Math.floor(Math.random() * numColors); var candy = new Candy(candyType); candy.gridX = x; candy.gridY = y; candy.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2; candy.y = GRID_START_Y - CELL_SIZE; var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2; candy.animateToPosition(candy.x, targetY, 400); grid[x][y] = candy; candies.push(candy); game.addChild(candy); added = true; } } } return added; } function initializeLevel(level) { var config = levelConfigs[level - 1]; movesLeft = config.moves; targetScore = config.target; currentScore = 0; // Clear existing candies for (var i = candies.length - 1; i >= 0; i--) { candies[i].destroy(); } candies = []; // Clear grid for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { grid[x][y] = null; } } // Fill with new candies fillGrid(); updateUI(); } function nextLevel() { if (currentLevel < maxLevel) { currentLevel++; initializeLevel(currentLevel); // Show level complete animation LK.effects.flashScreen(0x00FF00, 500); } else { // All levels completed LK.setTimeout(function () { LK.showYouWin(); }, 1000); } } function updateUI() { scoreText.setText('Score: ' + currentScore); movesText.setText('Moves: ' + movesLeft); levelText.setText('Level: ' + currentLevel); targetText.setText('Target: ' + targetScore); if (currentScore >= targetScore) { LK.setTimeout(function () { nextLevel(); }, 1000); } else if (movesLeft <= 0) { LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } function processMatches() { if (isProcessing) return; isProcessing = true; var matches = findMatches(); if (matches.length > 0) { removeMatches(matches); LK.setTimeout(function () { var gravityMoved = applyGravity(); var newCandiesAdded = addNewCandies(); if (gravityMoved || newCandiesAdded) { LK.setTimeout(function () { isProcessing = false; processMatches(); }, 500); } else { isProcessing = false; } }, 300); } else { isProcessing = false; } } game.down = function (x, y, obj) { if (isProcessing) return; var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE); var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE); var candy = getCandyAt(gridX, gridY); if (!candy) return; if (selectedCandy === null) { selectedCandy = candy; tween(candy, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200 }); } else if (selectedCandy === candy) { tween(selectedCandy, { scaleX: 0.8, scaleY: 0.8 }, { duration: 200 }); selectedCandy = null; } else { if (isValidSwap(selectedCandy, candy)) { var oldSelected = selectedCandy; tween(selectedCandy, { scaleX: 0.8, scaleY: 0.8 }, { duration: 200 }); selectedCandy = null; if (swapCandies(oldSelected, candy)) { LK.setTimeout(function () { var matches = findMatches(); if (matches.length > 0) { movesLeft--; updateUI(); processMatches(); } else { // No matches, swap back swapCandies(oldSelected, candy); } }, 400); } } else { tween(selectedCandy, { scaleX: 0.8, scaleY: 0.8 }, { duration: 200 }); selectedCandy = candy; tween(candy, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200 }); } } }; // Initialize the game initializeGrid(); initializeLevel(currentLevel); game.update = function () { // Game loop updates handled by individual candy animations and match processing };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Candy = Container.expand(function (type) {
var self = Container.call(this);
self.candyType = type;
self.gridX = 0;
self.gridY = 0;
self.isMatched = false;
self.isMoving = false;
var faceAssets = ['redFace', 'blueFace', 'greenFace', 'yellowFace', 'purpleFace', 'orangeFace'];
var faceGraphics = self.attachAsset(faceAssets[type], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Create facial features based on candy type
// Define face expressions for each color: 0=red(happy), 1=blue(sad), 2=green(happy), 3=yellow(sad), 4=purple(happy), 5=orange(sad)
var faceExpressions = [true, false, true, false, true, false]; // true=happy, false=sad
var isHappy = faceExpressions[type] || false;
// Eyes
var leftEye = self.attachAsset(isHappy ? 'happyEye' : 'sadEye', {
anchorX: 0.5,
anchorY: 0.5
});
leftEye.x = -30;
leftEye.y = -20;
var rightEye = self.attachAsset(isHappy ? 'happyEye' : 'sadEye', {
anchorX: 0.5,
anchorY: 0.5
});
rightEye.x = 30;
rightEye.y = -20;
// Mouth
var mouth = self.attachAsset(isHappy ? 'happyMouth' : 'sadMouth', {
anchorX: 0.5,
anchorY: 0.5
});
mouth.x = 0;
mouth.y = 30;
mouth.scaleY = isHappy ? 1 : -1; // Flip sad mouth upside down
self.faceGraphics = faceGraphics;
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, callback) {
self.isMoving = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
if (callback) callback();
}
});
};
self.markMatched = function () {
self.isMatched = true;
// Create explosion effect with scale bounce and color flash
tween(self, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Flash the face bright white
tween(self.faceGraphics, {
tint: 0xFFFFFF
}, {
duration: 50,
onFinish: function onFinish() {
// Scale down and fade out
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
}
});
};
return self;
});
var GridCell = Container.expand(function (gridX, gridY) {
var self = Container.call(this);
self.gridX = gridX;
self.gridY = gridY;
var cellBackground = self.attachAsset('gridBackground', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2a1810
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 250;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = 400;
var grid = [];
var candies = [];
var selectedCandy = null;
var isProcessing = false;
var movesLeft = 30;
var targetScore = 1000;
var currentScore = 0;
var currentLevel = 1;
var maxLevel = 10;
// Level configurations
var levelConfigs = [{
moves: 30,
target: 1000,
colors: 4
},
// Level 1
{
moves: 25,
target: 1500,
colors: 4
},
// Level 2
{
moves: 25,
target: 2000,
colors: 5
},
// Level 3
{
moves: 20,
target: 2500,
colors: 5
},
// Level 4
{
moves: 20,
target: 3000,
colors: 5
},
// Level 5
{
moves: 18,
target: 3500,
colors: 6
},
// Level 6
{
moves: 18,
target: 4000,
colors: 6
},
// Level 7
{
moves: 15,
target: 4500,
colors: 6
},
// Level 8
{
moves: 15,
target: 5000,
colors: 6
},
// Level 9
{
moves: 12,
target: 6000,
colors: 6
} // Level 10
];
// Initialize UI
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 150;
var movesText = new Text2('Moves: 30', {
size: 80,
fill: 0xFFFFFF
});
movesText.anchor.set(0.5, 0);
LK.gui.top.addChild(movesText);
movesText.y = 250;
var targetText = new Text2('Target: 1000', {
size: 60,
fill: 0xFFFF00
});
targetText.anchor.set(0.5, 0);
LK.gui.top.addChild(targetText);
targetText.y = 350;
var levelText = new Text2('Level: 1', {
size: 80,
fill: 0x00FFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
levelText.y = 50;
// Initialize grid
function initializeGrid() {
// Create grid cells
for (var x = 0; x < GRID_SIZE; x++) {
grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
var cell = new GridCell(x, y);
game.addChild(cell);
grid[x][y] = null;
}
}
// Fill grid with candies
fillGrid();
}
function fillGrid() {
var numColors = levelConfigs[currentLevel - 1].colors;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] === null) {
var candyType = Math.floor(Math.random() * numColors);
var candy = new Candy(candyType);
candy.setGridPosition(x, y);
grid[x][y] = candy;
candies.push(candy);
game.addChild(candy);
}
}
}
}
function getCandyAt(x, y) {
if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) return null;
return grid[x][y];
}
function isValidSwap(candy1, candy2) {
var dx = Math.abs(candy1.gridX - candy2.gridX);
var dy = Math.abs(candy1.gridY - candy2.gridY);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
function swapCandies(candy1, candy2) {
if (!candy1 || !candy2 || !isValidSwap(candy1, candy2)) return false;
var tempX = candy1.gridX;
var tempY = candy1.gridY;
grid[candy1.gridX][candy1.gridY] = candy2;
grid[candy2.gridX][candy2.gridY] = candy1;
candy1.gridX = candy2.gridX;
candy1.gridY = candy2.gridY;
candy2.gridX = tempX;
candy2.gridY = tempY;
var targetX1 = GRID_START_X + candy1.gridX * CELL_SIZE + CELL_SIZE / 2;
var targetY1 = GRID_START_Y + candy1.gridY * CELL_SIZE + CELL_SIZE / 2;
var targetX2 = GRID_START_X + candy2.gridX * CELL_SIZE + CELL_SIZE / 2;
var targetY2 = GRID_START_Y + candy2.gridY * CELL_SIZE + CELL_SIZE / 2;
candy1.animateToPosition(targetX1, targetY1, 300);
candy2.animateToPosition(targetX2, targetY2, 300);
LK.getSound('swap').play();
return true;
}
function findMatches() {
var matches = [];
// Check horizontal matches
for (var y = 0; y < GRID_SIZE; y++) {
var count = 1;
var currentType = grid[0][y] ? grid[0][y].candyType : -1;
for (var x = 1; x < GRID_SIZE; x++) {
var candy = grid[x][y];
if (candy && candy.candyType === currentType) {
count++;
} else {
if (count >= 3) {
for (var i = x - count; i < x; i++) {
matches.push(grid[i][y]);
}
}
count = 1;
currentType = candy ? candy.candyType : -1;
}
}
if (count >= 3) {
for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) {
matches.push(grid[i][y]);
}
}
}
// Check vertical matches
for (var x = 0; x < GRID_SIZE; x++) {
var count = 1;
var currentType = grid[x][0] ? grid[x][0].candyType : -1;
for (var y = 1; y < GRID_SIZE; y++) {
var candy = grid[x][y];
if (candy && candy.candyType === currentType) {
count++;
} else {
if (count >= 3) {
for (var i = y - count; i < y; i++) {
matches.push(grid[x][i]);
}
}
count = 1;
currentType = candy ? candy.candyType : -1;
}
}
if (count >= 3) {
for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) {
matches.push(grid[x][i]);
}
}
}
return matches;
}
function removeMatches(matches) {
if (matches.length === 0) return;
LK.getSound('match').play();
for (var i = 0; i < matches.length; i++) {
var candy = matches[i];
if (candy && !candy.isMatched) {
candy.markMatched();
grid[candy.gridX][candy.gridY] = null;
// Remove from candies array
var candyIndex = candies.indexOf(candy);
if (candyIndex !== -1) {
candies.splice(candyIndex, 1);
}
// Add to score
currentScore += 10;
}
}
updateUI();
}
function applyGravity() {
var moved = false;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (grid[x][y] === null) {
// Find candy above to fall down
for (var checkY = y - 1; checkY >= 0; checkY--) {
if (grid[x][checkY] !== null) {
var candy = grid[x][checkY];
grid[x][y] = candy;
grid[x][checkY] = null;
candy.gridY = y;
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
candy.animateToPosition(candy.x, targetY, 300);
moved = true;
break;
}
}
}
}
}
return moved;
}
function addNewCandies() {
var added = false;
var numColors = levelConfigs[currentLevel - 1].colors;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid[x][y] === null) {
var candyType = Math.floor(Math.random() * numColors);
var candy = new Candy(candyType);
candy.gridX = x;
candy.gridY = y;
candy.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
candy.y = GRID_START_Y - CELL_SIZE;
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
candy.animateToPosition(candy.x, targetY, 400);
grid[x][y] = candy;
candies.push(candy);
game.addChild(candy);
added = true;
}
}
}
return added;
}
function initializeLevel(level) {
var config = levelConfigs[level - 1];
movesLeft = config.moves;
targetScore = config.target;
currentScore = 0;
// Clear existing candies
for (var i = candies.length - 1; i >= 0; i--) {
candies[i].destroy();
}
candies = [];
// Clear grid
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
grid[x][y] = null;
}
}
// Fill with new candies
fillGrid();
updateUI();
}
function nextLevel() {
if (currentLevel < maxLevel) {
currentLevel++;
initializeLevel(currentLevel);
// Show level complete animation
LK.effects.flashScreen(0x00FF00, 500);
} else {
// All levels completed
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
}
function updateUI() {
scoreText.setText('Score: ' + currentScore);
movesText.setText('Moves: ' + movesLeft);
levelText.setText('Level: ' + currentLevel);
targetText.setText('Target: ' + targetScore);
if (currentScore >= targetScore) {
LK.setTimeout(function () {
nextLevel();
}, 1000);
} else if (movesLeft <= 0) {
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
function processMatches() {
if (isProcessing) return;
isProcessing = true;
var matches = findMatches();
if (matches.length > 0) {
removeMatches(matches);
LK.setTimeout(function () {
var gravityMoved = applyGravity();
var newCandiesAdded = addNewCandies();
if (gravityMoved || newCandiesAdded) {
LK.setTimeout(function () {
isProcessing = false;
processMatches();
}, 500);
} else {
isProcessing = false;
}
}, 300);
} else {
isProcessing = false;
}
}
game.down = function (x, y, obj) {
if (isProcessing) return;
var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE);
var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE);
var candy = getCandyAt(gridX, gridY);
if (!candy) return;
if (selectedCandy === null) {
selectedCandy = candy;
tween(candy, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
} else if (selectedCandy === candy) {
tween(selectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200
});
selectedCandy = null;
} else {
if (isValidSwap(selectedCandy, candy)) {
var oldSelected = selectedCandy;
tween(selectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200
});
selectedCandy = null;
if (swapCandies(oldSelected, candy)) {
LK.setTimeout(function () {
var matches = findMatches();
if (matches.length > 0) {
movesLeft--;
updateUI();
processMatches();
} else {
// No matches, swap back
swapCandies(oldSelected, candy);
}
}, 400);
}
} else {
tween(selectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200
});
selectedCandy = candy;
tween(candy, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
}
}
};
// Initialize the game
initializeGrid();
initializeLevel(currentLevel);
game.update = function () {
// Game loop updates handled by individual candy animations and match processing
};