/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Candy = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.gridX = 0;
self.gridY = 0;
self.isMatched = false;
var candyAsset = self.attachAsset('candy' + type, {
anchorX: 0.5,
anchorY: 0.5
});
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.animateToGridPosition = function (gridX, gridY, duration) {
self.gridX = gridX;
self.gridY = gridY;
var targetX = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
var targetY = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut
});
};
self.highlight = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
};
self.unhighlight = function () {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
};
self.markForRemoval = function () {
self.isMatched = true;
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 250,
easing: tween.easeIn
});
};
return self;
});
var ExplosivePowerUp = Container.expand(function () {
var self = Container.call(this);
// Create explosive visual effect using Power asset with different tint
var powerUpAsset = self.attachAsset('Power', {
anchorX: 0.5,
anchorY: 0.5
});
powerUpAsset.tint = 0xFF0000; // Red tint for explosive power-up
// Add pulsing animation
self.pulseAnimation = function () {
tween(self, {
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) self.pulseAnimation();
}
});
}
});
};
// Start pulsing immediately
self.pulseAnimation();
// Handle click on power-up
self.down = function (x, y, obj) {
self.activate();
};
self.activate = function () {
// Create explosion effect at power-up location
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = self.x;
explosion.y = self.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 6,
scaleY: 6,
alpha: 0,
rotation: Math.PI * 3
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Explode 5x5 random area
self.explode5x5Area();
// Remove power-up
var index = powerUps.indexOf(self);
if (index > -1) {
powerUps.splice(index, 1);
}
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
self.destroy();
};
self.explode5x5Area = function () {
// Find a random 5x5 area on the grid
var startX = Math.floor(Math.random() * (GRID_SIZE - 4)); // Ensure 5x5 fits
var startY = Math.floor(Math.random() * (GRID_SIZE - 4));
var candiesToExplode = [];
// Collect all candies in the 5x5 area
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 5; j++) {
var gridX = startX + i;
var gridY = startY + j;
if (grid[gridX][gridY] && !grid[gridX][gridY].isMatched) {
candiesToExplode.push(grid[gridX][gridY]);
}
}
}
// Explode all candies in the area with staggered timing
for (var i = 0; i < candiesToExplode.length; i++) {
(function (candy, delay) {
LK.setTimeout(function () {
// Create explosion effect
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = candy.x;
explosion.y = candy.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Remove candy from grid
candy.alpha = 0;
grid[candy.gridX][candy.gridY] = null;
// Remove from candies array
var index = candies.indexOf(candy);
if (index > -1) {
candies.splice(index, 1);
}
// Destroy candy after explosion
LK.setTimeout(function () {
candy.destroy();
}, 300);
}, delay);
})(candiesToExplode[i], i * 50);
}
// Process gravity and refill after all explosions
LK.setTimeout(function () {
// Add score for power-up activation
gameScore += 500;
scoreText.setText('Score: ' + gameScore);
LK.setScore(gameScore);
// Process the board
LK.setTimeout(function () {
applyGravity();
fillEmptySpaces();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 100);
}, candiesToExplode.length * 50 + 300);
};
return self;
});
var FirePowerUp = Container.expand(function () {
var self = Container.call(this);
// Create fiery visual effect using Power asset
var powerUpAsset = self.attachAsset('Power', {
anchorX: 0.5,
anchorY: 0.5
});
// Add pulsing animation
self.pulseAnimation = function () {
tween(self, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) self.pulseAnimation();
}
});
}
});
};
// Start pulsing immediately
self.pulseAnimation();
// Handle click on power-up
self.down = function (x, y, obj) {
self.activate();
};
self.activate = function () {
// Create explosion effect at power-up location
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = self.x;
explosion.y = self.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 4,
scaleY: 4,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Explode 5 random candies
self.explodeRandomCandies();
// Remove power-up
var index = powerUps.indexOf(self);
if (index > -1) {
powerUps.splice(index, 1);
}
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
self.destroy();
};
self.explodeRandomCandies = function () {
var availableCandies = [];
for (var i = 0; i < candies.length; i++) {
if (candies[i].parent && !candies[i].isMatched) {
availableCandies.push(candies[i]);
}
}
// Select up to 5 random candies
var candiesToExplode = [];
var numToExplode = Math.min(5, availableCandies.length);
for (var i = 0; i < numToExplode; i++) {
var randomIndex = Math.floor(Math.random() * availableCandies.length);
candiesToExplode.push(availableCandies[randomIndex]);
availableCandies.splice(randomIndex, 1);
}
// Explode selected candies with slight delay between each
for (var i = 0; i < candiesToExplode.length; i++) {
(function (candy, delay) {
LK.setTimeout(function () {
// Create explosion effect
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = candy.x;
explosion.y = candy.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Remove candy from grid
candy.alpha = 0;
grid[candy.gridX][candy.gridY] = null;
// Remove from candies array
var index = candies.indexOf(candy);
if (index > -1) {
candies.splice(index, 1);
}
// Destroy candy after explosion
LK.setTimeout(function () {
candy.destroy();
}, 300);
}, delay);
})(candiesToExplode[i], i * 100);
}
// Process gravity and refill after all explosions
LK.setTimeout(function () {
// Add score for power-up activation
gameScore += 250;
scoreText.setText('Score: ' + gameScore);
LK.setScore(gameScore);
// Process the board
LK.setTimeout(function () {
applyGravity();
fillEmptySpaces();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 100);
}, candiesToExplode.length * 100 + 300);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xFFC0CB
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 140;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2 - 200;
var grid = [];
var candies = [];
var selectedCandy = null;
var isProcessing = false;
var gameScore = 0;
var comboMultiplier = 1;
var powerUps = [];
var hasSpawned1000PowerUp = false;
var POWER_UP_AREA_Y = GRID_START_Y + GRID_SIZE * CELL_SIZE + 150;
var SECOND_POWER_UP_AREA_Y = POWER_UP_AREA_Y + 200;
var gameStarted = false;
var countdownValue = 3;
var countdownText = new Text2('3', {
size: 200,
fill: 0xFFD700
});
// Initialize grid background
var gridBackground = game.addChild(LK.getAsset('gridBg', {
anchorX: 0.5,
anchorY: 0.5
}));
gridBackground.x = 2048 / 2;
gridBackground.y = GRID_START_Y + GRID_SIZE * CELL_SIZE / 2;
// Create cell backgrounds
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
var cellBg = game.addChild(LK.getAsset('cellBg', {
anchorX: 0.5,
anchorY: 0.5
}));
cellBg.x = GRID_START_X + i * CELL_SIZE + CELL_SIZE / 2;
cellBg.y = GRID_START_Y + j * CELL_SIZE + CELL_SIZE / 2;
}
}
// Initialize score display
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.y = 50;
LK.gui.top.addChild(scoreText);
// Initialize combo display
var comboText = new Text2('', {
size: 50,
fill: 0xFFD700
});
comboText.anchor.set(0.5, 0);
comboText.y = 140;
LK.gui.top.addChild(comboText);
// Initialize power-up counter display
var powerUpCountText = new Text2('Power-ups: 0', {
size: 60,
fill: 0xFF4500
});
powerUpCountText.anchor.set(0.5, 0);
powerUpCountText.y = 200;
LK.gui.top.addChild(powerUpCountText);
// Setup countdown display
countdownText.anchor.set(0.5, 0.5);
countdownText.x = 2048 / 2;
countdownText.y = 2732 / 2 - 150;
game.addChild(countdownText);
// Create power-up area
var powerUpArea = game.addChild(LK.getAsset('powerUpBg', {
anchorX: 0.5,
anchorY: 0.5
}));
powerUpArea.x = 2048 / 2 - 250;
powerUpArea.y = POWER_UP_AREA_Y;
powerUpArea.alpha = 0.8;
// Create second power-up area
var secondPowerUpArea = game.addChild(LK.getAsset('powerUpBg', {
anchorX: 0.5,
anchorY: 0.5
}));
secondPowerUpArea.x = 2048 / 2 + 250;
secondPowerUpArea.y = POWER_UP_AREA_Y;
secondPowerUpArea.alpha = 0.8;
secondPowerUpArea.tint = 0xFF4444; // Red tint to distinguish from first area
// Initialize grid array
function initializeGrid() {
grid = [];
for (var i = 0; i < GRID_SIZE; i++) {
grid[i] = [];
for (var j = 0; j < GRID_SIZE; j++) {
grid[i][j] = null;
}
}
}
// Start countdown timer
function startCountdown() {
if (countdownValue > 0) {
countdownText.setText(countdownValue.toString());
tween(countdownText, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(countdownText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
countdownValue--;
LK.setTimeout(startCountdown, 1000);
} else {
countdownText.setText('GO!');
tween(countdownText, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
countdownText.destroy();
gameStarted = true;
// Play music when game starts
LK.playMusic('music');
// Initialize game after countdown
initializeGrid();
fillGrid();
// Remove initial matches
LK.setTimeout(function () {
processMatches();
}, 100);
}
});
}
}
// Generate random candy type
function getRandomCandyType() {
return Math.floor(Math.random() * 6) + 1;
}
// Create candy at grid position
function createCandy(gridX, gridY) {
var candyType = getRandomCandyType();
var candy = new Candy(candyType);
candy.setGridPosition(gridX, gridY);
game.addChild(candy);
candies.push(candy);
grid[gridX][gridY] = candy;
return candy;
}
// Fill grid with initial candies
function fillGrid() {
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
if (!grid[i][j]) {
createCandy(i, j);
}
}
}
}
// Check if coordinates are valid
function isValidPosition(x, y) {
return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;
}
// Check if two positions are adjacent
function areAdjacent(x1, y1, x2, y2) {
var dx = Math.abs(x1 - x2);
var dy = Math.abs(y1 - y2);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
// Swap two candies
function swapCandies(candy1, candy2) {
if (!candy1 || !candy2) return;
var tempX = candy1.gridX;
var tempY = candy1.gridY;
grid[candy1.gridX][candy1.gridY] = candy2;
grid[candy2.gridX][candy2.gridY] = candy1;
candy1.animateToGridPosition(candy2.gridX, candy2.gridY);
candy2.animateToGridPosition(tempX, tempY);
try {
LK.getSound('swap').play();
} catch (e) {
console.log('Error playing swap sound:', e);
}
}
// Find matches in a line
function findMatches(startX, startY, deltaX, deltaY) {
var matches = [];
var currentCandy = grid[startX][startY];
if (!currentCandy) return matches;
var count = 1;
matches.push(currentCandy);
// Check forward
var x = startX + deltaX;
var y = startY + deltaY;
while (isValidPosition(x, y) && grid[x][y] && grid[x][y].type === currentCandy.type) {
matches.push(grid[x][y]);
count++;
x += deltaX;
y += deltaY;
}
// Check backward
x = startX - deltaX;
y = startY - deltaY;
while (isValidPosition(x, y) && grid[x][y] && grid[x][y].type === currentCandy.type) {
matches.unshift(grid[x][y]);
count++;
x -= deltaX;
y -= deltaY;
}
return count >= 3 ? matches : [];
}
// Find all matches on the board
function findAllMatches() {
var allMatches = [];
var processed = [];
for (var i = 0; i < GRID_SIZE; i++) {
processed[i] = [];
for (var j = 0; j < GRID_SIZE; j++) {
processed[i][j] = false;
}
}
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
if (grid[i][j] && !processed[i][j]) {
// Check horizontal matches
var horizontalMatches = findMatches(i, j, 1, 0);
if (horizontalMatches.length >= 3) {
for (var k = 0; k < horizontalMatches.length; k++) {
var candy = horizontalMatches[k];
processed[candy.gridX][candy.gridY] = true;
if (allMatches.indexOf(candy) === -1) {
allMatches.push(candy);
}
}
}
// Check vertical matches
var verticalMatches = findMatches(i, j, 0, 1);
if (verticalMatches.length >= 3) {
for (var k = 0; k < verticalMatches.length; k++) {
var candy = verticalMatches[k];
processed[candy.gridX][candy.gridY] = true;
if (allMatches.indexOf(candy) === -1) {
allMatches.push(candy);
}
}
}
}
}
}
return allMatches;
}
// Remove matched candies
function removeMatches(matches) {
for (var i = 0; i < matches.length; i++) {
var candy = matches[i];
// Create explosion effect using "exp" asset
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = candy.x;
explosion.y = candy.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion growth and fade
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Hide the candy immediately
candy.alpha = 0;
grid[candy.gridX][candy.gridY] = null;
// Remove from candies array
var index = candies.indexOf(candy);
if (index > -1) {
candies.splice(index, 1);
}
}
// Check if we should create a power-up (4 or more candies matched)
if (matches.length >= 4) {
// Create fire power-up
var firePowerUp = new FirePowerUp();
firePowerUp.x = 2048 / 2 - 250;
firePowerUp.y = POWER_UP_AREA_Y;
game.addChild(firePowerUp);
powerUps.push(firePowerUp);
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
// Flash screen to indicate power-up creation
LK.effects.flashScreen(0xFF4500, 500);
}
// Check if we should create the special 1000-point explosive power-up
if (gameScore >= 1000 && !hasSpawned1000PowerUp) {
hasSpawned1000PowerUp = true;
// Create explosive power-up
var explosivePowerUp = new ExplosivePowerUp();
explosivePowerUp.x = 2048 / 2 + 250;
explosivePowerUp.y = POWER_UP_AREA_Y;
game.addChild(explosivePowerUp);
powerUps.push(explosivePowerUp);
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
// Flash screen with different color to indicate special power-up
LK.effects.flashScreen(0xFF0000, 800);
}
// Calculate score
var baseScore = matches.length * 10;
var bonusScore = matches.length > 3 ? (matches.length - 3) * 20 : 0;
var totalScore = (baseScore + bonusScore) * comboMultiplier;
gameScore += totalScore;
scoreText.setText('Score: ' + gameScore);
LK.setScore(gameScore);
// Show combo feedback
if (comboMultiplier > 1) {
comboText.setText('COMBO x' + comboMultiplier + ' (+' + totalScore + ')');
comboText.alpha = 1;
tween(comboText, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut
});
} else {
comboText.setText('');
}
// Flash screen effect for big matches
if (matches.length >= 5) {
LK.effects.flashScreen(0xFFD700, 300);
}
try {
LK.getSound('match').play();
} catch (e) {
console.log('Error playing match sound:', e);
}
// Schedule removal after explosion animation
LK.setTimeout(function () {
for (var i = 0; i < matches.length; i++) {
matches[i].destroy();
}
}, 300);
}
// Make candies fall down
function applyGravity() {
var moved = false;
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = GRID_SIZE - 2; j >= 0; j--) {
if (grid[i][j]) {
var fallDistance = 0;
var checkY = j + 1;
while (checkY < GRID_SIZE && !grid[i][checkY]) {
fallDistance++;
checkY++;
}
if (fallDistance > 0) {
var candy = grid[i][j];
grid[i][j] = null;
grid[i][j + fallDistance] = candy;
candy.animateToGridPosition(i, j + fallDistance);
moved = true;
}
}
}
}
return moved;
}
// Fill empty spaces with new candies
function fillEmptySpaces() {
var added = false;
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
if (!grid[i][j]) {
var candy = createCandy(i, j);
// Start candy above the grid and animate down
candy.y = GRID_START_Y - 100;
candy.animateToGridPosition(i, j);
added = true;
}
}
}
return added;
}
// Check if move creates matches
function wouldCreateMatch(candy1, candy2) {
// Store original positions
var origX1 = candy1.gridX;
var origY1 = candy1.gridY;
var origX2 = candy2.gridX;
var origY2 = candy2.gridY;
// Temporarily swap in grid
grid[candy1.gridX][candy1.gridY] = candy2;
grid[candy2.gridX][candy2.gridY] = candy1;
// Temporarily swap candy positions
candy1.gridX = origX2;
candy1.gridY = origY2;
candy2.gridX = origX1;
candy2.gridY = origY1;
var matches1 = findMatches(candy1.gridX, candy1.gridY, 1, 0);
var matches2 = findMatches(candy1.gridX, candy1.gridY, 0, 1);
var matches3 = findMatches(candy2.gridX, candy2.gridY, 1, 0);
var matches4 = findMatches(candy2.gridX, candy2.gridY, 0, 1);
var hasMatch = matches1.length >= 3 || matches2.length >= 3 || matches3.length >= 3 || matches4.length >= 3;
// Restore original positions
candy1.gridX = origX1;
candy1.gridY = origY1;
candy2.gridX = origX2;
candy2.gridY = origY2;
grid[origX1][origY1] = candy1;
grid[origX2][origY2] = candy2;
return hasMatch;
}
// Process matches and cascades
function processMatches() {
if (isProcessing) return;
isProcessing = true;
var matches = findAllMatches();
if (matches.length > 0) {
removeMatches(matches);
comboMultiplier++;
LK.setTimeout(function () {
var gravityApplied = applyGravity();
var spacesAdded = fillEmptySpaces();
if (gravityApplied || spacesAdded) {
LK.setTimeout(function () {
isProcessing = false;
processMatches(); // Check for new matches
}, 300);
} else {
isProcessing = false;
comboMultiplier = 1;
}
}, 300);
} else {
isProcessing = false;
comboMultiplier = 1;
}
}
// Get candy at screen position
function getCandyAt(x, y) {
// Calculate grid coordinates from screen position
var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE);
var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE);
// Check if coordinates are within grid bounds
if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) {
return grid[gridX][gridY];
}
return null;
}
var dragStartCandy = null;
var dragCurrentCandy = null;
// Game input handling
game.down = function (x, y, obj) {
if (!gameStarted || isProcessing) return;
var candy = getCandyAt(x, y);
if (candy) {
dragStartCandy = candy;
dragCurrentCandy = candy;
candy.highlight();
}
};
game.move = function (x, y, obj) {
if (!gameStarted || isProcessing || !dragStartCandy) return;
var candy = getCandyAt(x, y);
if (candy && candy !== dragCurrentCandy) {
if (dragCurrentCandy && dragCurrentCandy !== dragStartCandy) {
dragCurrentCandy.unhighlight();
}
dragCurrentCandy = candy;
if (candy !== dragStartCandy) {
candy.highlight();
}
}
};
game.up = function (x, y, obj) {
if (!gameStarted || isProcessing || !dragStartCandy) return;
var endCandy = getCandyAt(x, y);
if (endCandy && endCandy !== dragStartCandy && areAdjacent(dragStartCandy.gridX, dragStartCandy.gridY, endCandy.gridX, endCandy.gridY)) {
if (wouldCreateMatch(dragStartCandy, endCandy)) {
swapCandies(dragStartCandy, endCandy);
LK.setTimeout(function () {
processMatches();
}, 400);
} else {
// Invalid move - swap back
try {
LK.getSound('Wro').play();
} catch (e) {
console.log('Error playing wrong move sound:', e);
}
dragStartCandy.unhighlight();
if (endCandy) endCandy.unhighlight();
}
} else {
// No valid target - just unhighlight
dragStartCandy.unhighlight();
if (dragCurrentCandy && dragCurrentCandy !== dragStartCandy) {
dragCurrentCandy.unhighlight();
}
}
dragStartCandy = null;
dragCurrentCandy = null;
};
// Start countdown instead of immediate game initialization
startCountdown();
game.update = function () {
// Game runs automatically through event handling
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Candy = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.gridX = 0;
self.gridY = 0;
self.isMatched = false;
var candyAsset = self.attachAsset('candy' + type, {
anchorX: 0.5,
anchorY: 0.5
});
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.animateToGridPosition = function (gridX, gridY, duration) {
self.gridX = gridX;
self.gridY = gridY;
var targetX = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
var targetY = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut
});
};
self.highlight = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
};
self.unhighlight = function () {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
};
self.markForRemoval = function () {
self.isMatched = true;
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 250,
easing: tween.easeIn
});
};
return self;
});
var ExplosivePowerUp = Container.expand(function () {
var self = Container.call(this);
// Create explosive visual effect using Power asset with different tint
var powerUpAsset = self.attachAsset('Power', {
anchorX: 0.5,
anchorY: 0.5
});
powerUpAsset.tint = 0xFF0000; // Red tint for explosive power-up
// Add pulsing animation
self.pulseAnimation = function () {
tween(self, {
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) self.pulseAnimation();
}
});
}
});
};
// Start pulsing immediately
self.pulseAnimation();
// Handle click on power-up
self.down = function (x, y, obj) {
self.activate();
};
self.activate = function () {
// Create explosion effect at power-up location
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = self.x;
explosion.y = self.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 6,
scaleY: 6,
alpha: 0,
rotation: Math.PI * 3
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Explode 5x5 random area
self.explode5x5Area();
// Remove power-up
var index = powerUps.indexOf(self);
if (index > -1) {
powerUps.splice(index, 1);
}
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
self.destroy();
};
self.explode5x5Area = function () {
// Find a random 5x5 area on the grid
var startX = Math.floor(Math.random() * (GRID_SIZE - 4)); // Ensure 5x5 fits
var startY = Math.floor(Math.random() * (GRID_SIZE - 4));
var candiesToExplode = [];
// Collect all candies in the 5x5 area
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 5; j++) {
var gridX = startX + i;
var gridY = startY + j;
if (grid[gridX][gridY] && !grid[gridX][gridY].isMatched) {
candiesToExplode.push(grid[gridX][gridY]);
}
}
}
// Explode all candies in the area with staggered timing
for (var i = 0; i < candiesToExplode.length; i++) {
(function (candy, delay) {
LK.setTimeout(function () {
// Create explosion effect
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = candy.x;
explosion.y = candy.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Remove candy from grid
candy.alpha = 0;
grid[candy.gridX][candy.gridY] = null;
// Remove from candies array
var index = candies.indexOf(candy);
if (index > -1) {
candies.splice(index, 1);
}
// Destroy candy after explosion
LK.setTimeout(function () {
candy.destroy();
}, 300);
}, delay);
})(candiesToExplode[i], i * 50);
}
// Process gravity and refill after all explosions
LK.setTimeout(function () {
// Add score for power-up activation
gameScore += 500;
scoreText.setText('Score: ' + gameScore);
LK.setScore(gameScore);
// Process the board
LK.setTimeout(function () {
applyGravity();
fillEmptySpaces();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 100);
}, candiesToExplode.length * 50 + 300);
};
return self;
});
var FirePowerUp = Container.expand(function () {
var self = Container.call(this);
// Create fiery visual effect using Power asset
var powerUpAsset = self.attachAsset('Power', {
anchorX: 0.5,
anchorY: 0.5
});
// Add pulsing animation
self.pulseAnimation = function () {
tween(self, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) self.pulseAnimation();
}
});
}
});
};
// Start pulsing immediately
self.pulseAnimation();
// Handle click on power-up
self.down = function (x, y, obj) {
self.activate();
};
self.activate = function () {
// Create explosion effect at power-up location
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = self.x;
explosion.y = self.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 4,
scaleY: 4,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Explode 5 random candies
self.explodeRandomCandies();
// Remove power-up
var index = powerUps.indexOf(self);
if (index > -1) {
powerUps.splice(index, 1);
}
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
self.destroy();
};
self.explodeRandomCandies = function () {
var availableCandies = [];
for (var i = 0; i < candies.length; i++) {
if (candies[i].parent && !candies[i].isMatched) {
availableCandies.push(candies[i]);
}
}
// Select up to 5 random candies
var candiesToExplode = [];
var numToExplode = Math.min(5, availableCandies.length);
for (var i = 0; i < numToExplode; i++) {
var randomIndex = Math.floor(Math.random() * availableCandies.length);
candiesToExplode.push(availableCandies[randomIndex]);
availableCandies.splice(randomIndex, 1);
}
// Explode selected candies with slight delay between each
for (var i = 0; i < candiesToExplode.length; i++) {
(function (candy, delay) {
LK.setTimeout(function () {
// Create explosion effect
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = candy.x;
explosion.y = candy.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Remove candy from grid
candy.alpha = 0;
grid[candy.gridX][candy.gridY] = null;
// Remove from candies array
var index = candies.indexOf(candy);
if (index > -1) {
candies.splice(index, 1);
}
// Destroy candy after explosion
LK.setTimeout(function () {
candy.destroy();
}, 300);
}, delay);
})(candiesToExplode[i], i * 100);
}
// Process gravity and refill after all explosions
LK.setTimeout(function () {
// Add score for power-up activation
gameScore += 250;
scoreText.setText('Score: ' + gameScore);
LK.setScore(gameScore);
// Process the board
LK.setTimeout(function () {
applyGravity();
fillEmptySpaces();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 100);
}, candiesToExplode.length * 100 + 300);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xFFC0CB
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 140;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2 - 200;
var grid = [];
var candies = [];
var selectedCandy = null;
var isProcessing = false;
var gameScore = 0;
var comboMultiplier = 1;
var powerUps = [];
var hasSpawned1000PowerUp = false;
var POWER_UP_AREA_Y = GRID_START_Y + GRID_SIZE * CELL_SIZE + 150;
var SECOND_POWER_UP_AREA_Y = POWER_UP_AREA_Y + 200;
var gameStarted = false;
var countdownValue = 3;
var countdownText = new Text2('3', {
size: 200,
fill: 0xFFD700
});
// Initialize grid background
var gridBackground = game.addChild(LK.getAsset('gridBg', {
anchorX: 0.5,
anchorY: 0.5
}));
gridBackground.x = 2048 / 2;
gridBackground.y = GRID_START_Y + GRID_SIZE * CELL_SIZE / 2;
// Create cell backgrounds
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
var cellBg = game.addChild(LK.getAsset('cellBg', {
anchorX: 0.5,
anchorY: 0.5
}));
cellBg.x = GRID_START_X + i * CELL_SIZE + CELL_SIZE / 2;
cellBg.y = GRID_START_Y + j * CELL_SIZE + CELL_SIZE / 2;
}
}
// Initialize score display
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.y = 50;
LK.gui.top.addChild(scoreText);
// Initialize combo display
var comboText = new Text2('', {
size: 50,
fill: 0xFFD700
});
comboText.anchor.set(0.5, 0);
comboText.y = 140;
LK.gui.top.addChild(comboText);
// Initialize power-up counter display
var powerUpCountText = new Text2('Power-ups: 0', {
size: 60,
fill: 0xFF4500
});
powerUpCountText.anchor.set(0.5, 0);
powerUpCountText.y = 200;
LK.gui.top.addChild(powerUpCountText);
// Setup countdown display
countdownText.anchor.set(0.5, 0.5);
countdownText.x = 2048 / 2;
countdownText.y = 2732 / 2 - 150;
game.addChild(countdownText);
// Create power-up area
var powerUpArea = game.addChild(LK.getAsset('powerUpBg', {
anchorX: 0.5,
anchorY: 0.5
}));
powerUpArea.x = 2048 / 2 - 250;
powerUpArea.y = POWER_UP_AREA_Y;
powerUpArea.alpha = 0.8;
// Create second power-up area
var secondPowerUpArea = game.addChild(LK.getAsset('powerUpBg', {
anchorX: 0.5,
anchorY: 0.5
}));
secondPowerUpArea.x = 2048 / 2 + 250;
secondPowerUpArea.y = POWER_UP_AREA_Y;
secondPowerUpArea.alpha = 0.8;
secondPowerUpArea.tint = 0xFF4444; // Red tint to distinguish from first area
// Initialize grid array
function initializeGrid() {
grid = [];
for (var i = 0; i < GRID_SIZE; i++) {
grid[i] = [];
for (var j = 0; j < GRID_SIZE; j++) {
grid[i][j] = null;
}
}
}
// Start countdown timer
function startCountdown() {
if (countdownValue > 0) {
countdownText.setText(countdownValue.toString());
tween(countdownText, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(countdownText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
countdownValue--;
LK.setTimeout(startCountdown, 1000);
} else {
countdownText.setText('GO!');
tween(countdownText, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
countdownText.destroy();
gameStarted = true;
// Play music when game starts
LK.playMusic('music');
// Initialize game after countdown
initializeGrid();
fillGrid();
// Remove initial matches
LK.setTimeout(function () {
processMatches();
}, 100);
}
});
}
}
// Generate random candy type
function getRandomCandyType() {
return Math.floor(Math.random() * 6) + 1;
}
// Create candy at grid position
function createCandy(gridX, gridY) {
var candyType = getRandomCandyType();
var candy = new Candy(candyType);
candy.setGridPosition(gridX, gridY);
game.addChild(candy);
candies.push(candy);
grid[gridX][gridY] = candy;
return candy;
}
// Fill grid with initial candies
function fillGrid() {
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
if (!grid[i][j]) {
createCandy(i, j);
}
}
}
}
// Check if coordinates are valid
function isValidPosition(x, y) {
return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;
}
// Check if two positions are adjacent
function areAdjacent(x1, y1, x2, y2) {
var dx = Math.abs(x1 - x2);
var dy = Math.abs(y1 - y2);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
// Swap two candies
function swapCandies(candy1, candy2) {
if (!candy1 || !candy2) return;
var tempX = candy1.gridX;
var tempY = candy1.gridY;
grid[candy1.gridX][candy1.gridY] = candy2;
grid[candy2.gridX][candy2.gridY] = candy1;
candy1.animateToGridPosition(candy2.gridX, candy2.gridY);
candy2.animateToGridPosition(tempX, tempY);
try {
LK.getSound('swap').play();
} catch (e) {
console.log('Error playing swap sound:', e);
}
}
// Find matches in a line
function findMatches(startX, startY, deltaX, deltaY) {
var matches = [];
var currentCandy = grid[startX][startY];
if (!currentCandy) return matches;
var count = 1;
matches.push(currentCandy);
// Check forward
var x = startX + deltaX;
var y = startY + deltaY;
while (isValidPosition(x, y) && grid[x][y] && grid[x][y].type === currentCandy.type) {
matches.push(grid[x][y]);
count++;
x += deltaX;
y += deltaY;
}
// Check backward
x = startX - deltaX;
y = startY - deltaY;
while (isValidPosition(x, y) && grid[x][y] && grid[x][y].type === currentCandy.type) {
matches.unshift(grid[x][y]);
count++;
x -= deltaX;
y -= deltaY;
}
return count >= 3 ? matches : [];
}
// Find all matches on the board
function findAllMatches() {
var allMatches = [];
var processed = [];
for (var i = 0; i < GRID_SIZE; i++) {
processed[i] = [];
for (var j = 0; j < GRID_SIZE; j++) {
processed[i][j] = false;
}
}
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
if (grid[i][j] && !processed[i][j]) {
// Check horizontal matches
var horizontalMatches = findMatches(i, j, 1, 0);
if (horizontalMatches.length >= 3) {
for (var k = 0; k < horizontalMatches.length; k++) {
var candy = horizontalMatches[k];
processed[candy.gridX][candy.gridY] = true;
if (allMatches.indexOf(candy) === -1) {
allMatches.push(candy);
}
}
}
// Check vertical matches
var verticalMatches = findMatches(i, j, 0, 1);
if (verticalMatches.length >= 3) {
for (var k = 0; k < verticalMatches.length; k++) {
var candy = verticalMatches[k];
processed[candy.gridX][candy.gridY] = true;
if (allMatches.indexOf(candy) === -1) {
allMatches.push(candy);
}
}
}
}
}
}
return allMatches;
}
// Remove matched candies
function removeMatches(matches) {
for (var i = 0; i < matches.length; i++) {
var candy = matches[i];
// Create explosion effect using "exp" asset
var explosion = game.addChild(LK.getAsset('Exp', {
anchorX: 0.5,
anchorY: 0.5
}));
explosion.x = candy.x;
explosion.y = candy.y;
explosion.scaleX = 0.1;
explosion.scaleY = 0.1;
explosion.alpha = 0.8;
// Animate explosion growth and fade
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Hide the candy immediately
candy.alpha = 0;
grid[candy.gridX][candy.gridY] = null;
// Remove from candies array
var index = candies.indexOf(candy);
if (index > -1) {
candies.splice(index, 1);
}
}
// Check if we should create a power-up (4 or more candies matched)
if (matches.length >= 4) {
// Create fire power-up
var firePowerUp = new FirePowerUp();
firePowerUp.x = 2048 / 2 - 250;
firePowerUp.y = POWER_UP_AREA_Y;
game.addChild(firePowerUp);
powerUps.push(firePowerUp);
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
// Flash screen to indicate power-up creation
LK.effects.flashScreen(0xFF4500, 500);
}
// Check if we should create the special 1000-point explosive power-up
if (gameScore >= 1000 && !hasSpawned1000PowerUp) {
hasSpawned1000PowerUp = true;
// Create explosive power-up
var explosivePowerUp = new ExplosivePowerUp();
explosivePowerUp.x = 2048 / 2 + 250;
explosivePowerUp.y = POWER_UP_AREA_Y;
game.addChild(explosivePowerUp);
powerUps.push(explosivePowerUp);
// Update power-up counter display
powerUpCountText.setText('Power-ups: ' + powerUps.length);
// Flash screen with different color to indicate special power-up
LK.effects.flashScreen(0xFF0000, 800);
}
// Calculate score
var baseScore = matches.length * 10;
var bonusScore = matches.length > 3 ? (matches.length - 3) * 20 : 0;
var totalScore = (baseScore + bonusScore) * comboMultiplier;
gameScore += totalScore;
scoreText.setText('Score: ' + gameScore);
LK.setScore(gameScore);
// Show combo feedback
if (comboMultiplier > 1) {
comboText.setText('COMBO x' + comboMultiplier + ' (+' + totalScore + ')');
comboText.alpha = 1;
tween(comboText, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut
});
} else {
comboText.setText('');
}
// Flash screen effect for big matches
if (matches.length >= 5) {
LK.effects.flashScreen(0xFFD700, 300);
}
try {
LK.getSound('match').play();
} catch (e) {
console.log('Error playing match sound:', e);
}
// Schedule removal after explosion animation
LK.setTimeout(function () {
for (var i = 0; i < matches.length; i++) {
matches[i].destroy();
}
}, 300);
}
// Make candies fall down
function applyGravity() {
var moved = false;
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = GRID_SIZE - 2; j >= 0; j--) {
if (grid[i][j]) {
var fallDistance = 0;
var checkY = j + 1;
while (checkY < GRID_SIZE && !grid[i][checkY]) {
fallDistance++;
checkY++;
}
if (fallDistance > 0) {
var candy = grid[i][j];
grid[i][j] = null;
grid[i][j + fallDistance] = candy;
candy.animateToGridPosition(i, j + fallDistance);
moved = true;
}
}
}
}
return moved;
}
// Fill empty spaces with new candies
function fillEmptySpaces() {
var added = false;
for (var i = 0; i < GRID_SIZE; i++) {
for (var j = 0; j < GRID_SIZE; j++) {
if (!grid[i][j]) {
var candy = createCandy(i, j);
// Start candy above the grid and animate down
candy.y = GRID_START_Y - 100;
candy.animateToGridPosition(i, j);
added = true;
}
}
}
return added;
}
// Check if move creates matches
function wouldCreateMatch(candy1, candy2) {
// Store original positions
var origX1 = candy1.gridX;
var origY1 = candy1.gridY;
var origX2 = candy2.gridX;
var origY2 = candy2.gridY;
// Temporarily swap in grid
grid[candy1.gridX][candy1.gridY] = candy2;
grid[candy2.gridX][candy2.gridY] = candy1;
// Temporarily swap candy positions
candy1.gridX = origX2;
candy1.gridY = origY2;
candy2.gridX = origX1;
candy2.gridY = origY1;
var matches1 = findMatches(candy1.gridX, candy1.gridY, 1, 0);
var matches2 = findMatches(candy1.gridX, candy1.gridY, 0, 1);
var matches3 = findMatches(candy2.gridX, candy2.gridY, 1, 0);
var matches4 = findMatches(candy2.gridX, candy2.gridY, 0, 1);
var hasMatch = matches1.length >= 3 || matches2.length >= 3 || matches3.length >= 3 || matches4.length >= 3;
// Restore original positions
candy1.gridX = origX1;
candy1.gridY = origY1;
candy2.gridX = origX2;
candy2.gridY = origY2;
grid[origX1][origY1] = candy1;
grid[origX2][origY2] = candy2;
return hasMatch;
}
// Process matches and cascades
function processMatches() {
if (isProcessing) return;
isProcessing = true;
var matches = findAllMatches();
if (matches.length > 0) {
removeMatches(matches);
comboMultiplier++;
LK.setTimeout(function () {
var gravityApplied = applyGravity();
var spacesAdded = fillEmptySpaces();
if (gravityApplied || spacesAdded) {
LK.setTimeout(function () {
isProcessing = false;
processMatches(); // Check for new matches
}, 300);
} else {
isProcessing = false;
comboMultiplier = 1;
}
}, 300);
} else {
isProcessing = false;
comboMultiplier = 1;
}
}
// Get candy at screen position
function getCandyAt(x, y) {
// Calculate grid coordinates from screen position
var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE);
var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE);
// Check if coordinates are within grid bounds
if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) {
return grid[gridX][gridY];
}
return null;
}
var dragStartCandy = null;
var dragCurrentCandy = null;
// Game input handling
game.down = function (x, y, obj) {
if (!gameStarted || isProcessing) return;
var candy = getCandyAt(x, y);
if (candy) {
dragStartCandy = candy;
dragCurrentCandy = candy;
candy.highlight();
}
};
game.move = function (x, y, obj) {
if (!gameStarted || isProcessing || !dragStartCandy) return;
var candy = getCandyAt(x, y);
if (candy && candy !== dragCurrentCandy) {
if (dragCurrentCandy && dragCurrentCandy !== dragStartCandy) {
dragCurrentCandy.unhighlight();
}
dragCurrentCandy = candy;
if (candy !== dragStartCandy) {
candy.highlight();
}
}
};
game.up = function (x, y, obj) {
if (!gameStarted || isProcessing || !dragStartCandy) return;
var endCandy = getCandyAt(x, y);
if (endCandy && endCandy !== dragStartCandy && areAdjacent(dragStartCandy.gridX, dragStartCandy.gridY, endCandy.gridX, endCandy.gridY)) {
if (wouldCreateMatch(dragStartCandy, endCandy)) {
swapCandies(dragStartCandy, endCandy);
LK.setTimeout(function () {
processMatches();
}, 400);
} else {
// Invalid move - swap back
try {
LK.getSound('Wro').play();
} catch (e) {
console.log('Error playing wrong move sound:', e);
}
dragStartCandy.unhighlight();
if (endCandy) endCandy.unhighlight();
}
} else {
// No valid target - just unhighlight
dragStartCandy.unhighlight();
if (dragCurrentCandy && dragCurrentCandy !== dragStartCandy) {
dragCurrentCandy.unhighlight();
}
}
dragStartCandy = null;
dragCurrentCandy = null;
};
// Start countdown instead of immediate game initialization
startCountdown();
game.update = function () {
// Game runs automatically through event handling
};