/****
* 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
};