/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Candy = Container.expand(function (type) {
var self = Container.call(this);
self.candyType = type || 0;
self.isSpecial = false;
self.specialType = 'normal'; // 'normal', 'bomb', 'rainbow'
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
self.isSelected = false;
self.interactive = true;
var candyTypes = ['candy_red', 'candy_blue', 'candy_green', 'candy_yellow', 'candy_purple', 'candy_orange'];
var assetId = candyTypes[self.candyType] || candyTypes[0];
self.candyGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Set hit area for better touch detection
self.hitArea = new Rectangle(-60, -60, 120, 120);
self.makeSpecial = function (specialType) {
self.isSpecial = true;
self.specialType = specialType;
if (specialType === 'bomb') {
self.removeChild(self.candyGraphics);
self.candyGraphics = self.attachAsset('bomb_candy', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (specialType === 'rainbow') {
self.removeChild(self.candyGraphics);
self.candyGraphics = self.attachAsset('rainbow_candy', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.candyGraphics.scaleX = 1.2;
self.candyGraphics.scaleY = 1.2;
} else {
self.candyGraphics.scaleX = 1.0;
self.candyGraphics.scaleY = 1.0;
}
};
self.down = function (x, y, obj) {
if (!self.isAnimating) {
handleCandyClick(self);
}
};
return self;
});
var GameGrid = Container.expand(function () {
var self = Container.call(this);
self.gridSize = 8;
self.cellSize = 120;
self.grid = [];
self.backgroundCells = [];
self.init = function () {
// Create background grid
for (var row = 0; row < self.gridSize; row++) {
for (var col = 0; col < self.gridSize; col++) {
var bgCell = self.attachAsset('grid_bg', {
anchorX: 0.5,
anchorY: 0.5
});
bgCell.x = col * self.cellSize;
bgCell.y = row * self.cellSize;
bgCell.alpha = 0.3;
self.backgroundCells.push(bgCell);
}
}
// Initialize grid array
for (var row = 0; row < self.gridSize; row++) {
self.grid[row] = [];
for (var col = 0; col < self.gridSize; col++) {
self.grid[row][col] = null;
}
}
// Fill grid with candies ensuring no initial matches
self.fillGrid();
};
self.fillGrid = function () {
for (var row = 0; row < self.gridSize; row++) {
for (var col = 0; col < self.gridSize; col++) {
if (!self.grid[row][col]) {
var candyType = self.getValidCandyType(row, col);
var candy = new Candy(candyType);
candy.gridX = col;
candy.gridY = row;
candy.x = col * self.cellSize;
candy.y = row * self.cellSize;
self.grid[row][col] = candy;
self.addChild(candy);
}
}
}
};
self.getValidCandyType = function (row, col) {
var invalidTypes = [];
// Check horizontal matches
if (col >= 2) {
var type1 = self.grid[row][col - 1] ? self.grid[row][col - 1].candyType : -1;
var type2 = self.grid[row][col - 2] ? self.grid[row][col - 2].candyType : -1;
if (type1 === type2 && type1 !== -1) {
invalidTypes.push(type1);
}
}
// Check vertical matches
if (row >= 2) {
var type1 = self.grid[row - 1][col] ? self.grid[row - 1][col].candyType : -1;
var type2 = self.grid[row - 2][col] ? self.grid[row - 2][col].candyType : -1;
if (type1 === type2 && type1 !== -1) {
invalidTypes.push(type1);
}
}
var validTypes = [];
for (var i = 0; i < 6; i++) {
if (invalidTypes.indexOf(i) === -1) {
validTypes.push(i);
}
}
return validTypes[Math.floor(Math.random() * validTypes.length)];
};
self.swapCandies = function (candy1, candy2) {
if (!candy1 || !candy2) return false;
var tempX = candy1.gridX;
var tempY = candy1.gridY;
candy1.gridX = candy2.gridX;
candy1.gridY = candy2.gridY;
candy2.gridX = tempX;
candy2.gridY = tempY;
self.grid[candy1.gridY][candy1.gridX] = candy1;
self.grid[candy2.gridY][candy2.gridX] = candy2;
// Animate swap
candy1.isAnimating = true;
candy2.isAnimating = true;
tween(candy1, {
x: candy1.gridX * self.cellSize,
y: candy1.gridY * self.cellSize
}, {
duration: 200,
onFinish: function onFinish() {
candy1.isAnimating = false;
}
});
tween(candy2, {
x: candy2.gridX * self.cellSize,
y: candy2.gridY * self.cellSize
}, {
duration: 200,
onFinish: function onFinish() {
candy2.isAnimating = false;
self.checkMatches();
}
});
return true;
};
self.checkMatches = function () {
var matches = [];
var visited = [];
// Initialize visited array
for (var row = 0; row < self.gridSize; row++) {
visited[row] = [];
for (var col = 0; col < self.gridSize; col++) {
visited[row][col] = false;
}
}
// Check horizontal matches
for (var row = 0; row < self.gridSize; row++) {
var count = 1;
var currentType = self.grid[row][0] ? self.grid[row][0].candyType : -1;
for (var col = 1; col < self.gridSize; col++) {
var cellType = self.grid[row][col] ? self.grid[row][col].candyType : -1;
if (cellType === currentType && currentType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = col - count; i < col; i++) {
if (!visited[row][i]) {
matches.push({
row: row,
col: i
});
visited[row][i] = true;
}
}
}
count = 1;
currentType = cellType;
}
}
if (count >= 3) {
for (var i = self.gridSize - count; i < self.gridSize; i++) {
if (!visited[row][i]) {
matches.push({
row: row,
col: i
});
visited[row][i] = true;
}
}
}
}
// Check vertical matches
for (var col = 0; col < self.gridSize; col++) {
var count = 1;
var currentType = self.grid[0][col] ? self.grid[0][col].candyType : -1;
for (var row = 1; row < self.gridSize; row++) {
var cellType = self.grid[row][col] ? self.grid[row][col].candyType : -1;
if (cellType === currentType && currentType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = row - count; i < row; i++) {
if (!visited[i][col]) {
matches.push({
row: i,
col: col
});
visited[i][col] = true;
}
}
}
count = 1;
currentType = cellType;
}
}
if (count >= 3) {
for (var i = self.gridSize - count; i < self.gridSize; i++) {
if (!visited[i][col]) {
matches.push({
row: i,
col: col
});
visited[i][col] = true;
}
}
}
}
if (matches.length > 0) {
self.removeMatches(matches);
return true;
}
return false;
};
self.removeMatches = function (matches) {
var points = 0;
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
var candy = self.grid[match.row][match.col];
if (candy) {
points += 10;
// Check for special candy creation
var matchLength = self.getMatchLength(match.row, match.col, candy.candyType);
if (matchLength >= 5) {
// Create rainbow candy
candy.makeSpecial('rainbow');
continue;
} else if (matchLength >= 4) {
// Create bomb candy
candy.makeSpecial('bomb');
continue;
}
self.removeChild(candy);
self.grid[match.row][match.col] = null;
}
}
LK.setScore(LK.getScore() + points);
scoreText.setText(LK.getScore() + ' / ' + targetScore);
LK.getSound('match').play();
// Apply gravity and cascade
LK.setTimeout(function () {
self.applyGravity();
}, 100);
};
self.getMatchLength = function (row, col, candyType) {
var length = 1;
// Count horizontal
var left = col - 1;
while (left >= 0 && self.grid[row][left] && self.grid[row][left].candyType === candyType) {
length++;
left--;
}
var right = col + 1;
while (right < self.gridSize && self.grid[row][right] && self.grid[row][right].candyType === candyType) {
length++;
right++;
}
return length;
};
self.applyGravity = function () {
var moved = false;
for (var col = 0; col < self.gridSize; col++) {
for (var row = self.gridSize - 1; row >= 0; row--) {
if (!self.grid[row][col]) {
// Find candy above to fall down
for (var aboveRow = row - 1; aboveRow >= 0; aboveRow--) {
if (self.grid[aboveRow][col]) {
var candy = self.grid[aboveRow][col];
self.grid[row][col] = candy;
self.grid[aboveRow][col] = null;
candy.gridY = row;
candy.isAnimating = true;
moved = true;
tween(candy, {
y: row * self.cellSize
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
candy.isAnimating = false;
}
});
break;
}
}
}
}
}
if (moved) {
LK.getSound('cascade').play();
}
// Fill empty spaces and check for new matches
LK.setTimeout(function () {
self.fillGrid();
LK.setTimeout(function () {
if (!self.checkMatches()) {
isProcessingMatches = false;
}
}, 100);
}, 350);
};
self.isAdjacent = function (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;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
var gameGrid;
var selectedCandy = null;
var movesLeft = 20;
var targetScore = 1000;
var currentLevel = 1;
var isProcessingMatches = false;
// UI Elements
var scoreText = new Text2('0 / 1000', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var movesText = new Text2('Moves: 20', {
size: 50,
fill: 0xFFFFFF
});
movesText.anchor.set(0, 0);
movesText.x = 50;
movesText.y = 100;
LK.gui.topLeft.addChild(movesText);
var levelText = new Text2('Level 1', {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(1, 0);
levelText.x = -50;
levelText.y = 100;
LK.gui.topRight.addChild(levelText);
// Initialize game grid
gameGrid = new GameGrid();
gameGrid.init();
// Center the grid and ensure it's in touchable area
var gridWidth = gameGrid.gridSize * gameGrid.cellSize;
var gridHeight = gameGrid.gridSize * gameGrid.cellSize;
gameGrid.x = (2048 - gridWidth) / 2;
gameGrid.y = (2732 - gridHeight) / 2;
// Ensure grid is not too close to top (avoid menu area)
if (gameGrid.y < 200) {
gameGrid.y = 200;
}
game.addChild(gameGrid);
function handleCandyClick(candy) {
if (isProcessingMatches || movesLeft <= 0) return;
if (!selectedCandy) {
selectedCandy = candy;
candy.setSelected(true);
} else if (selectedCandy === candy) {
selectedCandy.setSelected(false);
selectedCandy = null;
} else if (gameGrid.isAdjacent(selectedCandy, candy)) {
// Valid swap
selectedCandy.setSelected(false);
var oldGrid1 = {
x: selectedCandy.gridX,
y: selectedCandy.gridY
};
var oldGrid2 = {
x: candy.gridX,
y: candy.gridY
};
// Capture candy references before nullifying selectedCandy
var candy1Ref = selectedCandy;
var candy2Ref = candy;
if (gameGrid.swapCandies(selectedCandy, candy)) {
movesLeft--;
movesText.setText('Moves: ' + movesLeft);
isProcessingMatches = true;
// Check if swap creates matches, if not, swap back
LK.setTimeout(function () {
if (!gameGrid.checkMatches()) {
// Swap back using captured references
candy1Ref.gridX = oldGrid1.x;
candy1Ref.gridY = oldGrid1.y;
candy2Ref.gridX = oldGrid2.x;
candy2Ref.gridY = oldGrid2.y;
gameGrid.grid[candy1Ref.gridY][candy1Ref.gridX] = candy1Ref;
gameGrid.grid[candy2Ref.gridY][candy2Ref.gridX] = candy2Ref;
tween(candy1Ref, {
x: candy1Ref.gridX * gameGrid.cellSize,
y: candy1Ref.gridY * gameGrid.cellSize
}, {
duration: 200
});
tween(candy2Ref, {
x: candy2Ref.gridX * gameGrid.cellSize,
y: candy2Ref.gridY * gameGrid.cellSize
}, {
duration: 200
});
movesLeft++;
movesText.setText('Moves: ' + movesLeft);
isProcessingMatches = false;
}
}, 250);
}
selectedCandy = null;
} else {
selectedCandy.setSelected(false);
selectedCandy = candy;
candy.setSelected(true);
}
}
game.update = function () {
// Check win condition
if (LK.getScore() >= targetScore) {
currentLevel++;
targetScore += 500;
movesLeft = 20;
levelText.setText('Level ' + currentLevel);
scoreText.setText(LK.getScore() + ' / ' + targetScore);
movesText.setText('Moves: ' + movesLeft);
// Reset grid for next level
for (var row = 0; row < gameGrid.gridSize; row++) {
for (var col = 0; col < gameGrid.gridSize; col++) {
if (gameGrid.grid[row][col]) {
gameGrid.removeChild(gameGrid.grid[row][col]);
gameGrid.grid[row][col] = null;
}
}
}
gameGrid.fillGrid();
}
// Check lose condition
if (movesLeft <= 0 && LK.getScore() < targetScore && !isProcessingMatches) {
LK.showGameOver();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Candy = Container.expand(function (type) {
var self = Container.call(this);
self.candyType = type || 0;
self.isSpecial = false;
self.specialType = 'normal'; // 'normal', 'bomb', 'rainbow'
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
self.isSelected = false;
self.interactive = true;
var candyTypes = ['candy_red', 'candy_blue', 'candy_green', 'candy_yellow', 'candy_purple', 'candy_orange'];
var assetId = candyTypes[self.candyType] || candyTypes[0];
self.candyGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Set hit area for better touch detection
self.hitArea = new Rectangle(-60, -60, 120, 120);
self.makeSpecial = function (specialType) {
self.isSpecial = true;
self.specialType = specialType;
if (specialType === 'bomb') {
self.removeChild(self.candyGraphics);
self.candyGraphics = self.attachAsset('bomb_candy', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (specialType === 'rainbow') {
self.removeChild(self.candyGraphics);
self.candyGraphics = self.attachAsset('rainbow_candy', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.candyGraphics.scaleX = 1.2;
self.candyGraphics.scaleY = 1.2;
} else {
self.candyGraphics.scaleX = 1.0;
self.candyGraphics.scaleY = 1.0;
}
};
self.down = function (x, y, obj) {
if (!self.isAnimating) {
handleCandyClick(self);
}
};
return self;
});
var GameGrid = Container.expand(function () {
var self = Container.call(this);
self.gridSize = 8;
self.cellSize = 120;
self.grid = [];
self.backgroundCells = [];
self.init = function () {
// Create background grid
for (var row = 0; row < self.gridSize; row++) {
for (var col = 0; col < self.gridSize; col++) {
var bgCell = self.attachAsset('grid_bg', {
anchorX: 0.5,
anchorY: 0.5
});
bgCell.x = col * self.cellSize;
bgCell.y = row * self.cellSize;
bgCell.alpha = 0.3;
self.backgroundCells.push(bgCell);
}
}
// Initialize grid array
for (var row = 0; row < self.gridSize; row++) {
self.grid[row] = [];
for (var col = 0; col < self.gridSize; col++) {
self.grid[row][col] = null;
}
}
// Fill grid with candies ensuring no initial matches
self.fillGrid();
};
self.fillGrid = function () {
for (var row = 0; row < self.gridSize; row++) {
for (var col = 0; col < self.gridSize; col++) {
if (!self.grid[row][col]) {
var candyType = self.getValidCandyType(row, col);
var candy = new Candy(candyType);
candy.gridX = col;
candy.gridY = row;
candy.x = col * self.cellSize;
candy.y = row * self.cellSize;
self.grid[row][col] = candy;
self.addChild(candy);
}
}
}
};
self.getValidCandyType = function (row, col) {
var invalidTypes = [];
// Check horizontal matches
if (col >= 2) {
var type1 = self.grid[row][col - 1] ? self.grid[row][col - 1].candyType : -1;
var type2 = self.grid[row][col - 2] ? self.grid[row][col - 2].candyType : -1;
if (type1 === type2 && type1 !== -1) {
invalidTypes.push(type1);
}
}
// Check vertical matches
if (row >= 2) {
var type1 = self.grid[row - 1][col] ? self.grid[row - 1][col].candyType : -1;
var type2 = self.grid[row - 2][col] ? self.grid[row - 2][col].candyType : -1;
if (type1 === type2 && type1 !== -1) {
invalidTypes.push(type1);
}
}
var validTypes = [];
for (var i = 0; i < 6; i++) {
if (invalidTypes.indexOf(i) === -1) {
validTypes.push(i);
}
}
return validTypes[Math.floor(Math.random() * validTypes.length)];
};
self.swapCandies = function (candy1, candy2) {
if (!candy1 || !candy2) return false;
var tempX = candy1.gridX;
var tempY = candy1.gridY;
candy1.gridX = candy2.gridX;
candy1.gridY = candy2.gridY;
candy2.gridX = tempX;
candy2.gridY = tempY;
self.grid[candy1.gridY][candy1.gridX] = candy1;
self.grid[candy2.gridY][candy2.gridX] = candy2;
// Animate swap
candy1.isAnimating = true;
candy2.isAnimating = true;
tween(candy1, {
x: candy1.gridX * self.cellSize,
y: candy1.gridY * self.cellSize
}, {
duration: 200,
onFinish: function onFinish() {
candy1.isAnimating = false;
}
});
tween(candy2, {
x: candy2.gridX * self.cellSize,
y: candy2.gridY * self.cellSize
}, {
duration: 200,
onFinish: function onFinish() {
candy2.isAnimating = false;
self.checkMatches();
}
});
return true;
};
self.checkMatches = function () {
var matches = [];
var visited = [];
// Initialize visited array
for (var row = 0; row < self.gridSize; row++) {
visited[row] = [];
for (var col = 0; col < self.gridSize; col++) {
visited[row][col] = false;
}
}
// Check horizontal matches
for (var row = 0; row < self.gridSize; row++) {
var count = 1;
var currentType = self.grid[row][0] ? self.grid[row][0].candyType : -1;
for (var col = 1; col < self.gridSize; col++) {
var cellType = self.grid[row][col] ? self.grid[row][col].candyType : -1;
if (cellType === currentType && currentType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = col - count; i < col; i++) {
if (!visited[row][i]) {
matches.push({
row: row,
col: i
});
visited[row][i] = true;
}
}
}
count = 1;
currentType = cellType;
}
}
if (count >= 3) {
for (var i = self.gridSize - count; i < self.gridSize; i++) {
if (!visited[row][i]) {
matches.push({
row: row,
col: i
});
visited[row][i] = true;
}
}
}
}
// Check vertical matches
for (var col = 0; col < self.gridSize; col++) {
var count = 1;
var currentType = self.grid[0][col] ? self.grid[0][col].candyType : -1;
for (var row = 1; row < self.gridSize; row++) {
var cellType = self.grid[row][col] ? self.grid[row][col].candyType : -1;
if (cellType === currentType && currentType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = row - count; i < row; i++) {
if (!visited[i][col]) {
matches.push({
row: i,
col: col
});
visited[i][col] = true;
}
}
}
count = 1;
currentType = cellType;
}
}
if (count >= 3) {
for (var i = self.gridSize - count; i < self.gridSize; i++) {
if (!visited[i][col]) {
matches.push({
row: i,
col: col
});
visited[i][col] = true;
}
}
}
}
if (matches.length > 0) {
self.removeMatches(matches);
return true;
}
return false;
};
self.removeMatches = function (matches) {
var points = 0;
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
var candy = self.grid[match.row][match.col];
if (candy) {
points += 10;
// Check for special candy creation
var matchLength = self.getMatchLength(match.row, match.col, candy.candyType);
if (matchLength >= 5) {
// Create rainbow candy
candy.makeSpecial('rainbow');
continue;
} else if (matchLength >= 4) {
// Create bomb candy
candy.makeSpecial('bomb');
continue;
}
self.removeChild(candy);
self.grid[match.row][match.col] = null;
}
}
LK.setScore(LK.getScore() + points);
scoreText.setText(LK.getScore() + ' / ' + targetScore);
LK.getSound('match').play();
// Apply gravity and cascade
LK.setTimeout(function () {
self.applyGravity();
}, 100);
};
self.getMatchLength = function (row, col, candyType) {
var length = 1;
// Count horizontal
var left = col - 1;
while (left >= 0 && self.grid[row][left] && self.grid[row][left].candyType === candyType) {
length++;
left--;
}
var right = col + 1;
while (right < self.gridSize && self.grid[row][right] && self.grid[row][right].candyType === candyType) {
length++;
right++;
}
return length;
};
self.applyGravity = function () {
var moved = false;
for (var col = 0; col < self.gridSize; col++) {
for (var row = self.gridSize - 1; row >= 0; row--) {
if (!self.grid[row][col]) {
// Find candy above to fall down
for (var aboveRow = row - 1; aboveRow >= 0; aboveRow--) {
if (self.grid[aboveRow][col]) {
var candy = self.grid[aboveRow][col];
self.grid[row][col] = candy;
self.grid[aboveRow][col] = null;
candy.gridY = row;
candy.isAnimating = true;
moved = true;
tween(candy, {
y: row * self.cellSize
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
candy.isAnimating = false;
}
});
break;
}
}
}
}
}
if (moved) {
LK.getSound('cascade').play();
}
// Fill empty spaces and check for new matches
LK.setTimeout(function () {
self.fillGrid();
LK.setTimeout(function () {
if (!self.checkMatches()) {
isProcessingMatches = false;
}
}, 100);
}, 350);
};
self.isAdjacent = function (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;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
var gameGrid;
var selectedCandy = null;
var movesLeft = 20;
var targetScore = 1000;
var currentLevel = 1;
var isProcessingMatches = false;
// UI Elements
var scoreText = new Text2('0 / 1000', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var movesText = new Text2('Moves: 20', {
size: 50,
fill: 0xFFFFFF
});
movesText.anchor.set(0, 0);
movesText.x = 50;
movesText.y = 100;
LK.gui.topLeft.addChild(movesText);
var levelText = new Text2('Level 1', {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(1, 0);
levelText.x = -50;
levelText.y = 100;
LK.gui.topRight.addChild(levelText);
// Initialize game grid
gameGrid = new GameGrid();
gameGrid.init();
// Center the grid and ensure it's in touchable area
var gridWidth = gameGrid.gridSize * gameGrid.cellSize;
var gridHeight = gameGrid.gridSize * gameGrid.cellSize;
gameGrid.x = (2048 - gridWidth) / 2;
gameGrid.y = (2732 - gridHeight) / 2;
// Ensure grid is not too close to top (avoid menu area)
if (gameGrid.y < 200) {
gameGrid.y = 200;
}
game.addChild(gameGrid);
function handleCandyClick(candy) {
if (isProcessingMatches || movesLeft <= 0) return;
if (!selectedCandy) {
selectedCandy = candy;
candy.setSelected(true);
} else if (selectedCandy === candy) {
selectedCandy.setSelected(false);
selectedCandy = null;
} else if (gameGrid.isAdjacent(selectedCandy, candy)) {
// Valid swap
selectedCandy.setSelected(false);
var oldGrid1 = {
x: selectedCandy.gridX,
y: selectedCandy.gridY
};
var oldGrid2 = {
x: candy.gridX,
y: candy.gridY
};
// Capture candy references before nullifying selectedCandy
var candy1Ref = selectedCandy;
var candy2Ref = candy;
if (gameGrid.swapCandies(selectedCandy, candy)) {
movesLeft--;
movesText.setText('Moves: ' + movesLeft);
isProcessingMatches = true;
// Check if swap creates matches, if not, swap back
LK.setTimeout(function () {
if (!gameGrid.checkMatches()) {
// Swap back using captured references
candy1Ref.gridX = oldGrid1.x;
candy1Ref.gridY = oldGrid1.y;
candy2Ref.gridX = oldGrid2.x;
candy2Ref.gridY = oldGrid2.y;
gameGrid.grid[candy1Ref.gridY][candy1Ref.gridX] = candy1Ref;
gameGrid.grid[candy2Ref.gridY][candy2Ref.gridX] = candy2Ref;
tween(candy1Ref, {
x: candy1Ref.gridX * gameGrid.cellSize,
y: candy1Ref.gridY * gameGrid.cellSize
}, {
duration: 200
});
tween(candy2Ref, {
x: candy2Ref.gridX * gameGrid.cellSize,
y: candy2Ref.gridY * gameGrid.cellSize
}, {
duration: 200
});
movesLeft++;
movesText.setText('Moves: ' + movesLeft);
isProcessingMatches = false;
}
}, 250);
}
selectedCandy = null;
} else {
selectedCandy.setSelected(false);
selectedCandy = candy;
candy.setSelected(true);
}
}
game.update = function () {
// Check win condition
if (LK.getScore() >= targetScore) {
currentLevel++;
targetScore += 500;
movesLeft = 20;
levelText.setText('Level ' + currentLevel);
scoreText.setText(LK.getScore() + ' / ' + targetScore);
movesText.setText('Moves: ' + movesLeft);
// Reset grid for next level
for (var row = 0; row < gameGrid.gridSize; row++) {
for (var col = 0; col < gameGrid.gridSize; col++) {
if (gameGrid.grid[row][col]) {
gameGrid.removeChild(gameGrid.grid[row][col]);
gameGrid.grid[row][col] = null;
}
}
}
gameGrid.fillGrid();
}
// Check lose condition
if (movesLeft <= 0 && LK.getScore() < targetScore && !isProcessingMatches) {
LK.showGameOver();
}
};