User prompt
test sürümünü kaldır
User prompt
5 mavi şeker bileşirse donşturucu oluşur donuşturucu hangi renk şekerle kombalanırsa o şeker 5 aynı şekerle kombolqanmış sayılır ve bomba kara delik roket gibi itemler oluşturulur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kırmızı roket ile disko topu birleşirse şeker patlaması olmaz sadece butun şekerler rasgele bir sekere donuşur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
test amaçlı başlangıçta yan yana 1 disko topu 1 kırmıı roket ile başlasın
User prompt
disko topu ile kırmızı roket birleşire butun şekerler random bir seker turune donuşur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Test modülü kaldır
User prompt
supernowayı baştakini kaldır
User prompt
test mdunu kaldır
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'scoreText.style.fill = '#FFFFFF';' Line Number: 1076
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'tween(star, {' Line Number: 159 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'tween(star, {' Line Number: 159 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'tween(star, {' Line Number: 159 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
deneme amaçlı oyundkai tum ozelliklere erişebilim
User prompt
mapte yeşil supernowa buyuk olan ondan
User prompt
yeşil supernowa başlangıçta bi tane mapte olsun
User prompt
ultra suprnowa yeşil çevreli olan test amaçlı sürükleyip istediğim yere koyabilim
User prompt
marketi sil
User prompt
%5 sans ile mor meyve gelir
User prompt
Deneme modu sonsuz para
User prompt
Disko topu ile mor birleşirse beyaz parlayan vripers ortaya çıkar vriper herkesle kombalanabilir ve kombalaninca kombalanan renk tüm taşlar beyaz çembere parlar sonra beyaz çemberi bi şeker başka bi şekerle kombalanirsa beyaz çemberi şekerler yok olur beyaz çemberi şekerle beyaz çemberi kombalanirsa disko topu oluşur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Lefekler her seviye atandığını kaç seviye olduğu ekranda belirir gider sugercrush yazar
User prompt
Gizli sekmedeyken tekrar yıldıza tıklanırsa başa döner
User prompt
Her seviye için gereken store 4x katlansın
User prompt
Please fix the bug: 'getRequiredScoreForLevel is not defined' in or related to this line: 'tween(star, {' Line Number: 141 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'getRequiredScoreForLevel is not defined' in or related to this line: 'tween(star, {' Line Number: 141 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
inventory: {},
gold: 0
});
/****
* 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',
'supernova': 'supernova',
'expires': 'expires',
'writerpir': 'writerpir',
'vriper': 'vriper'
};
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;
// Stop any existing pattern animations by stopping all tweens on graphics
if (self.graphics) {
tween.stop(self.graphics);
}
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: 200,
easing: tween.easeInOut,
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
****/
// Define getRequiredScoreForLevel function in global scope
function getRequiredScoreForLevel(targetLevel) {
if (targetLevel <= 1) return 0;
if (targetLevel === 2) return 50000;
// For levels 3+: 50000 * 4^(level-2)
return 50000 * Math.pow(4, targetLevel - 2);
}
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 = 0;
// Reset gold to starting value
storage.gold = gold;
var inventory = {};
// Reset inventory to empty
storage.inventory = inventory;
var isProcessing = false;
var comboMultiplier = 1;
// 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: 150,
easing: tween.easeOut
});
tween(candy2, {
x: GRID_START_X + col1 * CELL_SIZE + CELL_SIZE / 2,
y: GRID_START_Y + row1 * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 150,
easing: tween.easeOut
});
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 check4x4Formations() {
var formationsFound = false;
// Check all possible 4x4 positions
for (var row = 0; row <= GRID_SIZE - 4; row++) {
for (var col = 0; col <= GRID_SIZE - 4; col++) {
// Check if all 16 positions in the 4x4 area have candies of same type
var firstCandy = grid[row][col];
if (!firstCandy) continue;
var sameType = true;
var formationCandies = [];
// Check all positions in the 4x4 area
for (var r = row; r < row + 4; r++) {
for (var c = col; c < col + 4; c++) {
var currentCandy = grid[r][c];
if (!currentCandy || currentCandy.type !== firstCandy.type) {
sameType = false;
break;
}
formationCandies.push(currentCandy);
}
if (!sameType) break;
}
if (sameType && formationCandies.length === 16) {
// Found a 4x4 formation - trigger horizontal and vertical clearing
formationsFound = true;
// Get the center position of the 4x4 formation
var centerRow = row + 1;
var centerCol = col + 2;
// Clear entire row of the center
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[centerRow][c] && grid[centerRow][c] !== null) {
explodeCandyWithScore(grid[centerRow][c]);
grid[centerRow][c] = null;
}
}
// Clear entire column of the center
for (var r = 0; r < GRID_SIZE; r++) {
if (grid[r][centerCol] && grid[r][centerCol] !== null) {
explodeCandyWithScore(grid[r][centerCol]);
grid[r][centerCol] = null;
}
}
// Add massive bonus for 4x4 formation
score += 5000;
gold += 2500;
comboMultiplier += 10;
updateUI();
// Create spectacular visual effect
LK.effects.flashScreen(0xFFD700, 1000);
LK.getSound('powerup').play();
// Break out of loops since we found a formation
return formationsFound;
}
}
}
return formationsFound;
}
function checkBlackHoleCombinations() {
var combinationsFound = false;
// Check all grid positions for adjacent black holes
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
var candy = grid[row][col];
if (candy && candy.isSpecial && candy.specialType === 'blackHole') {
// Check adjacent positions for other black holes
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) {
var adjacentCandy = grid[adjRow][adjCol];
if (adjacentCandy && adjacentCandy.isSpecial && adjacentCandy.specialType === 'blackHole') {
// Found two adjacent black holes - combine them into supernova
combinationsFound = true;
// Invalidate special properties of both black holes before combining
candy.isSpecial = false;
candy.specialType = null;
adjacentCandy.isSpecial = false;
adjacentCandy.specialType = null;
// Transform first black hole into supernova
candy.makeSpecial('supernova');
// Remove second black hole
grid[adjRow][adjCol] = null;
adjacentCandy.explode();
// Ensure the supernova stays in the grid and is not processed for removal
candy.justCreated = true;
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0xFFD700,
rotation: Math.PI * 6
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add continuous pulsing glow effect
var _pulseSuperNova2 = function pulseSuperNova() {
if (candy && candy.isSpecial && candy.specialType === 'supernova' && candy.parent) {
tween(candy.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFF00
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(candy.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFFFF
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseSuperNova2, 200);
}
});
}
});
}
};
_pulseSuperNova2();
LK.effects.flashScreen(0xFFD700, 800);
}
});
// Add bonus score for combination
score += 3000;
gold += 1500;
updateUI();
LK.getSound('powerup').play();
// Skip checking other adjacent positions for this candy
break;
}
}
}
}
}
}
return combinationsFound;
}
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 >= 7) {
// Create supernova with visual effect but don't activate it
var centerCandy = matches[Math.floor(matches.length / 2)];
centerCandy.makeSpecial('supernova');
// Add creation sparkle effect
tween(centerCandy.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFFFF
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Add continuous pulsing glow effect
var _pulseSuperNova = function pulseSuperNova() {
if (centerCandy && centerCandy.isSpecial && centerCandy.specialType === 'supernova' && centerCandy.parent) {
tween(centerCandy.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFF00
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(centerCandy.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFFFF
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseSuperNova, 200);
}
});
}
});
}
};
_pulseSuperNova();
}
});
// Don't remove the supernova from matches - keep it on the board
// Skip removing the supernova so it stays on the grid
var centerIndex = Math.floor(matches.length / 2);
matches.splice(centerIndex, 1);
} else 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
var newLevel = 1;
// Calculate required score for next level (50000 for level 2, then quadruple each time)
function getRequiredScoreForLevel(targetLevel) {
if (targetLevel <= 1) return 0;
if (targetLevel === 2) return 50000;
// For levels 3+: 50000 * 4^(level-2)
return 50000 * Math.pow(4, targetLevel - 2);
}
// Update level based on new progression system
while (score >= getRequiredScoreForLevel(newLevel + 1)) {
newLevel++;
}
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
});
}
});
// Show level up notification
showLevelUpNotification(level);
if (level % 5 === 0) {
gold += 4000;
}
}
updateUI();
LK.getSound('match').play();
// Check for 4x4 formations before black hole combinations
check4x4Formations();
// Check for black hole combinations before dropping candies
checkBlackHoleCombinations();
// 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] && grid[row][col] !== null && grid[row][col] !== undefined) {
// Move candy down to available position
if (row !== writeRow) {
var candyToMove = grid[row][col];
grid[writeRow][col] = candyToMove;
grid[row][col] = null;
if (candyToMove) {
candyToMove.row = writeRow;
candyToMove.col = col;
tween(candyToMove, {
y: GRID_START_Y + writeRow * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 150,
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, supernova)
var specialTypes = ['discoBall', 'redRocket', 'blueBomb', 'blackHole', 'supernova', 'expires', 'writerpir', 'vriper'];
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: 200 + (emptySpaces - (writeRow - row)) * 30,
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', 'supernova', 'expires', 'writerpir', 'vriper'];
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: 250,
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;
// Stop any existing tweens on this candy to prevent conflicts
tween.stop(candy);
if (candy.graphics) {
tween.stop(candy.graphics);
}
// 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: 200,
easing: tween.easeInOut
});
} else {
// Hide combo text when combo ends
tween(comboText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
}
}
function updateUI() {
// Load gold from storage to ensure synchronization
gold = storage.gold || 0;
scoreText.setText('Score: ' + score);
levelText.setText('Level: ' + level);
goldText.setText('Gold: ' + gold);
// Save gold to storage
storage.gold = gold;
// Update progress bar using new level progression system
var currentLevelScore = getRequiredScoreForLevel(level);
var nextLevelScore = getRequiredScoreForLevel(level + 1);
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: 200,
easing: tween.easeInOut
});
}
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 purple candy first
var adjacentPurpleCandies = [];
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].type === 'purple' && !grid[adjRow][adjCol].isSpecial) {
adjacentPurpleCandies.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentPurpleCandies.length > 0) {
// Disco ball + purple combo: create white shining vriper
var purpleCandy = adjacentPurpleCandies[0];
// Transform this disco ball into vriper
candy.makeSpecial('vriper');
// Remove purple candy
grid[purpleCandy.row][purpleCandy.col] = null;
purpleCandy.explode();
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFFFFF,
rotation: Math.PI * 4
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add continuous white shining effect
var _shineVriper = function shineVriper() {
if (candy && candy.isSpecial && candy.specialType === 'vriper' && candy.parent) {
tween(candy.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFFFF,
alpha: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(candy.graphics, {
scaleX: 1.1,
scaleY: 1.1,
tint: 0xF0F0F0,
alpha: 0.9
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_shineVriper, 100);
}
});
}
});
}
};
_shineVriper();
LK.effects.flashScreen(0xFFFFFF, 800);
}
});
// Add bonus score for combination
score += 4000;
gold += 2000;
updateUI();
LK.getSound('powerup').play();
break;
}
// Check if we're combining with another disco ball
var adjacentDiscoBalls = [];
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;
});
// Clear grid immediately to prevent null reference errors
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[r][c] && grid[r][c] !== candy) {
grid[r][c] = null;
}
}
}
// 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 && 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);
}
});
}
}, 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);
// After the flash effect, drop new candies to fill the entire grid
LK.setTimeout(function () {
dropCandies();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 500);
}, allCandies.length * 100 + 500);
}
});
} 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 'supernova':
// Check if we're combining with 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) {
// Supernova + Disco Ball combo: create writerpir (they disappear and writerpir appears)
var discoBallCandy = adjacentDiscoBalls[0];
// Transform this supernova into writerpir
candy.makeSpecial('writerpir');
// Remove disco ball
grid[discoBallCandy.row][discoBallCandy.col] = null;
discoBallCandy.explode();
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0x8B0000,
rotation: Math.PI * 6
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.effects.flashScreen(0x8B0000, 800);
}
});
break;
}
// Normal supernova: massive explosion that destroys everything on the grid in expanding waves
// Create expanding wave effect that destroys the entire grid
var maxWaves = Math.max(GRID_SIZE, GRID_SIZE);
for (var wave = 1; wave <= maxWaves; wave++) {
(function (waveDistance) {
LK.setTimeout(function () {
var candiesInWave = [];
// Collect all candies at this wave distance
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
var distance = Math.max(Math.abs(r - row), Math.abs(c - col));
if (distance === waveDistance && grid[r][c] && grid[r][c] !== candy) {
candiesInWave.push(grid[r][c]);
grid[r][c] = null; // Remove from grid immediately
}
}
}
// Destroy all candies in this wave with spectacular effect
for (var i = 0; i < candiesInWave.length; i++) {
(function (targetCandy, index) {
if (targetCandy && targetCandy.parent) {
// If the target candy is special, activate it first
if (targetCandy.isSpecial) {
// Create a temporary position for the special candy
var tempRow = targetCandy.row;
var tempCol = targetCandy.col;
// Activate the special candy effect
activateSpecialCandy(targetCandy);
} else {
// Flash bright gold then explode
tween(targetCandy.graphics, {
tint: 0xFFD700,
scaleX: 1.8,
scaleY: 1.8,
alpha: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
explodeCandyWithScore(targetCandy);
}
});
}
}
})(candiesInWave[i], i);
}
}, waveDistance * 150); // Stagger waves
})(wave);
}
// Create supernova visual effect
tween(candy.graphics, {
scaleX: 3.0,
scaleY: 3.0,
tint: 0xFFFFFF,
alpha: 0.8,
rotation: Math.PI * 6
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Massive screen flash when supernova completes
LK.effects.flashScreen(0xFFD700, 1000);
// Give massive bonus for supernova activation
score += 10000;
gold += 5000;
updateUI();
}
});
break;
case 'expires':
// Check if we're combining with black hole
var adjacentBlackHoles = [];
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 === 'blackHole') {
adjacentBlackHoles.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentBlackHoles.length > 0) {
// Expires + Black Hole combo: create writerpir
var blackHoleCandy = adjacentBlackHoles[0];
// Transform this expires into writerpir
candy.makeSpecial('writerpir');
// Remove black hole
grid[blackHoleCandy.row][blackHoleCandy.col] = null;
blackHoleCandy.explode();
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0x8B0000,
rotation: Math.PI * 6
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.effects.flashScreen(0x8B0000, 800);
}
});
break;
}
// Normal expires: turn all candies into red rockets
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[r][c] && grid[r][c] !== candy) {
var targetCandy = grid[r][c];
// Transform to red rocket with delay
(function (candyToTransform, delay) {
LK.setTimeout(function () {
if (candyToTransform && candyToTransform.parent) {
candyToTransform.makeSpecial('redRocket');
tween(candyToTransform.graphics, {
tint: 0xFF0000,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut
});
}
}, delay);
})(targetCandy, (r + c) * 50);
}
}
}
// Create expires visual effect
tween(candy.graphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0xFF4500,
rotation: Math.PI * 4
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.effects.flashScreen(0xFF4500, 500);
score += 8000;
gold += 4000;
updateUI();
}
});
break;
case 'writerpir':
// Writerpir: turn entire map into supernovas when it explodes
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[r][c] && grid[r][c] !== candy) {
var targetCandy = grid[r][c];
// Transform to supernova with spectacular delay
(function (candyToTransform, delay) {
LK.setTimeout(function () {
if (candyToTransform && candyToTransform.parent) {
candyToTransform.makeSpecial('supernova');
// Add supernova creation effect
tween(candyToTransform.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Add continuous pulsing glow effect
var _pulseSuperNova = function pulseSuperNova() {
if (candyToTransform && candyToTransform.isSpecial && candyToTransform.specialType === 'supernova' && candyToTransform.parent) {
tween(candyToTransform.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFF00
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(candyToTransform.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseSuperNova, 200);
}
});
}
});
}
};
_pulseSuperNova();
}
});
}
}, delay);
})(targetCandy, (r + c) * 80);
}
}
}
// Create writerpir visual effect
tween(candy.graphics, {
scaleX: 3.5,
scaleY: 3.5,
tint: 0x8B0000,
rotation: Math.PI * 8,
alpha: 0.9
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.effects.flashScreen(0x8B0000, 1000);
score += 15000;
gold += 8000;
updateUI();
}
});
break;
case 'blackHole':
// Check if we're combining with another black hole
var adjacentBlackHoles = [];
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 === 'blackHole') {
adjacentBlackHoles.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentBlackHoles.length > 0) {
// Black hole + black hole combo: create supernova
var otherBlackHole = adjacentBlackHoles[0];
// Transform this black hole into supernova
candy.makeSpecial('supernova');
// Remove other black hole
grid[otherBlackHole.row][otherBlackHole.col] = null;
otherBlackHole.explode();
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0xFFD700,
rotation: Math.PI * 6
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add continuous pulsing glow effect
var _pulseSuperNova = function pulseSuperNova() {
if (candy && candy.isSpecial && candy.specialType === 'supernova' && candy.parent) {
tween(candy.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFF00
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(candy.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFFFF
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseSuperNova, 200);
}
});
}
});
}
};
_pulseSuperNova();
LK.effects.flashScreen(0xFFD700, 800);
}
});
break;
}
// Normal 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) {
// Validate candy still exists before animating
if (targetCandy && targetCandy.parent) {
// 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 candy still exists before processing
if (targetCandy && targetCandy.parent) {
// 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;
case 'vriper':
// First check for vriper + vriper combination
var adjacentVripers = [];
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 === 'vriper') {
adjacentVripers.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentVripers.length > 0) {
// Vriper + vriper combo: both disappear and create disco ball
var otherVriper = adjacentVripers[0];
// Transform this vriper into disco ball
candy.makeSpecial('discoBall');
// Remove other vriper
grid[otherVriper.row][otherVriper.col] = null;
otherVriper.explode();
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFFFFF,
rotation: Math.PI * 4
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add continuous rotation to disco ball
var _rotateDiscoBall = function rotateDiscoBall() {
if (candy.isSpecial && candy.specialType === 'discoBall' && candy.parent) {
tween(candy.graphics, {
rotation: candy.graphics.rotation + Math.PI * 2
}, {
duration: 6000,
easing: tween.linear,
onFinish: function onFinish() {
LK.setTimeout(_rotateDiscoBall, 100);
}
});
}
};
_rotateDiscoBall();
LK.effects.flashScreen(0xFFFFFF, 800);
}
});
// Add bonus score for combination
score += 6000;
gold += 3000;
updateUI();
LK.getSound('powerup').play();
break;
}
// Vriper: can combine with any color candy to destroy all candies of that color
// Check adjacent positions for any candy (not special)
var adjacentCandies = [];
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) {
adjacentCandies.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentCandies.length > 0) {
// Combine with first adjacent candy
var targetCandy = adjacentCandies[0];
var targetColor = targetCandy.type;
// Create white circle effect that expands
tween(candy.graphics, {
scaleX: 4.0,
scaleY: 4.0,
alpha: 0.3,
tint: 0xFFFFFF
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
// After white circle expansion, destroy all candies of target color
var candiesOfTargetColor = [];
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
if (grid[r][c] && grid[r][c].type === targetColor && grid[r][c] !== candy) {
candiesOfTargetColor.push(grid[r][c]);
grid[r][c] = null;
}
}
}
// Destroy all candies of target color with white flash effect
for (var i = 0; i < candiesOfTargetColor.length; i++) {
(function (candyToDestroy, index) {
LK.setTimeout(function () {
if (candyToDestroy && candyToDestroy.parent) {
// Flash white before exploding
tween(candyToDestroy.graphics, {
tint: 0xFFFFFF,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
explodeCandyWithScore(candyToDestroy);
}
});
}
}, index * 50);
})(candiesOfTargetColor[i], i);
}
// Create disco ball at vriper position when vriper + candy combination is complete
LK.setTimeout(function () {
if (candy && candy.parent) {
candy.makeSpecial('discoBall');
// Add creation sparkle effect
tween(candy.graphics, {
scaleX: 1.0,
scaleY: 1.0,
rotation: Math.PI,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
}
}, candiesOfTargetColor.length * 50 + 500);
}
});
// Add massive bonus for vriper activation
score += 8000;
gold += 4000;
updateUI();
LK.effects.flashScreen(0xFFFFFF, 1000);
LK.getSound('powerup').play();
break;
}
// Normal vriper without adjacent candies - just shine
tween(candy.graphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFFFFF,
alpha: 0.8
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(candy.graphics, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 1.0
}, {
duration: 500,
easing: tween.easeOut
});
}
});
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) {
// Check for market button click
var marketPos = LK.gui.bottom.toGlobal({
x: 0,
y: -50
});
var gameMarketPos = game.toLocal(marketPos);
var marketDx = x - gameMarketPos.x;
var marketDy = y - gameMarketPos.y;
var marketDistance = Math.sqrt(marketDx * marketDx + marketDy * marketDy);
if (marketDistance < 100) {
if (!isMarketOpen) {
openMarket();
} else {
closeMarket();
}
return;
}
// Check for market screen interactions
if (isMarketOpen && marketScreen) {
// Check close button
if (marketScreen.closeButton) {
var closeBtnPos = marketScreen.toGlobal(marketScreen.closeButton.position);
var gameClosePos = game.toLocal(closeBtnPos);
var closeDx = x - gameClosePos.x;
var closeDy = y - gameClosePos.y;
var closeDistance = Math.sqrt(closeDx * closeDx + closeDy * closeDy);
if (closeDistance < 100) {
closeMarket();
return;
}
}
// Check buy buttons
for (var i = 0; i < marketScreen.itemButtons.length; i++) {
var button = marketScreen.itemButtons[i];
var btnPos = marketScreen.toGlobal(button.position);
var gameBtnPos = game.toLocal(btnPos);
var btnDx = x - gameBtnPos.x;
var btnDy = y - gameBtnPos.y;
var btnDistance = Math.sqrt(btnDx * btnDx + btnDy * btnDy);
if (btnDistance < 120 && button.canAfford) {
buyMarketItem(button.itemIndex);
return;
}
}
return; // Don't process other clicks while market is open
}
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 beginning of game if already in secret mode
restartGame();
}
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;
}
// Add shrinking animation when candy is clicked
tween(candy, {
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
tween(candy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 150,
easing: tween.bounceOut
});
}
});
// Click-to-select then click-to-swap mode
if (selectedCandy === null) {
// Check if clicking on a supernova - activate it directly
if (candy.isSpecial && candy.specialType === 'supernova') {
isProcessing = true;
activateSpecialCandy(candy);
return;
}
// 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 or activate special
var tempSelectedCandy = selectedCandy;
// Check if clicking on a supernova - activate it directly
if (candy.isSpecial && candy.specialType === 'supernova') {
selectedCandy.graphics.tint = 0xFFFFFF;
tween(selectedCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
selectedCandy = null;
isProcessing = true;
activateSpecialCandy(candy);
return;
}
// 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 && tempSelectedCandy.specialType !== 'supernova' || candy.isSpecial && candy.specialType !== 'supernova') {
// Valid move
if (tempSelectedCandy.isSpecial && tempSelectedCandy.specialType !== 'supernova') {
activateSpecialCandy(tempSelectedCandy);
}
if (candy.isSpecial && candy.specialType !== 'supernova') {
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 && tempSelectedCandy.specialType !== 'supernova' || targetCandy.isSpecial && targetCandy.specialType !== 'supernova') {
// Valid move
if (tempSelectedCandy.isSpecial && tempSelectedCandy.specialType !== 'supernova') {
activateSpecialCandy(tempSelectedCandy);
}
if (targetCandy.isSpecial && targetCandy.specialType !== 'supernova') {
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 = [];
// Set unlimited gold for test mode
gold = 999999999;
storage.gold = gold;
updateUI();
// 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', 'supernova', 'expires', 'writerpir', 'vriper'];
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 unlimited gold for test mode
gold = 999999999;
storage.gold = gold;
updateUI();
// Set 20x score multiplier for matches
comboMultiplier = 20;
showComboDisplay();
// Activate special candy spawning mode
onlySpecialCandies = true;
secretMode = false;
isProcessing = false;
}
function openMarket() {
if (isMarketOpen) return;
isMarketOpen = true;
isProcessing = true; // Pause game while market is open
// Create market screen background
marketScreen = LK.getAsset('gridBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.2,
scaleY: 1.5
});
game.addChild(marketScreen);
// Create market title
var marketTitle = new Text2('MARKET', {
size: 120,
fill: '#FFD700'
});
marketTitle.anchor.set(0.5, 0.5);
marketTitle.x = 1024;
marketTitle.y = 500;
marketScreen.addChild(marketTitle);
// Create close button
var closeButton = new Text2('CLOSE', {
size: 80,
fill: '#FF0000'
});
closeButton.anchor.set(0.5, 0.5);
closeButton.x = 1024;
closeButton.y = 2200;
marketScreen.addChild(closeButton);
marketScreen.closeButton = closeButton;
// Display current gold
var goldDisplay = new Text2('Gold: ' + gold, {
size: 80,
fill: '#FFD700'
});
goldDisplay.anchor.set(0.5, 0.5);
goldDisplay.x = 1024;
goldDisplay.y = 600;
marketScreen.addChild(goldDisplay);
marketScreen.goldDisplay = goldDisplay;
// Create market items in a cube/grid layout (3 columns x 4 rows)
marketScreen.itemButtons = [];
var itemsPerRow = 3;
var startX = 200;
var startY = 750;
var itemWidth = 200;
var itemHeight = 280;
var itemSpacing = 20;
for (var i = 0; i < marketItems.length; i++) {
var item = marketItems[i];
var row = Math.floor(i / itemsPerRow);
var col = i % itemsPerRow;
var xPos = startX + col * (itemWidth + itemSpacing);
var yPos = startY + row * (itemHeight + itemSpacing);
// Item background - cube container
var itemBg = LK.getAsset('progressBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: xPos,
y: yPos,
scaleX: 1.6,
scaleY: 2.2
});
marketScreen.addChild(itemBg);
// Item icon - centered in cube
var itemIcon = LK.getAsset(item.specialType, {
anchorX: 0.5,
anchorY: 0.5,
x: xPos,
y: yPos - 40,
scaleX: 0.4,
scaleY: 0.4
});
marketScreen.addChild(itemIcon);
// Item name - centered below icon
var itemName = new Text2(item.name, {
size: 28,
fill: '#FFFFFF'
});
itemName.anchor.set(0.5, 0.5);
itemName.x = xPos;
itemName.y = yPos + 10;
marketScreen.addChild(itemName);
// Item price - centered below name
var itemPrice = new Text2(item.price + ' Gold', {
size: 24,
fill: '#FFD700'
});
itemPrice.anchor.set(0.5, 0.5);
itemPrice.x = xPos;
itemPrice.y = yPos + 35;
marketScreen.addChild(itemPrice);
// Buy button - centered at bottom of cube
var buyButton = new Text2('BUY', {
size: 32,
fill: gold >= item.price ? '#00FF00' : '#999999'
});
buyButton.anchor.set(0.5, 0.5);
buyButton.x = xPos;
buyButton.y = yPos + 65;
marketScreen.addChild(buyButton);
// Store original item data in button
buyButton.itemIndex = i;
buyButton.canAfford = gold >= item.price;
marketScreen.itemButtons.push(buyButton);
}
// Animate market screen in
marketScreen.alpha = 0;
marketScreen.scaleX = 0.5;
marketScreen.scaleY = 0.5;
tween(marketScreen, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.5
}, {
duration: 300,
easing: tween.bounceOut
});
}
function closeMarket() {
if (!isMarketOpen || !marketScreen) return;
tween(marketScreen, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
if (marketScreen && marketScreen.parent) {
marketScreen.parent.removeChild(marketScreen);
}
marketScreen = null;
isMarketOpen = false;
isProcessing = false; // Resume game
}
});
}
function buyMarketItem(itemIndex) {
var item = marketItems[itemIndex];
if (gold >= item.price) {
// Deduct gold
gold -= item.price;
storage.gold = gold;
updateUI();
// Update market display
if (marketScreen && marketScreen.goldDisplay) {
marketScreen.goldDisplay.setText('Gold: ' + gold);
}
// Update buy button colors
for (var i = 0; i < marketScreen.itemButtons.length; i++) {
var button = marketScreen.itemButtons[i];
var buttonItem = marketItems[button.itemIndex];
button.fill = gold >= buttonItem.price ? '#00FF00' : '#999999';
button.canAfford = gold >= buttonItem.price;
}
// Handle consumable items (kavanoz)
if (item.isConsumable) {
// Add to inventory
if (!inventory[item.specialType]) {
inventory[item.specialType] = 0;
}
inventory[item.specialType]++;
storage.inventory = inventory;
// Handle kavanoz effect immediately
if (item.specialType === 'kavanoz') {
useKavanoz();
}
} else {
// Find random empty grid position to place the special candy
var availablePositions = [];
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (grid[row][col] && !grid[row][col].isSpecial) {
availablePositions.push({
row: row,
col: col
});
}
}
}
if (availablePositions.length > 0) {
var randomPos = availablePositions[Math.floor(Math.random() * availablePositions.length)];
var targetCandy = grid[randomPos.row][randomPos.col];
if (targetCandy) {
// Transform the candy to the purchased special type
targetCandy.makeSpecial(item.specialType);
// Add purchase effect
LK.effects.flashObject(targetCandy, 0xFFD700, 500);
tween(targetCandy, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(targetCandy, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
}
}
// Success feedback
LK.effects.flashScreen(0x00FF00, 200);
LK.getSound('powerup').play();
} else {
// Not enough gold feedback
LK.effects.flashScreen(0xFF0000, 200);
if (marketScreen) {
tween(marketScreen, {
x: marketScreen.x + 20
}, {
duration: 100,
onFinish: function onFinish() {
tween(marketScreen, {
x: marketScreen.x - 40
}, {
duration: 100,
onFinish: function onFinish() {
tween(marketScreen, {
x: 1024
}, {
duration: 100
});
}
});
}
});
}
}
}
function useKavanoz() {
// Choose a random candy type to transform all candies to
var targetType = COLORS[Math.floor(Math.random() * COLORS.length)];
// Create spectacular transformation effect
LK.effects.flashScreen(0xFFD700, 1000);
var transformDelay = 0;
// Transform all candies to the same type
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (grid[row][col]) {
var candy = grid[row][col];
// Stagger transformations for visual effect
(function (candyToTransform, delay) {
LK.setTimeout(function () {
if (candyToTransform && candyToTransform.parent) {
// If it's special, remove special properties first
if (candyToTransform.isSpecial) {
candyToTransform.isSpecial = false;
candyToTransform.specialType = null;
}
// Change candy type and graphics
candyToTransform.type = targetType;
candyToTransform.removeChild(candyToTransform.graphics);
var assetMap = {
'blue': 'blueCandy',
'red': 'redCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
'purple': 'purpleCandy'
};
candyToTransform.graphics = candyToTransform.attachAsset(assetMap[targetType], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Add transformation sparkle effect
tween(candyToTransform.graphics, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFD700
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(candyToTransform.graphics, {
scaleX: 0.8,
scaleY: 0.8,
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
}, delay);
})(candy, transformDelay);
transformDelay += 50;
}
}
}
// Add massive bonus for using kavanoz
score += 50000;
gold += 25000;
updateUI();
// Play power-up sound
LK.getSound('powerup').play();
}
function restartGame() {
// Reset all game variables to initial state
score = 0;
level = 1;
gold = 0;
storage.gold = gold;
inventory = {};
storage.inventory = inventory;
isProcessing = false;
comboMultiplier = 1;
selectedCandy = null;
// Reset secret feature variables
secretMode = false;
secretBalls = [];
secretClickSequence = [];
secretGridBackup = null;
onlySpecialCandies = false;
// Reset market variables
if (isMarketOpen && marketScreen) {
if (marketScreen.parent) {
marketScreen.parent.removeChild(marketScreen);
}
marketScreen = null;
isMarketOpen = false;
}
// Clear all 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
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;
}
}
// Show UI elements again
tween(scoreText, {
alpha: 1
}, {
duration: 300
});
tween(levelText, {
alpha: 1
}, {
duration: 300
});
tween(goldText, {
alpha: 1
}, {
duration: 300
});
tween(comboText, {
alpha: 0
}, {
duration: 300
});
tween(progressBarBg, {
alpha: 1
}, {
duration: 300
});
// Reset progress bar
progressBarFill.scaleX = 0;
// Reinitialize grid with fresh candies
initializeGrid();
removeInitialMatches();
// Update UI to show reset values
updateUI();
}
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;
}
// Create market button at bottom
var marketButton = new Text2('MARKET', {
size: 80,
fill: '#FFD700'
});
marketButton.anchor.set(0.5, 1);
LK.gui.bottom.addChild(marketButton);
marketButton.y = -50;
// Market screen variables
var marketScreen = null;
var isMarketOpen = false;
var marketItems = [{
name: 'Bluetooth Bomb',
price: 5000,
specialType: 'blueBomb'
}, {
name: 'Red Rocket',
price: 9000,
specialType: 'redRocket'
}, {
name: 'Disco Ball',
price: 50000,
specialType: 'discoBall'
}, {
name: 'Black Hole',
price: 9999,
specialType: 'blackHole'
}, {
name: 'Green Pentagon',
price: 7500,
specialType: 'greenPentagon'
}, {
name: 'Orange Lollipop',
price: 6000,
specialType: 'orangeLollipop'
}, {
name: 'Purple Berry',
price: 8000,
specialType: 'purpleBerry'
}, {
name: 'Supernova',
price: 25000,
specialType: 'supernova'
}, {
name: 'Expires',
price: 15000,
specialType: 'expires'
}, {
name: 'Writerpir',
price: 99999,
specialType: 'writerpir'
}, {
name: 'White Vriper',
price: 12000,
specialType: 'vriper'
}];
// Initialize the game
initializeGrid();
// Give starting gold for new market experience
gold = 1000;
storage.gold = gold;
updateUI();
LK.playMusic('7week3days');
;
function showLevelUpNotification(reachedLevel) {
// Create level up notification text
var levelUpText = new Text2('LEVEL ' + reachedLevel + ' REACHED!', {
size: 120,
fill: '#FFD700'
});
levelUpText.anchor.set(0.5, 0.5);
levelUpText.x = 1024;
levelUpText.y = 1366;
levelUpText.alpha = 0;
levelUpText.scaleX = 0.5;
levelUpText.scaleY = 0.5;
game.addChild(levelUpText);
// Animate level text appearing
tween(levelUpText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(levelUpText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
if (levelUpText.parent) {
levelUpText.parent.removeChild(levelUpText);
}
// Show SUGERCRUSH text after level text disappears
showSugercrushText();
}
});
}, 1500);
}
});
}
function showSugercrushText() {
// Create SUGERCRUSH text
var sugercrushText = new Text2('SUGERCRUSH', {
size: 150,
fill: '#FF6B35'
});
sugercrushText.anchor.set(0.5, 0.5);
sugercrushText.x = 1024;
sugercrushText.y = 1366;
sugercrushText.alpha = 0;
sugercrushText.scaleX = 0.3;
sugercrushText.scaleY = 0.3;
sugercrushText.rotation = -0.2;
game.addChild(sugercrushText);
// Animate SUGERCRUSH text with spectacular effect
tween(sugercrushText, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5,
rotation: 0.2
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Add pulsing effect
var pulseCount = 0;
var maxPulses = 3;
var _pulseEffect = function pulseEffect() {
if (pulseCount < maxPulses) {
tween(sugercrushText, {
scaleX: 1.8,
scaleY: 1.8,
tint: 0xFFD700
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(sugercrushText, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
pulseCount++;
LK.setTimeout(_pulseEffect, 100);
}
});
}
});
} else {
// Final fade out
LK.setTimeout(function () {
tween(sugercrushText, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5,
rotation: 0.5
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
if (sugercrushText.parent) {
sugercrushText.parent.removeChild(sugercrushText);
}
}
});
}, 1000);
}
};
_pulseEffect();
}
});
// Add screen flash effect
LK.effects.flashScreen(0xFF6B35, 300);
} ===================================================================
--- original.js
+++ change.js
@@ -2181,8 +2181,12 @@
};
function activateSecretMode() {
secretMode = true;
secretClickSequence = [];
+ // Set unlimited gold for test mode
+ gold = 999999999;
+ storage.gold = gold;
+ updateUI();
// Backup current grid state
secretGridBackup = [];
for (var row = 0; row < GRID_SIZE; row++) {
secretGridBackup[row] = [];
@@ -2406,8 +2410,12 @@
alpha: 1
}, {
duration: 300
});
+ // Set unlimited gold for test mode
+ gold = 999999999;
+ storage.gold = gold;
+ updateUI();
// Set 20x score multiplier for matches
comboMultiplier = 20;
showComboDisplay();
// Activate special candy spawning mode