User prompt
Al explotar los candy 7 que vuelva a aparecer otros ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que sea muy difícil que salga un candy 8 pero possible
User prompt
Que después aparezcan
User prompt
Pero que de los puntos
User prompt
Que el 8 al tocarlo que explote ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que el 8 quite todos los caramelos
User prompt
Que haya caramelos de colores especiales que rompan una línea
Code edit (1 edits merged)
Please save this source code
User prompt
Candy Crush Match
Initial prompt
Haz un juego adonde tienes que quitar caramelos juntando 3 o más del mismo
/****
* 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.isMoving = false;
self.isMatched = false;
self.isSpecial = function () {
return self.candyType === 7 || self.candyType === 8;
};
self.isHorizontalBreaker = function () {
return self.candyType === 7;
};
self.isVerticalBreaker = function () {
return self.candyType === 8;
};
var candyGraphics = self.attachAsset('candy' + type, {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gx, gy) {
self.gridX = gx;
self.gridY = gy;
self.x = GRID_START_X + gx * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gy * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
if (!duration) duration = 300;
self.isMoving = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
if (onComplete) onComplete();
}
});
};
self.animateMatch = function (onComplete) {
self.isMatched = true;
tween(self, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.7
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: onComplete
});
}
});
};
return self;
});
var Grid = Container.expand(function () {
var self = Container.call(this);
self.grid = [];
self.selectedCandy = null;
self.swapping = false;
self.initializeGrid = function () {
// Create background cells
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var cell = self.attachAsset('gridCell', {
x: GRID_START_X + x * CELL_SIZE,
y: GRID_START_Y + y * CELL_SIZE,
alpha: 0.3
});
}
}
// Initialize grid array
for (var x = 0; x < GRID_SIZE; x++) {
self.grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
self.grid[x][y] = null;
}
}
// Fill grid with candies
self.fillGrid();
};
self.fillGrid = function () {
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (self.grid[x][y] === null) {
var candyType = self.getRandomCandyType();
var candy = new Candy(candyType);
candy.setGridPosition(x, y);
self.grid[x][y] = candy;
self.addChild(candy);
}
}
}
};
self.getRandomCandyType = function () {
// 0.5% chance for candy 8 (very rare)
if (Math.random() < 0.005) {
return 8; // Candy 8 is very rare
}
// 2% chance for candy 7 (horizontal line breaker)
if (Math.random() < 0.02) {
return 7; // Candy 7 is less rare
}
return Math.floor(Math.random() * 6) + 1;
};
self.getCandyAt = function (x, y) {
if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) return null;
return self.grid[x][y];
};
self.swapCandies = function (candy1, candy2) {
if (self.swapping || !candy1 || !candy2) return;
self.swapping = true;
var tempX = candy1.gridX;
var tempY = candy1.gridY;
// Update grid positions
self.grid[candy1.gridX][candy1.gridY] = candy2;
self.grid[candy2.gridX][candy2.gridY] = candy1;
// Update candy grid positions
candy1.gridX = candy2.gridX;
candy1.gridY = candy2.gridY;
candy2.gridX = tempX;
candy2.gridY = tempY;
// Animate swap
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;
var swapsComplete = 0;
var onSwapComplete = function onSwapComplete() {
swapsComplete++;
if (swapsComplete === 2) {
LK.getSound('swap').play();
self.swapping = false;
self.checkForMatches();
}
};
candy1.animateToPosition(targetX1, targetY1, 250, onSwapComplete);
candy2.animateToPosition(targetX2, targetY2, 250, onSwapComplete);
};
self.checkForMatches = function () {
var matches = self.findMatches();
if (matches.length > 0) {
self.removeMatches(matches);
}
};
self.findMatches = function () {
var matches = [];
var checked = [];
// Initialize checked array
for (var x = 0; x < GRID_SIZE; x++) {
checked[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
checked[x][y] = false;
}
}
// Check horizontal matches
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE - 2; x++) {
var candy1 = self.getCandyAt(x, y);
var candy2 = self.getCandyAt(x + 1, y);
var candy3 = self.getCandyAt(x + 2, y);
if (candy1 && candy2 && candy3 && candy1.candyType === candy2.candyType && candy2.candyType === candy3.candyType) {
var match = [candy1, candy2, candy3];
// Extend match if possible
var checkX = x + 3;
while (checkX < GRID_SIZE) {
var nextCandy = self.getCandyAt(checkX, y);
if (nextCandy && nextCandy.candyType === candy1.candyType) {
match.push(nextCandy);
checkX++;
} else {
break;
}
}
matches.push(match);
x += match.length - 1;
}
}
}
// Check vertical matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE - 2; y++) {
var candy1 = self.getCandyAt(x, y);
var candy2 = self.getCandyAt(x, y + 1);
var candy3 = self.getCandyAt(x, y + 2);
if (candy1 && candy2 && candy3 && candy1.candyType === candy2.candyType && candy2.candyType === candy3.candyType) {
var match = [candy1, candy2, candy3];
// Extend match if possible
var checkY = y + 3;
while (checkY < GRID_SIZE) {
var nextCandy = self.getCandyAt(x, checkY);
if (nextCandy && nextCandy.candyType === candy1.candyType) {
match.push(nextCandy);
checkY++;
} else {
break;
}
}
matches.push(match);
y += match.length - 1;
}
}
}
return matches;
};
self.removeMatches = function (matches) {
var totalMatched = 0;
var matchesRemoved = 0;
var specialCandiesActivated = [];
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
totalMatched += match.length;
for (var j = 0; j < match.length; j++) {
var candy = match[j];
// Check if this is a special candy before removing
if (candy.isSpecial()) {
specialCandiesActivated.push({
candy: candy,
x: candy.gridX,
y: candy.gridY
});
}
self.grid[candy.gridX][candy.gridY] = null;
candy.animateMatch(function () {
matchesRemoved++;
if (matchesRemoved === totalMatched) {
self.activateSpecialCandies(specialCandiesActivated);
}
});
}
}
// Add score
var baseScore = 10;
var scoreToAdd = 0;
for (var i = 0; i < matches.length; i++) {
var matchSize = matches[i].length;
scoreToAdd += baseScore * matchSize * matchSize;
}
LK.setScore(LK.getScore() + scoreToAdd);
scoreTxt.setText(LK.getScore());
LK.getSound('match').play();
};
self.applyGravity = function () {
var needsUpdate = false;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (self.grid[x][y] === null) {
// Find candy above to fall down
for (var searchY = y - 1; searchY >= 0; searchY--) {
if (self.grid[x][searchY] !== null) {
var candy = self.grid[x][searchY];
self.grid[x][y] = candy;
self.grid[x][searchY] = null;
candy.gridY = y;
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
candy.animateToPosition(candy.x, targetY, 400);
needsUpdate = true;
break;
}
}
}
}
}
if (needsUpdate) {
LK.setTimeout(function () {
self.fillGrid();
LK.setTimeout(function () {
self.checkForMatches();
}, 500);
}, 450);
}
};
self.activateSpecialCandies = function (specialCandies) {
var candiesRemoved = 0;
var totalToRemove = 0;
var hasClearAllCandy = false;
for (var i = 0; i < specialCandies.length; i++) {
var specialCandy = specialCandies[i];
if (specialCandy.candy.candyType === 8) {
// Candy 8 clears all candies
hasClearAllCandy = true;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (self.grid[x][y] !== null) {
totalToRemove++;
}
}
}
break;
} else if (specialCandy.candy.isHorizontalBreaker()) {
// Break entire horizontal line
for (var x = 0; x < GRID_SIZE; x++) {
if (self.grid[x][specialCandy.y] !== null) {
totalToRemove++;
}
}
} else if (specialCandy.candy.isVerticalBreaker()) {
// Break entire vertical line
for (var y = 0; y < GRID_SIZE; y++) {
if (self.grid[specialCandy.x][y] !== null) {
totalToRemove++;
}
}
}
}
if (totalToRemove === 0) {
self.applyGravity();
return;
}
if (hasClearAllCandy) {
// Remove all candies from the grid
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var candy = self.grid[x][y];
if (candy !== null) {
self.grid[x][y] = null;
candy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
self.applyGravity();
}
});
}
}
}
} else {
for (var i = 0; i < specialCandies.length; i++) {
var specialCandy = specialCandies[i];
if (specialCandy.candy.isHorizontalBreaker()) {
// Remove entire horizontal line
for (var x = 0; x < GRID_SIZE; x++) {
var candy = self.grid[x][specialCandy.y];
if (candy !== null) {
self.grid[x][specialCandy.y] = null;
candy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
self.applyGravity();
}
});
}
}
} else if (specialCandy.candy.isVerticalBreaker()) {
// Remove entire vertical line
for (var y = 0; y < GRID_SIZE; y++) {
var candy = self.grid[specialCandy.x][y];
if (candy !== null) {
self.grid[specialCandy.x][y] = null;
candy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
self.applyGravity();
}
});
}
}
}
}
}
};
self.getGridPosition = function (worldX, worldY) {
var localX = worldX - GRID_START_X;
var localY = worldY - GRID_START_Y;
if (localX < 0 || localY < 0 || localX >= GRID_SIZE * CELL_SIZE || localY >= GRID_SIZE * CELL_SIZE) {
return null;
}
return {
x: Math.floor(localX / CELL_SIZE),
y: Math.floor(localY / CELL_SIZE)
};
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1A1A2E
});
/****
* Game Code
****/
// Constants
var GRID_SIZE = 8;
var CELL_SIZE = 220;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2;
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.setText(LK.getScore());
LK.gui.top.addChild(scoreTxt);
// Game grid
var grid = new Grid();
game.addChild(grid);
grid.initializeGrid();
// Input handling
var dragStart = null;
var dragCandy = null;
game.down = function (x, y, obj) {
if (grid.swapping) return;
var gridPos = grid.getGridPosition(x, y);
if (gridPos) {
var candy = grid.getCandyAt(gridPos.x, gridPos.y);
if (candy && !candy.isMoving) {
// Check if it's candy 8 (clear all candy)
if (candy.candyType === 8) {
// Create explosion effect
tween(candy, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Clear all candies after explosion
var totalToRemove = 0;
var candiesRemoved = 0;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid.grid[x][y] !== null) {
totalToRemove++;
}
}
}
// Calculate score for clearing all candies
var scoreToAdd = totalToRemove * 50; // 50 points per candy cleared
LK.setScore(LK.getScore() + scoreToAdd);
scoreTxt.setText(LK.getScore());
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var gridCandy = grid.grid[x][y];
if (gridCandy !== null) {
grid.grid[x][y] = null;
gridCandy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
// Fill grid with new candies after clearing
LK.setTimeout(function () {
grid.fillGrid();
LK.setTimeout(function () {
grid.checkForMatches();
}, 300);
}, 200);
}
});
}
}
}
}
});
return; // Don't continue with normal drag behavior
}
// Check if it's candy 7 (horizontal line breaker)
if (candy.candyType === 7) {
// Create explosion effect
tween(candy, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Clear entire horizontal line
var totalToRemove = 0;
var candiesRemoved = 0;
var lineY = candy.gridY;
// Count candies in the line
for (var x = 0; x < GRID_SIZE; x++) {
if (grid.grid[x][lineY] !== null) {
totalToRemove++;
}
}
// Calculate score for clearing the line
var scoreToAdd = totalToRemove * 30; // 30 points per candy cleared
LK.setScore(LK.getScore() + scoreToAdd);
scoreTxt.setText(LK.getScore());
// Remove candies from the horizontal line
for (var x = 0; x < GRID_SIZE; x++) {
var gridCandy = grid.grid[x][lineY];
if (gridCandy !== null) {
grid.grid[x][lineY] = null;
gridCandy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
// Apply gravity and refill after line is cleared
LK.setTimeout(function () {
grid.applyGravity();
}, 200);
}
});
}
}
}
});
return; // Don't continue with normal drag behavior
}
dragStart = {
x: x,
y: y
};
dragCandy = candy;
grid.selectedCandy = candy;
// Visual feedback
tween(candy, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut
});
}
}
};
game.move = function (x, y, obj) {
if (dragStart && dragCandy && !grid.swapping) {
var deltaX = x - dragStart.x;
var deltaY = y - dragStart.y;
var threshold = 60;
if (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold) {
var swapX = dragCandy.gridX;
var swapY = dragCandy.gridY;
// Determine swap direction
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swap
if (deltaX > 0) {
swapX += 1;
} else {
swapX -= 1;
}
} else {
// Vertical swap
if (deltaY > 0) {
swapY += 1;
} else {
swapY -= 1;
}
}
var targetCandy = grid.getCandyAt(swapX, swapY);
if (targetCandy) {
grid.swapCandies(dragCandy, targetCandy);
}
// Reset drag
dragStart = null;
dragCandy = null;
}
}
};
game.up = function (x, y, obj) {
if (dragCandy) {
// Reset visual feedback
tween(dragCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
}
dragStart = null;
dragCandy = null;
grid.selectedCandy = null;
};
game.update = function () {
// Game loop runs automatically
// Grid handles its own updates through animations and match checking
}; /****
* 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.isMoving = false;
self.isMatched = false;
self.isSpecial = function () {
return self.candyType === 7 || self.candyType === 8;
};
self.isHorizontalBreaker = function () {
return self.candyType === 7;
};
self.isVerticalBreaker = function () {
return self.candyType === 8;
};
var candyGraphics = self.attachAsset('candy' + type, {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gx, gy) {
self.gridX = gx;
self.gridY = gy;
self.x = GRID_START_X + gx * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gy * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
if (!duration) duration = 300;
self.isMoving = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
if (onComplete) onComplete();
}
});
};
self.animateMatch = function (onComplete) {
self.isMatched = true;
tween(self, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.7
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: onComplete
});
}
});
};
return self;
});
var Grid = Container.expand(function () {
var self = Container.call(this);
self.grid = [];
self.selectedCandy = null;
self.swapping = false;
self.initializeGrid = function () {
// Create background cells
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var cell = self.attachAsset('gridCell', {
x: GRID_START_X + x * CELL_SIZE,
y: GRID_START_Y + y * CELL_SIZE,
alpha: 0.3
});
}
}
// Initialize grid array
for (var x = 0; x < GRID_SIZE; x++) {
self.grid[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
self.grid[x][y] = null;
}
}
// Fill grid with candies
self.fillGrid();
};
self.fillGrid = function () {
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (self.grid[x][y] === null) {
var candyType = self.getRandomCandyType();
var candy = new Candy(candyType);
candy.setGridPosition(x, y);
self.grid[x][y] = candy;
self.addChild(candy);
}
}
}
};
self.getRandomCandyType = function () {
// 0.5% chance for candy 8 (very rare)
if (Math.random() < 0.005) {
return 8; // Candy 8 is very rare
}
// 2% chance for candy 7 (horizontal line breaker)
if (Math.random() < 0.02) {
return 7; // Candy 7 is less rare
}
return Math.floor(Math.random() * 6) + 1;
};
self.getCandyAt = function (x, y) {
if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) return null;
return self.grid[x][y];
};
self.swapCandies = function (candy1, candy2) {
if (self.swapping || !candy1 || !candy2) return;
self.swapping = true;
var tempX = candy1.gridX;
var tempY = candy1.gridY;
// Update grid positions
self.grid[candy1.gridX][candy1.gridY] = candy2;
self.grid[candy2.gridX][candy2.gridY] = candy1;
// Update candy grid positions
candy1.gridX = candy2.gridX;
candy1.gridY = candy2.gridY;
candy2.gridX = tempX;
candy2.gridY = tempY;
// Animate swap
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;
var swapsComplete = 0;
var onSwapComplete = function onSwapComplete() {
swapsComplete++;
if (swapsComplete === 2) {
LK.getSound('swap').play();
self.swapping = false;
self.checkForMatches();
}
};
candy1.animateToPosition(targetX1, targetY1, 250, onSwapComplete);
candy2.animateToPosition(targetX2, targetY2, 250, onSwapComplete);
};
self.checkForMatches = function () {
var matches = self.findMatches();
if (matches.length > 0) {
self.removeMatches(matches);
}
};
self.findMatches = function () {
var matches = [];
var checked = [];
// Initialize checked array
for (var x = 0; x < GRID_SIZE; x++) {
checked[x] = [];
for (var y = 0; y < GRID_SIZE; y++) {
checked[x][y] = false;
}
}
// Check horizontal matches
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE - 2; x++) {
var candy1 = self.getCandyAt(x, y);
var candy2 = self.getCandyAt(x + 1, y);
var candy3 = self.getCandyAt(x + 2, y);
if (candy1 && candy2 && candy3 && candy1.candyType === candy2.candyType && candy2.candyType === candy3.candyType) {
var match = [candy1, candy2, candy3];
// Extend match if possible
var checkX = x + 3;
while (checkX < GRID_SIZE) {
var nextCandy = self.getCandyAt(checkX, y);
if (nextCandy && nextCandy.candyType === candy1.candyType) {
match.push(nextCandy);
checkX++;
} else {
break;
}
}
matches.push(match);
x += match.length - 1;
}
}
}
// Check vertical matches
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE - 2; y++) {
var candy1 = self.getCandyAt(x, y);
var candy2 = self.getCandyAt(x, y + 1);
var candy3 = self.getCandyAt(x, y + 2);
if (candy1 && candy2 && candy3 && candy1.candyType === candy2.candyType && candy2.candyType === candy3.candyType) {
var match = [candy1, candy2, candy3];
// Extend match if possible
var checkY = y + 3;
while (checkY < GRID_SIZE) {
var nextCandy = self.getCandyAt(x, checkY);
if (nextCandy && nextCandy.candyType === candy1.candyType) {
match.push(nextCandy);
checkY++;
} else {
break;
}
}
matches.push(match);
y += match.length - 1;
}
}
}
return matches;
};
self.removeMatches = function (matches) {
var totalMatched = 0;
var matchesRemoved = 0;
var specialCandiesActivated = [];
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
totalMatched += match.length;
for (var j = 0; j < match.length; j++) {
var candy = match[j];
// Check if this is a special candy before removing
if (candy.isSpecial()) {
specialCandiesActivated.push({
candy: candy,
x: candy.gridX,
y: candy.gridY
});
}
self.grid[candy.gridX][candy.gridY] = null;
candy.animateMatch(function () {
matchesRemoved++;
if (matchesRemoved === totalMatched) {
self.activateSpecialCandies(specialCandiesActivated);
}
});
}
}
// Add score
var baseScore = 10;
var scoreToAdd = 0;
for (var i = 0; i < matches.length; i++) {
var matchSize = matches[i].length;
scoreToAdd += baseScore * matchSize * matchSize;
}
LK.setScore(LK.getScore() + scoreToAdd);
scoreTxt.setText(LK.getScore());
LK.getSound('match').play();
};
self.applyGravity = function () {
var needsUpdate = false;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (self.grid[x][y] === null) {
// Find candy above to fall down
for (var searchY = y - 1; searchY >= 0; searchY--) {
if (self.grid[x][searchY] !== null) {
var candy = self.grid[x][searchY];
self.grid[x][y] = candy;
self.grid[x][searchY] = null;
candy.gridY = y;
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
candy.animateToPosition(candy.x, targetY, 400);
needsUpdate = true;
break;
}
}
}
}
}
if (needsUpdate) {
LK.setTimeout(function () {
self.fillGrid();
LK.setTimeout(function () {
self.checkForMatches();
}, 500);
}, 450);
}
};
self.activateSpecialCandies = function (specialCandies) {
var candiesRemoved = 0;
var totalToRemove = 0;
var hasClearAllCandy = false;
for (var i = 0; i < specialCandies.length; i++) {
var specialCandy = specialCandies[i];
if (specialCandy.candy.candyType === 8) {
// Candy 8 clears all candies
hasClearAllCandy = true;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (self.grid[x][y] !== null) {
totalToRemove++;
}
}
}
break;
} else if (specialCandy.candy.isHorizontalBreaker()) {
// Break entire horizontal line
for (var x = 0; x < GRID_SIZE; x++) {
if (self.grid[x][specialCandy.y] !== null) {
totalToRemove++;
}
}
} else if (specialCandy.candy.isVerticalBreaker()) {
// Break entire vertical line
for (var y = 0; y < GRID_SIZE; y++) {
if (self.grid[specialCandy.x][y] !== null) {
totalToRemove++;
}
}
}
}
if (totalToRemove === 0) {
self.applyGravity();
return;
}
if (hasClearAllCandy) {
// Remove all candies from the grid
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var candy = self.grid[x][y];
if (candy !== null) {
self.grid[x][y] = null;
candy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
self.applyGravity();
}
});
}
}
}
} else {
for (var i = 0; i < specialCandies.length; i++) {
var specialCandy = specialCandies[i];
if (specialCandy.candy.isHorizontalBreaker()) {
// Remove entire horizontal line
for (var x = 0; x < GRID_SIZE; x++) {
var candy = self.grid[x][specialCandy.y];
if (candy !== null) {
self.grid[x][specialCandy.y] = null;
candy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
self.applyGravity();
}
});
}
}
} else if (specialCandy.candy.isVerticalBreaker()) {
// Remove entire vertical line
for (var y = 0; y < GRID_SIZE; y++) {
var candy = self.grid[specialCandy.x][y];
if (candy !== null) {
self.grid[specialCandy.x][y] = null;
candy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
self.applyGravity();
}
});
}
}
}
}
}
};
self.getGridPosition = function (worldX, worldY) {
var localX = worldX - GRID_START_X;
var localY = worldY - GRID_START_Y;
if (localX < 0 || localY < 0 || localX >= GRID_SIZE * CELL_SIZE || localY >= GRID_SIZE * CELL_SIZE) {
return null;
}
return {
x: Math.floor(localX / CELL_SIZE),
y: Math.floor(localY / CELL_SIZE)
};
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1A1A2E
});
/****
* Game Code
****/
// Constants
var GRID_SIZE = 8;
var CELL_SIZE = 220;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2;
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.setText(LK.getScore());
LK.gui.top.addChild(scoreTxt);
// Game grid
var grid = new Grid();
game.addChild(grid);
grid.initializeGrid();
// Input handling
var dragStart = null;
var dragCandy = null;
game.down = function (x, y, obj) {
if (grid.swapping) return;
var gridPos = grid.getGridPosition(x, y);
if (gridPos) {
var candy = grid.getCandyAt(gridPos.x, gridPos.y);
if (candy && !candy.isMoving) {
// Check if it's candy 8 (clear all candy)
if (candy.candyType === 8) {
// Create explosion effect
tween(candy, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Clear all candies after explosion
var totalToRemove = 0;
var candiesRemoved = 0;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (grid.grid[x][y] !== null) {
totalToRemove++;
}
}
}
// Calculate score for clearing all candies
var scoreToAdd = totalToRemove * 50; // 50 points per candy cleared
LK.setScore(LK.getScore() + scoreToAdd);
scoreTxt.setText(LK.getScore());
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
var gridCandy = grid.grid[x][y];
if (gridCandy !== null) {
grid.grid[x][y] = null;
gridCandy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
// Fill grid with new candies after clearing
LK.setTimeout(function () {
grid.fillGrid();
LK.setTimeout(function () {
grid.checkForMatches();
}, 300);
}, 200);
}
});
}
}
}
}
});
return; // Don't continue with normal drag behavior
}
// Check if it's candy 7 (horizontal line breaker)
if (candy.candyType === 7) {
// Create explosion effect
tween(candy, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Clear entire horizontal line
var totalToRemove = 0;
var candiesRemoved = 0;
var lineY = candy.gridY;
// Count candies in the line
for (var x = 0; x < GRID_SIZE; x++) {
if (grid.grid[x][lineY] !== null) {
totalToRemove++;
}
}
// Calculate score for clearing the line
var scoreToAdd = totalToRemove * 30; // 30 points per candy cleared
LK.setScore(LK.getScore() + scoreToAdd);
scoreTxt.setText(LK.getScore());
// Remove candies from the horizontal line
for (var x = 0; x < GRID_SIZE; x++) {
var gridCandy = grid.grid[x][lineY];
if (gridCandy !== null) {
grid.grid[x][lineY] = null;
gridCandy.animateMatch(function () {
candiesRemoved++;
if (candiesRemoved === totalToRemove) {
// Apply gravity and refill after line is cleared
LK.setTimeout(function () {
grid.applyGravity();
}, 200);
}
});
}
}
}
});
return; // Don't continue with normal drag behavior
}
dragStart = {
x: x,
y: y
};
dragCandy = candy;
grid.selectedCandy = candy;
// Visual feedback
tween(candy, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut
});
}
}
};
game.move = function (x, y, obj) {
if (dragStart && dragCandy && !grid.swapping) {
var deltaX = x - dragStart.x;
var deltaY = y - dragStart.y;
var threshold = 60;
if (Math.abs(deltaX) > threshold || Math.abs(deltaY) > threshold) {
var swapX = dragCandy.gridX;
var swapY = dragCandy.gridY;
// Determine swap direction
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swap
if (deltaX > 0) {
swapX += 1;
} else {
swapX -= 1;
}
} else {
// Vertical swap
if (deltaY > 0) {
swapY += 1;
} else {
swapY -= 1;
}
}
var targetCandy = grid.getCandyAt(swapX, swapY);
if (targetCandy) {
grid.swapCandies(dragCandy, targetCandy);
}
// Reset drag
dragStart = null;
dragCandy = null;
}
}
};
game.up = function (x, y, obj) {
if (dragCandy) {
// Reset visual feedback
tween(dragCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
}
dragStart = null;
dragCandy = null;
grid.selectedCandy = null;
};
game.update = function () {
// Game loop runs automatically
// Grid handles its own updates through animations and match checking
};
Red candy. In-Game asset. 2d. High contrast. No shadows
Cyan candy. In-Game asset. 2d. High contrast. No shadows
Blue candy. In-Game asset. 2d. High contrast. No shadows
Orange candy. In-Game asset. 2d. High contrast. No shadows
Green candy. In-Game asset. 2d. High contrast. No shadows
Chocolate ball with candies. In-Game asset. 2d. High contrast. No shadows
Yellow candy. In-Game asset. 2d. High contrast. No shadows