/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
money: 0,
strongBombUnlocked: false
});
/****
* Classes
****/
var Candy = Container.expand(function (colorType) {
var self = Container.call(this);
self.colorType = colorType;
self.isSelected = false;
self.isExploding = false;
var candyAssets = ['candy_red', 'candy_blue', 'candy_green', 'candy_yellow', 'candy_purple', 'candy_orange', 'candy_bomb', 'candy_money'];
var candyGraphics = self.attachAsset(candyAssets[colorType], {
anchorX: 0.5,
anchorY: 0.5
});
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
candyGraphics.scaleX = 1.2;
candyGraphics.scaleY = 1.2;
} else {
candyGraphics.scaleX = 1.0;
candyGraphics.scaleY = 1.0;
}
};
self.explode = function () {
self.isExploding = true;
// Cut effect: rotate and scale down with fade
tween(candyGraphics, {
rotation: Math.PI * 2,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Grid = Container.expand(function () {
var self = Container.call(this);
self.gridWidth = 8;
self.gridHeight = 12;
self.cellSize = 130;
self.candies = [];
self.selectedGroup = [];
self.isAnimating = false;
// Initialize grid array
for (var i = 0; i < self.gridHeight; i++) {
self.candies[i] = [];
for (var j = 0; j < self.gridWidth; j++) {
self.candies[i][j] = null;
}
}
self.getGridPosition = function (x, y) {
var startX = (2048 - self.gridWidth * self.cellSize) / 2;
var startY = 300;
var col = Math.floor((x - startX) / self.cellSize);
var row = Math.floor((y - startY) / self.cellSize);
return {
row: row,
col: col
};
};
self.getWorldPosition = function (row, col) {
var startX = (2048 - self.gridWidth * self.cellSize) / 2;
var startY = 300;
return {
x: startX + col * self.cellSize + self.cellSize / 2,
y: startY + row * self.cellSize + self.cellSize / 2
};
};
self.createCandy = function (row, col) {
var colorType;
// 5% chance for money candy
if (Math.random() < 0.05) {
colorType = 7; // Money candy
} else {
colorType = Math.floor(Math.random() * 6);
}
var candy = new Candy(colorType);
var pos = self.getWorldPosition(row, col);
candy.x = pos.x;
candy.y = pos.y;
self.candies[row][col] = candy;
self.addChild(candy);
return candy;
};
self.fillGrid = function () {
for (var i = 0; i < self.gridHeight; i++) {
for (var j = 0; j < self.gridWidth; j++) {
if (!self.candies[i][j]) {
self.createCandy(i, j);
}
}
}
};
self.findConnectedGroup = function (row, col, colorType, visited) {
if (row < 0 || row >= self.gridHeight || col < 0 || col >= self.gridWidth) {
return [];
}
if (visited[row][col] || !self.candies[row][col] || self.candies[row][col].colorType !== colorType) {
return [];
}
visited[row][col] = true;
var group = [{
row: row,
col: col,
candy: self.candies[row][col]
}];
// Check adjacent cells (up, down, left, right)
var directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
for (var d = 0; d < directions.length; d++) {
var newRow = row + directions[d][0];
var newCol = col + directions[d][1];
var connected = self.findConnectedGroup(newRow, newCol, colorType, visited);
group = group.concat(connected);
}
return group;
};
self.selectGroup = function (row, col) {
if (self.isAnimating || !self.candies[row][col]) return;
// Clear previous selection
self.clearSelection();
var visited = [];
for (var i = 0; i < self.gridHeight; i++) {
visited[i] = [];
for (var j = 0; j < self.gridWidth; j++) {
visited[i][j] = false;
}
}
var colorType = self.candies[row][col].colorType;
self.selectedGroup = self.findConnectedGroup(row, col, colorType, visited);
if (self.selectedGroup.length >= 3) {
for (var i = 0; i < self.selectedGroup.length; i++) {
self.selectedGroup[i].candy.setSelected(true);
}
return true;
} else {
self.selectedGroup = [];
return false;
}
};
self.clearSelection = function () {
for (var i = 0; i < self.selectedGroup.length; i++) {
if (self.selectedGroup[i].candy && !self.selectedGroup[i].candy.isExploding) {
self.selectedGroup[i].candy.setSelected(false);
}
}
self.selectedGroup = [];
};
self.explodeBomb = function (row, col) {
if (!self.candies[row][col] || self.candies[row][col].colorType !== 6) return 0;
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode 3x3 area around bomb
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
var newRow = row + i;
var newCol = col + j;
if (newRow >= 0 && newRow < self.gridHeight && newCol >= 0 && newCol < self.gridWidth) {
if (self.candies[newRow][newCol]) {
bombsToExplode.push({
row: newRow,
col: newCol,
candy: self.candies[newRow][newCol]
});
points += 10;
}
}
}
}
// Add explosion flash effect to bomb area
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
// Flash effect before exploding
tween(item.candy, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
// Explode all candies in the bomb area
LK.setTimeout(function () {
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
}, 250);
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 600);
return points;
};
self.explodeStrongBomb = function (row, col) {
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode 5x5 area around selected position
for (var i = -2; i <= 2; i++) {
for (var j = -2; j <= 2; j++) {
var newRow = row + i;
var newCol = col + j;
if (newRow >= 0 && newRow < self.gridHeight && newCol >= 0 && newCol < self.gridWidth) {
if (self.candies[newRow][newCol]) {
bombsToExplode.push({
row: newRow,
col: newCol,
candy: self.candies[newRow][newCol]
});
points += 15;
}
}
}
}
// Explode all candies in the bomb area
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 350);
return points;
};
self.explodeSelectedGroup = function () {
if (self.selectedGroup.length < 3) return 0;
self.isAnimating = true;
var points = self.selectedGroup.length * 10;
var shouldCreateBomb = false;
// Bonus points for larger groups
if (self.selectedGroup.length >= 5) {
points += 50;
}
if (self.selectedGroup.length >= 4) {
shouldCreateBomb = true;
}
if (self.selectedGroup.length >= 7) {
points += 100;
}
// Apply combo multiplier
points = Math.floor(points * comboMultiplier);
// Increment combo count
comboCount++;
comboMultiplier = 1 + (comboCount - 1) * 0.5; // 1x, 1.5x, 2x, 2.5x, etc.
comboTimer = comboTimeout;
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + '!');
comboTxt.fill = comboCount >= 5 ? 0xFF0000 : 0xFFD700;
// Flash combo text
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
// Clear candy references from grid first
for (var i = 0; i < self.selectedGroup.length; i++) {
var item = self.selectedGroup[i];
self.candies[item.row][item.col] = null;
}
// Sound will be played when knife touches candies
// Create and animate knife to cut candies
var knife = new Knife();
self.addChild(knife);
knife.cutCandies(self.selectedGroup, function () {
// Remove knife after cutting
knife.destroy();
// Create sugar bomb if 4 or more sugar candies exploded
var sugarCount = 0;
for (var i = 0; i < self.selectedGroup.length; i++) {
if (self.selectedGroup[i].candy.colorType === 3) {
// Yellow candy (sugar)
sugarCount++;
}
}
if (sugarCount >= 4) {
var bombRow = self.selectedGroup[0].row;
var bombCol = self.selectedGroup[0].col;
LK.setTimeout(function () {
var sugarBomb = new Candy(3); // Using candy_yellow asset (index 3 in candyAssets array) for sugar bomb
var pos = self.getWorldPosition(bombRow, bombCol);
sugarBomb.x = pos.x;
sugarBomb.y = pos.y;
self.candies[bombRow][bombCol] = sugarBomb;
self.addChild(sugarBomb);
// Add visual effect to indicate it's a sugar bomb
tween(sugarBomb, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(sugarBomb, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}, 100);
}
// Apply gravity and spawn new candies after cutting animation
LK.setTimeout(function () {
self.applyGravity();
}, 350);
});
self.selectedGroup = [];
return points;
};
self.applyGravity = function () {
var moved = false;
// Move candies down
for (var col = 0; col < self.gridWidth; col++) {
for (var row = self.gridHeight - 1; row >= 0; row--) {
if (!self.candies[row][col]) {
// Find candy above to move down
for (var searchRow = row - 1; searchRow >= 0; searchRow--) {
if (self.candies[searchRow][col]) {
self.candies[row][col] = self.candies[searchRow][col];
self.candies[searchRow][col] = null;
var newPos = self.getWorldPosition(row, col);
tween(self.candies[row][col], {
x: newPos.x,
y: newPos.y
}, {
duration: 200,
easing: tween.easeIn
});
moved = true;
break;
}
}
}
}
}
// Fill empty spaces at top
for (var col = 0; col < self.gridWidth; col++) {
for (var row = 0; row < self.gridHeight; row++) {
if (!self.candies[row][col]) {
var candy = self.createCandy(row, col);
// Start candy above screen and animate down
candy.y = self.getWorldPosition(row, col).y - 500;
var targetPos = self.getWorldPosition(row, col);
tween(candy, {
y: targetPos.y
}, {
duration: 300,
easing: tween.easeOut
});
}
}
}
if (moved) {
LK.getSound('cascade').play();
}
// Check for chain reactions
LK.setTimeout(function () {
self.checkChainReactions();
}, 400);
};
self.checkChainReactions = function () {
// Simply finish the animation process without auto-exploding
self.isAnimating = false;
// Reset combo if no more valid moves after timeout
LK.setTimeout(function () {
if (comboTimer > 0) {
comboTimer = 0;
comboCount = 0;
comboMultiplier = 1;
comboTxt.setText('');
}
}, 100);
self.checkGameOver();
};
self.checkGameOver = function () {
var visited = [];
for (var i = 0; i < self.gridHeight; i++) {
visited[i] = [];
for (var j = 0; j < self.gridWidth; j++) {
visited[i][j] = false;
}
}
for (var row = 0; row < self.gridHeight; row++) {
for (var col = 0; col < self.gridWidth; col++) {
if (!visited[row][col] && self.candies[row][col]) {
var group = self.findConnectedGroup(row, col, self.candies[row][col].colorType, visited);
if (group.length >= 3) {
return; // Game can continue
}
}
}
}
// No valid moves left
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
};
self.explodeAreaBomb = function (row, col) {
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode 3x3 area around selected position
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
var newRow = row + i;
var newCol = col + j;
if (newRow >= 0 && newRow < self.gridHeight && newCol >= 0 && newCol < self.gridWidth) {
if (self.candies[newRow][newCol]) {
bombsToExplode.push({
row: newRow,
col: newCol,
candy: self.candies[newRow][newCol]
});
points += 10;
}
}
}
}
// Add explosion flash effect to bomb area
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
// Flash effect before exploding
tween(item.candy, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
// Explode all candies in the bomb area
LK.setTimeout(function () {
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
}, 250);
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 600);
return points;
};
self.explodeFirework = function (row, col) {
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode entire row
for (var j = 0; j < self.gridWidth; j++) {
if (self.candies[row][j]) {
bombsToExplode.push({
row: row,
col: j,
candy: self.candies[row][j]
});
points += 12;
}
}
// Explode entire column
for (var i = 0; i < self.gridHeight; i++) {
if (i !== row && self.candies[i][col]) {
bombsToExplode.push({
row: i,
col: col,
candy: self.candies[i][col]
});
points += 12;
}
}
// Add firework flash effect with colorful animation
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
// Colorful flash effect before exploding
tween(item.candy, {
tint: 0xFFD700,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0xFF69B4,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0x00FFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
});
}
// Explode all candies in the firework pattern
LK.setTimeout(function () {
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
}, 450);
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 800);
return points;
};
return self;
});
var Knife = Container.expand(function () {
var self = Container.call(this);
var knifeGraphics = self.attachAsset('knife', {
anchorX: 0.5,
anchorY: 0.5
});
self.cutCandies = function (targetCandies, onComplete) {
if (targetCandies.length === 0) {
if (onComplete) onComplete();
return;
}
// Position knife at start position (off screen left)
self.x = -200;
self.y = targetCandies[0].candy.y;
self.alpha = 1;
// Calculate end position (off screen right)
var endX = 2248;
// Animate knife cutting across screen
tween(self, {
x: endX
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out knife
tween(self, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
if (onComplete) onComplete();
}
});
}
});
// Trigger candy cutting effect when knife reaches each candy
for (var i = 0; i < targetCandies.length; i++) {
var candy = targetCandies[i].candy;
var candyX = candy.x;
var delay = (candyX + 200) / (endX + 200) * 500; // Calculate when knife reaches this candy
(function (candyTocut) {
LK.setTimeout(function () {
if (candyTocut && !candyTocut.isExploding) {
// Play sound when knife touches candy
LK.getSound('explode').play();
candyTocut.explode();
}
}, delay);
})(candy);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E1065
});
/****
* Game Code
****/
// Add visual background
var background = game.addChild(LK.getAsset('Bg', {
anchorX: 0,
anchorY: 0,
scaleX: 20.48,
scaleY: 27.32
}));
background.x = 0;
background.y = 0;
var grid = game.addChild(new Grid());
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 50;
scoreTxt.y = 400;
game.addChild(scoreTxt);
// Initialize score
LK.setScore(0);
scoreTxt.setText(LK.getScore().toString());
// Fill initial grid
grid.fillGrid();
// Instructions text
var instructionsTxt = new Text2('Tap groups of 3+ same colored candies!', {
size: 60,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0);
instructionsTxt.x = 2048 / 2;
instructionsTxt.y = 120;
game.addChild(instructionsTxt);
// Set money to 0 when game starts
storage.money = 0;
// Money counter
var moneyTxt = new Text2('Money: ' + storage.money, {
size: 80,
fill: 0xFFD700
});
moneyTxt.anchor.set(0, 0);
moneyTxt.x = 50;
moneyTxt.y = 300;
game.addChild(moneyTxt);
// Shop background
var shopBackground = game.addChild(LK.getAsset('gridBackground', {
anchorX: 0.5,
anchorY: 0,
scaleX: 20,
scaleY: 4
}));
shopBackground.x = 2048 / 2;
shopBackground.y = 2180;
// Shop UI
var shopTxt = new Text2('SHOP', {
size: 80,
fill: 0xFFFFFF
});
shopTxt.anchor.set(0.5, 0);
shopTxt.x = 2048 / 2;
shopTxt.y = 2200;
game.addChild(shopTxt);
var areaBombTxt = new Text2('3x3 Area Bomb (Cost: 15)', {
size: 60,
fill: 0xFFFFFF
});
areaBombTxt.anchor.set(0.5, 0);
areaBombTxt.x = 2048 / 2;
areaBombTxt.y = 2300;
game.addChild(areaBombTxt);
var strongBombTxt = new Text2('5x5 Area Bomb (Cost: 25)', {
size: 60,
fill: storage.strongBombUnlocked ? 0x00FF00 : 0xFFFFFF
});
strongBombTxt.anchor.set(0.5, 0);
strongBombTxt.x = 2048 / 2;
strongBombTxt.y = 2400;
game.addChild(strongBombTxt);
var fireworkTxt = new Text2('Firework Line Exploder (Cost: 20)', {
size: 60,
fill: 0xFFFFFF
});
fireworkTxt.anchor.set(0.5, 0);
fireworkTxt.x = 2048 / 2;
fireworkTxt.y = 2500;
game.addChild(fireworkTxt);
// Combo display
var comboTxt = new Text2('', {
size: 100,
fill: 0xFFD700
});
comboTxt.anchor.set(0.5, 0.5);
comboTxt.x = 2048 / 2;
comboTxt.y = 200;
game.addChild(comboTxt);
var usingAreaBomb = false;
var usingStrongBomb = false;
var usingFirework = false;
var strongBombTimer = 0;
var strongBombCooldown = 45000; // 45 seconds in milliseconds
var comboCount = 0;
var comboMultiplier = 1;
var comboTimer = 0;
var comboTimeout = 3000; // 3 seconds to maintain combo
game.down = function (x, y, obj) {
if (grid.isAnimating) return;
// Check if clicked on shop area
if (y >= 2200) {
// Check if clicked on area bomb purchase
if (y >= 2300 && y <= 2400) {
if (!usingAreaBomb && storage.money >= 15) {
storage.money -= 15;
usingAreaBomb = true;
moneyTxt.setText('Money: ' + storage.money);
areaBombTxt.setText('Select area to explode!');
areaBombTxt.fill = 0xFF0000;
}
}
// Check if clicked on strong bomb purchase
if (y >= 2400 && y <= 2500) {
if (!storage.strongBombUnlocked && storage.money >= 25) {
storage.money -= 25;
storage.strongBombUnlocked = true;
moneyTxt.setText('Money: ' + storage.money);
strongBombTxt.setText('5x5 Area Bomb (Unlocked!)');
strongBombTxt.fill = 0x00FF00;
} else if (storage.strongBombUnlocked && !usingStrongBomb) {
usingStrongBomb = true;
strongBombTxt.setText('Select area to explode!');
strongBombTxt.fill = 0xFF0000;
}
}
// Check if clicked on firework purchase
if (y >= 2500 && y <= 2600) {
if (!usingFirework && storage.money >= 20) {
storage.money -= 20;
usingFirework = true;
moneyTxt.setText('Money: ' + storage.money);
fireworkTxt.setText('Select line to explode!');
fireworkTxt.fill = 0xFF0000;
}
}
return;
}
var gridPos = grid.getGridPosition(x, y);
if (gridPos.row >= 0 && gridPos.row < grid.gridHeight && gridPos.col >= 0 && gridPos.col < grid.gridWidth) {
// Check if using area bomb
if (usingAreaBomb) {
var points = grid.explodeAreaBomb(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
usingAreaBomb = false;
areaBombTxt.setText('3x3 Area Bomb (Cost: 15)');
areaBombTxt.fill = 0xFFFFFF;
return;
}
// Check if using strong bomb
if (usingStrongBomb && storage.strongBombUnlocked) {
var points = grid.explodeStrongBomb(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
usingStrongBomb = false;
// Reset to purchasable state
storage.strongBombUnlocked = false;
strongBombTxt.setText('5x5 Area Bomb (Cost: 25)');
strongBombTxt.fill = 0xFFFFFF;
return;
}
// Check if using firework
if (usingFirework) {
var points = grid.explodeFirework(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
usingFirework = false;
fireworkTxt.setText('Firework Line Exploder (Cost: 20)');
fireworkTxt.fill = 0xFFFFFF;
return;
}
// Check if clicked candy is money candy
if (grid.candies[gridPos.row][gridPos.col] && grid.candies[gridPos.row][gridPos.col].colorType === 7) {
// Give money and remove candy
storage.money += 5;
moneyTxt.setText('Money: ' + storage.money);
grid.candies[gridPos.row][gridPos.col].explode();
grid.candies[gridPos.row][gridPos.col] = null;
LK.setTimeout(function () {
grid.applyGravity();
}, 350);
return;
}
// Check if clicked candy is a bomb
if (grid.candies[gridPos.row][gridPos.col] && grid.candies[gridPos.row][gridPos.col].colorType === 6) {
// Explode bomb immediately
var points = grid.explodeBomb(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
} else if (grid.selectGroup(gridPos.row, gridPos.col)) {
// Valid group selected, explode on next tap
LK.setTimeout(function () {
if (grid.selectedGroup.length >= 3) {
var points = grid.explodeSelectedGroup();
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
}
}, 100);
} else {
// Invalid move - reset combo
comboCount = 0;
comboMultiplier = 1;
comboTimer = 0;
comboTxt.setText('');
}
}
};
// Start background music
LK.playMusic('bgMusic');
game.update = function () {
// Timer logic removed - no cooldown needed
// Update combo timer
if (comboTimer > 0) {
comboTimer -= 16; // Approximately 60 FPS
if (comboTimer <= 0) {
// Reset combo
comboCount = 0;
comboMultiplier = 1;
comboTxt.setText('');
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
money: 0,
strongBombUnlocked: false
});
/****
* Classes
****/
var Candy = Container.expand(function (colorType) {
var self = Container.call(this);
self.colorType = colorType;
self.isSelected = false;
self.isExploding = false;
var candyAssets = ['candy_red', 'candy_blue', 'candy_green', 'candy_yellow', 'candy_purple', 'candy_orange', 'candy_bomb', 'candy_money'];
var candyGraphics = self.attachAsset(candyAssets[colorType], {
anchorX: 0.5,
anchorY: 0.5
});
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
candyGraphics.scaleX = 1.2;
candyGraphics.scaleY = 1.2;
} else {
candyGraphics.scaleX = 1.0;
candyGraphics.scaleY = 1.0;
}
};
self.explode = function () {
self.isExploding = true;
// Cut effect: rotate and scale down with fade
tween(candyGraphics, {
rotation: Math.PI * 2,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Grid = Container.expand(function () {
var self = Container.call(this);
self.gridWidth = 8;
self.gridHeight = 12;
self.cellSize = 130;
self.candies = [];
self.selectedGroup = [];
self.isAnimating = false;
// Initialize grid array
for (var i = 0; i < self.gridHeight; i++) {
self.candies[i] = [];
for (var j = 0; j < self.gridWidth; j++) {
self.candies[i][j] = null;
}
}
self.getGridPosition = function (x, y) {
var startX = (2048 - self.gridWidth * self.cellSize) / 2;
var startY = 300;
var col = Math.floor((x - startX) / self.cellSize);
var row = Math.floor((y - startY) / self.cellSize);
return {
row: row,
col: col
};
};
self.getWorldPosition = function (row, col) {
var startX = (2048 - self.gridWidth * self.cellSize) / 2;
var startY = 300;
return {
x: startX + col * self.cellSize + self.cellSize / 2,
y: startY + row * self.cellSize + self.cellSize / 2
};
};
self.createCandy = function (row, col) {
var colorType;
// 5% chance for money candy
if (Math.random() < 0.05) {
colorType = 7; // Money candy
} else {
colorType = Math.floor(Math.random() * 6);
}
var candy = new Candy(colorType);
var pos = self.getWorldPosition(row, col);
candy.x = pos.x;
candy.y = pos.y;
self.candies[row][col] = candy;
self.addChild(candy);
return candy;
};
self.fillGrid = function () {
for (var i = 0; i < self.gridHeight; i++) {
for (var j = 0; j < self.gridWidth; j++) {
if (!self.candies[i][j]) {
self.createCandy(i, j);
}
}
}
};
self.findConnectedGroup = function (row, col, colorType, visited) {
if (row < 0 || row >= self.gridHeight || col < 0 || col >= self.gridWidth) {
return [];
}
if (visited[row][col] || !self.candies[row][col] || self.candies[row][col].colorType !== colorType) {
return [];
}
visited[row][col] = true;
var group = [{
row: row,
col: col,
candy: self.candies[row][col]
}];
// Check adjacent cells (up, down, left, right)
var directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
for (var d = 0; d < directions.length; d++) {
var newRow = row + directions[d][0];
var newCol = col + directions[d][1];
var connected = self.findConnectedGroup(newRow, newCol, colorType, visited);
group = group.concat(connected);
}
return group;
};
self.selectGroup = function (row, col) {
if (self.isAnimating || !self.candies[row][col]) return;
// Clear previous selection
self.clearSelection();
var visited = [];
for (var i = 0; i < self.gridHeight; i++) {
visited[i] = [];
for (var j = 0; j < self.gridWidth; j++) {
visited[i][j] = false;
}
}
var colorType = self.candies[row][col].colorType;
self.selectedGroup = self.findConnectedGroup(row, col, colorType, visited);
if (self.selectedGroup.length >= 3) {
for (var i = 0; i < self.selectedGroup.length; i++) {
self.selectedGroup[i].candy.setSelected(true);
}
return true;
} else {
self.selectedGroup = [];
return false;
}
};
self.clearSelection = function () {
for (var i = 0; i < self.selectedGroup.length; i++) {
if (self.selectedGroup[i].candy && !self.selectedGroup[i].candy.isExploding) {
self.selectedGroup[i].candy.setSelected(false);
}
}
self.selectedGroup = [];
};
self.explodeBomb = function (row, col) {
if (!self.candies[row][col] || self.candies[row][col].colorType !== 6) return 0;
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode 3x3 area around bomb
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
var newRow = row + i;
var newCol = col + j;
if (newRow >= 0 && newRow < self.gridHeight && newCol >= 0 && newCol < self.gridWidth) {
if (self.candies[newRow][newCol]) {
bombsToExplode.push({
row: newRow,
col: newCol,
candy: self.candies[newRow][newCol]
});
points += 10;
}
}
}
}
// Add explosion flash effect to bomb area
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
// Flash effect before exploding
tween(item.candy, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
// Explode all candies in the bomb area
LK.setTimeout(function () {
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
}, 250);
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 600);
return points;
};
self.explodeStrongBomb = function (row, col) {
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode 5x5 area around selected position
for (var i = -2; i <= 2; i++) {
for (var j = -2; j <= 2; j++) {
var newRow = row + i;
var newCol = col + j;
if (newRow >= 0 && newRow < self.gridHeight && newCol >= 0 && newCol < self.gridWidth) {
if (self.candies[newRow][newCol]) {
bombsToExplode.push({
row: newRow,
col: newCol,
candy: self.candies[newRow][newCol]
});
points += 15;
}
}
}
}
// Explode all candies in the bomb area
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 350);
return points;
};
self.explodeSelectedGroup = function () {
if (self.selectedGroup.length < 3) return 0;
self.isAnimating = true;
var points = self.selectedGroup.length * 10;
var shouldCreateBomb = false;
// Bonus points for larger groups
if (self.selectedGroup.length >= 5) {
points += 50;
}
if (self.selectedGroup.length >= 4) {
shouldCreateBomb = true;
}
if (self.selectedGroup.length >= 7) {
points += 100;
}
// Apply combo multiplier
points = Math.floor(points * comboMultiplier);
// Increment combo count
comboCount++;
comboMultiplier = 1 + (comboCount - 1) * 0.5; // 1x, 1.5x, 2x, 2.5x, etc.
comboTimer = comboTimeout;
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + '!');
comboTxt.fill = comboCount >= 5 ? 0xFF0000 : 0xFFD700;
// Flash combo text
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
// Clear candy references from grid first
for (var i = 0; i < self.selectedGroup.length; i++) {
var item = self.selectedGroup[i];
self.candies[item.row][item.col] = null;
}
// Sound will be played when knife touches candies
// Create and animate knife to cut candies
var knife = new Knife();
self.addChild(knife);
knife.cutCandies(self.selectedGroup, function () {
// Remove knife after cutting
knife.destroy();
// Create sugar bomb if 4 or more sugar candies exploded
var sugarCount = 0;
for (var i = 0; i < self.selectedGroup.length; i++) {
if (self.selectedGroup[i].candy.colorType === 3) {
// Yellow candy (sugar)
sugarCount++;
}
}
if (sugarCount >= 4) {
var bombRow = self.selectedGroup[0].row;
var bombCol = self.selectedGroup[0].col;
LK.setTimeout(function () {
var sugarBomb = new Candy(3); // Using candy_yellow asset (index 3 in candyAssets array) for sugar bomb
var pos = self.getWorldPosition(bombRow, bombCol);
sugarBomb.x = pos.x;
sugarBomb.y = pos.y;
self.candies[bombRow][bombCol] = sugarBomb;
self.addChild(sugarBomb);
// Add visual effect to indicate it's a sugar bomb
tween(sugarBomb, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(sugarBomb, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}, 100);
}
// Apply gravity and spawn new candies after cutting animation
LK.setTimeout(function () {
self.applyGravity();
}, 350);
});
self.selectedGroup = [];
return points;
};
self.applyGravity = function () {
var moved = false;
// Move candies down
for (var col = 0; col < self.gridWidth; col++) {
for (var row = self.gridHeight - 1; row >= 0; row--) {
if (!self.candies[row][col]) {
// Find candy above to move down
for (var searchRow = row - 1; searchRow >= 0; searchRow--) {
if (self.candies[searchRow][col]) {
self.candies[row][col] = self.candies[searchRow][col];
self.candies[searchRow][col] = null;
var newPos = self.getWorldPosition(row, col);
tween(self.candies[row][col], {
x: newPos.x,
y: newPos.y
}, {
duration: 200,
easing: tween.easeIn
});
moved = true;
break;
}
}
}
}
}
// Fill empty spaces at top
for (var col = 0; col < self.gridWidth; col++) {
for (var row = 0; row < self.gridHeight; row++) {
if (!self.candies[row][col]) {
var candy = self.createCandy(row, col);
// Start candy above screen and animate down
candy.y = self.getWorldPosition(row, col).y - 500;
var targetPos = self.getWorldPosition(row, col);
tween(candy, {
y: targetPos.y
}, {
duration: 300,
easing: tween.easeOut
});
}
}
}
if (moved) {
LK.getSound('cascade').play();
}
// Check for chain reactions
LK.setTimeout(function () {
self.checkChainReactions();
}, 400);
};
self.checkChainReactions = function () {
// Simply finish the animation process without auto-exploding
self.isAnimating = false;
// Reset combo if no more valid moves after timeout
LK.setTimeout(function () {
if (comboTimer > 0) {
comboTimer = 0;
comboCount = 0;
comboMultiplier = 1;
comboTxt.setText('');
}
}, 100);
self.checkGameOver();
};
self.checkGameOver = function () {
var visited = [];
for (var i = 0; i < self.gridHeight; i++) {
visited[i] = [];
for (var j = 0; j < self.gridWidth; j++) {
visited[i][j] = false;
}
}
for (var row = 0; row < self.gridHeight; row++) {
for (var col = 0; col < self.gridWidth; col++) {
if (!visited[row][col] && self.candies[row][col]) {
var group = self.findConnectedGroup(row, col, self.candies[row][col].colorType, visited);
if (group.length >= 3) {
return; // Game can continue
}
}
}
}
// No valid moves left
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
};
self.explodeAreaBomb = function (row, col) {
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode 3x3 area around selected position
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
var newRow = row + i;
var newCol = col + j;
if (newRow >= 0 && newRow < self.gridHeight && newCol >= 0 && newCol < self.gridWidth) {
if (self.candies[newRow][newCol]) {
bombsToExplode.push({
row: newRow,
col: newCol,
candy: self.candies[newRow][newCol]
});
points += 10;
}
}
}
}
// Add explosion flash effect to bomb area
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
// Flash effect before exploding
tween(item.candy, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
// Explode all candies in the bomb area
LK.setTimeout(function () {
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
}, 250);
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 600);
return points;
};
self.explodeFirework = function (row, col) {
self.isAnimating = true;
var points = 0;
var bombsToExplode = [];
// Explode entire row
for (var j = 0; j < self.gridWidth; j++) {
if (self.candies[row][j]) {
bombsToExplode.push({
row: row,
col: j,
candy: self.candies[row][j]
});
points += 12;
}
}
// Explode entire column
for (var i = 0; i < self.gridHeight; i++) {
if (i !== row && self.candies[i][col]) {
bombsToExplode.push({
row: i,
col: col,
candy: self.candies[i][col]
});
points += 12;
}
}
// Add firework flash effect with colorful animation
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
// Colorful flash effect before exploding
tween(item.candy, {
tint: 0xFFD700,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0xFF69B4,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
tween(item.candy, {
tint: 0x00FFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
});
}
// Explode all candies in the firework pattern
LK.setTimeout(function () {
for (var i = 0; i < bombsToExplode.length; i++) {
var item = bombsToExplode[i];
self.candies[item.row][item.col] = null;
item.candy.explode();
}
}, 450);
LK.getSound('explode').play();
// Apply gravity and spawn new candies after explosion animation
LK.setTimeout(function () {
self.applyGravity();
}, 800);
return points;
};
return self;
});
var Knife = Container.expand(function () {
var self = Container.call(this);
var knifeGraphics = self.attachAsset('knife', {
anchorX: 0.5,
anchorY: 0.5
});
self.cutCandies = function (targetCandies, onComplete) {
if (targetCandies.length === 0) {
if (onComplete) onComplete();
return;
}
// Position knife at start position (off screen left)
self.x = -200;
self.y = targetCandies[0].candy.y;
self.alpha = 1;
// Calculate end position (off screen right)
var endX = 2248;
// Animate knife cutting across screen
tween(self, {
x: endX
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Fade out knife
tween(self, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
if (onComplete) onComplete();
}
});
}
});
// Trigger candy cutting effect when knife reaches each candy
for (var i = 0; i < targetCandies.length; i++) {
var candy = targetCandies[i].candy;
var candyX = candy.x;
var delay = (candyX + 200) / (endX + 200) * 500; // Calculate when knife reaches this candy
(function (candyTocut) {
LK.setTimeout(function () {
if (candyTocut && !candyTocut.isExploding) {
// Play sound when knife touches candy
LK.getSound('explode').play();
candyTocut.explode();
}
}, delay);
})(candy);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E1065
});
/****
* Game Code
****/
// Add visual background
var background = game.addChild(LK.getAsset('Bg', {
anchorX: 0,
anchorY: 0,
scaleX: 20.48,
scaleY: 27.32
}));
background.x = 0;
background.y = 0;
var grid = game.addChild(new Grid());
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 50;
scoreTxt.y = 400;
game.addChild(scoreTxt);
// Initialize score
LK.setScore(0);
scoreTxt.setText(LK.getScore().toString());
// Fill initial grid
grid.fillGrid();
// Instructions text
var instructionsTxt = new Text2('Tap groups of 3+ same colored candies!', {
size: 60,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0);
instructionsTxt.x = 2048 / 2;
instructionsTxt.y = 120;
game.addChild(instructionsTxt);
// Set money to 0 when game starts
storage.money = 0;
// Money counter
var moneyTxt = new Text2('Money: ' + storage.money, {
size: 80,
fill: 0xFFD700
});
moneyTxt.anchor.set(0, 0);
moneyTxt.x = 50;
moneyTxt.y = 300;
game.addChild(moneyTxt);
// Shop background
var shopBackground = game.addChild(LK.getAsset('gridBackground', {
anchorX: 0.5,
anchorY: 0,
scaleX: 20,
scaleY: 4
}));
shopBackground.x = 2048 / 2;
shopBackground.y = 2180;
// Shop UI
var shopTxt = new Text2('SHOP', {
size: 80,
fill: 0xFFFFFF
});
shopTxt.anchor.set(0.5, 0);
shopTxt.x = 2048 / 2;
shopTxt.y = 2200;
game.addChild(shopTxt);
var areaBombTxt = new Text2('3x3 Area Bomb (Cost: 15)', {
size: 60,
fill: 0xFFFFFF
});
areaBombTxt.anchor.set(0.5, 0);
areaBombTxt.x = 2048 / 2;
areaBombTxt.y = 2300;
game.addChild(areaBombTxt);
var strongBombTxt = new Text2('5x5 Area Bomb (Cost: 25)', {
size: 60,
fill: storage.strongBombUnlocked ? 0x00FF00 : 0xFFFFFF
});
strongBombTxt.anchor.set(0.5, 0);
strongBombTxt.x = 2048 / 2;
strongBombTxt.y = 2400;
game.addChild(strongBombTxt);
var fireworkTxt = new Text2('Firework Line Exploder (Cost: 20)', {
size: 60,
fill: 0xFFFFFF
});
fireworkTxt.anchor.set(0.5, 0);
fireworkTxt.x = 2048 / 2;
fireworkTxt.y = 2500;
game.addChild(fireworkTxt);
// Combo display
var comboTxt = new Text2('', {
size: 100,
fill: 0xFFD700
});
comboTxt.anchor.set(0.5, 0.5);
comboTxt.x = 2048 / 2;
comboTxt.y = 200;
game.addChild(comboTxt);
var usingAreaBomb = false;
var usingStrongBomb = false;
var usingFirework = false;
var strongBombTimer = 0;
var strongBombCooldown = 45000; // 45 seconds in milliseconds
var comboCount = 0;
var comboMultiplier = 1;
var comboTimer = 0;
var comboTimeout = 3000; // 3 seconds to maintain combo
game.down = function (x, y, obj) {
if (grid.isAnimating) return;
// Check if clicked on shop area
if (y >= 2200) {
// Check if clicked on area bomb purchase
if (y >= 2300 && y <= 2400) {
if (!usingAreaBomb && storage.money >= 15) {
storage.money -= 15;
usingAreaBomb = true;
moneyTxt.setText('Money: ' + storage.money);
areaBombTxt.setText('Select area to explode!');
areaBombTxt.fill = 0xFF0000;
}
}
// Check if clicked on strong bomb purchase
if (y >= 2400 && y <= 2500) {
if (!storage.strongBombUnlocked && storage.money >= 25) {
storage.money -= 25;
storage.strongBombUnlocked = true;
moneyTxt.setText('Money: ' + storage.money);
strongBombTxt.setText('5x5 Area Bomb (Unlocked!)');
strongBombTxt.fill = 0x00FF00;
} else if (storage.strongBombUnlocked && !usingStrongBomb) {
usingStrongBomb = true;
strongBombTxt.setText('Select area to explode!');
strongBombTxt.fill = 0xFF0000;
}
}
// Check if clicked on firework purchase
if (y >= 2500 && y <= 2600) {
if (!usingFirework && storage.money >= 20) {
storage.money -= 20;
usingFirework = true;
moneyTxt.setText('Money: ' + storage.money);
fireworkTxt.setText('Select line to explode!');
fireworkTxt.fill = 0xFF0000;
}
}
return;
}
var gridPos = grid.getGridPosition(x, y);
if (gridPos.row >= 0 && gridPos.row < grid.gridHeight && gridPos.col >= 0 && gridPos.col < grid.gridWidth) {
// Check if using area bomb
if (usingAreaBomb) {
var points = grid.explodeAreaBomb(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
usingAreaBomb = false;
areaBombTxt.setText('3x3 Area Bomb (Cost: 15)');
areaBombTxt.fill = 0xFFFFFF;
return;
}
// Check if using strong bomb
if (usingStrongBomb && storage.strongBombUnlocked) {
var points = grid.explodeStrongBomb(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
usingStrongBomb = false;
// Reset to purchasable state
storage.strongBombUnlocked = false;
strongBombTxt.setText('5x5 Area Bomb (Cost: 25)');
strongBombTxt.fill = 0xFFFFFF;
return;
}
// Check if using firework
if (usingFirework) {
var points = grid.explodeFirework(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
usingFirework = false;
fireworkTxt.setText('Firework Line Exploder (Cost: 20)');
fireworkTxt.fill = 0xFFFFFF;
return;
}
// Check if clicked candy is money candy
if (grid.candies[gridPos.row][gridPos.col] && grid.candies[gridPos.row][gridPos.col].colorType === 7) {
// Give money and remove candy
storage.money += 5;
moneyTxt.setText('Money: ' + storage.money);
grid.candies[gridPos.row][gridPos.col].explode();
grid.candies[gridPos.row][gridPos.col] = null;
LK.setTimeout(function () {
grid.applyGravity();
}, 350);
return;
}
// Check if clicked candy is a bomb
if (grid.candies[gridPos.row][gridPos.col] && grid.candies[gridPos.row][gridPos.col].colorType === 6) {
// Explode bomb immediately
var points = grid.explodeBomb(gridPos.row, gridPos.col);
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
} else if (grid.selectGroup(gridPos.row, gridPos.col)) {
// Valid group selected, explode on next tap
LK.setTimeout(function () {
if (grid.selectedGroup.length >= 3) {
var points = grid.explodeSelectedGroup();
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore().toString());
}
}, 100);
} else {
// Invalid move - reset combo
comboCount = 0;
comboMultiplier = 1;
comboTimer = 0;
comboTxt.setText('');
}
}
};
// Start background music
LK.playMusic('bgMusic');
game.update = function () {
// Timer logic removed - no cooldown needed
// Update combo timer
if (comboTimer > 0) {
comboTimer -= 16; // Approximately 60 FPS
if (comboTimer <= 0) {
// Reset combo
comboCount = 0;
comboMultiplier = 1;
comboTxt.setText('');
}
}
};
uncut watermelon. In-Game asset. 2d. High contrast. No shadows
Coin. In-Game asset. 2d. High contrast. No shadows
uncut lemon. In-Game asset. 2d. High contrast. No shadows
Uncut orange. In-Game asset. 2d. High contrast. No shadows
Uncut dragonfruit. In-Game asset. 2d. High contrast. No shadows
Strawberry. In-Game asset. 2d. High contrast. No shadows
Blueberry. In-Game asset. 2d. High contrast. No shadows
Bomb. In-Game asset. 2d. High contrast. No shadows
HORIZONTAL BLADE. In-Game asset. 2d. High contrast. No shadows