User prompt
Zamansıznkara delik herhangi bir şekerle kombolandığında kombolanan şeker türünün ebedi şekere dönüştürür ebedi mor şeker ebedi turuncu şeker ebedi yeşil şeker ebedi mavi şeker ebedi şeker haritanın herhangi bir yere isinlanabilir ve kombolanir kombolanirsa 6x6lık bir kısmı içine çeker %80 daha fazla store verir ve tüm herkesi etkinleştirilmelidir ve patlatır ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'length')' in or related to this line: 'self.graphics = self.attachAsset(specialAssetMap[specialType], {' Line Number: 86
User prompt
Sonsuz boşluk ile mor şeker kombolanırsa ebedi şeker oluşur ebedi şeker haritanın herhangi bir şekerle yer değiştirebilir ve kombolanir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Vid oluşmuyor mapre bulunabilen fiziksel bir destek nesnesi
User prompt
Boşluk herhangi bir şeker ile kombolanınca kombolanan şeker türünün mapteki hepsini boşluk şekerine dönüştürür ve boşluk şekeri 4x4luk menzili içindeki herkesi içine çeker etkinleştirilmelidir patlatır %60 daha gazla store kazandırır ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara delik ile mor şeker kombolanırsa boşluk oluşur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara deliğe 5 kere tıklanırsa void dönüşür void kombolandigi şeker türünün hepsini void şekere dönüştürür ve void şekerin craftanan tüm şekerler türlerine voide dönüşür sonra coid şekerler 3x3luk bir alanı içine çeker ve patlatır ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yıldızlar daha nadir kayar
User prompt
Zamansız kara deliğe 3 kere tıklanırsa 2 kum saati eksilir ve boşluk oluşur boşluk kombolaninca kombolanan şeker türü boşluk şekerine dönüşür ve kombolaninca yine kombolanan şeker türünün hepsini boşluğa dönüştürür boşluk boslukla 4lu kombolanirsa bütün mapi yok eder ve +8474477 store puanı kazandırır ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara delik bütün mapi kırmızı roket yapmicak bir kombolanabilir şeker türü yapacak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kum saati tüm mapi rastgele bir şeker türü ile kaplar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kum saati kombolandığında tüm mepi mor şeker yapar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kum saati bütün mapi mor şeker yapar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara delik tüm mapi mor şeker yapar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara delikle zamansız kara delik kombolanirsa warlek oluşur bütün şekerleri mor renk yapar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara delik kombolanınca patlar ve patlamadan tekrar kombo ortaya çıkarsa tekrar oluşur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara delik patlamaz komboliyarak yok eder kırmızı rokete dönüşecek ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zamansız kara delikle bi şekeri kombolayınca kombolanan şeker patlar zamansız kara delikvyok olmaz yerinde kalır patlamaz 40 kere bu yapılabilir ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '3')' in or related to this line: 'return grid[row][col];' Line Number: 571
User prompt
Zamansız jara delik herkesle kombalanir kombalanan şeker patlar zamansız kara delik patlamaz 40 şekerle kombolanabilir ve sadece kombolanan şeker patlar 40 şeker boyu zamansız kara delik çatlar 40. Şekerle kombalaninca patlar ve tüm mapi patlatır ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Bir şekere çift tıklanarak kum saati kullanılır o şeker zamansız Karadenize dönüşür zamansız Karadeniz her türlü şeker kombalanir zamansız kara delik yok olmaz 40 şekerle kombolanana kadar ve çatlama efekti canı azaldıkça artar patlayınca tüm mapi patlatır ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Oyuna ana menü ekle oyuna başla ayarlar seçeneği olacak
User prompt
Kum saati tam olarak şu işe yarar oyuncu şeker patlatarak 3 kere ard arda kombi yaptı sonra kum saati devreye girer süper kombi seviyesinde tutar ve oyuncu kombi yapınca superkombonun üstüne eklenir ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Üstüne tıklayarak küçültülmüş sarı şekerler 4lu kombo yapılırsa kum saati elde edilir kum saati kullanımında. Kombi yapıldıktan sonrakombo 2 oldu bitti oyuncu sonraki kombi yapısında kaldığı yerden kombi yazısı devam eder ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Bir Karadeniz üretildiğini evren başarımı alınır +2000 altın ↪💡 Consider importing and using the following plugins: @upit/storage.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',
'converter': 'vriper',
'hourglass': 'hourglass'
};
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 - 1% chance
if (Math.random() < 0.01 && shootingStars.length < 5) {
// 1% chance per frame, max 5 shooting stars
self.createShootingStar();
}
// Make shooting stars slide with 40% probability
for (var i = 0; i < shootingStars.length; i++) {
var star = shootingStars[i];
// Check if this star should slide (40% chance when created)
if (star.shouldSlide === undefined) {
star.shouldSlide = Math.random() < 0.4; // 40% chance
star.slideDirection = Math.random() * Math.PI * 2; // Random direction
star.slideSpeed = Math.random() * 2 + 1; // Random slide speed
}
// Apply sliding movement if enabled
if (star.shouldSlide) {
star.x += Math.cos(star.slideDirection) * star.slideSpeed;
// Keep star within screen bounds horizontally
if (star.x < 0 || star.x > 2048) {
star.slideDirection = Math.PI - star.slideDirection; // Reverse horizontal direction
}
}
}
};
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
var cascadeComboCount = 0; // Track consecutive cascade combos
var savedComboCount = 0; // Track saved combo count from hourglass
var cascadeComboNames = ['', 'COMBO', 'DOUBLE COMBO', 'BRUTALITY', 'AMAZING', 'SUPERBEAST', 'ULTRA SUPER COMBO', 'PERFECT']; // Combo names for each level
var lastCascadeTime = 0; // Track time of last cascade for timeout
var hourglassCount = 0; // Track number of hourglasses available
var yellowCandiesClicked = []; // Track yellow candies that have been clicked small
// Timeless Karadeniz system variables
var timelessKaradenizCandies = []; // Track all timeless Karadeniz candies
var lastClickTime = 0; // Track last click time for double-click detection
var lastClickedCandy = null; // Track last clicked candy for double-click detection
var DOUBLE_CLICK_THRESHOLD = 500; // Maximum time between clicks for double-click (ms)
// Black hole click tracking for void creation
var blackHoleClickCounts = {}; // key: row_col, value: click count
var voidPositions = []; // Array of {row, col} for voids on the grid
var eternalCandies = []; // Array to track eternal candies on the grid
var selectedEternalCandy = null; // Track selected eternal candy for swapping
// Helper: get key for black hole/void click tracking
function getGridKey(row, col) {
return row + "_" + col;
}
// Helper: create an eternal candy at a given position
function createEternalCandy(row, col) {
// Remove any candy at this position
if (grid[row][col] && grid[row][col].parent) {
grid[row][col].parent.removeChild(grid[row][col]);
}
// Create eternal candy (special candy with unique properties)
var eternalCandy = new Candy('purple', row, col);
eternalCandy.isSpecial = true;
eternalCandy.specialType = 'eternal';
eternalCandy.type = 'eternal';
eternalCandy.canSwapAnywhere = true;
// Replace graphics with a unique eternal look (golden glowing purple)
eternalCandy.removeChild(eternalCandy.graphics);
eternalCandy.graphics = eternalCandy.attachAsset('purpleCandy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
tween(eternalCandy.graphics, {
tint: 0xFFD700,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 500,
onFinish: function onFinish() {
// Add continuous golden glow effect
var _pulseEternal = function pulseEternal() {
if (eternalCandy && eternalCandy.parent && eternalCandy.specialType === 'eternal') {
tween(eternalCandy.graphics, {
tint: 0xFFFF00,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.9
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(eternalCandy.graphics, {
tint: 0xFFD700,
scaleX: 1.3,
scaleY: 1.3,
alpha: 1.0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseEternal, 200);
}
});
}
});
}
};
_pulseEternal();
}
});
// Add to grid and game
grid[row][col] = eternalCandy;
gameContainer.addChild(eternalCandy);
// Track eternal candy
eternalCandies.push({
row: row,
col: col
});
// Visual effect
LK.effects.flashScreen(0xFFD700, 1000);
// Show notification
var eternalText = new Text2('EBEDI ŞEKER YARATILDI!', {
size: 90,
fill: '#FFD700'
});
eternalText.anchor.set(0.5, 0.5);
eternalText.x = 1024;
eternalText.y = 1366;
eternalText.alpha = 0;
game.addChild(eternalText);
tween(eternalText, {
alpha: 1,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(eternalText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (eternalText.parent) eternalText.parent.removeChild(eternalText);
}
});
}, 1500);
}
});
}
// Helper: check if a candy is eternal
function isEternalCandy(candy) {
return candy && candy.isSpecial && candy.specialType === 'eternal';
}
// Helper: handle eternal candy swapping with any candy on the map
function handleEternalCandySwap(eternalCandy, targetCandy) {
if (!eternalCandy || !targetCandy || eternalCandy === targetCandy) return false;
var eternalRow = eternalCandy.row;
var eternalCol = eternalCandy.col;
var targetRow = targetCandy.row;
var targetCol = targetCandy.col;
// Swap positions in grid
grid[eternalRow][eternalCol] = targetCandy;
grid[targetRow][targetCol] = eternalCandy;
// Update candy properties
eternalCandy.row = targetRow;
eternalCandy.col = targetCol;
targetCandy.row = eternalRow;
targetCandy.col = eternalCol;
// Animate the swap with spectacular effect
tween(eternalCandy, {
x: GRID_START_X + targetCol * CELL_SIZE + CELL_SIZE / 2,
y: GRID_START_Y + targetRow * CELL_SIZE + CELL_SIZE / 2,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(eternalCandy, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 200,
easing: tween.easeOut
});
}
});
tween(targetCandy, {
x: GRID_START_X + eternalCol * CELL_SIZE + CELL_SIZE / 2,
y: GRID_START_Y + eternalRow * CELL_SIZE + CELL_SIZE / 2
}, {
duration: 300,
easing: tween.easeOut
});
// Update eternal candy position tracking
for (var i = 0; i < eternalCandies.length; i++) {
if (eternalCandies[i].row === eternalRow && eternalCandies[i].col === eternalCol) {
eternalCandies[i].row = targetRow;
eternalCandies[i].col = targetCol;
break;
}
}
// Create swap effect
LK.effects.flashScreen(0xFFD700, 500);
return true;
}
// Helper: create a void at a given position
function createVoidAt(row, col) {
// Remove any candy at this position
if (grid[row][col] && grid[row][col].parent) {
grid[row][col].parent.removeChild(grid[row][col]);
}
// Create a void object (special candy with type 'void')
var voidCandy = new Candy('purple', row, col);
voidCandy.isSpecial = true;
voidCandy.specialType = 'void';
voidCandy.type = 'void';
voidCandy.voidComboType = null; // Will be set on first combo
voidCandy.voidComboActive = false;
// Replace graphics with a unique void look (purpleCandy with special tint)
voidCandy.removeChild(voidCandy.graphics);
voidCandy.graphics = voidCandy.attachAsset('purpleCandy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
tween(voidCandy.graphics, {
tint: 0x6e00ff,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
onFinish: function onFinish() {
tween(voidCandy.graphics, {
tint: 0x9013fe,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300
});
}
});
// Add to grid and game
grid[row][col] = voidCandy;
gameContainer.addChild(voidCandy);
// Track void position
voidPositions.push({
row: row,
col: col
});
}
// Helper: check if a candy is a void
function isVoidCandy(candy) {
return candy && candy.isSpecial && candy.specialType === 'void';
}
// Helper: get all void candies on the grid
function getAllVoidCandies() {
var result = [];
for (var i = 0; i < voidPositions.length; i++) {
var pos = voidPositions[i];
if (grid[pos.row][pos.col] && isVoidCandy(grid[pos.row][pos.col])) {
result.push(grid[pos.row][pos.col]);
}
}
return result;
}
// Helper: clear all voids from the grid and voidPositions
function clearAllVoids() {
for (var i = 0; i < voidPositions.length; i++) {
var pos = voidPositions[i];
if (grid[pos.row][pos.col] && grid[pos.row][pos.col].parent) {
grid[pos.row][pos.col].parent.removeChild(grid[pos.row][pos.col]);
}
grid[pos.row][pos.col] = null;
}
voidPositions = [];
}
// Helper: handle void combo logic
function handleVoidCombo(matchArr) {
// Find if any void is in this match
var voidCandy = null;
var infiniteVoidCandy = null;
for (var i = 0; i < matchArr.length; i++) {
if (isVoidCandy(matchArr[i])) {
voidCandy = matchArr[i];
// Check if this is an infinite void (enhanced void with special property)
if (matchArr[i].isInfiniteVoid) {
infiniteVoidCandy = matchArr[i];
}
break;
}
}
if (!voidCandy) return false;
// Check for infinite void + purple candy combo first
if (infiniteVoidCandy) {
var purpleCandy = null;
for (var i = 0; i < matchArr.length; i++) {
if (matchArr[i] !== infiniteVoidCandy && matchArr[i].type === 'purple' && !matchArr[i].isSpecial) {
purpleCandy = matchArr[i];
break;
}
}
if (purpleCandy) {
// Create eternal candy at infinite void position
createEternalCandy(infiniteVoidCandy.row, infiniteVoidCandy.col);
// Remove purple candy
grid[purpleCandy.row][purpleCandy.col] = null;
purpleCandy.explode();
// Remove infinite void
grid[infiniteVoidCandy.row][infiniteVoidCandy.col] = null;
infiniteVoidCandy.explode();
return true;
}
}
// Find the type of candy being comboed with void
var comboType = null;
for (var i = 0; i < matchArr.length; i++) {
if (matchArr[i] !== voidCandy && !isVoidCandy(matchArr[i])) {
comboType = matchArr[i].type;
break;
}
}
if (!comboType) return false;
// Transform all candies of comboType on the map to void
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
var c = grid[row][col];
if (c && c.type === comboType && !isVoidCandy(c)) {
createVoidAt(row, col);
}
}
}
// Trigger 4x4 attraction effect for the original void
LK.setTimeout(function () {
triggerVoid4x4Attraction(voidCandy);
}, 500);
// Visual effect
LK.effects.flashScreen(0x6e00ff, 800);
// Show notification
var voidText = new Text2('VOID CONSUMES ALL ' + comboType.toUpperCase() + '!', {
size: 80,
fill: '#6e00ff'
});
voidText.anchor.set(0.5, 0.5);
voidText.x = 1024;
voidText.y = 1366;
voidText.alpha = 0;
game.addChild(voidText);
tween(voidText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(voidText, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
if (voidText.parent) voidText.parent.removeChild(voidText);
}
});
}, 1200);
}
});
return true;
}
// Helper: trigger void attraction and explosion in 4x4 area with 60% bonus
function triggerVoid4x4Attraction(voidCandy) {
if (!voidCandy || !voidCandy.parent) return;
var centerRow = voidCandy.row;
var centerCol = voidCandy.col;
// Collect all candies in 4x4 area around void (2 cells in each direction)
var attractedCandies = [];
for (var r = Math.max(0, centerRow - 2); r <= Math.min(GRID_SIZE - 1, centerRow + 2); r++) {
for (var c = Math.max(0, centerCol - 2); c <= Math.min(GRID_SIZE - 1, centerCol + 2); c++) {
if (grid[r][c] && grid[r][c] !== voidCandy) {
attractedCandies.push(grid[r][c]);
grid[r][c] = null; // Remove from grid immediately
}
}
}
// Animate attraction of candies to void
for (var i = 0; i < attractedCandies.length; i++) {
(function (targetCandy, index) {
if (targetCandy && targetCandy.parent) {
// Animate candy moving to void
tween(targetCandy, {
x: voidCandy.x,
y: voidCandy.y,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.7
}, {
duration: 800 + index * 50,
easing: tween.easeIn,
onFinish: function onFinish() {
if (targetCandy && targetCandy.parent) {
// Explode with 60% bonus store points
var bonusScore = Math.floor(15 * comboMultiplier * 1.6);
var bonusGold = Math.floor(8 * 1.6);
if (comboMultiplier > 1) {
bonusGold += Math.floor(10 * 1.6);
}
score += bonusScore;
gold += bonusGold;
targetCandy.explode();
}
}
});
}
})(attractedCandies[i], i);
}
// Create visual void implosion effect
tween(voidCandy.graphics, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0.5,
rotation: Math.PI * 4
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Massive explosion after attraction
LK.effects.flashScreen(0x6e00ff, 1000);
// Add score bonus for void activation
score += Math.floor(25000 * 1.6);
gold += Math.floor(12500 * 1.6);
updateUI();
// Clean up the void
if (voidCandy && voidCandy.parent) {
voidCandy.parent.removeChild(voidCandy);
}
grid[centerRow][centerCol] = null;
// Remove from void positions
for (var i = 0; i < voidPositions.length; i++) {
if (voidPositions[i].row === centerRow && voidPositions[i].col === centerCol) {
voidPositions.splice(i, 1);
break;
}
}
// Drop new candies after explosion
LK.setTimeout(function () {
dropCandies();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 500);
}
});
}
// Helper: trigger void attraction and explosion in 3x3 area
function triggerVoidAttraction() {
// Find all void candies
var allVoids = getAllVoidCandies();
if (allVoids.length === 0) return;
// Choose a central void as the attraction point
var centralVoid = allVoids[Math.floor(allVoids.length / 2)];
var centerRow = centralVoid.row;
var centerCol = centralVoid.col;
// Collect all candies in 3x3 area around central void
var attractedCandies = [];
for (var r = Math.max(0, centerRow - 1); r <= Math.min(GRID_SIZE - 1, centerRow + 1); r++) {
for (var c = Math.max(0, centerCol - 1); c <= Math.min(GRID_SIZE - 1, centerCol + 1); c++) {
if (grid[r][c] && grid[r][c] !== centralVoid) {
attractedCandies.push(grid[r][c]);
grid[r][c] = null; // Remove from grid immediately
}
}
}
// Animate attraction of candies to central void
for (var i = 0; i < attractedCandies.length; i++) {
(function (targetCandy, index) {
if (targetCandy && targetCandy.parent) {
// Animate candy moving to central void
tween(targetCandy, {
x: centralVoid.x,
y: centralVoid.y,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.7
}, {
duration: 800 + index * 50,
easing: tween.easeIn,
onFinish: function onFinish() {
if (targetCandy && targetCandy.parent) {
explodeCandyWithScore(targetCandy);
}
}
});
}
})(attractedCandies[i], i);
}
// Create visual void implosion effect
tween(centralVoid.graphics, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0.5,
rotation: Math.PI * 4
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Massive explosion after attraction
LK.effects.flashScreen(0x6e00ff, 1000);
// Add score bonus
score += 25000;
gold += 12500;
updateUI();
// Clean up the central void
if (centralVoid && centralVoid.parent) {
centralVoid.parent.removeChild(centralVoid);
}
grid[centerRow][centerCol] = null;
// Remove from void positions
for (var i = 0; i < voidPositions.length; i++) {
if (voidPositions[i].row === centerRow && voidPositions[i].col === centerCol) {
voidPositions.splice(i, 1);
break;
}
}
// Drop new candies after explosion
LK.setTimeout(function () {
dropCandies();
LK.setTimeout(function () {
processMatches();
}, 300);
}, 500);
}
});
}
// Helper: handle 4-void combo (map clear)
function handleFourVoidCombo(matchArr) {
// Check if all are voids and length is 4
if (matchArr.length === 4 && matchArr.every(isVoidCandy)) {
// Clear the entire map
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;
}
}
clearAllVoids();
// Add massive store points
score += 8474477;
gold += 8474477;
updateUI();
// Visual effect
LK.effects.flashScreen(0x6e00ff, 2000);
var voidText = new Text2('VOID APOCALYPSE! +8474477', {
size: 120,
fill: '#6e00ff'
});
voidText.anchor.set(0.5, 0.5);
voidText.x = 1024;
voidText.y = 1366;
voidText.alpha = 0;
game.addChild(voidText);
tween(voidText, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(voidText, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
if (voidText.parent) voidText.parent.removeChild(voidText);
}
});
}, 2000);
}
});
return true;
}
return false;
}
// Main menu system variables
var gameState = 'menu'; // 'menu', 'playing', 'settings'
var mainMenuContainer = null;
var settingsMenuContainer = null;
var gameContainer = null;
// Achievement system variables
var achievements = {
smallCollector: false,
hiddenStars: false,
leagues: false,
universe: false
};
var ballsClickedSmall = []; // Track which balls have been clicked to small size
var totalBallsToClick = 0; // Total number of balls that need to be clicked small
// Hidden Stars achievement variables
var hiddenStarsSequence = []; // Track the sequence entered after clicking shooting star
var hiddenStarsActivated = false; // Track if shooting star was clicked
// Save system variables
var saveButtonPressed = false;
var gameStateSaved = false;
// Create animated starfield background
var starField = new StarField();
game.addChild(starField);
// Create main menu
function createMainMenu() {
mainMenuContainer = new Container();
game.addChild(mainMenuContainer);
// Game title
var titleText = new Text2('ŞEKERLERI PATLAT', {
size: 140,
fill: '#FFD700'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
mainMenuContainer.addChild(titleText);
// Start Game button
var startButton = LK.getAsset('progressBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 1.5
});
startButton.x = 1024;
startButton.y = 1200;
mainMenuContainer.addChild(startButton);
var startButtonText = new Text2('OYUNA BAŞLA', {
size: 80,
fill: '#FFFFFF'
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 1024;
startButtonText.y = 1200;
mainMenuContainer.addChild(startButtonText);
// Settings button
var settingsButton = LK.getAsset('progressBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 1.5
});
settingsButton.x = 1024;
settingsButton.y = 1500;
mainMenuContainer.addChild(settingsButton);
var settingsButtonText = new Text2('AYARLAR', {
size: 80,
fill: '#FFFFFF'
});
settingsButtonText.anchor.set(0.5, 0.5);
settingsButtonText.x = 1024;
settingsButtonText.y = 1500;
mainMenuContainer.addChild(settingsButtonText);
// Store button references for click detection
mainMenuContainer.startButton = startButton;
mainMenuContainer.settingsButton = settingsButton;
}
// Create settings menu
function createSettingsMenu() {
settingsMenuContainer = new Container();
game.addChild(settingsMenuContainer);
settingsMenuContainer.alpha = 0;
// Settings title
var settingsTitle = new Text2('AYARLAR', {
size: 120,
fill: '#FFD700'
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.x = 1024;
settingsTitle.y = 600;
settingsMenuContainer.addChild(settingsTitle);
// Music volume info (since LK handles music automatically)
var musicText = new Text2('Müzik: Otomatik', {
size: 60,
fill: '#FFFFFF'
});
musicText.anchor.set(0.5, 0.5);
musicText.x = 1024;
musicText.y = 1000;
settingsMenuContainer.addChild(musicText);
// Sound effects info
var soundText = new Text2('Ses Efektleri: Açık', {
size: 60,
fill: '#FFFFFF'
});
soundText.anchor.set(0.5, 0.5);
soundText.x = 1024;
soundText.y = 1150;
settingsMenuContainer.addChild(soundText);
// Back button
var backButton = LK.getAsset('progressBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.2
});
backButton.x = 1024;
backButton.y = 1800;
settingsMenuContainer.addChild(backButton);
var backButtonText = new Text2('GERİ', {
size: 70,
fill: '#FFFFFF'
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 1024;
backButtonText.y = 1800;
settingsMenuContainer.addChild(backButtonText);
// Store button reference for click detection
settingsMenuContainer.backButton = backButton;
}
// Create game container to hold all game elements
function createGameContainer() {
gameContainer = new Container();
game.addChild(gameContainer);
gameContainer.alpha = 0;
}
// Initialize menus
createMainMenu();
createSettingsMenu();
createGameContainer();
// Create grid background
var gridBg = game.attachAsset('gridBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
gameContainer.addChild(gridBg);
// 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
});
gameContainer.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
});
gameContainer.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 hourglass display
var hourglassText = new Text2('Hourglass: 0', {
size: 50,
fill: '#FFD700'
});
hourglassText.anchor.set(1, 0);
LK.gui.topRight.addChild(hourglassText);
hourglassText.x = -20;
hourglassText.y = 170;
// 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++) {
// Normal candy creation with 5% chance for purple
var color;
if (Math.random() < 0.05) {
// 5% chance for purple fruit
color = 'purple';
} else {
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;
gameContainer.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;
// Random color with 5% chance for purple
var randomColor;
if (Math.random() < 0.05) {
// 5% chance for purple fruit
randomColor = 'purple';
} else {
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 && grid[row] && grid[row][col]) {
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) {
// Check if this was a cascade (not user-initiated)
var currentTime = Date.now();
if (currentTime - lastCascadeTime < 2000 && cascadeComboCount > 0) {
// This was part of a cascade sequence, don't reset cascade combo yet
// Reset cascade combo after a delay if no more matches found
LK.setTimeout(function () {
// Save current combo count before resetting
if (cascadeComboCount > savedComboCount) {
savedComboCount = cascadeComboCount;
}
// Only reset if not in hourglass super combo mode
if (savedComboCount < 3) {
cascadeComboCount = 0;
} else {
// Keep combo at super combo level when hourglass is active
cascadeComboCount = savedComboCount;
}
}, 1000);
} else {
// Save current combo count before resetting
if (cascadeComboCount > savedComboCount) {
savedComboCount = cascadeComboCount;
}
// Only reset if not in hourglass super combo mode
if (savedComboCount < 3) {
cascadeComboCount = 0; // Reset if too much time passed or no cascade
} else {
// Keep combo at super combo level when hourglass is active
cascadeComboCount = savedComboCount;
}
}
comboMultiplier = 1;
showComboDisplay(); // Hide combo display when combo ends
isProcessing = false;
return;
}
// Check for timeless Karadeniz combinations first
checkTimelessKaradenizCombinations(allMatches);
// Process matches and create special candies
var totalScore = 0;
var totalGold = 0;
for (var m = 0; m < allMatches.length; m++) {
var matches = allMatches[m];
// --- VOID LOGIC: handle 4-void combo first ---
if (handleFourVoidCombo(matches)) {
// Remove all candies from this match to prevent further processing
matches.length = 0;
continue;
}
// --- VOID LOGIC: handle void combo (transform or spread) ---
if (handleVoidCombo(matches)) {
// Remove all candies from this match to prevent further processing
matches.length = 0;
continue;
}
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') {
// Create converter instead of blueBomb for blue 5-match
centerCandy.makeSpecial('vriper'); // Use vriper as converter visual
centerCandy.specialType = 'converter'; // Set special type to converter
// Add converter creation effect
tween(centerCandy.graphics, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0x4a90e2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Add pulsing blue glow effect for converter
var _pulseConverter = function pulseConverter() {
if (centerCandy.isSpecial && centerCandy.specialType === 'converter' && centerCandy.parent) {
tween(centerCandy.graphics, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0x6ba3f0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(centerCandy.graphics, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0x4a90e2
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseConverter, 100);
}
});
}
});
}
};
_pulseConverter();
}
});
} 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' && color !== 'blue') {
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);
// Add +1000 gold for each level completed
gold += 1000;
if (level % 5 === 0) {
gold += 4000;
}
// Check for Leagues achievement
checkLeaguesAchievement();
}
updateUI();
LK.getSound('match').play();
// Check for 4x4 formations before black hole combinations
check4x4Formations();
// Check for black hole combinations before dropping candies
checkBlackHoleCombinations();
// Track cascade combo if this was an auto-cascade (not user-initiated)
var currentTime = Date.now();
if (currentTime - lastCascadeTime < 2000 || lastCascadeTime === 0) {
// If hourglass is active and we're at super combo level, add to it instead of incrementing normally
if (savedComboCount >= 3 && cascadeComboCount >= 3) {
// Player is in hourglass super combo mode - add to the super combo
cascadeComboCount++;
} else {
cascadeComboCount++;
}
lastCascadeTime = currentTime;
// Show cascade combo display for levels 1-7
if (cascadeComboCount >= 1 && cascadeComboCount <= 7) {
showCascadeComboDisplay(cascadeComboCount);
}
// Special reward: Create supernova if reached 7th cascade combo
if (cascadeComboCount === 7) {
createSupernovaReward();
}
}
// 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', 'converter'];
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);
// Check for Universe achievement if expires (Karadeniz) was created
if (randomSpecialType === 'expires') {
checkUniverseAchievement();
}
} else {
// Normal candy creation with 5% chance for purple
var randomColor;
if (Math.random() < 0.05) {
// 5% chance for purple fruit
randomColor = 'purple';
} else {
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;
gameContainer.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', 'converter'];
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);
// Check for Universe achievement if expires (Karadeniz) was created
if (randomSpecialType === 'expires') {
checkUniverseAchievement();
}
} else {
// Normal candy creation with 5% chance for purple
var randomColor;
if (Math.random() < 0.05) {
// 5% chance for purple fruit
randomColor = 'purple';
} else {
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;
gameContainer.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);
hourglassText.setText('Hourglass: ' + hourglassCount);
// 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]);
}
}
}
// Check if we're combining with red rocket first
var adjacentRedRockets = [];
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 === 'redRocket') {
adjacentRedRockets.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentRedRockets.length > 0) {
// Disco ball + red rocket combo: transform all candies to random candy types (no explosions)
var redRocketCandy = adjacentRedRockets[0];
// Remove red rocket without explosion
grid[redRocketCandy.row][redRocketCandy.col] = null;
if (redRocketCandy.parent) {
redRocketCandy.parent.removeChild(redRocketCandy);
}
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFF0000,
rotation: Math.PI * 4
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Transform all candies to random candy types
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];
// Choose random candy type
var randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
// Transform candy with delay for visual effect
(function (candyToTransform, newColor, delay) {
LK.setTimeout(function () {
if (candyToTransform && candyToTransform.parent) {
// Update candy type
candyToTransform.type = newColor;
// Remove old graphics
candyToTransform.removeChild(candyToTransform.graphics);
// Create new graphics with new color
var assetMap = {
'blue': 'blueCandy',
'red': 'redCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
'purple': 'purpleCandy'
};
candyToTransform.graphics = candyToTransform.attachAsset(assetMap[newColor], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Reset special properties if any
candyToTransform.isSpecial = false;
candyToTransform.specialType = null;
// Add transformation effect
tween(candyToTransform.graphics, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(candyToTransform.graphics, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
}, delay);
})(targetCandy, randomColor, (r + c) * 30);
}
}
}
LK.effects.flashScreen(0xFF0000, 800);
}
});
// Add bonus score for combination
score += 5000;
gold += 2500;
updateUI();
LK.getSound('powerup').play();
break;
}
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 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) {
// Expires + Purple candy combo: create void
var purpleCandy = adjacentPurpleCandies[0];
// Remove purple candy
grid[purpleCandy.row][purpleCandy.col] = null;
purpleCandy.explode();
// Transform expires into void
createVoidAt(candy.row, candy.col);
// Create spectacular combination effect
LK.effects.flashScreen(0x6e00ff, 800);
// Show void creation notification
var voidText = new Text2('ZAMANSIZ KARA DELIK + MOR = VOID!', {
size: 80,
fill: '#6e00ff'
});
voidText.anchor.set(0.5, 0.5);
voidText.x = 1024;
voidText.y = 1366;
voidText.alpha = 0;
game.addChild(voidText);
tween(voidText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(voidText, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
if (voidText.parent) voidText.parent.removeChild(voidText);
}
});
}, 1200);
}
});
// Add bonus score for combination
score += 6000;
gold += 3000;
updateUI();
LK.getSound('powerup').play();
break;
}
// Check if we're combining with black hole
var adjacentBlackHoles = [];
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 a single random non-special, non-redRocket candy type
// Pick a random color from COLORS, but not 'red' (to avoid redRocket), and not a special
var availableColors = [];
for (var i = 0; i < COLORS.length; i++) {
if (COLORS[i] !== 'red') availableColors.push(COLORS[i]);
}
var randomType = availableColors[Math.floor(Math.random() * availableColors.length)];
var assetMap = {
'blue': 'blueCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
'purple': 'purpleCandy'
};
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 the chosen randomType with delay
(function (candyToTransform, delay) {
LK.setTimeout(function () {
if (candyToTransform && candyToTransform.parent) {
// Remove old graphics
candyToTransform.removeChild(candyToTransform.graphics);
// Set new type
candyToTransform.type = randomType;
// Attach new graphics
candyToTransform.graphics = candyToTransform.attachAsset(assetMap[randomType], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Reset special properties
candyToTransform.isSpecial = false;
candyToTransform.specialType = null;
candyToTransform.isTimeless = false;
// Add transformation effect
tween(candyToTransform.graphics, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(candyToTransform.graphics, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
}, 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 'converter':
// Converter: check for adjacent candies to combine with
var adjacentPositions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
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;
// Remove the target candy
grid[targetCandy.row][targetCandy.col] = null;
targetCandy.explode();
// Create the appropriate special candy based on target color
var newSpecialType;
if (targetColor === 'blue') {
newSpecialType = 'blueBomb';
} else if (targetColor === 'red') {
newSpecialType = 'redRocket';
} else if (targetColor === 'green') {
newSpecialType = 'greenPentagon';
} else if (targetColor === 'orange') {
newSpecialType = 'orangeLollipop';
} else if (targetColor === 'purple') {
newSpecialType = 'blackHole';
}
// Transform converter into the new special candy
candy.makeSpecial(newSpecialType);
// Set flag to prevent immediate activation
candy.justCreated = true;
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0x4a90e2,
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Flash effect to show transformation
LK.effects.flashScreen(0x4a90e2, 500);
// Add bonus score for converter combination
score += 3000;
gold += 1500;
updateUI();
LK.getSound('powerup').play();
// Remove the creation flag after animation completes
LK.setTimeout(function () {
if (candy && candy.parent) {
candy.justCreated = false;
}
}, 1000);
}
});
// Don't break here - return early to prevent converter destruction
return;
}
// No adjacent candies - converter just explodes without effect
tween(candy.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x4a90e2,
alpha: 0.5
}, {
duration: 500,
easing: tween.easeOut
});
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;
case 'hourglass':
// Check if we're combining with another candy first
var adjacentCandies = [];
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) {
adjacentCandies.push(grid[adjRow][adjCol]);
}
}
}
if (adjacentCandies.length > 0) {
// Hourglass combining with adjacent candy - cover all map with a random candy type
var targetCandy = adjacentCandies[0];
// Remove the adjacent candy
grid[targetCandy.row][targetCandy.col] = null;
targetCandy.explode();
// Create spectacular combination effect
tween(candy.graphics, {
scaleX: 3.0,
scaleY: 3.0,
tint: 0xFFD700,
rotation: Math.PI * 6
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.effects.flashScreen(0xFFD700, 1200);
}
});
} else {
// Normal hourglass activation
// Create hourglass visual effect
tween(candy.graphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0xFFD700,
rotation: Math.PI * 4
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.effects.flashScreen(0xFFD700, 800);
}
});
}
// Hourglass: turn all candies on the map to a single random candy type with wave effect
var centerRow = candy.row;
var centerCol = candy.col;
var maxDistance = Math.max(GRID_SIZE, GRID_SIZE);
// Pick a random color for the whole map (from COLORS)
var randomColorForMap = COLORS[Math.floor(Math.random() * COLORS.length)];
var assetMap = {
'blue': 'blueCandy',
'red': 'redCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
'purple': 'purpleCandy'
};
for (var distance = 1; distance <= maxDistance; distance++) {
(function (dist) {
LK.setTimeout(function () {
// Collect all candies at this distance
var candiesAtDistance = [];
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
var actualDist = Math.max(Math.abs(r - centerRow), Math.abs(c - centerCol));
if (actualDist === dist && grid[r][c] && grid[r][c] !== candy) {
candiesAtDistance.push(grid[r][c]);
}
}
}
// Transform all candies at this distance to the random color
for (var i = 0; i < candiesAtDistance.length; i++) {
(function (targetCandy, index) {
if (targetCandy && targetCandy.parent) {
// Update candy type to the random color
targetCandy.type = randomColorForMap;
// Remove old graphics
targetCandy.removeChild(targetCandy.graphics);
// Create new graphics for the random color
targetCandy.graphics = targetCandy.attachAsset(assetMap[randomColorForMap], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Reset special properties
targetCandy.isSpecial = false;
targetCandy.specialType = null;
targetCandy.isTimeless = false;
// Add transformation effect
tween(targetCandy.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(targetCandy.graphics, {
scaleX: 0.8,
scaleY: 0.8,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
})(candiesAtDistance[i], i);
}
}, dist * 100); // Stagger waves outward
})(distance);
}
// Add bonus for hourglass activation
score += 8000;
gold += 4000;
updateUI();
LK.getSound('powerup').play();
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) {
// Handle menu navigation first
if (gameState === 'menu') {
// Check start button click
var dx = x - mainMenuContainer.startButton.x;
var dy = y - mainMenuContainer.startButton.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
// Animate button press
tween(mainMenuContainer.startButton, {
scaleX: 1.8,
scaleY: 1.3
}, {
duration: 100,
onFinish: function onFinish() {
tween(mainMenuContainer.startButton, {
scaleX: 2.0,
scaleY: 1.5
}, {
duration: 100,
onFinish: function onFinish() {
startGame();
}
});
}
});
return;
}
// Check settings button click
dx = x - mainMenuContainer.settingsButton.x;
dy = y - mainMenuContainer.settingsButton.y;
distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
// Animate button press
tween(mainMenuContainer.settingsButton, {
scaleX: 1.8,
scaleY: 1.3
}, {
duration: 100,
onFinish: function onFinish() {
tween(mainMenuContainer.settingsButton, {
scaleX: 2.0,
scaleY: 1.5
}, {
duration: 100,
onFinish: function onFinish() {
showSettingsMenu();
}
});
}
});
return;
}
return; // Don't process game clicks in menu state
}
if (gameState === 'settings') {
// Check back button click
var dx = x - settingsMenuContainer.backButton.x;
var dy = y - settingsMenuContainer.backButton.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
// Animate button press
tween(settingsMenuContainer.backButton, {
scaleX: 1.3,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsMenuContainer.backButton, {
scaleX: 1.5,
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
showMainMenu();
}
});
}
});
return;
}
return; // Don't process game clicks in settings state
}
// Only process game clicks when in playing state
if (gameState !== 'playing') return;
// Check for save button click
var dx = x - saveButton.x;
var dy = y - saveButton.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
// Animate button press
tween(saveButton, {
scaleX: 0.8,
scaleY: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(saveButton, {
scaleX: 1.0,
scaleY: 0.6
}, {
duration: 100,
onFinish: function onFinish() {
// Save game state using individual storage properties
storage.savedScore = score;
storage.savedLevel = level;
storage.savedGold = gold;
storage.savedInventory = inventory;
storage.savedHourglassCount = hourglassCount;
storage.savedComboCount = savedComboCount;
storage.savedYellowCandiesClicked = yellowCandiesClicked;
storage.savedTimestamp = Date.now();
gameStateSaved = true;
// Show save confirmation
var savedText = new Text2('Game Saved!', {
size: 60,
fill: '#00FF00'
});
savedText.anchor.set(0.5, 0.5);
savedText.x = 1024;
savedText.y = 2500;
savedText.alpha = 0;
game.addChild(savedText);
tween(savedText, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(savedText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (savedText.parent) {
savedText.parent.removeChild(savedText);
}
}
});
}, 2000);
}
});
}
});
}
});
return;
}
if (isProcessing) return;
// Reset cascade combo when user makes a new move
cascadeComboCount = 0;
lastCascadeTime = 0;
// 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
// Activate Hidden Stars achievement tracking if not already achieved
if (!achievements.hiddenStars && !hiddenStarsActivated) {
hiddenStarsActivated = true;
hiddenStarsSequence = [];
return;
}
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 Hidden Stars achievement sequence tracking
if (hiddenStarsActivated && !achievements.hiddenStars) {
// Check if any of the numbered balls (1-4) are clicked by checking proximity to their positions
var ballPositions = [{
x: 512,
y: 683,
number: 1
},
// Ball 1
{
x: 1536,
y: 683,
number: 2
},
// Ball 2
{
x: 512,
y: 2049,
number: 3
},
// Ball 3
{
x: 1536,
y: 2049,
number: 4
} // Ball 4
];
for (var i = 0; i < ballPositions.length; i++) {
var pos = ballPositions[i];
var dx = x - pos.x;
var dy = y - pos.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
// Hit radius for sequence tracking
hiddenStarsSequence.push(pos.number);
// Visual feedback
var feedbackText = new Text2(pos.number.toString(), {
size: 80,
fill: '#FFD700'
});
feedbackText.anchor.set(0.5, 0.5);
feedbackText.x = pos.x;
feedbackText.y = pos.y - 200;
feedbackText.alpha = 0;
game.addChild(feedbackText);
tween(feedbackText, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
tween(feedbackText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (feedbackText.parent) {
feedbackText.parent.removeChild(feedbackText);
}
}
});
}
});
// Check achievement after each number
checkHiddenStarsAchievement();
// Reset sequence if it gets too long or wrong
if (hiddenStarsSequence.length > 4 || hiddenStarsSequence.length === 4 && !achievements.hiddenStars) {
if (!achievements.hiddenStars) {
hiddenStarsSequence = [];
}
}
return;
}
}
}
// 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;
}
if (selectedEternalCandy) {
selectedEternalCandy.graphics.tint = 0xFFD700;
tween(selectedEternalCandy, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100
});
selectedEternalCandy = null;
}
return;
}
// Check for double-click to use hourglass and create timeless Karadeniz
var currentTime = Date.now();
var isDoubleClick = currentTime - lastClickTime < DOUBLE_CLICK_THRESHOLD && lastClickedCandy === candy;
if (isDoubleClick && hourglassCount > 0 && candy && !candy.isSpecial) {
// Use hourglass to create timeless Karadeniz
hourglassCount--;
// Transform candy into timeless Karadeniz
candy.makeSpecial('expires');
candy.isTimeless = true;
candy.timelessHealth = 40; // Starts with 40 health
candy.maxTimelessHealth = 40;
// Add to timeless tracking array
timelessKaradenizCandies.push(candy);
// Create transformation effect
tween(candy.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4500,
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Start cracking effect animation
startCrackingEffect(candy);
}
});
// Show timeless creation notification
var timelessNotification = new Text2('TIMELESS KARADENIZ CREATED!', {
size: 70,
fill: '#FF4500'
});
timelessNotification.anchor.set(0.5, 0.5);
timelessNotification.x = 1024;
timelessNotification.y = 1200;
timelessNotification.alpha = 0;
game.addChild(timelessNotification);
tween(timelessNotification, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(timelessNotification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (timelessNotification.parent) {
timelessNotification.parent.removeChild(timelessNotification);
}
}
});
}, 2500);
}
});
updateUI();
LK.getSound('powerup').play();
// Reset click tracking
lastClickTime = 0;
lastClickedCandy = null;
return;
}
// Black hole click tracking for void creation
if (candy && candy.isSpecial && candy.specialType === 'blackHole') {
var key = getGridKey(candy.row, candy.col);
if (!blackHoleClickCounts[key]) blackHoleClickCounts[key] = 0;
blackHoleClickCounts[key]++;
// Visual feedback for click count
var clickText = new Text2(blackHoleClickCounts[key] + '/3', {
size: 60,
fill: '#6e00ff'
});
clickText.anchor.set(0.5, 0.5);
clickText.x = candy.x;
clickText.y = candy.y - 120;
clickText.alpha = 0;
game.addChild(clickText);
tween(clickText, {
alpha: 1,
scaleX: 1.3,
scaleY: 1.3,
y: candy.y - 150
}, {
duration: 200,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(clickText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
onFinish: function onFinish() {
if (clickText.parent) clickText.parent.removeChild(clickText);
}
});
}, 600);
}
});
// On 3rd click, create void and remove 2 hourglasses
if (blackHoleClickCounts[key] === 3) {
if (hourglassCount >= 2) {
hourglassCount -= 2;
// Remove black hole and create void
if (candy.parent) candy.parent.removeChild(candy);
grid[candy.row][candy.col] = null;
createVoidAt(candy.row, candy.col);
// Show void creation notification
var voidText = new Text2('VOID CREATED!', {
size: 80,
fill: '#6e00ff'
});
voidText.anchor.set(0.5, 0.5);
voidText.x = 1024;
voidText.y = 1366;
voidText.alpha = 0;
game.addChild(voidText);
tween(voidText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(voidText, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
if (voidText.parent) voidText.parent.removeChild(voidText);
}
});
}, 1200);
}
});
updateUI();
} else {
// Not enough hourglasses
var warnText = new Text2('Need 2 Hourglasses!', {
size: 60,
fill: '#FF0000'
});
warnText.anchor.set(0.5, 0.5);
warnText.x = 1024;
warnText.y = 1366;
warnText.alpha = 0;
game.addChild(warnText);
tween(warnText, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(warnText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
if (warnText.parent) warnText.parent.removeChild(warnText);
}
});
}, 1000);
}
});
}
blackHoleClickCounts[key] = 0;
return;
}
// On 5th click, transform into void directly
if (blackHoleClickCounts[key] === 5) {
// Transform black hole into void directly
candy.makeSpecial('void');
candy.specialType = 'void';
candy.type = 'void';
candy.voidComboType = null;
candy.voidComboActive = false;
// Replace graphics with void look
candy.removeChild(candy.graphics);
candy.graphics = candy.attachAsset('purpleCandy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
tween(candy.graphics, {
tint: 0x6e00ff,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
onFinish: function onFinish() {
tween(candy.graphics, {
tint: 0x9013fe,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300
});
}
});
// Add to void positions tracking
voidPositions.push({
row: candy.row,
col: candy.col
});
// Show void transformation notification
var voidText = new Text2('BLACK HOLE → VOID!', {
size: 80,
fill: '#6e00ff'
});
voidText.anchor.set(0.5, 0.5);
voidText.x = 1024;
voidText.y = 1366;
voidText.alpha = 0;
game.addChild(voidText);
tween(voidText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(voidText, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
if (voidText.parent) voidText.parent.removeChild(voidText);
}
});
}, 1200);
}
});
blackHoleClickCounts[key] = 0;
return;
}
// On 7th click, transform void into infinite void
if (blackHoleClickCounts[key] === 7) {
// Transform void into infinite void
candy.isInfiniteVoid = true;
candy.specialType = 'infiniteVoid';
// Enhanced visual effects for infinite void
candy.removeChild(candy.graphics);
candy.graphics = candy.attachAsset('purpleCandy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
tween(candy.graphics, {
tint: 0x4B0082,
scaleX: 1.5,
scaleY: 1.5,
rotation: Math.PI * 2
}, {
duration: 600,
onFinish: function onFinish() {
// Add continuous swirling effect for infinite void
var _swirl = function swirl() {
if (candy && candy.isInfiniteVoid && candy.parent) {
tween(candy.graphics, {
tint: 0x8A2BE2,
scaleX: 1.7,
scaleY: 1.7,
rotation: candy.graphics.rotation + Math.PI * 2
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(candy.graphics, {
tint: 0x4B0082,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_swirl, 100);
}
});
}
});
}
};
_swirl();
}
});
// Show infinite void transformation notification
var infiniteVoidText = new Text2('SONSUZ BOŞLUK!', {
size: 90,
fill: '#8A2BE2'
});
infiniteVoidText.anchor.set(0.5, 0.5);
infiniteVoidText.x = 1024;
infiniteVoidText.y = 1366;
infiniteVoidText.alpha = 0;
game.addChild(infiniteVoidText);
tween(infiniteVoidText, {
alpha: 1,
scaleX: 1.4,
scaleY: 1.4,
rotation: 0.1
}, {
duration: 600,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(infiniteVoidText, {
alpha: 0
}, {
duration: 600,
onFinish: function onFinish() {
if (infiniteVoidText.parent) infiniteVoidText.parent.removeChild(infiniteVoidText);
}
});
}, 1500);
}
});
LK.effects.flashScreen(0x8A2BE2, 1000);
blackHoleClickCounts[key] = 0;
return;
}
}
// Update click tracking for double-click detection
lastClickTime = currentTime;
lastClickedCandy = candy;
// Check if clicking on yellow candy for hourglass system (orange candies)
if (candy && candy.type === 'orange') {
// Create unique identifier for this candy position
var candyId = candy.row + '_' + candy.col + '_' + candy.type;
// Check if this yellow candy hasn't been clicked yet
var alreadyClicked = false;
for (var i = 0; i < yellowCandiesClicked.length; i++) {
if (yellowCandiesClicked[i] === candyId) {
alreadyClicked = true;
break;
}
}
// If candy hasn't been clicked yet, mark it as clicked
if (!alreadyClicked) {
yellowCandiesClicked.push(candyId);
// Check if we have 4 yellow candies clicked to create hourglass
if (yellowCandiesClicked.length >= 4) {
// Create hourglass
hourglassCount++;
// Reset yellow candies counter
yellowCandiesClicked = [];
// Save combo count for later use
savedComboCount = cascadeComboCount;
// Show hourglass creation notification
var hourglassNotification = new Text2('HOURGLASS CREATED!', {
size: 80,
fill: '#FFD700'
});
hourglassNotification.anchor.set(0.5, 0.5);
hourglassNotification.x = 1024;
hourglassNotification.y = 1200;
hourglassNotification.alpha = 0;
game.addChild(hourglassNotification);
tween(hourglassNotification, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(hourglassNotification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (hourglassNotification.parent) {
hourglassNotification.parent.removeChild(hourglassNotification);
}
}
});
}, 2000);
}
});
updateUI();
LK.getSound('powerup').play();
}
}
}
// Check if clicking on a ball (any candy) for Small Collector achievement
if (candy && !achievements.smallCollector) {
// Count total balls on first click if not already set
if (totalBallsToClick === 0) {
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (grid[row][col]) {
totalBallsToClick++;
}
}
}
}
// Create unique identifier for this ball position
var ballId = candy.row + '_' + candy.col;
// Check if this ball hasn't been clicked small yet
var alreadyClickedSmall = false;
for (var i = 0; i < ballsClickedSmall.length; i++) {
if (ballsClickedSmall[i] === ballId) {
alreadyClickedSmall = true;
break;
}
}
// If ball hasn't been clicked small yet, mark it as clicked small
if (!alreadyClickedSmall) {
ballsClickedSmall.push(ballId);
// Check if achievement should be unlocked
checkSmallCollectorAchievement();
}
}
// 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
});
}
});
// Handle eternal candy clicks first
if (isEternalCandy(candy)) {
if (selectedEternalCandy === null) {
// Select eternal candy
selectedEternalCandy = candy;
candy.graphics.tint = 0xFFFFFF;
tween(candy, {
scaleX: 1.6,
scaleY: 1.6
}, {
duration: 150
});
// Show instruction text
var instructionText = new Text2('Herhangi bir şekere tıklayın!', {
size: 60,
fill: '#FFD700'
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1100;
instructionText.alpha = 0;
game.addChild(instructionText);
tween(instructionText, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(instructionText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
if (instructionText.parent) instructionText.parent.removeChild(instructionText);
}
});
}, 2000);
}
});
return;
} else if (selectedEternalCandy === candy) {
// Deselect eternal candy
selectedEternalCandy.graphics.tint = 0xFFD700;
tween(selectedEternalCandy, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100
});
selectedEternalCandy = null;
return;
}
}
// If eternal candy is selected and we click another candy, swap them
if (selectedEternalCandy && candy !== selectedEternalCandy) {
if (handleEternalCandySwap(selectedEternalCandy, candy)) {
// Reset selection
selectedEternalCandy.graphics.tint = 0xFFD700;
selectedEternalCandy = null;
// Process matches after swap
LK.setTimeout(function () {
// Check for matches at both positions
processMatches();
}, 400);
return;
}
}
// Click-to-select then click-to-swap mode
if (selectedCandy === null) {
// Check if player has reached 3 consecutive combos and should activate hourglass
if (hourglassCount > 0 && cascadeComboCount >= 3) {
// Use hourglass to maintain super combo level
hourglassCount--;
// Keep combo at super combo level (level 3)
cascadeComboCount = 3;
savedComboCount = 3;
lastCascadeTime = Date.now();
// Show hourglass activation notification
var hourglassUseNotification = new Text2('HOURGLASS ACTIVATED! SUPER COMBO MAINTAINED!', {
size: 65,
fill: '#FFD700'
});
hourglassUseNotification.anchor.set(0.5, 0.5);
hourglassUseNotification.x = 1024;
hourglassUseNotification.y = 1200;
hourglassUseNotification.alpha = 0;
game.addChild(hourglassUseNotification);
tween(hourglassUseNotification, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(hourglassUseNotification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (hourglassUseNotification.parent) {
hourglassUseNotification.parent.removeChild(hourglassUseNotification);
}
}
});
}, 2000);
}
});
// Show current combo display
if (cascadeComboCount >= 1 && cascadeComboCount <= 7) {
showCascadeComboDisplay(cascadeComboCount);
}
updateUI();
LK.getSound('powerup').play();
}
// Check if clicking on a supernova - activate it directly (but not if just created)
if (candy.isSpecial && candy.specialType === 'supernova' && !candy.justCreated) {
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 (but not if just created)
if (candy.isSpecial && candy.specialType === 'supernova' && !candy.justCreated) {
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' && !tempSelectedCandy.justCreated) {
activateSpecialCandy(tempSelectedCandy);
}
if (candy.isSpecial && candy.specialType !== 'supernova' && !candy.justCreated) {
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' && !tempSelectedCandy.justCreated) {
activateSpecialCandy(tempSelectedCandy);
}
if (targetCandy.isSpecial && targetCandy.specialType !== 'supernova' && !targetCandy.justCreated) {
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 = [];
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', 'converter'];
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 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;
// 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 save button
var saveButton = LK.getAsset('greenCandy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 0.6
});
saveButton.x = 1024;
saveButton.y = 2600;
gameContainer.addChild(saveButton);
var saveButtonText = new Text2('SAVE GAME', {
size: 50,
fill: '#FFFFFF'
});
saveButtonText.anchor.set(0.5, 0.5);
saveButtonText.x = 1024;
saveButtonText.y = 2600;
gameContainer.addChild(saveButtonText);
// Try to load saved game state on startup
LK.setTimeout(function () {
if (storage.savedScore !== undefined) {
score = storage.savedScore || 0;
level = storage.savedLevel || 1;
gold = storage.savedGold || 0;
inventory = storage.savedInventory || {};
hourglassCount = storage.savedHourglassCount || 0;
savedComboCount = storage.savedComboCount || 0;
yellowCandiesClicked = storage.savedYellowCandiesClicked || [];
storage.gold = gold;
storage.inventory = inventory;
updateUI();
gameStateSaved = true;
// Show loaded message
var loadedText = new Text2('Game Loaded!', {
size: 60,
fill: '#00FF00'
});
loadedText.anchor.set(0.5, 0.5);
loadedText.x = 1024;
loadedText.y = 2500;
loadedText.alpha = 0;
game.addChild(loadedText);
tween(loadedText, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(loadedText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (loadedText.parent) {
loadedText.parent.removeChild(loadedText);
}
}
});
}, 2000);
}
});
}
// Load achievements from storage
if (storage.smallCollectorAchieved) {
achievements.smallCollector = true;
}
if (storage.hiddenStarsAchieved) {
achievements.hiddenStars = true;
}
if (storage.leaguesAchieved) {
achievements.leagues = true;
}
if (storage.universeAchieved) {
achievements.universe = true;
}
}, 1000);
// Menu navigation functions
function showMainMenu() {
gameState = 'menu';
// Show main menu
mainMenuContainer.alpha = 1;
// Hide other menus and game
if (settingsMenuContainer) settingsMenuContainer.alpha = 0;
if (gameContainer) gameContainer.alpha = 0;
}
function showSettingsMenu() {
gameState = 'settings';
// Hide main menu
mainMenuContainer.alpha = 0;
// Show settings menu with animation
tween(settingsMenuContainer, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
function startGame() {
gameState = 'playing';
// Hide all menus
mainMenuContainer.alpha = 0;
if (settingsMenuContainer) settingsMenuContainer.alpha = 0;
// Show game with animation
tween(gameContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Initialize the game after animation
initializeGrid();
removeInitialMatches();
// Give starting gold for new market experience
gold = 1000;
storage.gold = gold;
updateUI();
LK.playMusic('7week3days');
}
});
}
// Start with main menu visible
showMainMenu();
;
// Track current cascade combo text to prevent overlapping
var currentCascadeText = null;
function showCascadeComboDisplay(comboLevel) {
if (comboLevel < 1 || comboLevel > 7) return;
var comboName = cascadeComboNames[comboLevel];
if (!comboName) return;
// Remove previous cascade text immediately if it exists
if (currentCascadeText && currentCascadeText.parent) {
tween.stop(currentCascadeText);
currentCascadeText.parent.removeChild(currentCascadeText);
currentCascadeText = null;
}
// Create cascade combo text
var cascadeText = new Text2(comboName, {
size: 100 + comboLevel * 20,
// Size increases with combo level
fill: comboLevel <= 2 ? '#FFFF00' : comboLevel <= 4 ? '#FF8C00' : comboLevel <= 6 ? '#FF0000' : '#FFD700' // Colors get more intense
});
cascadeText.anchor.set(0.5, 0.5);
cascadeText.x = 1024;
cascadeText.y = 1000; // Position below center
cascadeText.alpha = 0;
cascadeText.scaleX = 0.3;
cascadeText.scaleY = 0.3;
game.addChild(cascadeText);
// Set as current cascade text
currentCascadeText = cascadeText;
// Animate cascade text with increasing intensity
var animationDuration = Math.max(800 - comboLevel * 50, 300); // Faster for higher combos
tween(cascadeText, {
alpha: 1,
scaleX: 1.0 + comboLevel * 0.2,
scaleY: 1.0 + comboLevel * 0.2,
rotation: comboLevel % 2 === 0 ? 0.1 : -0.1 // Alternate rotation
}, {
duration: animationDuration,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Hold briefly then fade out
LK.setTimeout(function () {
tween(cascadeText, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 400,
easing: tween.easeIn,
onFinish: function onFinish() {
if (cascadeText.parent) {
cascadeText.parent.removeChild(cascadeText);
}
// Clear reference if this is still the current text
if (currentCascadeText === cascadeText) {
currentCascadeText = null;
}
}
});
}, 1000 + comboLevel * 200); // Hold longer for higher combos
}
});
// Add screen flash effect for higher combos
if (comboLevel >= 3) {
var flashColor = comboLevel <= 4 ? 0xFF8C00 : comboLevel <= 6 ? 0xFF0000 : 0xFFD700;
var flashDuration = Math.min(200 + comboLevel * 100, 800);
LK.effects.flashScreen(flashColor, flashDuration);
}
// Play sound effect
LK.getSound('powerup').play();
}
function createSupernovaReward() {
// Find a random empty position or replace a regular 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 && Math.random() < 0.3) {
availablePositions.push({
row: row,
col: col
});
}
}
}
if (availablePositions.length > 0) {
var randomPos = availablePositions[Math.floor(Math.random() * availablePositions.length)];
var row = randomPos.row;
var col = randomPos.col;
// Remove existing candy if present
if (grid[row][col] && grid[row][col].parent) {
grid[row][col].parent.removeChild(grid[row][col]);
}
// Create supernova reward
var rewardColor = COLORS[Math.floor(Math.random() * COLORS.length)];
var supernovaReward = new Candy(rewardColor, row, col);
supernovaReward.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2;
supernovaReward.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2;
supernovaReward.makeSpecial('supernova');
grid[row][col] = supernovaReward;
game.addChild(supernovaReward);
// Add spectacular creation effect for the reward
tween(supernovaReward.graphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFD700,
rotation: Math.PI * 4
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Add continuous pulsing glow effect
var _pulseSuperNova = function pulseSuperNova() {
if (supernovaReward && supernovaReward.isSpecial && supernovaReward.specialType === 'supernova' && supernovaReward.parent) {
tween(supernovaReward.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFF00
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(supernovaReward.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFFFF
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(_pulseSuperNova, 200);
}
});
}
});
}
};
_pulseSuperNova();
}
});
// Add massive bonus for 7th cascade combo
score += 50000;
gold += 25000;
updateUI();
// Show special reward text
var rewardText = new Text2('SUPERNOVA REWARD!', {
size: 140,
fill: '#FFD700'
});
rewardText.anchor.set(0.5, 0.5);
rewardText.x = 1024;
rewardText.y = 800;
rewardText.alpha = 0;
rewardText.scaleX = 0.2;
rewardText.scaleY = 0.2;
game.addChild(rewardText);
tween(rewardText, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5,
rotation: 0.1
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(rewardText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
if (rewardText.parent) {
rewardText.parent.removeChild(rewardText);
}
}
});
}, 2000);
}
});
// Create spectacular screen effects
LK.effects.flashScreen(0xFFD700, 1500);
}
}
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);
}
function checkSmallCollectorAchievement() {
// Check if all balls have been clicked to small size
if (!achievements.smallCollector && ballsClickedSmall.length >= totalBallsToClick && totalBallsToClick > 0) {
// Achievement unlocked!
achievements.smallCollector = true;
// Save achievement to storage
storage.smallCollectorAchieved = true;
// Award +5000 gold
gold += 5000;
storage.gold = gold;
updateUI();
// Show achievement notification
showAchievementNotification('SMALL COLLECTOR', 'All balls clicked small!', '+5000 Gold');
// Play achievement sound
LK.getSound('powerup').play();
}
}
function checkHiddenStarsAchievement() {
// Check if the sequence 1, 1, 1, 3 has been entered after clicking shooting star
if (!achievements.hiddenStars && hiddenStarsActivated && hiddenStarsSequence.length >= 4) {
if (hiddenStarsSequence[0] === 1 && hiddenStarsSequence[1] === 1 && hiddenStarsSequence[2] === 1 && hiddenStarsSequence[3] === 3) {
// Achievement unlocked!
achievements.hiddenStars = true;
// Save achievement to storage
storage.hiddenStarsAchieved = true;
// Award +8000 gold
gold += 8000;
// Ensure gold is saved to storage
storage.gold = gold;
updateUI();
// Show achievement notification
showAchievementNotification('HIDDEN STARS', 'Secret sequence discovered!', '+8000 Gold');
// Play achievement sound
LK.getSound('powerup').play();
// Reset the tracking variables
hiddenStarsActivated = false;
hiddenStarsSequence = [];
}
}
}
function checkLeaguesAchievement() {
// Check if player has reached level 4
if (!achievements.leagues && level >= 4) {
// Achievement unlocked!
achievements.leagues = true;
// Save achievement to storage
storage.leaguesAchieved = true;
// Add special rewards to map: 1 supernova, 1 Karadeniz, 2 writerpir
var rewardsAdded = 0;
var maxRewards = 4;
// Find positions to place rewards
for (var row = 0; row < GRID_SIZE && rewardsAdded < maxRewards; row++) {
for (var col = 0; col < GRID_SIZE && rewardsAdded < maxRewards; col++) {
if (grid[row][col] && !grid[row][col].isSpecial && Math.random() < 0.3) {
var rewardType;
if (rewardsAdded === 0) {
rewardType = 'supernova'; // 1 supernova
} else if (rewardsAdded === 1) {
rewardType = 'expires'; // 1 Karadeniz (using expires asset)
} else {
rewardType = 'writerpir'; // 2 writerpir
}
// Transform existing candy into reward
grid[row][col].makeSpecial(rewardType);
// Add creation sparkle effect
tween(grid[row][col].graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFD700
}, {
duration: 500,
easing: tween.bounceOut
});
rewardsAdded++;
}
}
}
updateUI();
// Show achievement notification
showAchievementNotification('LEAGUES', 'Reached Level 4!', 'Special rewards added to map!');
// Play achievement sound
LK.getSound('powerup').play();
}
}
function checkUniverseAchievement() {
// Check if a Karadeniz (expires) has been produced
if (!achievements.universe) {
// Achievement unlocked!
achievements.universe = true;
// Save achievement to storage
storage.universeAchieved = true;
// Award +2000 gold
gold += 2000;
storage.gold = gold;
updateUI();
// Show achievement notification
showAchievementNotification('UNIVERSE', 'Karadeniz produced!', '+2000 Gold');
// Play achievement sound
LK.getSound('powerup').play();
}
}
function checkTimelessKaradenizCombinations(allMatches) {
// First check for timeless Karadeniz + timeless Karadeniz combinations
for (var m = 0; m < allMatches.length; m++) {
var matches = allMatches[m];
// Count timeless Karadeniz in this match
var timelessCount = 0;
var timelessCandies = [];
for (var i = 0; i < matches.length; i++) {
var candy = matches[i];
if (candy && candy.isTimeless && candy.specialType === 'expires') {
timelessCount++;
timelessCandies.push(candy);
}
}
// If we have 2 or more timeless Karadeniz in the same match, create warlek
if (timelessCount >= 2) {
// Create warlek effect - turn all candies purple
var firstTimeless = timelessCandies[0];
var secondTimeless = timelessCandies[1];
// Remove both timeless Karadeniz from tracking
for (var t = timelessKaradenizCandies.length - 1; t >= 0; t--) {
if (timelessKaradenizCandies[t] === firstTimeless || timelessKaradenizCandies[t] === secondTimeless) {
timelessKaradenizCandies.splice(t, 1);
}
}
// Create warlek at first timeless position
firstTimeless.makeSpecial('ultraSupernova');
firstTimeless.isTimeless = false;
firstTimeless.specialType = 'warlek';
firstTimeless.isSpecial = true;
// Remove second timeless
grid[secondTimeless.row][secondTimeless.col] = null;
secondTimeless.explode();
// Create spectacular warlek creation effect
tween(firstTimeless.graphics, {
scaleX: 3.0,
scaleY: 3.0,
tint: 0x9013fe,
rotation: Math.PI * 8
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Turn all candies purple with wave effect
turnAllCandiesPurple(firstTimeless);
}
});
// Show warlek creation notification
var warlekText = new Text2('WARLEK CREATED!', {
size: 120,
fill: '#9013fe'
});
warlekText.anchor.set(0.5, 0.5);
warlekText.x = 1024;
warlekText.y = 1366;
warlekText.alpha = 0;
game.addChild(warlekText);
tween(warlekText, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5,
rotation: 0.2
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(warlekText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
if (warlekText.parent) {
warlekText.parent.removeChild(warlekText);
}
}
});
}, 2000);
}
});
// Add massive bonus for warlek creation
score += 50000;
gold += 25000;
updateUI();
LK.effects.flashScreen(0x9013fe, 1500);
LK.getSound('powerup').play();
// Clear the match to prevent further processing
matches.length = 0;
return; // Exit early since warlek was created
}
}
// Check each match group for timeless Karadeniz participation
for (var m = 0; m < allMatches.length; m++) {
var matches = allMatches[m];
// Look for timeless Karadeniz in this match
for (var i = 0; i < matches.length; i++) {
var candy = matches[i];
if (candy && candy.isTimeless && candy.specialType === 'expires') {
// Found timeless Karadeniz in match - it can combine with any candy type
var combiningCandiesCount = matches.length - 1; // Exclude the timeless Karadeniz itself
candy.timelessHealth -= combiningCandiesCount;
// Update cracking effect based on new health
startCrackingEffect(candy);
// Show health status
showTimelessHealthStatus(candy);
// Explode only the combining candies, not the timeless Karadeniz
for (var j = 0; j < matches.length; j++) {
if (matches[j] !== candy) {
// This is a combining candy - explode it with score
explodeCandyWithScore(matches[j]);
grid[matches[j].row][matches[j].col] = null;
}
}
// Check if timeless Karadeniz should explode (when health reaches 0, meaning 40 candies combined)
if (candy.timelessHealth <= 0) {
// Store position for potential recreation
var timelessRow = candy.row;
var timelessCol = candy.col;
// Remove from timeless tracking array
for (var t = 0; t < timelessKaradenizCandies.length; t++) {
if (timelessKaradenizCandies[t] === candy) {
timelessKaradenizCandies.splice(t, 1);
break;
}
}
// Explode the timeless Karadeniz and entire map
explodeEntireMap(candy);
// Schedule check for new combo formation after explosion effects complete
LK.setTimeout(function () {
// Check if new combos formed at the same position after explosion
var newMatches = checkMatch(timelessRow, timelessCol);
if (newMatches.length >= 3) {
// New combo formed - recreate timeless Karadeniz
recreateTimelessKaradeniz(timelessRow, timelessCol);
}
}, 1000); // Wait for explosion effects to complete
return; // Exit early since map exploded
}
// Remove ALL candies from this match since they've been processed
// This prevents them from being processed again in the normal match logic
matches.length = 0;
break; // Only one timeless Karadeniz per match
}
}
}
// Also check for adjacent combinations with timeless Karadeniz
checkTimelessAdjacentCombinations();
}
function checkTimelessAdjacentCombinations() {
// Check if any timeless Karadeniz has adjacent candies it can combine with
for (var t = 0; t < timelessKaradenizCandies.length; t++) {
var timelessCandy = timelessKaradenizCandies[t];
if (!timelessCandy || !timelessCandy.parent) continue;
var row = timelessCandy.row;
var col = timelessCandy.col;
var adjacentPositions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
// Check each adjacent position for any candy to combine with
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];
// Timeless Karadeniz can combine with any candy type
if (adjacentCandy && adjacentCandy !== timelessCandy && !adjacentCandy.isTimeless) {
// Timeless Karadeniz combines with this adjacent candy directly
timelessCandy.timelessHealth -= 1; // Reduce health by 1 for each candy it combines with
// Update cracking effect
startCrackingEffect(timelessCandy);
// Show health status
showTimelessHealthStatus(timelessCandy);
// Remove the adjacent candy (it gets "consumed" by timeless Karadeniz)
explodeCandyWithScore(adjacentCandy);
grid[adjRow][adjCol] = null;
// Check if timeless Karadeniz should explode (reached 40 combinations)
if (timelessCandy.timelessHealth <= 0) {
// Remove from tracking array
for (var tr = 0; tr < timelessKaradenizCandies.length; tr++) {
if (timelessKaradenizCandies[tr] === timelessCandy) {
timelessKaradenizCandies.splice(tr, 1);
break;
}
}
// Explode entire map
explodeEntireMap(timelessCandy);
return;
}
break; // Only process one adjacent candy per timeless candy per cycle
}
}
}
}
}
function showTimelessHealthStatus(candy) {
if (!candy || !candy.isTimeless) return;
// Calculate remaining combinations needed (health represents remaining combinations)
var remainingCombinations = candy.timelessHealth;
var totalCombinations = 40;
var completedCombinations = totalCombinations - remainingCombinations;
// Create status text showing combinations progress
var statusText = new Text2(completedCombinations + '/' + totalCombinations, {
size: 60,
fill: remainingCombinations > 20 ? '#FFD700' : remainingCombinations > 10 ? '#FF8C00' : '#FF0000'
});
statusText.anchor.set(0.5, 0.5);
statusText.x = candy.x;
statusText.y = candy.y - 120;
statusText.alpha = 0;
game.addChild(statusText);
// Animate status text
tween(statusText, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5,
y: candy.y - 150
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(statusText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
onFinish: function onFinish() {
if (statusText.parent) {
statusText.parent.removeChild(statusText);
}
}
});
}, 1000);
}
});
}
function explodeEntireMap(timelessCandy) {
// Transform timeless Karadeniz into red rocket instead of exploding
if (timelessCandy && timelessCandy.parent) {
// Remove timeless properties
timelessCandy.isTimeless = false;
timelessCandy.timelessHealth = 0;
// Transform into red rocket
timelessCandy.makeSpecial('redRocket');
timelessCandy.justCreated = true; // Prevent immediate activation
// Create transformation effect
tween(timelessCandy.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x991b1b,
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Reset creation flag after animation
LK.setTimeout(function () {
if (timelessCandy && timelessCandy.parent) {
timelessCandy.justCreated = false;
}
}, 500);
}
});
// Add score bonus for transformation
score += 15000;
gold += 7500;
updateUI();
// Create transformation effects
LK.effects.flashScreen(0x991b1b, 1000);
// Show transformation notification
var transformText = new Text2('TIMELESS KARADENIZ → RED ROCKET!', {
size: 100,
fill: '#991b1b'
});
transformText.anchor.set(0.5, 0.5);
transformText.x = 1024;
transformText.y = 1366;
transformText.alpha = 0;
transformText.scaleX = 0.5;
transformText.scaleY = 0.5;
game.addChild(transformText);
tween(transformText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(transformText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
if (transformText.parent) {
transformText.parent.removeChild(transformText);
}
}
});
}, 2000);
}
});
}
}
function startCrackingEffect(candy) {
if (!candy || !candy.isTimeless || !candy.parent) return;
// Calculate crack intensity based on combination progress (40 total combinations needed)
var totalCombinations = 40;
var completedCombinations = totalCombinations - candy.timelessHealth;
var crackIntensity = completedCombinations / totalCombinations; // More cracks as more combinations completed
// Create cracking visual effect with scale pulsing
var pulseScale = 1.0 + crackIntensity * 0.5; // More intense pulsing as more combinations completed
var pulseSpeed = Math.max(2000 - crackIntensity * 1500, 300); // Faster pulsing as more combinations completed
// Apply cracking tint - gets redder as more combinations completed
var crackTint = 0xFF4500; // Orange base
if (crackIntensity > 0.75) {
crackTint = 0xFF0000; // Red when close to explosion (30+ combinations)
} else if (crackIntensity > 0.5) {
crackTint = 0xFF2500; // Dark orange when moderately damaged (20+ combinations)
} else if (crackIntensity > 0.25) {
crackTint = 0xFF3500; // Light orange when lightly damaged (10+ combinations)
}
tween(candy.graphics, {
scaleX: pulseScale,
scaleY: pulseScale,
tint: crackTint,
alpha: 0.8 + crackIntensity * 0.2
}, {
duration: pulseSpeed / 2,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (candy && candy.isTimeless && candy.parent) {
tween(candy.graphics, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 1.0
}, {
duration: pulseSpeed / 2,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue cracking effect if still timeless and alive
if (candy && candy.isTimeless && candy.parent && candy.timelessHealth > 0) {
LK.setTimeout(function () {
startCrackingEffect(candy);
}, 100);
}
}
});
}
}
});
}
function showAchievementNotification(title, description, reward) {
// Create achievement notification background
var achievementBg = LK.getAsset('progressBarBg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 3.0
});
achievementBg.x = 1024;
achievementBg.y = 1366;
achievementBg.alpha = 0;
game.addChild(achievementBg);
// Create achievement title text
var titleText = new Text2(title, {
size: 80,
fill: '#FFD700'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 1266;
titleText.alpha = 0;
game.addChild(titleText);
// Create achievement description text
var descText = new Text2(description, {
size: 60,
fill: '#FFFFFF'
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 1366;
descText.alpha = 0;
game.addChild(descText);
// Create achievement reward text
var rewardText = new Text2(reward, {
size: 70,
fill: '#00FF00'
});
rewardText.anchor.set(0.5, 0.5);
rewardText.x = 1024;
rewardText.y = 1466;
rewardText.alpha = 0;
game.addChild(rewardText);
// Animate achievement notification appearing
tween(achievementBg, {
alpha: 0.9,
scaleX: 2.2,
scaleY: 3.2
}, {
duration: 300,
easing: tween.bounceOut
});
tween(titleText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.bounceOut
});
tween(descText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(rewardText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
// Fade out all elements
tween(achievementBg, {
alpha: 0,
scaleX: 1.8,
scaleY: 2.8
}, {
duration: 500,
easing: tween.easeIn
});
tween(titleText, {
alpha: 0,
scaleY: 0.8
}, {
duration: 500,
easing: tween.easeIn
});
tween(descText, {
alpha: 0
}, {
duration: 500,
easing: tween.easeIn
});
tween(rewardText, {
alpha: 0,
scaleY: 0.8
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
// Clean up elements
if (achievementBg.parent) achievementBg.parent.removeChild(achievementBg);
if (titleText.parent) titleText.parent.removeChild(titleText);
if (descText.parent) descText.parent.removeChild(descText);
if (rewardText.parent) rewardText.parent.removeChild(rewardText);
}
});
}, 3000);
}
});
// Add screen flash effect
LK.effects.flashScreen(0xFFD700, 500);
}
;
function recreateTimelessKaradeniz(row, col) {
// Check if position is valid and has a candy
if (row >= 0 && row < GRID_SIZE && col >= 0 && col < GRID_SIZE && grid[row] && grid[row][col]) {
var candy = grid[row][col];
// Transform candy into timeless Karadeniz
candy.makeSpecial('expires');
candy.isTimeless = true;
candy.timelessHealth = 40; // Reset with full health
candy.maxTimelessHealth = 40;
// Add to timeless tracking array
timelessKaradenizCandies.push(candy);
// Create recreation effect
tween(candy.graphics, {
scaleX: 1.8,
scaleY: 1.8,
tint: 0xFF4500,
rotation: Math.PI * 3
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Start cracking effect animation
startCrackingEffect(candy);
}
});
// Show recreation notification
var recreationText = new Text2('TIMELESS KARADENIZ REBORN!', {
size: 80,
fill: '#FF4500'
});
recreationText.anchor.set(0.5, 0.5);
recreationText.x = 1024;
recreationText.y = 1200;
recreationText.alpha = 0;
game.addChild(recreationText);
tween(recreationText, {
alpha: 1,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 600,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(recreationText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (recreationText.parent) {
recreationText.parent.removeChild(recreationText);
}
}
});
}, 2000);
}
});
// Add bonus for recreation
score += 5000;
gold += 2500;
updateUI();
LK.getSound('powerup').play();
LK.effects.flashScreen(0xFF4500, 800);
}
}
function turnAllCandiesPurple(warlekCandy) {
// Turn all candies on the grid purple with expanding wave effect
var centerRow = warlekCandy.row;
var centerCol = warlekCandy.col;
var maxDistance = Math.max(GRID_SIZE, GRID_SIZE);
for (var distance = 1; distance <= maxDistance; distance++) {
(function (dist) {
LK.setTimeout(function () {
// Collect all candies at this distance
var candiesAtDistance = [];
for (var r = 0; r < GRID_SIZE; r++) {
for (var c = 0; c < GRID_SIZE; c++) {
var actualDist = Math.max(Math.abs(r - centerRow), Math.abs(c - centerCol));
if (actualDist === dist && grid[r][c] && grid[r][c] !== warlekCandy) {
candiesAtDistance.push(grid[r][c]);
}
}
}
// Transform all candies at this distance to purple
for (var i = 0; i < candiesAtDistance.length; i++) {
(function (targetCandy, index) {
if (targetCandy && targetCandy.parent) {
// Update candy type to purple
targetCandy.type = 'purple';
// Remove old graphics
targetCandy.removeChild(targetCandy.graphics);
// Create new purple graphics
targetCandy.graphics = targetCandy.attachAsset('purpleCandy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Reset special properties
targetCandy.isSpecial = false;
targetCandy.specialType = null;
targetCandy.isTimeless = false;
// Add transformation effect
tween(targetCandy.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0x9013fe
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(targetCandy.graphics, {
scaleX: 0.8,
scaleY: 0.8,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
})(candiesAtDistance[i], i);
}
}, dist * 150); // Stagger waves outward
})(distance);
}
} ===================================================================
--- original.js
+++ change.js
@@ -22,10 +22,9 @@
'blue': 'blueCandy',
'red': 'redCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
- 'purple': 'purpleCandy',
- 'void': 'purpleCandy'
+ 'purple': 'purpleCandy'
};
var specialAssetMap = {
'blueBomb': 'blueBomb',
'redRocket': 'redRocket',
@@ -46,35 +45,8 @@
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
- // Apply void-specific visual treatment
- if (type === 'void') {
- self.isSpecial = true;
- self.specialType = 'void';
- // Apply void tinting
- tween(self.graphics, {
- tint: 0x6e00ff,
- scaleX: 1.0,
- scaleY: 1.0
- }, {
- duration: 200,
- onFinish: function onFinish() {
- tween(self.graphics, {
- tint: 0x9013fe,
- scaleX: 0.8,
- scaleY: 0.8
- }, {
- duration: 200
- });
- }
- });
- // Add to void positions tracking
- voidPositions.push({
- row: row,
- col: col
- });
- }
self.makeSpecial = function (specialType) {
self.isSpecial = true;
self.specialType = specialType;
// Stop any existing pattern animations by stopping all tweens on graphics
@@ -241,9 +213,9 @@
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', 'void'];
+var COLORS = ['blue', 'red', 'green', 'orange', 'purple'];
var grid = [];
var selectedCandy = null;
var score = 0;
var level = 1;
@@ -274,12 +246,171 @@
var DOUBLE_CLICK_THRESHOLD = 500; // Maximum time between clicks for double-click (ms)
// Black hole click tracking for void creation
var blackHoleClickCounts = {}; // key: row_col, value: click count
var voidPositions = []; // Array of {row, col} for voids on the grid
+var eternalCandies = []; // Array to track eternal candies on the grid
+var selectedEternalCandy = null; // Track selected eternal candy for swapping
// Helper: get key for black hole/void click tracking
function getGridKey(row, col) {
return row + "_" + col;
}
+// Helper: create an eternal candy at a given position
+function createEternalCandy(row, col) {
+ // Remove any candy at this position
+ if (grid[row][col] && grid[row][col].parent) {
+ grid[row][col].parent.removeChild(grid[row][col]);
+ }
+ // Create eternal candy (special candy with unique properties)
+ var eternalCandy = new Candy('purple', row, col);
+ eternalCandy.isSpecial = true;
+ eternalCandy.specialType = 'eternal';
+ eternalCandy.type = 'eternal';
+ eternalCandy.canSwapAnywhere = true;
+ // Replace graphics with a unique eternal look (golden glowing purple)
+ eternalCandy.removeChild(eternalCandy.graphics);
+ eternalCandy.graphics = eternalCandy.attachAsset('purpleCandy', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+ });
+ tween(eternalCandy.graphics, {
+ tint: 0xFFD700,
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ // Add continuous golden glow effect
+ var _pulseEternal = function pulseEternal() {
+ if (eternalCandy && eternalCandy.parent && eternalCandy.specialType === 'eternal') {
+ tween(eternalCandy.graphics, {
+ tint: 0xFFFF00,
+ scaleX: 1.5,
+ scaleY: 1.5,
+ alpha: 0.9
+ }, {
+ duration: 1000,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(eternalCandy.graphics, {
+ tint: 0xFFD700,
+ scaleX: 1.3,
+ scaleY: 1.3,
+ alpha: 1.0
+ }, {
+ duration: 1000,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ LK.setTimeout(_pulseEternal, 200);
+ }
+ });
+ }
+ });
+ }
+ };
+ _pulseEternal();
+ }
+ });
+ // Add to grid and game
+ grid[row][col] = eternalCandy;
+ gameContainer.addChild(eternalCandy);
+ // Track eternal candy
+ eternalCandies.push({
+ row: row,
+ col: col
+ });
+ // Visual effect
+ LK.effects.flashScreen(0xFFD700, 1000);
+ // Show notification
+ var eternalText = new Text2('EBEDI ŞEKER YARATILDI!', {
+ size: 90,
+ fill: '#FFD700'
+ });
+ eternalText.anchor.set(0.5, 0.5);
+ eternalText.x = 1024;
+ eternalText.y = 1366;
+ eternalText.alpha = 0;
+ game.addChild(eternalText);
+ tween(eternalText, {
+ alpha: 1,
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ LK.setTimeout(function () {
+ tween(eternalText, {
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ if (eternalText.parent) eternalText.parent.removeChild(eternalText);
+ }
+ });
+ }, 1500);
+ }
+ });
+}
+// Helper: check if a candy is eternal
+function isEternalCandy(candy) {
+ return candy && candy.isSpecial && candy.specialType === 'eternal';
+}
+// Helper: handle eternal candy swapping with any candy on the map
+function handleEternalCandySwap(eternalCandy, targetCandy) {
+ if (!eternalCandy || !targetCandy || eternalCandy === targetCandy) return false;
+ var eternalRow = eternalCandy.row;
+ var eternalCol = eternalCandy.col;
+ var targetRow = targetCandy.row;
+ var targetCol = targetCandy.col;
+ // Swap positions in grid
+ grid[eternalRow][eternalCol] = targetCandy;
+ grid[targetRow][targetCol] = eternalCandy;
+ // Update candy properties
+ eternalCandy.row = targetRow;
+ eternalCandy.col = targetCol;
+ targetCandy.row = eternalRow;
+ targetCandy.col = eternalCol;
+ // Animate the swap with spectacular effect
+ tween(eternalCandy, {
+ x: GRID_START_X + targetCol * CELL_SIZE + CELL_SIZE / 2,
+ y: GRID_START_Y + targetRow * CELL_SIZE + CELL_SIZE / 2,
+ scaleX: 1.5,
+ scaleY: 1.5,
+ tint: 0xFFFFFF
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(eternalCandy, {
+ scaleX: 1.3,
+ scaleY: 1.3,
+ tint: 0xFFD700
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ }
+ });
+ tween(targetCandy, {
+ x: GRID_START_X + eternalCol * CELL_SIZE + CELL_SIZE / 2,
+ y: GRID_START_Y + eternalRow * CELL_SIZE + CELL_SIZE / 2
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ // Update eternal candy position tracking
+ for (var i = 0; i < eternalCandies.length; i++) {
+ if (eternalCandies[i].row === eternalRow && eternalCandies[i].col === eternalCol) {
+ eternalCandies[i].row = targetRow;
+ eternalCandies[i].col = targetCol;
+ break;
+ }
+ }
+ // Create swap effect
+ LK.effects.flashScreen(0xFFD700, 500);
+ return true;
+}
// Helper: create a void at a given position
function createVoidAt(row, col) {
// Remove any candy at this position
if (grid[row][col] && grid[row][col].parent) {
@@ -354,15 +485,41 @@
// Helper: handle void combo logic
function handleVoidCombo(matchArr) {
// Find if any void is in this match
var voidCandy = null;
+ var infiniteVoidCandy = null;
for (var i = 0; i < matchArr.length; i++) {
if (isVoidCandy(matchArr[i])) {
voidCandy = matchArr[i];
+ // Check if this is an infinite void (enhanced void with special property)
+ if (matchArr[i].isInfiniteVoid) {
+ infiniteVoidCandy = matchArr[i];
+ }
break;
}
}
if (!voidCandy) return false;
+ // Check for infinite void + purple candy combo first
+ if (infiniteVoidCandy) {
+ var purpleCandy = null;
+ for (var i = 0; i < matchArr.length; i++) {
+ if (matchArr[i] !== infiniteVoidCandy && matchArr[i].type === 'purple' && !matchArr[i].isSpecial) {
+ purpleCandy = matchArr[i];
+ break;
+ }
+ }
+ if (purpleCandy) {
+ // Create eternal candy at infinite void position
+ createEternalCandy(infiniteVoidCandy.row, infiniteVoidCandy.col);
+ // Remove purple candy
+ grid[purpleCandy.row][purpleCandy.col] = null;
+ purpleCandy.explode();
+ // Remove infinite void
+ grid[infiniteVoidCandy.row][infiniteVoidCandy.col] = null;
+ infiniteVoidCandy.explode();
+ return true;
+ }
+ }
// Find the type of candy being comboed with void
var comboType = null;
for (var i = 0; i < matchArr.length; i++) {
if (matchArr[i] !== voidCandy && !isVoidCandy(matchArr[i])) {
@@ -891,14 +1048,11 @@
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (checkMatch(row, col).length >= 3) {
hasMatches = true;
- // Random color with 1% chance for void, 5% chance for purple
+ // Random color with 5% chance for purple
var randomColor;
- if (Math.random() < 0.01) {
- // 1% chance for void
- randomColor = 'void';
- } else if (Math.random() < 0.05) {
+ if (Math.random() < 0.05) {
// 5% chance for purple fruit
randomColor = 'purple';
} else {
randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
@@ -909,10 +1063,9 @@
'blue': 'blueCandy',
'red': 'redCandy',
'green': 'greenCandy',
'orange': 'orangeCandy',
- 'purple': 'purpleCandy',
- 'void': 'purpleCandy'
+ 'purple': 'purpleCandy'
};
grid[row][col].graphics = grid[row][col].attachAsset(assetMap[randomColor], {
anchorX: 0.5,
anchorY: 0.5,
@@ -1537,14 +1690,11 @@
if (randomSpecialType === 'expires') {
checkUniverseAchievement();
}
} else {
- // Normal candy creation with 5% chance for purple, 1% chance for void
+ // Normal candy creation with 5% chance for purple
var randomColor;
- if (Math.random() < 0.01) {
- // 1% chance for void to appear naturally
- randomColor = 'void';
- } else if (Math.random() < 0.05) {
+ if (Math.random() < 0.05) {
// 5% chance for purple fruit
randomColor = 'purple';
} else {
randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
@@ -1584,14 +1734,11 @@
if (randomSpecialType === 'expires') {
checkUniverseAchievement();
}
} else {
- // Normal candy creation with 1% chance for void, 5% chance for purple
+ // Normal candy creation with 5% chance for purple
var randomColor;
- if (Math.random() < 0.01) {
- // 1% chance for void
- randomColor = 'void';
- } else if (Math.random() < 0.05) {
+ if (Math.random() < 0.05) {
// 5% chance for purple fruit
randomColor = 'purple';
} else {
randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
@@ -3244,8 +3391,18 @@
duration: 100
});
selectedCandy = null;
}
+ if (selectedEternalCandy) {
+ selectedEternalCandy.graphics.tint = 0xFFD700;
+ tween(selectedEternalCandy, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 100
+ });
+ selectedEternalCandy = null;
+ }
return;
}
// Check for double-click to use hourglass and create timeless Karadeniz
var currentTime = Date.now();
@@ -3488,8 +3645,93 @@
});
blackHoleClickCounts[key] = 0;
return;
}
+ // On 7th click, transform void into infinite void
+ if (blackHoleClickCounts[key] === 7) {
+ // Transform void into infinite void
+ candy.isInfiniteVoid = true;
+ candy.specialType = 'infiniteVoid';
+ // Enhanced visual effects for infinite void
+ candy.removeChild(candy.graphics);
+ candy.graphics = candy.attachAsset('purpleCandy', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+ });
+ tween(candy.graphics, {
+ tint: 0x4B0082,
+ scaleX: 1.5,
+ scaleY: 1.5,
+ rotation: Math.PI * 2
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ // Add continuous swirling effect for infinite void
+ var _swirl = function swirl() {
+ if (candy && candy.isInfiniteVoid && candy.parent) {
+ tween(candy.graphics, {
+ tint: 0x8A2BE2,
+ scaleX: 1.7,
+ scaleY: 1.7,
+ rotation: candy.graphics.rotation + Math.PI * 2
+ }, {
+ duration: 1500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(candy.graphics, {
+ tint: 0x4B0082,
+ scaleX: 1.5,
+ scaleY: 1.5
+ }, {
+ duration: 1500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ LK.setTimeout(_swirl, 100);
+ }
+ });
+ }
+ });
+ }
+ };
+ _swirl();
+ }
+ });
+ // Show infinite void transformation notification
+ var infiniteVoidText = new Text2('SONSUZ BOŞLUK!', {
+ size: 90,
+ fill: '#8A2BE2'
+ });
+ infiniteVoidText.anchor.set(0.5, 0.5);
+ infiniteVoidText.x = 1024;
+ infiniteVoidText.y = 1366;
+ infiniteVoidText.alpha = 0;
+ game.addChild(infiniteVoidText);
+ tween(infiniteVoidText, {
+ alpha: 1,
+ scaleX: 1.4,
+ scaleY: 1.4,
+ rotation: 0.1
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ LK.setTimeout(function () {
+ tween(infiniteVoidText, {
+ alpha: 0
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ if (infiniteVoidText.parent) infiniteVoidText.parent.removeChild(infiniteVoidText);
+ }
+ });
+ }, 1500);
+ }
+ });
+ LK.effects.flashScreen(0x8A2BE2, 1000);
+ blackHoleClickCounts[key] = 0;
+ return;
+ }
}
// Update click tracking for double-click detection
lastClickTime = currentTime;
lastClickedCandy = candy;
@@ -3598,8 +3840,75 @@
easing: tween.bounceOut
});
}
});
+ // Handle eternal candy clicks first
+ if (isEternalCandy(candy)) {
+ if (selectedEternalCandy === null) {
+ // Select eternal candy
+ selectedEternalCandy = candy;
+ candy.graphics.tint = 0xFFFFFF;
+ tween(candy, {
+ scaleX: 1.6,
+ scaleY: 1.6
+ }, {
+ duration: 150
+ });
+ // Show instruction text
+ var instructionText = new Text2('Herhangi bir şekere tıklayın!', {
+ size: 60,
+ fill: '#FFD700'
+ });
+ instructionText.anchor.set(0.5, 0.5);
+ instructionText.x = 1024;
+ instructionText.y = 1100;
+ instructionText.alpha = 0;
+ game.addChild(instructionText);
+ tween(instructionText, {
+ alpha: 1
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ LK.setTimeout(function () {
+ tween(instructionText, {
+ alpha: 0
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ if (instructionText.parent) instructionText.parent.removeChild(instructionText);
+ }
+ });
+ }, 2000);
+ }
+ });
+ return;
+ } else if (selectedEternalCandy === candy) {
+ // Deselect eternal candy
+ selectedEternalCandy.graphics.tint = 0xFFD700;
+ tween(selectedEternalCandy, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 100
+ });
+ selectedEternalCandy = null;
+ return;
+ }
+ }
+ // If eternal candy is selected and we click another candy, swap them
+ if (selectedEternalCandy && candy !== selectedEternalCandy) {
+ if (handleEternalCandySwap(selectedEternalCandy, candy)) {
+ // Reset selection
+ selectedEternalCandy.graphics.tint = 0xFFD700;
+ selectedEternalCandy = null;
+ // Process matches after swap
+ LK.setTimeout(function () {
+ // Check for matches at both positions
+ processMatches();
+ }, 400);
+ return;
+ }
+ }
// Click-to-select then click-to-swap mode
if (selectedCandy === null) {
// Check if player has reached 3 consecutive combos and should activate hourglass
if (hourglassCount > 0 && cascadeComboCount >= 3) {