/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Add gentle swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.1; // More pronounced sway than candies
var swayDuration = 600 + Math.random() * 300; // Faster sway
function swayLeft() {
tween(bombGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(bombGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(bombGraphics);
tween(self, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Candy = Container.expand(function (candyType) {
var self = Container.call(this);
self.candyType = candyType;
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var candyAssets = [];
if (currentTheme === 'classic') {
candyAssets = ['classic_candy_red', 'classic_candy_blue', 'classic_candy_green', 'classic_candy_purple', 'classic_candy_orange'];
} else if (currentTheme === 'fruits') {
candyAssets = ['fruit_apple', 'fruit_banana', 'fruit_cherry', 'fruit_grape', 'fruit_orange', 'fruit_strawberry'];
} else {
candyAssets = ['candy_red', 'candy_blue', 'candy_green', 'candy_yellow', 'candy_purple', 'candy_orange'];
}
var candyGraphics = self.attachAsset(candyAssets[candyType], {
anchorX: 0.5,
anchorY: 0.5
});
// Add gentle swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.05; // Small rotation amount
var swayDuration = 1000 + Math.random() * 500; // 1-1.5 seconds for variety (2x faster)
function swayLeft() {
tween(candyGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(candyGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(candyGraphics);
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Firecracker = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var firecrackerGraphics = self.attachAsset('firecracker', {
anchorX: 0.5,
anchorY: 0.5
});
// Add gentle swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.08; // Slightly more sway than candies
var swayDuration = 800 + Math.random() * 400; // Faster sway
function swayLeft() {
tween(firecrackerGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(firecrackerGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(firecrackerGraphics);
tween(self, {
scaleX: 2,
scaleY: 2,
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.cells = [];
self.candies = [];
self.walls = [];
// Create grid cells
for (var y = 0; y < GRID_SIZE; y++) {
self.cells[y] = [];
self.candies[y] = [];
self.walls[y] = [];
for (var x = 0; x < GRID_SIZE; x++) {
var cell = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
x: GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2,
y: GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2
});
self.cells[y][x] = cell;
self.candies[y][x] = null;
self.walls[y][x] = null;
}
}
// Place exactly one wall per move
self.placeWalls = function () {
var wallCount = 1; // Always spawn exactly one wall
var placedWalls = 0;
var attempts = 0;
var maxAttempts = 500;
// Define border areas for wall placement
var borderAreas = [
// Top border
{
minX: 1,
maxX: GRID_SIZE - 2,
minY: 1,
maxY: 2
},
// Bottom border
{
minX: 1,
maxX: GRID_SIZE - 2,
minY: GRID_SIZE - 3,
maxY: GRID_SIZE - 2
},
// Left border
{
minX: 1,
maxX: 2,
minY: 1,
maxY: GRID_SIZE - 2
},
// Right border
{
minX: GRID_SIZE - 3,
maxX: GRID_SIZE - 2,
minY: 1,
maxY: GRID_SIZE - 2
}];
// Choose a random border area to place wall
var chosenArea = borderAreas[Math.floor(Math.random() * borderAreas.length)];
while (placedWalls < wallCount && attempts < maxAttempts) {
var x = Math.floor(Math.random() * (chosenArea.maxX - chosenArea.minX + 1)) + chosenArea.minX;
var y = Math.floor(Math.random() * (chosenArea.maxY - chosenArea.minY + 1)) + chosenArea.minY;
attempts++;
// Don't place walls if already occupied
if (!self.walls[y][x]) {
// Clear any candy at this position before placing wall
if (self.candies[y][x]) {
self.candies[y][x].destroy();
self.candies[y][x] = null;
}
var wall = new Wall();
wall.setGridPosition(x, y);
self.walls[y][x] = wall;
self.addChild(wall);
placedWalls++;
}
}
};
self.fillGrid = function () {
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE; x++) {
if (!self.candies[y][x] && !self.walls[y][x]) {
// 1% chance to spawn bomb
if (Math.random() < 0.01) {
var bomb = new Bomb();
bomb.setGridPosition(x, y);
self.candies[y][x] = bomb;
self.addChild(bomb);
} else if (Math.random() < 0.001) {
var superBomb = new SuperBomb();
superBomb.setGridPosition(x, y);
self.candies[y][x] = superBomb;
self.addChild(superBomb);
} else if (Math.random() < 0.02) {
var firecracker = new Firecracker();
firecracker.setGridPosition(x, y);
self.candies[y][x] = firecracker;
self.addChild(firecracker);
} else {
var candyType;
var attempts = 0;
// Try to find a candy type that doesn't create immediate matches
do {
if (currentTheme === 'classic') {
candyType = Math.floor(Math.random() * 5);
} else if (currentTheme === 'fruits') {
candyType = Math.floor(Math.random() * 6);
} else {
candyType = Math.floor(Math.random() * 6);
}
attempts++;
} while (attempts < 10 && self.wouldCreateMatch(x, y, candyType));
var candy = new Candy(candyType);
candy.setGridPosition(x, y);
self.candies[y][x] = candy;
self.addChild(candy);
}
}
}
}
};
self.findMatches = function () {
var matches = [];
// Check horizontal matches
for (var y = 0; y < GRID_SIZE; y++) {
var count = 1;
var currentType = self.candies[y][0] ? self.candies[y][0].candyType : -1;
for (var x = 1; x < GRID_SIZE; x++) {
var candyType = self.candies[y][x] ? self.candies[y][x].candyType : -1;
if (candyType === currentType && candyType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = x - count; i < x; i++) {
matches.push({
x: i,
y: y
});
}
}
count = 1;
currentType = candyType;
}
}
if (count >= 3) {
for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) {
matches.push({
x: i,
y: y
});
}
}
}
// Check vertical matches
for (var x = 0; x < GRID_SIZE; x++) {
var count = 1;
var currentType = self.candies[0][x] ? self.candies[0][x].candyType : -1;
for (var y = 1; y < GRID_SIZE; y++) {
var candyType = self.candies[y][x] ? self.candies[y][x].candyType : -1;
if (candyType === currentType && candyType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = y - count; i < y; i++) {
matches.push({
x: x,
y: i
});
}
}
count = 1;
currentType = candyType;
}
}
if (count >= 3) {
for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) {
matches.push({
x: x,
y: i
});
}
}
}
return matches;
};
self.removeMatches = function (matches) {
var score = 0;
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (self.candies[match.y][match.x]) {
self.candies[match.y][match.x].explode();
self.candies[match.y][match.x] = null;
score += 10;
}
}
return score;
};
self.explodeRow = function (rowY) {
var score = 0;
LK.getSound('firecracker_explode').play();
// Destroy entire row including walls
for (var x = 0; x < GRID_SIZE; x++) {
// Destroy candy if present
if (self.candies[rowY][x]) {
self.candies[rowY][x].explode();
self.candies[rowY][x] = null;
score += 25;
}
// Destroy wall if present
if (self.walls[rowY][x]) {
self.walls[rowY][x].destroy();
self.walls[rowY][x] = null;
score += 15; // Give points for destroying walls
}
}
return score;
};
self.explodeBomb = function (centerX, centerY) {
var score = 0;
LK.getSound('bomb_explode').play();
// Explode 3x3 area around the bomb
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
var x = centerX + dx;
var y = centerY + dy;
// Check bounds
if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE) {
// Destroy candy if present
if (self.candies[y][x]) {
self.candies[y][x].explode();
self.candies[y][x] = null;
score += 20; // More points for bomb explosion
}
// Destroy wall if present
if (self.walls[y][x]) {
self.walls[y][x].destroy();
self.walls[y][x] = null;
score += 15; // Give points for destroying walls
}
}
}
}
return score;
};
self.explodeSuperBomb = function (centerX, centerY) {
var score = 0;
LK.getSound('super_bomb_explode').play();
// Explode entire 10x10 area
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
// Destroy candy if present
if (self.candies[y][x]) {
self.candies[y][x].explode();
self.candies[y][x] = null;
}
// Destroy wall if present
if (self.walls[y][x]) {
self.walls[y][x].destroy();
self.walls[y][x] = null;
}
}
}
return score;
};
self.checkFirecrackerBombCombo = function (centerX, centerY) {
// Check adjacent positions for bomb-firecracker combination
var adjacentPositions = [{
x: centerX - 1,
y: centerY
},
// Left
{
x: centerX + 1,
y: centerY
},
// Right
{
x: centerX,
y: centerY - 1
},
// Up
{
x: centerX,
y: centerY + 1
} // Down
];
var currentCandy = self.candies[centerY][centerX];
var hasFirecracker = currentCandy && currentCandy.constructor === Firecracker;
var hasBomb = currentCandy && currentCandy.constructor === Bomb;
for (var i = 0; i < adjacentPositions.length; i++) {
var pos = adjacentPositions[i];
if (pos.x >= 0 && pos.x < GRID_SIZE && pos.y >= 0 && pos.y < GRID_SIZE) {
var adjacentCandy = self.candies[pos.y][pos.x];
if (adjacentCandy) {
// Check if we have firecracker next to bomb or bomb next to firecracker
if (hasFirecracker && adjacentCandy.constructor === Bomb || hasBomb && adjacentCandy.constructor === Firecracker) {
return {
x: pos.x,
y: pos.y,
candy: adjacentCandy
};
}
}
}
}
return null;
};
self.explodeAllWalls = function (centerX, centerY, comboX, comboY) {
var score = 0;
// Create spectacular animation before exploding walls
var centerCandy = self.candies[centerY][centerX];
var comboCandy = self.candies[comboY][comboX];
// Phase 1: Scale up both candies dramatically
if (centerCandy) {
tween(centerCandy, {
scaleX: 3,
scaleY: 3,
rotation: Math.PI * 4
}, {
duration: 800,
easing: tween.easeOut
});
}
if (comboCandy) {
tween(comboCandy, {
scaleX: 3,
scaleY: 3,
rotation: -Math.PI * 4
}, {
duration: 800,
easing: tween.easeOut
});
}
// Phase 2: Flash screen effect
LK.setTimeout(function () {
LK.effects.flashScreen(0xFFFF00, 200); // Yellow flash
LK.setTimeout(function () {
LK.effects.flashScreen(0xFF4500, 150); // Orange flash
LK.setTimeout(function () {
LK.effects.flashScreen(0xFF0000, 100); // Red flash
}, 200);
}, 150);
}, 400);
// Phase 3: Create expanding shockwave effect with all walls
LK.setTimeout(function () {
LK.getSound('super_bomb_explode').play();
// Animate all walls before destroying them
var wallsToDestroy = [];
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (self.walls[y][x]) {
wallsToDestroy.push({
wall: self.walls[y][x],
x: x,
y: y
});
}
}
}
// Animate each wall with staggered timing based on distance from center
for (var i = 0; i < wallsToDestroy.length; i++) {
(function (wallData, index) {
var distance = Math.sqrt(Math.pow(wallData.x - centerX, 2) + Math.pow(wallData.y - centerY, 2));
var delay = distance * 50; // Stagger based on distance
LK.setTimeout(function () {
// Scale up and rotate wall before destroying
tween(wallData.wall, {
scaleX: 2.5,
scaleY: 2.5,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
wallData.wall.destroy();
self.walls[wallData.y][wallData.x] = null;
// Spawn a new candy in place of the destroyed wall
var candyType;
if (currentTheme === 'classic') {
candyType = Math.floor(Math.random() * 5);
} else if (currentTheme === 'fruits') {
candyType = Math.floor(Math.random() * 6);
} else {
candyType = Math.floor(Math.random() * 6);
}
var newCandy = new Candy(candyType);
newCandy.setGridPosition(wallData.x, wallData.y);
self.candies[wallData.y][wallData.x] = newCandy;
self.addChild(newCandy);
// Start with small scale and animate to normal size
newCandy.scaleX = 0.1;
newCandy.scaleY = 0.1;
tween(newCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}, delay);
})(wallsToDestroy[i], i);
score += 50; // Give more points for destroying all walls
}
}, 800);
return score;
};
self.applyGravity = function () {
var moved = false;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (!self.candies[y][x] && !self.walls[y][x]) {
// Find candy above to fall down
for (var aboveY = y - 1; aboveY >= 0; aboveY--) {
if (self.candies[aboveY][x]) {
self.candies[y][x] = self.candies[aboveY][x];
self.candies[aboveY][x] = null;
self.candies[y][x].gridX = x;
self.candies[y][x].gridY = y;
var targetX = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
self.candies[y][x].animateToPosition(targetX, targetY, 300);
moved = true;
break;
}
}
}
}
}
return moved;
};
self.spawnNewCandies = function () {
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (!self.candies[y][x] && !self.walls[y][x]) {
// 1% chance to spawn bomb
if (Math.random() < 0.01) {
var bomb = new Bomb();
bomb.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
bomb.y = GRID_START_Y - CELL_SIZE;
bomb.gridX = x;
bomb.gridY = y;
self.candies[y][x] = bomb;
self.addChild(bomb);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
bomb.animateToPosition(bomb.x, targetY, 400);
} else if (Math.random() < 0.001) {
var superBomb = new SuperBomb();
superBomb.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
superBomb.y = GRID_START_Y - CELL_SIZE;
superBomb.gridX = x;
superBomb.gridY = y;
self.candies[y][x] = superBomb;
self.addChild(superBomb);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
superBomb.animateToPosition(superBomb.x, targetY, 400);
} else if (Math.random() < 0.02) {
var firecracker = new Firecracker();
firecracker.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
firecracker.y = GRID_START_Y - CELL_SIZE;
firecracker.gridX = x;
firecracker.gridY = y;
self.candies[y][x] = firecracker;
self.addChild(firecracker);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
firecracker.animateToPosition(firecracker.x, targetY, 400);
} else {
var candyType;
if (currentTheme === 'classic') {
candyType = Math.floor(Math.random() * 5);
} else if (currentTheme === 'fruits') {
candyType = Math.floor(Math.random() * 6);
} else {
candyType = Math.floor(Math.random() * 6);
}
var candy = new Candy(candyType);
candy.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
candy.y = GRID_START_Y - CELL_SIZE;
candy.gridX = x;
candy.gridY = y;
self.candies[y][x] = candy;
self.addChild(candy);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
candy.animateToPosition(candy.x, targetY, 400);
}
}
}
}
};
self.swapCandies = function (x1, y1, x2, y2) {
var candy1 = self.candies[y1][x1];
var candy2 = self.candies[y2][x2];
if (!candy1 || !candy2) return false;
// Swap in grid
self.candies[y1][x1] = candy2;
self.candies[y2][x2] = candy1;
// Update grid positions
candy1.gridX = x2;
candy1.gridY = y2;
candy2.gridX = x1;
candy2.gridY = y1;
// Animate to new positions
var pos1X = GRID_START_X + x2 * CELL_SIZE + CELL_SIZE / 2;
var pos1Y = GRID_START_Y + y2 * CELL_SIZE + CELL_SIZE / 2;
var pos2X = GRID_START_X + x1 * CELL_SIZE + CELL_SIZE / 2;
var pos2Y = GRID_START_Y + y1 * CELL_SIZE + CELL_SIZE / 2;
candy1.animateToPosition(pos1X, pos1Y, 200);
candy2.animateToPosition(pos2X, pos2Y, 200);
return true;
};
self.getCandyAt = function (x, y) {
var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE);
var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE);
if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) {
// Don't return candy info if there's a wall
if (self.walls[gridY][gridX]) return null;
return {
x: gridX,
y: gridY,
candy: self.candies[gridY][gridX]
};
}
return null;
};
self.wouldCreateMatch = function (x, y, candyType) {
// Check horizontal match potential
var horizontalCount = 1;
// Check left
for (var i = x - 1; i >= 0 && self.candies[y][i] && self.candies[y][i].candyType === candyType; i--) {
horizontalCount++;
}
// Check right
for (var i = x + 1; i < GRID_SIZE && self.candies[y][i] && self.candies[y][i].candyType === candyType; i++) {
horizontalCount++;
}
if (horizontalCount >= 3) return true;
// Check vertical match potential
var verticalCount = 1;
// Check up
for (var i = y - 1; i >= 0 && self.candies[i][x] && self.candies[i][x].candyType === candyType; i--) {
verticalCount++;
}
// Check down
for (var i = y + 1; i < GRID_SIZE && self.candies[i][x] && self.candies[i][x].candyType === candyType; i++) {
verticalCount++;
}
if (verticalCount >= 3) return true;
return false;
};
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
var title = new Text2('Guna Blast', {
size: 180,
fill: 0xFFFF00
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
self.addChild(title);
var startButton = new MenuButton('BAŞLA', function () {
startGame();
});
startButton.x = 1024;
startButton.y = 800;
self.addChild(startButton);
var themeButton = new MenuButton('TEMALAR', function () {
showThemeSelection();
});
themeButton.x = 1024;
themeButton.y = 1100;
self.addChild(themeButton);
return self;
});
var MenuButton = Container.expand(function (text, onClick) {
var self = Container.call(this);
var background = self.attachAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2(text, {
size: 80,
fill: 0x000000
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function (x, y, obj) {
if (onClick) onClick();
};
return self;
});
var SuperBomb = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var superBombGraphics = self.attachAsset('super_bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Add more pronounced swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.15; // More pronounced sway than regular bomb
var swayDuration = 500 + Math.random() * 200; // Faster sway
function swayLeft() {
tween(superBombGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(superBombGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(superBombGraphics);
tween(self, {
scaleX: 3.5,
scaleY: 3.5,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var ThemeSelection = Container.expand(function () {
var self = Container.call(this);
var title = new Text2('Tema Seç', {
size: 120,
fill: 0xFFFF00
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 300;
self.addChild(title);
// Classic theme button
var classicButton = new MenuButton('Klasik', function () {
storage.currentTheme = 'classic';
currentTheme = 'classic';
showMainMenu();
});
classicButton.x = 1024;
classicButton.y = 700;
self.addChild(classicButton);
// Fruits theme button
var fruitsButton = new MenuButton('Meyveler', function () {
storage.currentTheme = 'fruits';
currentTheme = 'fruits';
showMainMenu();
});
fruitsButton.x = 1024;
fruitsButton.y = 950;
self.addChild(fruitsButton);
// Candies theme button
var candiesButton = new MenuButton('Fast Food', function () {
storage.currentTheme = 'candies';
currentTheme = 'candies';
showMainMenu();
});
candiesButton.x = 1024;
candiesButton.y = 1200;
self.addChild(candiesButton);
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c1810
});
/****
* Game Code
****/
var GRID_SIZE = 10;
var CELL_SIZE = 200;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = 600;
var currentScore = 0;
var highScore = 0;
var gameState = 'menu'; // 'menu', 'playing', 'processing', 'gameover'
var selectedCandy = null;
var grid = null;
var isProcessing = false;
var currentTheme = storage.currentTheme || 'classic';
var mainMenu = null;
var themeSelection = null;
var gameUI = null;
var movesLeft = 30;
var maxMoves = 30;
// UI Elements (will be created when game starts)
var scoreText = null;
var movesText = null;
// Show main menu on start
showMainMenu();
function processMatches() {
if (isProcessing) return; // Prevent multiple simultaneous processing
isProcessing = true;
var processDepth = 0;
var maxDepth = 10;
function processMatchesInner() {
if (processDepth >= maxDepth) {
isProcessing = false;
checkGameState();
return;
}
var matches = grid.findMatches();
if (matches.length > 0) {
processDepth++;
var points = grid.removeMatches(matches);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
LK.getSound('match').play();
LK.setTimeout(function () {
if (!grid || gameState !== 'playing') {
isProcessing = false;
return;
}
var moved = grid.applyGravity();
LK.setTimeout(function () {
if (!grid || gameState !== 'playing') {
isProcessing = false;
return;
}
grid.spawnNewCandies();
LK.setTimeout(function () {
if (!grid || gameState !== 'playing') {
isProcessing = false;
return;
}
processMatchesInner(); // Check for chain reactions with depth control
}, 500);
}, 300);
}, 300);
} else {
isProcessing = false;
checkGameState();
}
}
processMatchesInner();
}
function hasValidMoves() {
if (!grid || !grid.candies) return false;
// Check all possible adjacent swaps
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE; x++) {
if (!grid.candies[y] || !grid.candies[y][x] || grid.walls[y] && grid.walls[y][x]) continue;
// Check right neighbor
if (x + 1 < GRID_SIZE && grid.candies[y][x + 1] && (!grid.walls[y] || !grid.walls[y][x + 1])) {
// Temporarily swap
var candy1 = grid.candies[y][x];
var candy2 = grid.candies[y][x + 1];
if (candy1 && candy2 && candy1.candyType !== undefined && candy2.candyType !== undefined) {
grid.candies[y][x] = candy2;
grid.candies[y][x + 1] = candy1;
// Check if this creates matches
var matches = grid.findMatches();
// Swap back
grid.candies[y][x] = candy1;
grid.candies[y][x + 1] = candy2;
if (matches.length > 0) return true;
}
}
// Check bottom neighbor
if (y + 1 < GRID_SIZE && grid.candies[y + 1] && grid.candies[y + 1][x] && (!grid.walls[y + 1] || !grid.walls[y + 1][x])) {
// Temporarily swap
var candy1 = grid.candies[y][x];
var candy2 = grid.candies[y + 1][x];
if (candy1 && candy2 && candy1.candyType !== undefined && candy2.candyType !== undefined) {
grid.candies[y][x] = candy2;
grid.candies[y + 1][x] = candy1;
// Check if this creates matches
var matches = grid.findMatches();
// Swap back
grid.candies[y][x] = candy1;
grid.candies[y + 1][x] = candy2;
if (matches.length > 0) return true;
}
}
}
}
return false;
}
function checkGameState() {
if (gameState !== 'playing' || isProcessing) return;
// Check if moves are exhausted or no valid moves remain
if (movesLeft <= 0 || !hasValidMoves()) {
gameState = 'gameover';
// Check if current score is a new high score
if (currentScore > highScore) {
highScore = currentScore;
}
LK.showGameOver();
}
}
function showThemeSelection() {
gameState = 'menu';
if (mainMenu) {
mainMenu.destroy();
mainMenu = null;
}
if (grid) {
grid.destroy();
grid = null;
}
if (gameUI) {
gameUI.destroy();
gameUI = null;
}
themeSelection = game.addChild(new ThemeSelection());
}
function showMainMenu() {
gameState = 'menu';
if (themeSelection) {
themeSelection.destroy();
themeSelection = null;
}
if (grid) {
grid.destroy();
grid = null;
}
if (gameUI) {
gameUI.destroy();
gameUI = null;
}
mainMenu = game.addChild(new MainMenu());
}
function startGame() {
gameState = 'playing';
currentScore = 0;
movesLeft = maxMoves;
selectedCandy = null;
isProcessing = false;
if (mainMenu) {
mainMenu.destroy();
mainMenu = null;
}
// Play the second music track when game starts
LK.playMusic('Candy');
initializeGameUI();
grid = game.addChild(new Grid());
grid.placeWalls();
grid.fillGrid();
LK.setTimeout(function () {
processMatches();
}, 500);
}
function initializeGameUI() {
gameUI = new Container();
game.addChild(gameUI);
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var highScoreText = new Text2('High Score: ' + highScore, {
size: 50,
fill: 0xFFFF00
});
highScoreText.anchor.set(0.5, 0);
highScoreText.y = 150;
LK.gui.top.addChild(highScoreText);
movesText = new Text2('Moves: ' + movesLeft, {
size: 50,
fill: 0x00FF00
});
movesText.anchor.set(0.5, 0);
movesText.y = 200;
LK.gui.top.addChild(movesText);
}
function isAdjacent(x1, y1, x2, y2) {
var dx = Math.abs(x1 - x2);
var dy = Math.abs(y1 - y2);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
var dragStartCandy = null;
var dragStartPos = null;
game.down = function (x, y, obj) {
if (gameState !== 'playing' || isProcessing) return;
var candyInfo = grid.getCandyAt(x, y);
if (candyInfo && candyInfo.candy) {
// Check if it's a bomb
if (candyInfo.candy.constructor === Bomb) {
// Check if there's an adjacent firecracker for combination
var comboCandy = grid.checkFirecrackerBombCombo(candyInfo.x, candyInfo.y);
if (comboCandy) {
// Start spectacular combo animation, then explode all walls
var points = grid.explodeAllWalls(candyInfo.x, candyInfo.y, comboCandy.x, comboCandy.y);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
// Delay the candy destruction to allow animation to complete
LK.setTimeout(function () {
candyInfo.candy.explode();
comboCandy.candy.explode();
grid.candies[candyInfo.y][candyInfo.x] = null;
grid.candies[comboCandy.y][comboCandy.x] = null;
}, 1200);
} else {
// Regular bomb explosion - 3x3 area
var points = grid.explodeBomb(candyInfo.x, candyInfo.y);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
}
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
// Process gravity and spawn new candies after explosion
LK.setTimeout(function () {
var moved = grid.applyGravity();
LK.setTimeout(function () {
grid.spawnNewCandies();
LK.setTimeout(function () {
processMatches();
}, 500);
}, 300);
}, 300);
return;
}
// Check if it's a super bomb
if (candyInfo.candy.constructor === SuperBomb) {
// Explode entire 10x10 area
grid.explodeSuperBomb(candyInfo.x, candyInfo.y);
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
// Process gravity and spawn new candies after explosion
LK.setTimeout(function () {
var moved = grid.applyGravity();
LK.setTimeout(function () {
grid.spawnNewCandies();
LK.setTimeout(function () {
processMatches();
}, 500);
}, 300);
}, 300);
return;
}
// Check if it's a firecracker
if (candyInfo.candy.constructor === Firecracker) {
// Check if there's an adjacent bomb for combination
var comboCandy = grid.checkFirecrackerBombCombo(candyInfo.x, candyInfo.y);
if (comboCandy) {
// Start spectacular combo animation, then explode all walls
var points = grid.explodeAllWalls(candyInfo.x, candyInfo.y, comboCandy.x, comboCandy.y);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
// Delay the candy destruction to allow animation to complete
LK.setTimeout(function () {
candyInfo.candy.explode();
comboCandy.candy.explode();
grid.candies[candyInfo.y][candyInfo.x] = null;
grid.candies[comboCandy.y][comboCandy.x] = null;
}, 1200);
} else {
// Regular firecracker explosion - entire row
var firecrackerRow = candyInfo.y;
var points = grid.explodeRow(firecrackerRow);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
}
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
// Process gravity and spawn new candies after explosion
LK.setTimeout(function () {
var moved = grid.applyGravity();
LK.setTimeout(function () {
grid.spawnNewCandies();
LK.setTimeout(function () {
processMatches();
}, 500);
}, 300);
}, 300);
return;
}
// Start drag for regular candies
dragStartCandy = candyInfo;
dragStartPos = {
x: x,
y: y
};
// Scale up the candy to show it's being dragged
candyInfo.candy.scaleX = 1.1;
candyInfo.candy.scaleY = 1.1;
}
};
game.move = function (x, y, obj) {
if (gameState !== 'playing' || isProcessing || !dragStartCandy) return;
// Calculate drag distance
var dx = x - dragStartPos.x;
var dy = y - dragStartPos.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If dragged far enough, determine direction and target
if (distance > CELL_SIZE / 3) {
var targetX = dragStartCandy.x;
var targetY = dragStartCandy.y;
// Determine primary drag direction
if (Math.abs(dx) > Math.abs(dy)) {
// Horizontal drag
if (dx > 0) {
targetX = dragStartCandy.x + 1; // Right
} else {
targetX = dragStartCandy.x - 1; // Left
}
} else {
// Vertical drag
if (dy > 0) {
targetY = dragStartCandy.y + 1; // Down
} else {
targetY = dragStartCandy.y - 1; // Up
}
}
// Check if target position is valid and has a candy
if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
var targetCandyInfo = {
x: targetX,
y: targetY,
candy: grid.candies[targetY][targetX]
};
if (targetCandyInfo.candy && !grid.walls[targetY][targetX]) {
// Perform the swap
performCandySwap(dragStartCandy, targetCandyInfo);
// Reset drag state
dragStartCandy.candy.scaleX = 1;
dragStartCandy.candy.scaleY = 1;
dragStartCandy = null;
dragStartPos = null;
}
}
}
};
game.up = function (x, y, obj) {
if (dragStartCandy) {
// Reset candy scale and clear drag state
dragStartCandy.candy.scaleX = 1;
dragStartCandy.candy.scaleY = 1;
dragStartCandy = null;
dragStartPos = null;
}
};
function performCandySwap(candyInfo1, candyInfo2) {
// Try the swap
grid.swapCandies(candyInfo1.x, candyInfo1.y, candyInfo2.x, candyInfo2.y);
LK.getSound('swap').play();
// Check if swap creates matches
LK.setTimeout(function () {
var matches = grid.findMatches();
if (matches.length > 0) {
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
processMatches();
} else {
// Swap back if no matches
grid.swapCandies(candyInfo2.x, candyInfo2.y, candyInfo1.x, candyInfo1.y);
// Decrease moves counter even for failed moves
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
checkGameState();
}
}, 250);
}
game.update = function () {
// Game update logic handled by event system and timers
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Add gentle swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.1; // More pronounced sway than candies
var swayDuration = 600 + Math.random() * 300; // Faster sway
function swayLeft() {
tween(bombGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(bombGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(bombGraphics);
tween(self, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Candy = Container.expand(function (candyType) {
var self = Container.call(this);
self.candyType = candyType;
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var candyAssets = [];
if (currentTheme === 'classic') {
candyAssets = ['classic_candy_red', 'classic_candy_blue', 'classic_candy_green', 'classic_candy_purple', 'classic_candy_orange'];
} else if (currentTheme === 'fruits') {
candyAssets = ['fruit_apple', 'fruit_banana', 'fruit_cherry', 'fruit_grape', 'fruit_orange', 'fruit_strawberry'];
} else {
candyAssets = ['candy_red', 'candy_blue', 'candy_green', 'candy_yellow', 'candy_purple', 'candy_orange'];
}
var candyGraphics = self.attachAsset(candyAssets[candyType], {
anchorX: 0.5,
anchorY: 0.5
});
// Add gentle swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.05; // Small rotation amount
var swayDuration = 1000 + Math.random() * 500; // 1-1.5 seconds for variety (2x faster)
function swayLeft() {
tween(candyGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(candyGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(candyGraphics);
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Firecracker = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var firecrackerGraphics = self.attachAsset('firecracker', {
anchorX: 0.5,
anchorY: 0.5
});
// Add gentle swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.08; // Slightly more sway than candies
var swayDuration = 800 + Math.random() * 400; // Faster sway
function swayLeft() {
tween(firecrackerGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(firecrackerGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(firecrackerGraphics);
tween(self, {
scaleX: 2,
scaleY: 2,
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.cells = [];
self.candies = [];
self.walls = [];
// Create grid cells
for (var y = 0; y < GRID_SIZE; y++) {
self.cells[y] = [];
self.candies[y] = [];
self.walls[y] = [];
for (var x = 0; x < GRID_SIZE; x++) {
var cell = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
x: GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2,
y: GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2
});
self.cells[y][x] = cell;
self.candies[y][x] = null;
self.walls[y][x] = null;
}
}
// Place exactly one wall per move
self.placeWalls = function () {
var wallCount = 1; // Always spawn exactly one wall
var placedWalls = 0;
var attempts = 0;
var maxAttempts = 500;
// Define border areas for wall placement
var borderAreas = [
// Top border
{
minX: 1,
maxX: GRID_SIZE - 2,
minY: 1,
maxY: 2
},
// Bottom border
{
minX: 1,
maxX: GRID_SIZE - 2,
minY: GRID_SIZE - 3,
maxY: GRID_SIZE - 2
},
// Left border
{
minX: 1,
maxX: 2,
minY: 1,
maxY: GRID_SIZE - 2
},
// Right border
{
minX: GRID_SIZE - 3,
maxX: GRID_SIZE - 2,
minY: 1,
maxY: GRID_SIZE - 2
}];
// Choose a random border area to place wall
var chosenArea = borderAreas[Math.floor(Math.random() * borderAreas.length)];
while (placedWalls < wallCount && attempts < maxAttempts) {
var x = Math.floor(Math.random() * (chosenArea.maxX - chosenArea.minX + 1)) + chosenArea.minX;
var y = Math.floor(Math.random() * (chosenArea.maxY - chosenArea.minY + 1)) + chosenArea.minY;
attempts++;
// Don't place walls if already occupied
if (!self.walls[y][x]) {
// Clear any candy at this position before placing wall
if (self.candies[y][x]) {
self.candies[y][x].destroy();
self.candies[y][x] = null;
}
var wall = new Wall();
wall.setGridPosition(x, y);
self.walls[y][x] = wall;
self.addChild(wall);
placedWalls++;
}
}
};
self.fillGrid = function () {
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE; x++) {
if (!self.candies[y][x] && !self.walls[y][x]) {
// 1% chance to spawn bomb
if (Math.random() < 0.01) {
var bomb = new Bomb();
bomb.setGridPosition(x, y);
self.candies[y][x] = bomb;
self.addChild(bomb);
} else if (Math.random() < 0.001) {
var superBomb = new SuperBomb();
superBomb.setGridPosition(x, y);
self.candies[y][x] = superBomb;
self.addChild(superBomb);
} else if (Math.random() < 0.02) {
var firecracker = new Firecracker();
firecracker.setGridPosition(x, y);
self.candies[y][x] = firecracker;
self.addChild(firecracker);
} else {
var candyType;
var attempts = 0;
// Try to find a candy type that doesn't create immediate matches
do {
if (currentTheme === 'classic') {
candyType = Math.floor(Math.random() * 5);
} else if (currentTheme === 'fruits') {
candyType = Math.floor(Math.random() * 6);
} else {
candyType = Math.floor(Math.random() * 6);
}
attempts++;
} while (attempts < 10 && self.wouldCreateMatch(x, y, candyType));
var candy = new Candy(candyType);
candy.setGridPosition(x, y);
self.candies[y][x] = candy;
self.addChild(candy);
}
}
}
}
};
self.findMatches = function () {
var matches = [];
// Check horizontal matches
for (var y = 0; y < GRID_SIZE; y++) {
var count = 1;
var currentType = self.candies[y][0] ? self.candies[y][0].candyType : -1;
for (var x = 1; x < GRID_SIZE; x++) {
var candyType = self.candies[y][x] ? self.candies[y][x].candyType : -1;
if (candyType === currentType && candyType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = x - count; i < x; i++) {
matches.push({
x: i,
y: y
});
}
}
count = 1;
currentType = candyType;
}
}
if (count >= 3) {
for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) {
matches.push({
x: i,
y: y
});
}
}
}
// Check vertical matches
for (var x = 0; x < GRID_SIZE; x++) {
var count = 1;
var currentType = self.candies[0][x] ? self.candies[0][x].candyType : -1;
for (var y = 1; y < GRID_SIZE; y++) {
var candyType = self.candies[y][x] ? self.candies[y][x].candyType : -1;
if (candyType === currentType && candyType !== -1) {
count++;
} else {
if (count >= 3) {
for (var i = y - count; i < y; i++) {
matches.push({
x: x,
y: i
});
}
}
count = 1;
currentType = candyType;
}
}
if (count >= 3) {
for (var i = GRID_SIZE - count; i < GRID_SIZE; i++) {
matches.push({
x: x,
y: i
});
}
}
}
return matches;
};
self.removeMatches = function (matches) {
var score = 0;
for (var i = 0; i < matches.length; i++) {
var match = matches[i];
if (self.candies[match.y][match.x]) {
self.candies[match.y][match.x].explode();
self.candies[match.y][match.x] = null;
score += 10;
}
}
return score;
};
self.explodeRow = function (rowY) {
var score = 0;
LK.getSound('firecracker_explode').play();
// Destroy entire row including walls
for (var x = 0; x < GRID_SIZE; x++) {
// Destroy candy if present
if (self.candies[rowY][x]) {
self.candies[rowY][x].explode();
self.candies[rowY][x] = null;
score += 25;
}
// Destroy wall if present
if (self.walls[rowY][x]) {
self.walls[rowY][x].destroy();
self.walls[rowY][x] = null;
score += 15; // Give points for destroying walls
}
}
return score;
};
self.explodeBomb = function (centerX, centerY) {
var score = 0;
LK.getSound('bomb_explode').play();
// Explode 3x3 area around the bomb
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
var x = centerX + dx;
var y = centerY + dy;
// Check bounds
if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE) {
// Destroy candy if present
if (self.candies[y][x]) {
self.candies[y][x].explode();
self.candies[y][x] = null;
score += 20; // More points for bomb explosion
}
// Destroy wall if present
if (self.walls[y][x]) {
self.walls[y][x].destroy();
self.walls[y][x] = null;
score += 15; // Give points for destroying walls
}
}
}
}
return score;
};
self.explodeSuperBomb = function (centerX, centerY) {
var score = 0;
LK.getSound('super_bomb_explode').play();
// Explode entire 10x10 area
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
// Destroy candy if present
if (self.candies[y][x]) {
self.candies[y][x].explode();
self.candies[y][x] = null;
}
// Destroy wall if present
if (self.walls[y][x]) {
self.walls[y][x].destroy();
self.walls[y][x] = null;
}
}
}
return score;
};
self.checkFirecrackerBombCombo = function (centerX, centerY) {
// Check adjacent positions for bomb-firecracker combination
var adjacentPositions = [{
x: centerX - 1,
y: centerY
},
// Left
{
x: centerX + 1,
y: centerY
},
// Right
{
x: centerX,
y: centerY - 1
},
// Up
{
x: centerX,
y: centerY + 1
} // Down
];
var currentCandy = self.candies[centerY][centerX];
var hasFirecracker = currentCandy && currentCandy.constructor === Firecracker;
var hasBomb = currentCandy && currentCandy.constructor === Bomb;
for (var i = 0; i < adjacentPositions.length; i++) {
var pos = adjacentPositions[i];
if (pos.x >= 0 && pos.x < GRID_SIZE && pos.y >= 0 && pos.y < GRID_SIZE) {
var adjacentCandy = self.candies[pos.y][pos.x];
if (adjacentCandy) {
// Check if we have firecracker next to bomb or bomb next to firecracker
if (hasFirecracker && adjacentCandy.constructor === Bomb || hasBomb && adjacentCandy.constructor === Firecracker) {
return {
x: pos.x,
y: pos.y,
candy: adjacentCandy
};
}
}
}
}
return null;
};
self.explodeAllWalls = function (centerX, centerY, comboX, comboY) {
var score = 0;
// Create spectacular animation before exploding walls
var centerCandy = self.candies[centerY][centerX];
var comboCandy = self.candies[comboY][comboX];
// Phase 1: Scale up both candies dramatically
if (centerCandy) {
tween(centerCandy, {
scaleX: 3,
scaleY: 3,
rotation: Math.PI * 4
}, {
duration: 800,
easing: tween.easeOut
});
}
if (comboCandy) {
tween(comboCandy, {
scaleX: 3,
scaleY: 3,
rotation: -Math.PI * 4
}, {
duration: 800,
easing: tween.easeOut
});
}
// Phase 2: Flash screen effect
LK.setTimeout(function () {
LK.effects.flashScreen(0xFFFF00, 200); // Yellow flash
LK.setTimeout(function () {
LK.effects.flashScreen(0xFF4500, 150); // Orange flash
LK.setTimeout(function () {
LK.effects.flashScreen(0xFF0000, 100); // Red flash
}, 200);
}, 150);
}, 400);
// Phase 3: Create expanding shockwave effect with all walls
LK.setTimeout(function () {
LK.getSound('super_bomb_explode').play();
// Animate all walls before destroying them
var wallsToDestroy = [];
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (self.walls[y][x]) {
wallsToDestroy.push({
wall: self.walls[y][x],
x: x,
y: y
});
}
}
}
// Animate each wall with staggered timing based on distance from center
for (var i = 0; i < wallsToDestroy.length; i++) {
(function (wallData, index) {
var distance = Math.sqrt(Math.pow(wallData.x - centerX, 2) + Math.pow(wallData.y - centerY, 2));
var delay = distance * 50; // Stagger based on distance
LK.setTimeout(function () {
// Scale up and rotate wall before destroying
tween(wallData.wall, {
scaleX: 2.5,
scaleY: 2.5,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
wallData.wall.destroy();
self.walls[wallData.y][wallData.x] = null;
// Spawn a new candy in place of the destroyed wall
var candyType;
if (currentTheme === 'classic') {
candyType = Math.floor(Math.random() * 5);
} else if (currentTheme === 'fruits') {
candyType = Math.floor(Math.random() * 6);
} else {
candyType = Math.floor(Math.random() * 6);
}
var newCandy = new Candy(candyType);
newCandy.setGridPosition(wallData.x, wallData.y);
self.candies[wallData.y][wallData.x] = newCandy;
self.addChild(newCandy);
// Start with small scale and animate to normal size
newCandy.scaleX = 0.1;
newCandy.scaleY = 0.1;
tween(newCandy, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}, delay);
})(wallsToDestroy[i], i);
score += 50; // Give more points for destroying all walls
}
}, 800);
return score;
};
self.applyGravity = function () {
var moved = false;
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = GRID_SIZE - 1; y >= 0; y--) {
if (!self.candies[y][x] && !self.walls[y][x]) {
// Find candy above to fall down
for (var aboveY = y - 1; aboveY >= 0; aboveY--) {
if (self.candies[aboveY][x]) {
self.candies[y][x] = self.candies[aboveY][x];
self.candies[aboveY][x] = null;
self.candies[y][x].gridX = x;
self.candies[y][x].gridY = y;
var targetX = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
self.candies[y][x].animateToPosition(targetX, targetY, 300);
moved = true;
break;
}
}
}
}
}
return moved;
};
self.spawnNewCandies = function () {
for (var x = 0; x < GRID_SIZE; x++) {
for (var y = 0; y < GRID_SIZE; y++) {
if (!self.candies[y][x] && !self.walls[y][x]) {
// 1% chance to spawn bomb
if (Math.random() < 0.01) {
var bomb = new Bomb();
bomb.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
bomb.y = GRID_START_Y - CELL_SIZE;
bomb.gridX = x;
bomb.gridY = y;
self.candies[y][x] = bomb;
self.addChild(bomb);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
bomb.animateToPosition(bomb.x, targetY, 400);
} else if (Math.random() < 0.001) {
var superBomb = new SuperBomb();
superBomb.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
superBomb.y = GRID_START_Y - CELL_SIZE;
superBomb.gridX = x;
superBomb.gridY = y;
self.candies[y][x] = superBomb;
self.addChild(superBomb);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
superBomb.animateToPosition(superBomb.x, targetY, 400);
} else if (Math.random() < 0.02) {
var firecracker = new Firecracker();
firecracker.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
firecracker.y = GRID_START_Y - CELL_SIZE;
firecracker.gridX = x;
firecracker.gridY = y;
self.candies[y][x] = firecracker;
self.addChild(firecracker);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
firecracker.animateToPosition(firecracker.x, targetY, 400);
} else {
var candyType;
if (currentTheme === 'classic') {
candyType = Math.floor(Math.random() * 5);
} else if (currentTheme === 'fruits') {
candyType = Math.floor(Math.random() * 6);
} else {
candyType = Math.floor(Math.random() * 6);
}
var candy = new Candy(candyType);
candy.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
candy.y = GRID_START_Y - CELL_SIZE;
candy.gridX = x;
candy.gridY = y;
self.candies[y][x] = candy;
self.addChild(candy);
var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
candy.animateToPosition(candy.x, targetY, 400);
}
}
}
}
};
self.swapCandies = function (x1, y1, x2, y2) {
var candy1 = self.candies[y1][x1];
var candy2 = self.candies[y2][x2];
if (!candy1 || !candy2) return false;
// Swap in grid
self.candies[y1][x1] = candy2;
self.candies[y2][x2] = candy1;
// Update grid positions
candy1.gridX = x2;
candy1.gridY = y2;
candy2.gridX = x1;
candy2.gridY = y1;
// Animate to new positions
var pos1X = GRID_START_X + x2 * CELL_SIZE + CELL_SIZE / 2;
var pos1Y = GRID_START_Y + y2 * CELL_SIZE + CELL_SIZE / 2;
var pos2X = GRID_START_X + x1 * CELL_SIZE + CELL_SIZE / 2;
var pos2Y = GRID_START_Y + y1 * CELL_SIZE + CELL_SIZE / 2;
candy1.animateToPosition(pos1X, pos1Y, 200);
candy2.animateToPosition(pos2X, pos2Y, 200);
return true;
};
self.getCandyAt = function (x, y) {
var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE);
var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE);
if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) {
// Don't return candy info if there's a wall
if (self.walls[gridY][gridX]) return null;
return {
x: gridX,
y: gridY,
candy: self.candies[gridY][gridX]
};
}
return null;
};
self.wouldCreateMatch = function (x, y, candyType) {
// Check horizontal match potential
var horizontalCount = 1;
// Check left
for (var i = x - 1; i >= 0 && self.candies[y][i] && self.candies[y][i].candyType === candyType; i--) {
horizontalCount++;
}
// Check right
for (var i = x + 1; i < GRID_SIZE && self.candies[y][i] && self.candies[y][i].candyType === candyType; i++) {
horizontalCount++;
}
if (horizontalCount >= 3) return true;
// Check vertical match potential
var verticalCount = 1;
// Check up
for (var i = y - 1; i >= 0 && self.candies[i][x] && self.candies[i][x].candyType === candyType; i--) {
verticalCount++;
}
// Check down
for (var i = y + 1; i < GRID_SIZE && self.candies[i][x] && self.candies[i][x].candyType === candyType; i++) {
verticalCount++;
}
if (verticalCount >= 3) return true;
return false;
};
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
var title = new Text2('Guna Blast', {
size: 180,
fill: 0xFFFF00
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
self.addChild(title);
var startButton = new MenuButton('BAŞLA', function () {
startGame();
});
startButton.x = 1024;
startButton.y = 800;
self.addChild(startButton);
var themeButton = new MenuButton('TEMALAR', function () {
showThemeSelection();
});
themeButton.x = 1024;
themeButton.y = 1100;
self.addChild(themeButton);
return self;
});
var MenuButton = Container.expand(function (text, onClick) {
var self = Container.call(this);
var background = self.attachAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2(text, {
size: 80,
fill: 0x000000
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function (x, y, obj) {
if (onClick) onClick();
};
return self;
});
var SuperBomb = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
self.isAnimating = false;
var superBombGraphics = self.attachAsset('super_bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Add more pronounced swaying animation
self.startSwayAnimation = function () {
var swayAmount = 0.15; // More pronounced sway than regular bomb
var swayDuration = 500 + Math.random() * 200; // Faster sway
function swayLeft() {
tween(superBombGraphics, {
rotation: -swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayRight
});
}
function swayRight() {
tween(superBombGraphics, {
rotation: swayAmount
}, {
duration: swayDuration,
easing: tween.easeInOut,
onFinish: swayLeft
});
}
// Start with random direction and slight delay for variety
LK.setTimeout(function () {
if (Math.random() > 0.5) {
swayLeft();
} else {
swayRight();
}
}, Math.random() * 250);
};
// Start swaying animation
self.startSwayAnimation();
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration || 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.explode = function () {
// Stop swaying animation
tween.stop(superBombGraphics);
tween(self, {
scaleX: 3.5,
scaleY: 3.5,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var ThemeSelection = Container.expand(function () {
var self = Container.call(this);
var title = new Text2('Tema Seç', {
size: 120,
fill: 0xFFFF00
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 300;
self.addChild(title);
// Classic theme button
var classicButton = new MenuButton('Klasik', function () {
storage.currentTheme = 'classic';
currentTheme = 'classic';
showMainMenu();
});
classicButton.x = 1024;
classicButton.y = 700;
self.addChild(classicButton);
// Fruits theme button
var fruitsButton = new MenuButton('Meyveler', function () {
storage.currentTheme = 'fruits';
currentTheme = 'fruits';
showMainMenu();
});
fruitsButton.x = 1024;
fruitsButton.y = 950;
self.addChild(fruitsButton);
// Candies theme button
var candiesButton = new MenuButton('Fast Food', function () {
storage.currentTheme = 'candies';
currentTheme = 'candies';
showMainMenu();
});
candiesButton.x = 1024;
candiesButton.y = 1200;
self.addChild(candiesButton);
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
self.gridX = 0;
self.gridY = 0;
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (gridX, gridY) {
self.gridX = gridX;
self.gridY = gridY;
self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c1810
});
/****
* Game Code
****/
var GRID_SIZE = 10;
var CELL_SIZE = 200;
var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
var GRID_START_Y = 600;
var currentScore = 0;
var highScore = 0;
var gameState = 'menu'; // 'menu', 'playing', 'processing', 'gameover'
var selectedCandy = null;
var grid = null;
var isProcessing = false;
var currentTheme = storage.currentTheme || 'classic';
var mainMenu = null;
var themeSelection = null;
var gameUI = null;
var movesLeft = 30;
var maxMoves = 30;
// UI Elements (will be created when game starts)
var scoreText = null;
var movesText = null;
// Show main menu on start
showMainMenu();
function processMatches() {
if (isProcessing) return; // Prevent multiple simultaneous processing
isProcessing = true;
var processDepth = 0;
var maxDepth = 10;
function processMatchesInner() {
if (processDepth >= maxDepth) {
isProcessing = false;
checkGameState();
return;
}
var matches = grid.findMatches();
if (matches.length > 0) {
processDepth++;
var points = grid.removeMatches(matches);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
LK.getSound('match').play();
LK.setTimeout(function () {
if (!grid || gameState !== 'playing') {
isProcessing = false;
return;
}
var moved = grid.applyGravity();
LK.setTimeout(function () {
if (!grid || gameState !== 'playing') {
isProcessing = false;
return;
}
grid.spawnNewCandies();
LK.setTimeout(function () {
if (!grid || gameState !== 'playing') {
isProcessing = false;
return;
}
processMatchesInner(); // Check for chain reactions with depth control
}, 500);
}, 300);
}, 300);
} else {
isProcessing = false;
checkGameState();
}
}
processMatchesInner();
}
function hasValidMoves() {
if (!grid || !grid.candies) return false;
// Check all possible adjacent swaps
for (var y = 0; y < GRID_SIZE; y++) {
for (var x = 0; x < GRID_SIZE; x++) {
if (!grid.candies[y] || !grid.candies[y][x] || grid.walls[y] && grid.walls[y][x]) continue;
// Check right neighbor
if (x + 1 < GRID_SIZE && grid.candies[y][x + 1] && (!grid.walls[y] || !grid.walls[y][x + 1])) {
// Temporarily swap
var candy1 = grid.candies[y][x];
var candy2 = grid.candies[y][x + 1];
if (candy1 && candy2 && candy1.candyType !== undefined && candy2.candyType !== undefined) {
grid.candies[y][x] = candy2;
grid.candies[y][x + 1] = candy1;
// Check if this creates matches
var matches = grid.findMatches();
// Swap back
grid.candies[y][x] = candy1;
grid.candies[y][x + 1] = candy2;
if (matches.length > 0) return true;
}
}
// Check bottom neighbor
if (y + 1 < GRID_SIZE && grid.candies[y + 1] && grid.candies[y + 1][x] && (!grid.walls[y + 1] || !grid.walls[y + 1][x])) {
// Temporarily swap
var candy1 = grid.candies[y][x];
var candy2 = grid.candies[y + 1][x];
if (candy1 && candy2 && candy1.candyType !== undefined && candy2.candyType !== undefined) {
grid.candies[y][x] = candy2;
grid.candies[y + 1][x] = candy1;
// Check if this creates matches
var matches = grid.findMatches();
// Swap back
grid.candies[y][x] = candy1;
grid.candies[y + 1][x] = candy2;
if (matches.length > 0) return true;
}
}
}
}
return false;
}
function checkGameState() {
if (gameState !== 'playing' || isProcessing) return;
// Check if moves are exhausted or no valid moves remain
if (movesLeft <= 0 || !hasValidMoves()) {
gameState = 'gameover';
// Check if current score is a new high score
if (currentScore > highScore) {
highScore = currentScore;
}
LK.showGameOver();
}
}
function showThemeSelection() {
gameState = 'menu';
if (mainMenu) {
mainMenu.destroy();
mainMenu = null;
}
if (grid) {
grid.destroy();
grid = null;
}
if (gameUI) {
gameUI.destroy();
gameUI = null;
}
themeSelection = game.addChild(new ThemeSelection());
}
function showMainMenu() {
gameState = 'menu';
if (themeSelection) {
themeSelection.destroy();
themeSelection = null;
}
if (grid) {
grid.destroy();
grid = null;
}
if (gameUI) {
gameUI.destroy();
gameUI = null;
}
mainMenu = game.addChild(new MainMenu());
}
function startGame() {
gameState = 'playing';
currentScore = 0;
movesLeft = maxMoves;
selectedCandy = null;
isProcessing = false;
if (mainMenu) {
mainMenu.destroy();
mainMenu = null;
}
// Play the second music track when game starts
LK.playMusic('Candy');
initializeGameUI();
grid = game.addChild(new Grid());
grid.placeWalls();
grid.fillGrid();
LK.setTimeout(function () {
processMatches();
}, 500);
}
function initializeGameUI() {
gameUI = new Container();
game.addChild(gameUI);
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var highScoreText = new Text2('High Score: ' + highScore, {
size: 50,
fill: 0xFFFF00
});
highScoreText.anchor.set(0.5, 0);
highScoreText.y = 150;
LK.gui.top.addChild(highScoreText);
movesText = new Text2('Moves: ' + movesLeft, {
size: 50,
fill: 0x00FF00
});
movesText.anchor.set(0.5, 0);
movesText.y = 200;
LK.gui.top.addChild(movesText);
}
function isAdjacent(x1, y1, x2, y2) {
var dx = Math.abs(x1 - x2);
var dy = Math.abs(y1 - y2);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
var dragStartCandy = null;
var dragStartPos = null;
game.down = function (x, y, obj) {
if (gameState !== 'playing' || isProcessing) return;
var candyInfo = grid.getCandyAt(x, y);
if (candyInfo && candyInfo.candy) {
// Check if it's a bomb
if (candyInfo.candy.constructor === Bomb) {
// Check if there's an adjacent firecracker for combination
var comboCandy = grid.checkFirecrackerBombCombo(candyInfo.x, candyInfo.y);
if (comboCandy) {
// Start spectacular combo animation, then explode all walls
var points = grid.explodeAllWalls(candyInfo.x, candyInfo.y, comboCandy.x, comboCandy.y);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
// Delay the candy destruction to allow animation to complete
LK.setTimeout(function () {
candyInfo.candy.explode();
comboCandy.candy.explode();
grid.candies[candyInfo.y][candyInfo.x] = null;
grid.candies[comboCandy.y][comboCandy.x] = null;
}, 1200);
} else {
// Regular bomb explosion - 3x3 area
var points = grid.explodeBomb(candyInfo.x, candyInfo.y);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
}
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
// Process gravity and spawn new candies after explosion
LK.setTimeout(function () {
var moved = grid.applyGravity();
LK.setTimeout(function () {
grid.spawnNewCandies();
LK.setTimeout(function () {
processMatches();
}, 500);
}, 300);
}, 300);
return;
}
// Check if it's a super bomb
if (candyInfo.candy.constructor === SuperBomb) {
// Explode entire 10x10 area
grid.explodeSuperBomb(candyInfo.x, candyInfo.y);
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
// Process gravity and spawn new candies after explosion
LK.setTimeout(function () {
var moved = grid.applyGravity();
LK.setTimeout(function () {
grid.spawnNewCandies();
LK.setTimeout(function () {
processMatches();
}, 500);
}, 300);
}, 300);
return;
}
// Check if it's a firecracker
if (candyInfo.candy.constructor === Firecracker) {
// Check if there's an adjacent bomb for combination
var comboCandy = grid.checkFirecrackerBombCombo(candyInfo.x, candyInfo.y);
if (comboCandy) {
// Start spectacular combo animation, then explode all walls
var points = grid.explodeAllWalls(candyInfo.x, candyInfo.y, comboCandy.x, comboCandy.y);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
// Delay the candy destruction to allow animation to complete
LK.setTimeout(function () {
candyInfo.candy.explode();
comboCandy.candy.explode();
grid.candies[candyInfo.y][candyInfo.x] = null;
grid.candies[comboCandy.y][comboCandy.x] = null;
}, 1200);
} else {
// Regular firecracker explosion - entire row
var firecrackerRow = candyInfo.y;
var points = grid.explodeRow(firecrackerRow);
currentScore += points;
if (scoreText) scoreText.setText('Score: ' + currentScore);
}
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
// Process gravity and spawn new candies after explosion
LK.setTimeout(function () {
var moved = grid.applyGravity();
LK.setTimeout(function () {
grid.spawnNewCandies();
LK.setTimeout(function () {
processMatches();
}, 500);
}, 300);
}, 300);
return;
}
// Start drag for regular candies
dragStartCandy = candyInfo;
dragStartPos = {
x: x,
y: y
};
// Scale up the candy to show it's being dragged
candyInfo.candy.scaleX = 1.1;
candyInfo.candy.scaleY = 1.1;
}
};
game.move = function (x, y, obj) {
if (gameState !== 'playing' || isProcessing || !dragStartCandy) return;
// Calculate drag distance
var dx = x - dragStartPos.x;
var dy = y - dragStartPos.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If dragged far enough, determine direction and target
if (distance > CELL_SIZE / 3) {
var targetX = dragStartCandy.x;
var targetY = dragStartCandy.y;
// Determine primary drag direction
if (Math.abs(dx) > Math.abs(dy)) {
// Horizontal drag
if (dx > 0) {
targetX = dragStartCandy.x + 1; // Right
} else {
targetX = dragStartCandy.x - 1; // Left
}
} else {
// Vertical drag
if (dy > 0) {
targetY = dragStartCandy.y + 1; // Down
} else {
targetY = dragStartCandy.y - 1; // Up
}
}
// Check if target position is valid and has a candy
if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) {
var targetCandyInfo = {
x: targetX,
y: targetY,
candy: grid.candies[targetY][targetX]
};
if (targetCandyInfo.candy && !grid.walls[targetY][targetX]) {
// Perform the swap
performCandySwap(dragStartCandy, targetCandyInfo);
// Reset drag state
dragStartCandy.candy.scaleX = 1;
dragStartCandy.candy.scaleY = 1;
dragStartCandy = null;
dragStartPos = null;
}
}
}
};
game.up = function (x, y, obj) {
if (dragStartCandy) {
// Reset candy scale and clear drag state
dragStartCandy.candy.scaleX = 1;
dragStartCandy.candy.scaleY = 1;
dragStartCandy = null;
dragStartPos = null;
}
};
function performCandySwap(candyInfo1, candyInfo2) {
// Try the swap
grid.swapCandies(candyInfo1.x, candyInfo1.y, candyInfo2.x, candyInfo2.y);
LK.getSound('swap').play();
// Check if swap creates matches
LK.setTimeout(function () {
var matches = grid.findMatches();
if (matches.length > 0) {
// Decrease moves counter
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
processMatches();
} else {
// Swap back if no matches
grid.swapCandies(candyInfo2.x, candyInfo2.y, candyInfo1.x, candyInfo1.y);
// Decrease moves counter even for failed moves
movesLeft--;
if (movesText) movesText.setText('Moves: ' + movesLeft);
// Add one wall after each move
grid.placeWalls();
checkGameState();
}
}, 250);
}
game.update = function () {
// Game update logic handled by event system and timers
};
Boş renkli düğme. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Pizza. In-Game asset. 2d. High contrast. No shadows
Bomba . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Hamburger. In-Game asset. 2d. High contrast. No shadows
Coca Cola. In-Game asset. 2d. High contrast. No shadows
Döner Shavurma. In-Game asset. 2d. High contrast. No shadows
Oatates kızartması Fast Food. In-Game asset. 2d. High contrast. No shadows
Lahmacun. In-Game asset. 2d. High contrast. No shadows
Basit mavi kare yüz. Burnu kocaman olsun. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Basit ağzı kocaman sarı renkde kare yüz. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Basit turuncu renkde kare yüz. In-Game asset. 2d. High contrast. No shadows
Basit mor renkde kare yüz. Burnu çok küçük, dişleri çok büyük. In-Game asset. 2d. High contrast. No shadows
İki gözü iki kaşı olsun
Düz sade kare duvar. In-Game asset. 2d. High contrast. No shadows
Hacvai Fişek. In-Game asset. 2d. High contrast. No shadows
Renkli süper bomba. In-Game asset. 2d. High contrast. No shadows
Elma. In-Game asset. 2d. High contrast. No shadows
Çiyelek. In-Game asset. 2d. High contrast. No shadows
Portakal. In-Game asset. 2d. High contrast. No shadows
Ananas. In-Game asset. 2d. High contrast. No shadows
Üzüm. In-Game asset. 2d. High contrast. No shadows
Muz. In-Game asset. 2d. High contrast. No shadows
Üzerinde soru işaresi olan renkli sandık. In-Game asset. 2d. High contrast. No shadows