User prompt
Oluştuğu an yok oluyo olmamalı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
2 kara delik yan yana gelirse 1 supernow oluşur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyun parası sıfırlanır ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Supernowa sadece oyuncu patlayabilir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Supernowa oluşunca kombolanmadan patlamaz ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
2 kara delik birleşince 1 supernowa oluşur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Supernowa ile disko topu birleşince patlamaz yok olur ve writerpi ortaya çıkar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Deneme modu kenarda expir supernowa kara delik sürükleyerek yerleştirebilelim ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Supernowa ile disko topu birleşirse expires oluşur ve bütün topları kırmızı roket yapar exipires ile kara delik birleşirse writerpir oluşur patladığında bütün mapi supernowa yapar supwrnowa patlattığı herkesi etkinleştirilmelidir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Supernowa eklenmesi ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Bunları düzelt ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
2 disko topu birleştiğinde ve tüm toplar yok olduktan sonra yeni toplar düşmeli ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Qsla boş kare kalmamalı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Fps up
User prompt
Test sürüm iptal
User prompt
daha fazla yıldız ve %80 olasılıkla yıldız kayar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
tets deneme amaçlı 5 yan yana gelen 5 mor top, ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
gizli sekmeyi açıp kapatınca gizli sekme arkda yok olur
User prompt
gizli sekmedeyken tekrar kayan yıldıza tıklanırsa oyun normale döner
User prompt
kara deliğe çekilen bir özel şeker direk etkinleşir birbrlerini tetiklerler ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
mor şekerden 5 tanesi kombolanırsa kara delik oluşur kullanılınca 8 menzillik alandaki tüm şekerleri tek kareye sığdırır ve patlatır aynı zamanda gizli seansdaki disko topu bomba roketin yanına kara delik ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
gizli alana kara delikte ekle
User prompt
gizli kayan yıldıza basıp 1. 1. 1. 3. bastıktan sonra artık normal şeker gelmez hep disko topu bomba roket gelir
User prompt
duvar özelliğini oyundan kaldır
User prompt
gizli bolumdeki topların üstünde numaraları yazar
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Candy = Container.expand(function (type, row, col) {
var self = Container.call(this);
self.type = type;
self.row = row;
self.col = col;
self.isSpecial = false;
self.specialType = null;
self.matchCount = 0;
var assetMap = {
'blue': 'blueCandy',
'red': 'redCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
'purple': 'purpleCandy'
};
var specialAssetMap = {
'blueBomb': 'blueBomb',
'redRocket': 'redRocket',
'greenPentagon': 'greenPentagon',
'orangeLollipop': 'orangeLollipop',
'purpleBerry': 'purpleBerry',
'discoBall': 'discoBall',
'blackHole': 'blackHole'
};
self.graphics = self.attachAsset(assetMap[type], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.makeSpecial = function (specialType) {
self.isSpecial = true;
self.specialType = specialType;
self.removeChild(self.graphics);
self.graphics = self.attachAsset(specialAssetMap[specialType], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
};
self.explode = function () {
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
return self;
});
var ShootingStar = Container.expand(function () {
var self = Container.call(this);
var star = LK.getAsset('gridLine', {
width: 8,
height: 8,
color: 0xFFFFFF,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(star);
// Set random starting position at top of screen
self.x = Math.random() * 2048;
self.y = -50;
// Set falling speed
self.speed = Math.random() * 5 + 3;
// Add trail effect
self.alpha = 0.9;
self.update = function () {
self.y += self.speed;
// Remove when off screen
if (self.y > 2732 + 50) {
if (self.parent) {
self.parent.removeChild(self);
}
}
};
return self;
});
var StarField = Container.expand(function () {
var self = Container.call(this);
var stars = [];
var numStars = 30; // Reduced for better performance
var twinkleTimer = 0;
self.twinkle = function (star) {
var targetAlpha = Math.random() * 0.8 + 0.2;
var duration = Math.random() * 3000 + 2000; // Longer duration
tween(star, {
alpha: targetAlpha
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add longer delay before next twinkle to reduce frequency
LK.setTimeout(function () {
self.twinkle(star);
}, Math.random() * 3000 + 2000);
}
});
};
// Create individual stars
for (var i = 0; i < numStars; i++) {
var star = LK.getAsset('gridLine', {
width: Math.random() * 6 + 2,
height: Math.random() * 6 + 2,
color: 0xFFFFFF,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: Math.random() * 2732,
alpha: Math.random() * 0.8 + 0.2
});
self.addChild(star);
stars.push(star);
// Start twinkling animation for each star with staggered timing
LK.setTimeout(function () {
self.twinkle(star);
}, i * 100); // Stagger start times
}
// Track shooting stars
var shootingStars = [];
// Create shooting star occasionally
self.createShootingStar = function () {
var shootingStar = new ShootingStar();
self.addChild(shootingStar);
shootingStars.push(shootingStar);
};
self.update = function () {
// Clean up shooting stars that are off screen - check less frequently
if (LK.ticks % 60 === 0) {
// Only check every 60 frames (1 second)
for (var i = shootingStars.length - 1; i >= 0; i--) {
if (shootingStars[i].y > 2732 + 50) {
shootingStars.splice(i, 1);
}
}
}
// Randomly create shooting stars - 5% chance
if (Math.random() < 0.05 && shootingStars.length < 5) {
// 5% chance per frame, max 5 shooting stars
self.createShootingStar();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E1065
});
/****
* Game Code
****/
var GRID_SIZE = 8;
var CELL_SIZE = 200;
var GRID_START_X = 224;
var GRID_START_Y = 566;
var COLORS = ['blue', 'red', 'green', 'orange', 'purple'];
var grid = [];
var selectedCandy = null;
var score = 0;
var level = 1;
var gold = storage.gold || 0;
var isProcessing = false;
var comboMultiplier = 1;
var clickCounts = {}; // Track click counts for each candy position
var lastClickTime = 0;
var CLICK_TIMEOUT = 1000; // Reset click count after 1 second
// Secret feature variables
var secretMode = false;
var secretBalls = [];
var secretClickSequence = []; // Track sequence of ball clicks
var secretGridBackup = null; // Backup of original grid state
var onlySpecialCandies = false; // Flag to spawn only special candies
// Create animated starfield background
var starField = new StarField();
game.addChild(starField);
// Create grid background
var gridBg = game.attachAsset('gridBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
// Create grid lines
for (var i = 0; i <= GRID_SIZE; i++) {
// Vertical lines
var verticalLine = LK.getAsset('gridLine', {
width: 4,
height: GRID_SIZE * CELL_SIZE,
color: 0x000000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: GRID_START_X + i * CELL_SIZE,
y: GRID_START_Y + GRID_SIZE * CELL_SIZE / 2
});
game.addChild(verticalLine);
// Horizontal lines
var horizontalLine = LK.getAsset('gridLine', {
width: GRID_SIZE * CELL_SIZE,
height: 4,
color: 0x000000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: GRID_START_X + GRID_SIZE * CELL_SIZE / 2,
y: GRID_START_Y + i * CELL_SIZE
});
game.addChild(horizontalLine);
}
// Create UI elements
var scoreText = new Text2('Score: 0', {
size: 80,
fill: '#FFFFFF'
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 100;
var levelText = new Text2('Level: 1', {
size: 60,
fill: '#FFFFFF'
});
levelText.anchor.set(0, 0);
LK.gui.topLeft.addChild(levelText);
levelText.x = 120;
levelText.y = 100;
var goldText = new Text2('Gold: 0', {
size: 60,
fill: '#FFD700'
});
goldText.anchor.set(1, 0);
LK.gui.topRight.addChild(goldText);
goldText.x = -20;
goldText.y = 100;
// Create combo display text
var comboText = new Text2('', {
size: 100,
fill: '#FFFF00'
});
comboText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(comboText);
comboText.alpha = 0; // Start invisible
// Create level progress bar
var progressBarBg = LK.getAsset('progressBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.top.addChild(progressBarBg);
progressBarBg.y = 200;
var progressBarFill = LK.getAsset('progressBarFill', {
anchorX: 0,
anchorY: 0.5
});
progressBarBg.addChild(progressBarFill);
progressBarFill.x = -300; // Start from left edge of background
progressBarFill.scaleX = 0; // Start empty
// Initialize grid
function initializeGrid() {
grid = [];
for (var row = 0; row < GRID_SIZE; row++) {
grid[row] = [];
for (var col = 0; col < GRID_SIZE; col++) {
var color;
// Random colors for all positions
color = COLORS[Math.floor(Math.random() * COLORS.length)];
var candy = new Candy(color, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
candy.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2;
grid[row][col] = candy;
game.addChild(candy);
}
}
}
function removeInitialMatches() {
var hasMatches = true;
while (hasMatches) {
hasMatches = false;
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (checkMatch(row, col).length >= 3) {
hasMatches = true;
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
grid[row][col].type = randomColor;
grid[row][col].removeChild(grid[row][col].graphics);
var assetMap = {
'blue': 'blueCandy',
'red': 'redCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
'purple': 'purpleCandy'
};
grid[row][col].graphics = grid[row][col].attachAsset(assetMap[randomColor], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
}
}
}
}
}
function getCandyAt(x, y) {
var col = Math.floor((x - GRID_START_X) / CELL_SIZE);
var row = Math.floor((y - GRID_START_Y) / CELL_SIZE);
if (row >= 0 && row < GRID_SIZE && col >= 0 && col < GRID_SIZE) {
return grid[row][col];
}
return null;
}
function swapCandies(candy1, candy2) {
if (!candy1 || !candy2 || candy1 === candy2) return false;
var row1 = candy1.row,
col1 = candy1.col;
var row2 = candy2.row,
col2 = candy2.col;
// Check if adjacent
var dx = Math.abs(col1 - col2);
var dy = Math.abs(row1 - row2);
if (dx + dy !== 1) return false;
// Swap in grid
grid[row1][col1] = candy2;
grid[row2][col2] = candy1;
// Update candy properties
candy1.row = row2;
candy1.col = col2;
candy2.row = row1;
candy2.col = col1;
// Animate swap
tween(candy1, {
x: GRID_START_X + col2 * CELL_SIZE + CELL_SIZE / 2,
y: GRID_START_Y + row2 * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 200
});
tween(candy2, {
x: GRID_START_X + col1 * CELL_SIZE + CELL_SIZE / 2,
y: GRID_START_Y + row1 * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 200
});
return true;
}
function checkMatch(row, col) {
if (!grid[row] || !grid[row][col]) return [];
var candy = grid[row][col];
var matches = [candy];
var type = candy.type;
// Check horizontal
for (var c = col - 1; c >= 0 && grid[row][c] && grid[row][c].type === type; c--) {
matches.unshift(grid[row][c]);
}
for (var c = col + 1; c < GRID_SIZE && grid[row][c] && grid[row][c].type === type; c++) {
matches.push(grid[row][c]);
}
if (matches.length >= 3) return matches;
// Check vertical
matches = [candy];
for (var r = row - 1; r >= 0 && grid[r][col] && grid[r][col].type === type; r--) {
matches.unshift(grid[r][col]);
}
for (var r = row + 1; r < GRID_SIZE && grid[r][col] && grid[r][col].type === type; r++) {
matches.push(grid[r][col]);
}
return matches.length >= 3 ? matches : [];
}
function findAllMatches() {
var allMatches = [];
var processed = [];
for (var row = 0; row < GRID_SIZE; row++) {
processed[row] = [];
for (var col = 0; col < GRID_SIZE; col++) {
processed[row][col] = false;
}
}
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (!processed[row][col]) {
var matches = checkMatch(row, col);
if (matches.length >= 3) {
allMatches.push(matches);
for (var i = 0; i < matches.length; i++) {
processed[matches[i].row][matches[i].col] = true;
}
}
}
}
}
return allMatches;
}
function processMatches() {
var allMatches = findAllMatches();
if (allMatches.length === 0) {
comboMultiplier = 1;
showComboDisplay(); // Hide combo display when combo ends
isProcessing = false;
return;
}
// Process matches and create special candies
var totalScore = 0;
var totalGold = 0;
for (var m = 0; m < allMatches.length; m++) {
var matches = allMatches[m];
var matchScore = matches.length * 10 * comboMultiplier;
var matchGold = matches.length * 5;
if (comboMultiplier > 1) {
matchGold += 50; // Combo bonus
}
totalScore += matchScore;
totalGold += matchGold;
// Check for special candy creation
if (matches.length >= 6) {
// Create disco ball with visual effect
var centerCandy = matches[Math.floor(matches.length / 2)];
centerCandy.makeSpecial('discoBall');
// Add creation sparkle effect
tween(centerCandy.graphics, {
scaleX: 1.0,
scaleY: 1.0,
rotation: Math.PI
}, {
duration: 300,
easing: tween.bounceOut
});
// Add continuous rotation to disco ball with optimized performance
var _rotateDiscoBall = function rotateDiscoBall() {
if (centerCandy.isSpecial && centerCandy.specialType === 'discoBall' && centerCandy.parent) {
tween(centerCandy.graphics, {
rotation: centerCandy.graphics.rotation + Math.PI * 2
}, {
duration: 6000,
// Slower rotation for better performance
easing: tween.linear,
onFinish: function onFinish() {
// Add delay before next rotation to reduce CPU load
LK.setTimeout(_rotateDiscoBall, 100);
}
});
}
};
_rotateDiscoBall();
matches.splice(Math.floor(matches.length / 2), 1);
} else if (matches.length === 5) {
// Create special based on color with unique effects
var centerCandy = matches[2];
var color = centerCandy.type;
var specialType;
if (color === 'blue') {
specialType = 'blueBomb';
} else if (color === 'red') {
specialType = 'redRocket';
} else if (color === 'green') {
specialType = 'greenPentagon';
} else if (color === 'orange') {
specialType = 'orangeLollipop';
} else if (color === 'purple') {
// Check if this is purple candy - create black hole instead
centerCandy.makeSpecial('blackHole');
// Add black hole creation effect
tween(centerCandy.graphics, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add pulsing animation to black hole
var _pulseBlackHole2 = function _pulseBlackHole() {
if (centerCandy.isSpecial && centerCandy.specialType === 'blackHole' && centerCandy.parent) {
tween(centerCandy.graphics, {
scaleX: 1.4,
scaleY: 1.4,
alpha: 0.6
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(centerCandy.graphics, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.8
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseBlackHole2, 100);
}
});
}
});
}
};
_pulseBlackHole2();
}
});
} else {
specialType = 'purpleBerry';
}
if (color !== 'purple') {
centerCandy.makeSpecial(specialType);
}
matches.splice(2, 1);
}
// Explode remaining matches with staggered timing to reduce simultaneous animations
for (var i = 0; i < matches.length; i++) {
var candy = matches[i];
var candyRow = candy.row;
var candyCol = candy.col;
grid[candy.row][candy.col] = null;
// Stagger explosions to reduce simultaneous tween load
(function (candyToExplode, delay) {
LK.setTimeout(function () {
candyToExplode.explode();
}, delay);
})(candy, i * 100);
}
}
score += totalScore;
gold += totalGold;
comboMultiplier += 5;
showComboDisplay(); // Show updated combo display
// Update level
var newLevel = Math.floor(score / 200) + 1;
if (newLevel > level) {
level = newLevel;
// Level up animation - flash progress bar
tween(progressBarFill, {
tint: 0xFFFF00
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(progressBarFill, {
tint: 0x00FF00
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
if (level % 5 === 0) {
gold += 4000;
}
}
updateUI();
LK.getSound('match').play();
// Drop candies and continue processing
LK.setTimeout(function () {
dropCandies();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 400);
}
function dropCandies() {
// Always ensure no empty squares remain by filling all null positions
for (var col = 0; col < GRID_SIZE; col++) {
var writeRow = GRID_SIZE - 1;
// Move existing candies down
for (var row = GRID_SIZE - 1; row >= 0; row--) {
if (grid[row][col] !== null) {
// Move candy down to available position
if (row !== writeRow) {
grid[writeRow][col] = grid[row][col];
grid[row][col] = null;
grid[writeRow][col].row = writeRow;
grid[writeRow][col].col = col;
tween(grid[writeRow][col], {
y: GRID_START_Y + writeRow * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 200,
easing: tween.easeOut
});
}
writeRow--;
}
}
// Create new candies for ALL empty spaces - ensuring no empty squares remain
for (var row = writeRow; row >= 0; row--) {
var candy;
if (onlySpecialCandies) {
// Create only special candies (disco ball, rocket, bomb, black hole)
var specialTypes = ['discoBall', 'redRocket', 'blueBomb', 'blackHole'];
var randomSpecialType = specialTypes[Math.floor(Math.random() * specialTypes.length)];
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
candy = new Candy(randomColor, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
// Start candies above the visible grid area
var emptySpaces = writeRow + 1;
var startRow = row - emptySpaces;
candy.y = GRID_START_Y + startRow * CELL_SIZE + CELL_SIZE / 2;
// Make it special immediately
candy.makeSpecial(randomSpecialType);
} else {
// Normal candy creation
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
candy = new Candy(randomColor, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
// Start candies above the visible grid area
var emptySpaces = writeRow + 1;
var startRow = row - emptySpaces;
candy.y = GRID_START_Y + startRow * CELL_SIZE + CELL_SIZE / 2;
}
grid[row][col] = candy;
game.addChild(candy);
// Animate falling with bounce effect
tween(candy, {
y: GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 300 + (emptySpaces - (writeRow - row)) * 50,
easing: tween.bounceOut
});
}
}
// Double-check: Fill any remaining null positions (safety measure)
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (grid[row][col] === null) {
var candy;
if (onlySpecialCandies) {
var specialTypes = ['discoBall', 'redRocket', 'blueBomb', 'blackHole'];
var randomSpecialType = specialTypes[Math.floor(Math.random() * specialTypes.length)];
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
candy = new Candy(randomColor, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
candy.y = GRID_START_Y - CELL_SIZE; // Start slightly above
candy.makeSpecial(randomSpecialType);
} else {
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
candy = new Candy(randomColor, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
candy.y = GRID_START_Y - CELL_SIZE; // Start slightly above
}
grid[row][col] = candy;
game.addChild(candy);
// Animate to final position
tween(candy, {
y: GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 400,
easing: tween.bounceOut
});
}
}
}
// Add special bonus if entire grid was cleared
var totalCandies = 0;
for (var checkRow = 0; checkRow < GRID_SIZE; checkRow++) {
for (var checkCol = 0; checkCol < GRID_SIZE; checkCol++) {
if (grid[checkRow][checkCol] !== null) {
totalCandies++;
}
}
}
if (totalCandies === GRID_SIZE * GRID_SIZE) {
// Grid was completely refilled - give bonus
score += 5000;
gold += 2500;
updateUI();
LK.effects.flashScreen(0xFFD700, 500); // Gold flash for complete refill
}
}
function explodeCandyWithScore(candy) {
if (!candy || !candy.parent) return;
// Add score and gold for each exploding candy
var candyScore = 15 * comboMultiplier;
var candyGold = 8;
if (comboMultiplier > 1) {
candyGold += 10; // Combo bonus
}
score += candyScore;
gold += candyGold;
// Explode the candy
candy.explode();
}
function showComboDisplay() {
if (comboMultiplier > 1) {
// Update combo text
comboText.setText('COMBO x' + comboMultiplier);
// Show combo text with scale animation
comboText.alpha = 1;
comboText.scaleX = 0.5;
comboText.scaleY = 0.5;
tween(comboText, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 1
}, {
duration: 300,
easing: tween.bounceOut
});
} else {
// Hide combo text when combo ends
tween(comboText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
}
}
function updateUI() {
scoreText.setText('Score: ' + score);
levelText.setText('Level: ' + level);
goldText.setText('Gold: ' + gold);
// Save gold to storage
storage.gold = gold;
// Update progress bar
var currentLevelScore = (level - 1) * 200;
var nextLevelScore = level * 200;
var progress = (score - currentLevelScore) / (nextLevelScore - currentLevelScore);
progress = Math.max(0, Math.min(1, progress)); // Clamp between 0 and 1
// Animate progress bar fill
tween(progressBarFill, {
scaleX: progress
}, {
duration: 300,
easing: tween.easeOut
});
}
function activateSpecialCandy(candy) {
if (!candy.isSpecial) return;
var row = candy.row;
var col = candy.col;
switch (candy.specialType) {
case 'blueBomb':
// Destroy 3x3 area
for (var r = Math.max(0, row - 1); r <= Math.min(GRID_SIZE - 1, row + 1); r++) {
for (var c = Math.max(0, col - 1); c <= Math.min(GRID_SIZE - 1, col + 1); c++) {
if (grid[r][c] && grid[r][c] !== candy) {
explodeCandyWithScore(grid[r][c]);
grid[r][c] = null;
}
}
}
break;
case 'redRocket':
// Clear entire row and column
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[row][c] && grid[row][c] !== candy) {
explodeCandyWithScore(grid[row][c]);
grid[row][c] = null;
}
}
for (var r = 0; r < GRID_SIZE; r++) {
if (grid[r][col] && grid[r][col] !== candy) {
explodeCandyWithScore(grid[r][col]);
grid[r][col] = null;
}
}
break;
case 'greenPentagon':
// Destroy candies in a plus pattern (5 directions)
var directions = [[-2, 0], [-1, 0], [0, 0], [1, 0], [2, 0],
// Horizontal line
[0, -2], [0, -1], [0, 1], [0, 2] // Vertical line (excluding center)
];
for (var d = 0; d < directions.length; d++) {
var newRow = row + directions[d][0];
var newCol = col + directions[d][1];
if (newRow >= 0 && newRow < GRID_SIZE && newCol >= 0 && newCol < GRID_SIZE) {
if (grid[newRow][newCol] && grid[newRow][newCol] !== candy) {
explodeCandyWithScore(grid[newRow][newCol]);
grid[newRow][newCol] = null;
}
}
}
break;
case 'orangeLollipop':
// Destroy all candies of the same color as adjacent candies
var adjacentColors = [];
var adjacentPositions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
for (var a = 0; a < adjacentPositions.length; a++) {
var adjRow = row + adjacentPositions[a][0];
var adjCol = col + adjacentPositions[a][1];
if (adjRow >= 0 && adjRow < GRID_SIZE && adjCol >= 0 && adjCol < GRID_SIZE) {
if (grid[adjRow][adjCol] && adjacentColors.indexOf(grid[adjRow][adjCol].type) === -1) {
adjacentColors.push(grid[adjRow][adjCol].type);
}
}
}
// Destroy all candies of adjacent colors with staggered timing
var destroyIndex = 0;
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[r][c] && grid[r][c] !== candy && adjacentColors.indexOf(grid[r][c].type) !== -1) {
(function (targetCandy, delay) {
LK.setTimeout(function () {
if (targetCandy.parent) {
tween(targetCandy.graphics, {
tint: 0xFFA500
}, {
duration: 100,
onFinish: function onFinish() {
explodeCandyWithScore(targetCandy);
grid[targetCandy.row][targetCandy.col] = null;
}
});
}
}, delay);
})(grid[r][c], destroyIndex * 30);
destroyIndex++;
}
}
}
break;
case 'purpleBerry':
// Create a wave effect that spreads outward in rings
var maxDistance = 3;
for (var distance = 1; distance <= maxDistance; distance++) {
(function (dist) {
LK.setTimeout(function () {
for (var r = Math.max(0, row - dist); r <= Math.min(GRID_SIZE - 1, row + dist); r++) {
for (var c = Math.max(0, col - dist); c <= Math.min(GRID_SIZE - 1, col + dist); c++) {
// Only destroy candies on the ring edge
var actualDist = Math.max(Math.abs(r - row), Math.abs(c - col));
if (actualDist === dist && grid[r][c] && grid[r][c] !== candy) {
tween(grid[r][c].graphics, {
tint: 0x9013fe,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
onFinish: function onFinish() {
if (grid[r] && grid[r][c]) {
explodeCandyWithScore(grid[r][c]);
grid[r][c] = null;
}
}
});
}
}
}
}, (dist - 1) * 200);
})(distance);
}
break;
case 'discoBall':
// Check if we're combining with another disco ball
var adjacentDiscoBalls = [];
var adjacentPositions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
for (var a = 0; a < adjacentPositions.length; a++) {
var adjRow = row + adjacentPositions[a][0];
var adjCol = col + adjacentPositions[a][1];
if (adjRow >= 0 && adjRow < GRID_SIZE && adjCol >= 0 && adjCol < GRID_SIZE) {
if (grid[adjRow][adjCol] && grid[adjRow][adjCol].isSpecial && grid[adjRow][adjCol].specialType === 'discoBall') {
adjacentDiscoBalls.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentDiscoBalls.length > 0) {
// Disco ball + disco ball combo: destroy ALL candies on the grid
// Create massive visual effect
tween(candy.graphics, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * 4
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Destroy all candies in waves from center outward
var allCandies = [];
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[r][c] && grid[r][c] !== candy) {
// Calculate distance from center for wave effect
var distance = Math.abs(r - row) + Math.abs(c - col);
allCandies.push({
candy: grid[r][c],
distance: distance
});
}
}
}
// Sort by distance for wave effect
allCandies.sort(function (a, b) {
return a.distance - b.distance;
});
// Destroy all candies with wave timing
for (var i = 0; i < allCandies.length; i++) {
(function (candyData, index) {
LK.setTimeout(function () {
var targetCandy = candyData.candy;
if (targetCandy.parent) {
// Flash the candy bright white before exploding
tween(targetCandy.graphics, {
tint: 0xFFFFFF,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 150,
onFinish: function onFinish() {
explodeCandyWithScore(targetCandy);
grid[targetCandy.row][targetCandy.col] = null;
}
});
}
}, candyData.distance * 80 + index * 20);
})(allCandies[i], i);
}
// Add screen flash effect when all candies are destroyed
LK.setTimeout(function () {
LK.effects.flashScreen(0xFFFFFF, 500);
}, allCandies.length * 100);
}
});
} else {
// Normal disco ball activation
// Create sparkle effect on disco ball before activation
tween(candy.graphics, {
scaleX: 1.2,
scaleY: 1.2,
rotation: Math.PI * 2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Destroy 13 random candies
var randomCandies = [];
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[r][c] && grid[r][c] !== candy) {
randomCandies.push(grid[r][c]);
}
}
}
// Destroy candies with staggered timing for visual effect
var destroyCount = Math.min(13, randomCandies.length);
for (var i = 0; i < destroyCount; i++) {
(function (index) {
LK.setTimeout(function () {
if (randomCandies.length > 0) {
var randomIndex = Math.floor(Math.random() * randomCandies.length);
var randomCandy = randomCandies[randomIndex];
// Flash the candy white before exploding
tween(randomCandy.graphics, {
tint: 0xFFFFFF
}, {
duration: 100,
onFinish: function onFinish() {
explodeCandyWithScore(randomCandy);
grid[randomCandy.row][randomCandy.col] = null;
}
});
randomCandies.splice(randomIndex, 1);
}
}, index * 50);
})(i);
}
}
});
}
break;
case 'blackHole':
// Black hole: compress all candies in 8-range area into one square and explode
var blackHoleRange = 4; // 8-range means 4 cells in each direction (9x9 area total)
var candiesInRange = [];
// Collect all candies within 8-range (4 cells in each direction)
for (var r = Math.max(0, row - blackHoleRange); r <= Math.min(GRID_SIZE - 1, row + blackHoleRange); r++) {
for (var c = Math.max(0, col - blackHoleRange); c <= Math.min(GRID_SIZE - 1, col + blackHoleRange); c++) {
if (grid[r][c] && grid[r][c] !== candy) {
candiesInRange.push(grid[r][c]);
grid[r][c] = null; // Remove from grid immediately
}
}
}
// Create compression effect - move all candies to black hole center
for (var i = 0; i < candiesInRange.length; i++) {
(function (targetCandy, index) {
// Animate candy moving to black hole center
tween(targetCandy, {
x: candy.x,
y: candy.y,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.5
}, {
duration: 800 + index * 20,
// Staggered timing
easing: tween.easeIn,
onFinish: function onFinish() {
// Check if the pulled candy is special and activate it first
if (targetCandy.isSpecial) {
// Create a temporary grid position for the special candy at black hole center
var tempRow = row;
var tempCol = col;
targetCandy.row = tempRow;
targetCandy.col = tempCol;
// Activate the special candy effect
activateSpecialCandy(targetCandy);
} else {
// Explode candy with score when it reaches center
explodeCandyWithScore(targetCandy);
}
}
});
})(candiesInRange[i], i);
}
// Create visual black hole effect
tween(candy.graphics, {
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * 4,
alpha: 0.3
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Flash effect when compression is complete
LK.effects.flashScreen(0x000000, 300);
}
});
break;
}
candy.explode();
grid[row][col] = null;
updateUI(); // Update UI to show earned points
LK.getSound('powerup').play();
// Drop candies to fill empty spaces after special candy activation
LK.setTimeout(function () {
dropCandies();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 400);
}
// Variables for swipe detection
var dragStartX = 0;
var dragStartY = 0;
var dragCandy = null;
var isDragging = false;
var SWIPE_THRESHOLD = 80; // Minimum distance for swipe
game.down = function (x, y, obj) {
if (isProcessing) return;
// Check for shooting star click first (secret feature)
for (var i = 0; i < starField.children.length; i++) {
var child = starField.children[i];
if (child instanceof ShootingStar) {
// Check if click is near the shooting star
var dx = x - child.x;
var dy = y - child.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 50) {
// 50px hit radius
if (!secretMode) {
activateSecretMode();
} else {
// Return to normal game if already in secret mode
returnToNormalGame();
}
return;
}
}
}
// Handle secret mode ball clicks
if (secretMode) {
for (var i = 0; i < secretBalls.length; i++) {
var ball = secretBalls[i];
var dx = x - ball.x;
var dy = y - ball.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// Ball hit radius
handleSecretBallClick(i);
return;
}
}
return; // Don't handle normal candy clicks in secret mode
}
// Handle candy selection
var candy = getCandyAt(x, y);
if (!candy) {
// Clear selection if clicking empty space
if (selectedCandy) {
selectedCandy.graphics.tint = 0xFFFFFF;
tween(selectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
selectedCandy = null;
}
return;
}
// Handle triple click detection for disco ball transformation
var currentTime = Date.now();
var candyKey = candy.row + "_" + candy.col;
// Reset click count if too much time has passed
if (currentTime - lastClickTime > CLICK_TIMEOUT) {
clickCounts = {};
}
// Initialize or increment click count for this candy position
if (!clickCounts[candyKey]) {
clickCounts[candyKey] = 0;
}
clickCounts[candyKey]++;
lastClickTime = currentTime;
// Check for triple click
if (clickCounts[candyKey] >= 3) {
// Check if player has enough gold
if (gold >= 1000 && candy.makeSpecial) {
// Deduct gold and transform to disco ball
gold -= 1000;
storage.gold = gold;
updateUI();
// Transform candy to disco ball
candy.makeSpecial('discoBall');
// Add transformation effect
tween(candy.graphics, {
scaleX: 1.2,
scaleY: 1.2,
rotation: Math.PI * 2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Start continuous rotation
var _rotateDiscoBall2 = function rotateDiscoBall() {
if (candy.isSpecial && candy.specialType === 'discoBall' && candy.parent) {
tween(candy.graphics, {
rotation: candy.graphics.rotation + Math.PI * 2
}, {
duration: 4000,
easing: tween.linear,
onFinish: function onFinish() {
LK.setTimeout(_rotateDiscoBall2, 100);
}
});
}
};
_rotateDiscoBall2();
}
});
// Flash effect to show transformation
LK.effects.flashObject(candy, 0xFFFFFF, 500);
// Reset click count for this position
clickCounts[candyKey] = 0;
return;
} else if (gold < 1000) {
// Not enough gold - show feedback
LK.effects.flashObject(candy, 0xFF0000, 300);
clickCounts[candyKey] = 0;
return;
} else {
// Invalid object - reset click count
clickCounts[candyKey] = 0;
return;
}
}
// Click-to-select then click-to-swap mode
if (selectedCandy === null) {
// First click - select candy
selectedCandy = candy;
// Visual feedback for selected candy
candy.graphics.tint = 0x00FF00; // Green tint for selection
tween(candy, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
} else if (selectedCandy === candy) {
// Clicking same candy - deselect
selectedCandy.graphics.tint = 0xFFFFFF;
tween(selectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
selectedCandy = null;
} else {
// Second click - try to swap with selected candy
var tempSelectedCandy = selectedCandy;
// Check if candies are adjacent
var dx = Math.abs(tempSelectedCandy.col - candy.col);
var dy = Math.abs(tempSelectedCandy.row - candy.row);
if (dx + dy === 1) {
// Adjacent candies - perform swap
isProcessing = true;
// Reset visual effects
tempSelectedCandy.graphics.tint = 0xFFFFFF;
tween(tempSelectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
selectedCandy = null;
if (swapCandies(tempSelectedCandy, candy)) {
LK.setTimeout(function () {
// Check if swap creates matches
var matches1 = checkMatch(tempSelectedCandy.row, tempSelectedCandy.col);
var matches2 = checkMatch(candy.row, candy.col);
if (matches1.length >= 3 || matches2.length >= 3 || tempSelectedCandy.isSpecial || candy.isSpecial) {
// Valid move
if (tempSelectedCandy.isSpecial) {
activateSpecialCandy(tempSelectedCandy);
}
if (candy.isSpecial) {
activateSpecialCandy(candy);
}
LK.setTimeout(function () {
processMatches();
}, 200);
} else {
// Invalid move, swap back with animation
swapCandies(tempSelectedCandy, candy);
isProcessing = false;
}
}, 250);
}
} else {
// Not adjacent - switch selection to new candy
tempSelectedCandy.graphics.tint = 0xFFFFFF;
tween(tempSelectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
selectedCandy = candy;
candy.graphics.tint = 0x00FF00;
tween(candy, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
}
// Start drag tracking for drag mode (fallback)
dragStartX = x;
dragStartY = y;
dragCandy = candy;
isDragging = false;
};
game.move = function (x, y, obj) {
if (isProcessing || !dragCandy) return;
var deltaX = x - dragStartX;
var deltaY = y - dragStartY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Check if we've moved far enough to start dragging
if (distance > SWIPE_THRESHOLD && !isDragging) {
isDragging = true;
// Add visual feedback - slightly scale up the dragged candy
tween(dragCandy, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
dragCandy.graphics.tint = 0xFFFF00; // Yellow tint during drag
}
};
game.up = function (x, y, obj) {
if (isProcessing || !dragCandy) return;
var deltaX = x - dragStartX;
var deltaY = y - dragStartY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Reset visual effects
dragCandy.graphics.tint = 0xFFFFFF;
tween(dragCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
if (distance > SWIPE_THRESHOLD) {
// Determine swipe direction
var targetCandy = null;
var absX = Math.abs(deltaX);
var absY = Math.abs(deltaY);
if (absX > absY) {
// Horizontal swipe
if (deltaX > 0) {
// Swipe right
if (dragCandy.col < GRID_SIZE - 1) {
targetCandy = grid[dragCandy.row][dragCandy.col + 1];
}
} else {
// Swipe left
if (dragCandy.col > 0) {
targetCandy = grid[dragCandy.row][dragCandy.col - 1];
}
}
} else {
// Vertical swipe
if (deltaY > 0) {
// Swipe down
if (dragCandy.row < GRID_SIZE - 1) {
targetCandy = grid[dragCandy.row + 1][dragCandy.col];
}
} else {
// Swipe up
if (dragCandy.row > 0) {
targetCandy = grid[dragCandy.row - 1][dragCandy.col];
}
}
}
// If we have a valid target, try to swap
if (targetCandy) {
var tempSelectedCandy = dragCandy;
selectedCandy = null;
isProcessing = true;
if (swapCandies(tempSelectedCandy, targetCandy)) {
LK.setTimeout(function () {
// Check if swap creates matches
var matches1 = checkMatch(tempSelectedCandy.row, tempSelectedCandy.col);
var matches2 = checkMatch(targetCandy.row, targetCandy.col);
if (matches1.length >= 3 || matches2.length >= 3 || tempSelectedCandy.isSpecial || targetCandy.isSpecial) {
// Valid move
if (tempSelectedCandy.isSpecial) {
activateSpecialCandy(tempSelectedCandy);
}
if (targetCandy.isSpecial) {
activateSpecialCandy(targetCandy);
}
LK.setTimeout(function () {
processMatches();
}, 200);
} else {
// Invalid move, swap back with animation
swapCandies(tempSelectedCandy, targetCandy);
isProcessing = false;
}
}, 250);
}
}
}
// Reset drag state
dragCandy = null;
dragStartX = 0;
dragStartY = 0;
isDragging = false;
selectedCandy = null;
};
function activateSecretMode() {
secretMode = true;
secretClickSequence = [];
// Backup current grid state
secretGridBackup = [];
for (var row = 0; row < GRID_SIZE; row++) {
secretGridBackup[row] = [];
for (var col = 0; col < GRID_SIZE; col++) {
secretGridBackup[row][col] = grid[row][col];
}
}
// Clear everything from screen
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (grid[row][col] && grid[row][col].parent) {
grid[row][col].parent.removeChild(grid[row][col]);
}
grid[row][col] = null;
}
}
// Hide UI elements
tween(scoreText, {
alpha: 0
}, {
duration: 300
});
tween(levelText, {
alpha: 0
}, {
duration: 300
});
tween(goldText, {
alpha: 0
}, {
duration: 300
});
tween(comboText, {
alpha: 0
}, {
duration: 300
});
tween(progressBarBg, {
alpha: 0
}, {
duration: 300
});
// Create 4 secret balls in sequence positions
createSecretBalls();
}
function createSecretBalls() {
secretBalls = [];
var positions = [{
x: 512,
y: 683
},
// Top left quadrant
{
x: 1536,
y: 683
},
// Top right quadrant
{
x: 512,
y: 2049
},
// Bottom left quadrant
{
x: 1536,
y: 2049
} // Bottom right quadrant
];
for (var i = 0; i < 4; i++) {
var ball = LK.getAsset('discoBall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
x: positions[i].x,
y: positions[i].y
});
game.addChild(ball);
secretBalls.push(ball);
// Add number text on top of each ball
var numberText = new Text2((i + 1).toString(), {
size: 120,
fill: '#FFFFFF'
});
numberText.anchor.set(0.5, 0.5);
numberText.x = positions[i].x;
numberText.y = positions[i].y - 150; // Position above the ball
game.addChild(numberText);
ball.numberText = numberText; // Store reference for cleanup
// Add continuous rotation
var _rotateBall = function rotateBall(ballRef) {
tween(ballRef, {
rotation: ballRef.rotation + Math.PI * 2
}, {
duration: 3000,
easing: tween.linear,
onFinish: function onFinish() {
if (secretMode) {
_rotateBall(ballRef);
}
}
});
};
_rotateBall(ball);
}
// Create black hole in center
var blackHole = LK.getAsset('blackHole', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
x: 1024,
// Center of screen
y: 1366 // Center of screen
});
game.addChild(blackHole);
secretBalls.push(blackHole); // Add to secretBalls for cleanup
// Add pulsing animation to black hole
var _pulseBlackHole = function pulseBlackHole() {
tween(blackHole, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 0.7
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(blackHole, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (secretMode) {
_pulseBlackHole();
}
}
});
}
});
};
_pulseBlackHole();
}
function handleSecretBallClick(ballIndex) {
secretClickSequence.push(ballIndex);
// Flash the clicked ball
var ball = secretBalls[ballIndex];
tween(ball, {
tint: 0xFFFFFF,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(ball, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
// Check if sequence is correct: 1st ball, 1st ball, 1st ball, 3rd ball (indices 0,0,0,2)
if (secretClickSequence.length >= 4) {
if (secretClickSequence[0] === 0 && secretClickSequence[1] === 0 && secretClickSequence[2] === 0 && secretClickSequence[3] === 2) {
// Correct sequence - restore game with special candies
restoreGameWithSpecialCandies();
} else {
// Wrong sequence - reset
secretClickSequence = [];
}
}
}
function restoreGameWithSpecialCandies() {
// Remove secret balls and their number texts
for (var i = 0; i < secretBalls.length; i++) {
if (secretBalls[i].parent) {
secretBalls[i].parent.removeChild(secretBalls[i]);
}
// Remove the number text as well
if (secretBalls[i].numberText && secretBalls[i].numberText.parent) {
secretBalls[i].numberText.parent.removeChild(secretBalls[i].numberText);
}
}
secretBalls = [];
// Restore grid with only special candies
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
var specialTypes = ['discoBall', 'redRocket', 'blueBomb', 'blackHole'];
var randomSpecialType = specialTypes[Math.floor(Math.random() * specialTypes.length)];
// Create candy with original color but make it special
var originalColor = COLORS[Math.floor(Math.random() * COLORS.length)];
var candy = new Candy(originalColor, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
candy.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2;
// Make it special immediately
candy.makeSpecial(randomSpecialType);
grid[row][col] = candy;
game.addChild(candy);
}
}
// Show UI elements again
tween(scoreText, {
alpha: 1
}, {
duration: 300
});
tween(levelText, {
alpha: 1
}, {
duration: 300
});
tween(goldText, {
alpha: 1
}, {
duration: 300
});
tween(progressBarBg, {
alpha: 1
}, {
duration: 300
});
// Set 20x score multiplier for matches
comboMultiplier = 20;
showComboDisplay();
// Activate special candy spawning mode
onlySpecialCandies = true;
secretMode = false;
isProcessing = false;
}
function returnToNormalGame() {
// Remove secret balls and their number texts
for (var i = 0; i < secretBalls.length; i++) {
if (secretBalls[i].parent) {
secretBalls[i].parent.removeChild(secretBalls[i]);
}
// Remove the number text as well
if (secretBalls[i].numberText && secretBalls[i].numberText.parent) {
secretBalls[i].numberText.parent.removeChild(secretBalls[i].numberText);
}
}
secretBalls = [];
// Clear current grid completely before restoring
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (grid[row][col] && grid[row][col].parent) {
grid[row][col].parent.removeChild(grid[row][col]);
}
grid[row][col] = null;
}
}
// Restore original grid state from backup
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (secretGridBackup && secretGridBackup[row] && secretGridBackup[row][col]) {
var originalCandy = secretGridBackup[row][col];
originalCandy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
originalCandy.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2;
grid[row][col] = originalCandy;
game.addChild(originalCandy);
}
}
}
// Show UI elements again
tween(scoreText, {
alpha: 1
}, {
duration: 300
});
tween(levelText, {
alpha: 1
}, {
duration: 300
});
tween(goldText, {
alpha: 1
}, {
duration: 300
});
tween(progressBarBg, {
alpha: 1
}, {
duration: 300
});
// Reset to normal game state
comboMultiplier = 1;
showComboDisplay();
onlySpecialCandies = false;
secretMode = false;
isProcessing = false;
secretGridBackup = null;
}
// Initialize the game
initializeGrid();
updateUI();
LK.playMusic('bgmusic');
; ===================================================================
--- original.js
+++ change.js
@@ -575,63 +575,9 @@
}, 300);
}, 400);
}
function dropCandies() {
- // Check if entire grid is empty (all candies destroyed)
- var totalCandies = 0;
- for (var checkRow = 0; checkRow < GRID_SIZE; checkRow++) {
- for (var checkCol = 0; checkCol < GRID_SIZE; checkCol++) {
- if (grid[checkRow][checkCol] !== null) {
- totalCandies++;
- }
- }
- }
- // If grid is completely empty, refill entire grid
- if (totalCandies === 0) {
- // Add big bonus for clearing entire grid
- score += 10000;
- gold += 5000;
- updateUI();
- LK.effects.flashScreen(0xFFD700, 1000); // Gold flash for grid clear bonus
- // Create new candies for entire grid
- for (var row = 0; row < GRID_SIZE; row++) {
- for (var col = 0; col < GRID_SIZE; col++) {
- var candy;
- if (onlySpecialCandies) {
- // Create only special candies (disco ball, rocket, bomb, black hole)
- var specialTypes = ['discoBall', 'redRocket', 'blueBomb', 'blackHole'];
- var randomSpecialType = specialTypes[Math.floor(Math.random() * specialTypes.length)];
- var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
- candy = new Candy(randomColor, row, col);
- candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
- // Start all candies well above the visible grid area
- candy.y = GRID_START_Y - (GRID_SIZE + 2 - row) * CELL_SIZE;
- // Make it special immediately
- candy.makeSpecial(randomSpecialType);
- } else {
- // Normal candy creation
- var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
- candy = new Candy(randomColor, row, col);
- candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
- // Start all candies well above the visible grid area
- candy.y = GRID_START_Y - (GRID_SIZE + 2 - row) * CELL_SIZE;
- }
- grid[row][col] = candy;
- game.addChild(candy);
- // Animate falling with staggered timing for natural cascade effect
- var fallDelay = col * 100 + row * 50;
- var fallDuration = 600 + row * 100;
- tween(candy, {
- y: GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2
- }, {
- duration: fallDuration,
- easing: tween.bounceOut
- });
- }
- }
- return; // Exit early since we refilled the entire grid
- }
- // Normal drop candy logic for partial empty spaces
+ // Always ensure no empty squares remain by filling all null positions
for (var col = 0; col < GRID_SIZE; col++) {
var writeRow = GRID_SIZE - 1;
// Move existing candies down
for (var row = GRID_SIZE - 1; row >= 0; row--) {
@@ -651,10 +597,9 @@
}
writeRow--;
}
}
- // Create new candies for empty spaces - they fall from above
- var emptySpaces = writeRow + 1; // Number of empty spaces from top
+ // Create new candies for ALL empty spaces - ensuring no empty squares remain
for (var row = writeRow; row >= 0; row--) {
var candy;
if (onlySpecialCandies) {
// Create only special candies (disco ball, rocket, bomb, black hole)
@@ -663,8 +608,9 @@
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
candy = new Candy(randomColor, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
// Start candies above the visible grid area
+ var emptySpaces = writeRow + 1;
var startRow = row - emptySpaces;
candy.y = GRID_START_Y + startRow * CELL_SIZE + CELL_SIZE / 2;
// Make it special immediately
candy.makeSpecial(randomSpecialType);
@@ -673,8 +619,9 @@
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
candy = new Candy(randomColor, row, col);
candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
// Start candies above the visible grid area
+ var emptySpaces = writeRow + 1;
var startRow = row - emptySpaces;
candy.y = GRID_START_Y + startRow * CELL_SIZE + CELL_SIZE / 2;
}
grid[row][col] = candy;
@@ -687,8 +634,55 @@
easing: tween.bounceOut
});
}
}
+ // Double-check: Fill any remaining null positions (safety measure)
+ for (var row = 0; row < GRID_SIZE; row++) {
+ for (var col = 0; col < GRID_SIZE; col++) {
+ if (grid[row][col] === null) {
+ var candy;
+ if (onlySpecialCandies) {
+ var specialTypes = ['discoBall', 'redRocket', 'blueBomb', 'blackHole'];
+ var randomSpecialType = specialTypes[Math.floor(Math.random() * specialTypes.length)];
+ var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
+ candy = new Candy(randomColor, row, col);
+ candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
+ candy.y = GRID_START_Y - CELL_SIZE; // Start slightly above
+ candy.makeSpecial(randomSpecialType);
+ } else {
+ var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
+ candy = new Candy(randomColor, row, col);
+ candy.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
+ candy.y = GRID_START_Y - CELL_SIZE; // Start slightly above
+ }
+ grid[row][col] = candy;
+ game.addChild(candy);
+ // Animate to final position
+ tween(candy, {
+ y: GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2
+ }, {
+ duration: 400,
+ easing: tween.bounceOut
+ });
+ }
+ }
+ }
+ // Add special bonus if entire grid was cleared
+ var totalCandies = 0;
+ for (var checkRow = 0; checkRow < GRID_SIZE; checkRow++) {
+ for (var checkCol = 0; checkCol < GRID_SIZE; checkCol++) {
+ if (grid[checkRow][checkCol] !== null) {
+ totalCandies++;
+ }
+ }
+ }
+ if (totalCandies === GRID_SIZE * GRID_SIZE) {
+ // Grid was completely refilled - give bonus
+ score += 5000;
+ gold += 2500;
+ updateUI();
+ LK.effects.flashScreen(0xFFD700, 500); // Gold flash for complete refill
+ }
}
function explodeCandyWithScore(candy) {
if (!candy || !candy.parent) return;
// Add score and gold for each exploding candy