User prompt
haz que el juego sea más dinamico disminuyendo el tiempo de caida y diley de roptura
User prompt
mejora la logica de caida
User prompt
arregla la caida de los memes despues de usar habilidades especiales
User prompt
crea un sistema de puntos
User prompt
Please fix the bug: 'Timeout.tick error: isValidCell is not defined' in or related to this line: 'if (isValidCell(fallInfo.cell)) {' Line Number: 810
User prompt
arregla la caida de los memes para evitar errores de atravesar memes, etc
User prompt
arregla la caída para evitar errores de mmes atravesando otros memes, etc
User prompt
Mejora las lineas de codigo utilizando metodos mas optimizados y ordenados
User prompt
arregla la caida por gravedad cuando se usa habilidades
User prompt
Please fix the bug: 'Timeout.tick error: isValidCell is not defined' in or related to this line: 'if (isValidCell(fallInfo.cell)) {' Line Number: 810
User prompt
Mejora las lineas de codigo utilizando metodos mas optimizados y ordenados
Code edit (3 edits merged)
Please save this source code
User prompt
elimina el diley de roptura
User prompt
si empieza un nuevo sonido de combo que el anterior se corte
Code edit (3 edits merged)
Please save this source code
User prompt
Si se mueve depende cuantos grupos se rompen empezaran a sonar sonidos de combo (2 grupos combo 1 / 3 grupos combo 2 / 4 combos etc ...)
Code edit (1 edits merged)
Please save this source code
User prompt
mejora la mecanica para que cualquier giro se regrese despues de gastar los movimientos libres
User prompt
haz que se puedan mover los memes libremente hasta 2 veces, si en la tercera no se rompe nada el meme regresara a su posición anterior
User prompt
Agrega animaciones ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
dale vida al proyecto con animaciones ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
haz que todos los memes sean especiales verde
User prompt
si se cambia de posición 2 memes especiales verde se activa una habilidad especial que rompe todos los memes visibles
User prompt
si se cambia de posición un meme especial verde con un bomb transformara todos los memes de ese tipo en bomb y consecutivamente activarlos
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var GridCell = Container.expand(function () { var self = Container.call(this); self.init = function () { if (!self.background) { self.background = self.attachAsset('cuadricula', { anchorX: 0.5, anchorY: 0.5 }); } self.value = 0; self.sprite = null; self.row = -1; self.col = -1; self.isSpecial = false; self.specialType = null; return self; }; self.setValue = function (newValue) { if (self.value === newValue) { return; } self.value = newValue; if (self.sprite) { self.removeChild(self.sprite); } var spriteId = 'meme' + newValue; self.sprite = LK.getAsset(spriteId, { anchorX: 0.5, anchorY: 0.5 }); self.addChild(self.sprite); self.updateSpecialAppearance(); }; self.updateSpecialAppearance = function () { if (self.isSpecial && self.sprite) { if (self.specialType === 'bomb') { self.sprite.tint = 0x0088FF; } else if (self.specialType === 'green') { self.sprite.tint = 0x00FF00; } else { self.sprite.tint = 0xFF8800; } } }; self.activateSpecialPower = function () { if (!self.isSpecial) { return; } var cellsToDestroy = []; if (self.specialType === 'horizontal') { for (var row = extraRows; row < gridSize + extraRows; row++) { if (gridCells[row][self.col] && gridCells[row][self.col] !== self) { cellsToDestroy.push(gridCells[row][self.col]); } } } else if (self.specialType === 'vertical') { for (var col = 0; col < gridSize; col++) { if (gridCells[self.row][col] && gridCells[self.row][col] !== self) { cellsToDestroy.push(gridCells[self.row][col]); } } } else if (self.specialType === 'bomb') { for (var row = Math.max(extraRows, self.row - 1); row <= Math.min(gridSize + extraRows - 1, self.row + 1); row++) { for (var col = Math.max(0, self.col - 1); col <= Math.min(gridSize - 1, self.col + 1); col++) { if (gridCells[row][col] && gridCells[row][col] !== self) { cellsToDestroy.push(gridCells[row][col]); } } } } else if (self.specialType === 'green') {} if (cellsToDestroy.length > 0) { destroyCells(cellsToDestroy); self.beingDestroyed = true; LK.getSound('Explosion').play(); LK.effects.flashObject(self, 0xFFFFFF, 200); gridContainer.removeChild(self); self.destroy(); gridCells[self.row][self.col] = null; } }; self.showSelection = function () { if (self.selectionHighlight) { return; } self.selectionHighlight = new Container(); var highlight = LK.getAsset('cuadricula', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.15, scaleY: 1.15, alpha: 0.6 }); highlight.tint = 0x00FFFF; self.selectionHighlight.addChild(highlight); self.addChildAt(self.selectionHighlight, 0); function pulseAnimation() { tween(highlight, { alpha: 0.3, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOutQuad, onComplete: function onComplete() { tween(highlight, { alpha: 0.6, scaleX: 1.15, scaleY: 1.15 }, { duration: 500, easing: tween.easeInOutQuad, onComplete: pulseAnimation }); } }); } pulseAnimation(); }; self.hideSelection = function () { if (self.selectionHighlight) { self.removeChild(self.selectionHighlight); self.selectionHighlight = null; } }; self.down = function (x, y, obj) { handleCellTap(self); }; self.init(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xF4FFFF }); /**** * Game Code ****/ var cellPool = []; function getGridCell() { if (cellPool.length > 0) { return cellPool.pop().init(); } return new GridCell(); } function recycleGridCell(cell) { if (cell) { cellPool.push(cell); } } var selectedCell = null; var isAnimating = false; window.gravityInProgress = false; window.fillInProgress = false; var comboCounter = 0; var comboInProgress = false; function handleCellTap(tappedCell) { if (isAnimating || window.gravityInProgress || window.fillInProgress) { return; } if (!isValidCell(tappedCell)) { return; } function isValidCell(cell) { return cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell && !cell.beingDestroyed; } if (selectedCell !== null) { if (selectedCell && gridCells[selectedCell.row] && gridCells[selectedCell.row][selectedCell.col] === selectedCell) { var areAdjacentCells = function areAdjacentCells(cell1, cell2) { return Math.abs(cell1.row - cell2.row) === 1 && cell1.col === cell2.col || Math.abs(cell1.col - cell2.col) === 1 && cell1.row === cell2.row; }; if (selectedCell === tappedCell) { selectedCell.hideSelection(); selectedCell = null; return; } if (!areAdjacentCells(selectedCell, tappedCell)) { selectedCell.hideSelection(); selectedCell = tappedCell; selectedCell.showSelection(); return; } var cell1 = selectedCell; var cell2 = tappedCell; cell1.hideSelection(); selectedCell = null; var isAdjacent = Math.abs(cell1.row - cell2.row) === 1 && cell1.col === cell2.col || Math.abs(cell1.col - cell2.col) === 1 && cell1.row === cell2.row; if (!isAdjacent) { return; } } else { if (selectedCell) { selectedCell.hideSelection(); } selectedCell = tappedCell; selectedCell.showSelection(); return; } } else { selectedCell = tappedCell; selectedCell.showSelection(); return; } isAnimating = true; var pos1_x = cell1.x; var pos1_y = cell1.y; var pos2_x = cell2.x; var pos2_y = cell2.y; var row1 = cell1.row; var col1 = cell1.col; var row2 = cell2.row; var col2 = cell2.col; var greenSpecialCell = null; var regularCell = null; var lineSpecialCells = []; var twoGreenSpecials = false; if (cell1.isSpecial && cell1.specialType === 'green' && cell2.isSpecial && cell2.specialType === 'green') { twoGreenSpecials = true; } else if (cell1.isSpecial && cell1.specialType === 'green') { greenSpecialCell = cell1; regularCell = cell2; } else if (cell2.isSpecial && cell2.specialType === 'green') { greenSpecialCell = cell2; regularCell = cell1; } if (cell1.isSpecial && (cell1.specialType === 'horizontal' || cell1.specialType === 'vertical')) { lineSpecialCells.push(cell1); } if (cell2.isSpecial && (cell2.specialType === 'horizontal' || cell2.specialType === 'vertical')) { lineSpecialCells.push(cell2); } gridCells[row1][col1] = cell2; gridCells[row2][col2] = cell1; cell1.row = row2; cell1.col = col2; cell2.row = row1; cell2.col = col1; if (cell1.selectionHighlight) { cell1.hideSelection(); } if (cell2.selectionHighlight) { cell2.hideSelection(); } if (twoGreenSpecials) { var cellsToDestroy = []; for (var row = extraRows; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { if (gridCells[row][col] && gridCells[row][col] !== cell1 && gridCells[row][col] !== cell2) { cellsToDestroy.push(gridCells[row][col]); } } } cell1.beingDestroyed = true; cell2.beingDestroyed = true; LK.setTimeout(function () { LK.getSound('Explosion').play(); LK.effects.flashScreen(0x00FF00, 500); if (cellsToDestroy.length > 0) { destroyCells(cellsToDestroy); } LK.effects.flashObject(cell1, 0xFFFFFF, 200); LK.effects.flashObject(cell2, 0xFFFFFF, 200); gridContainer.removeChild(cell1); gridContainer.removeChild(cell2); cell1.destroy(); cell2.destroy(); gridCells[cell1.row][cell1.col] = null; gridCells[cell2.row][cell2.col] = null; }, 350); } else if (cell1.isSpecial && cell1.specialType === 'bomb' && cell2.isSpecial && cell2.specialType === 'bomb') { var cellsToDestroy = []; var activatedCell = cell1; for (var r = Math.max(extraRows, cell1.row - 2); r <= Math.min(gridSize + extraRows - 1, cell1.row + 2); r++) { for (var c = Math.max(0, cell1.col - 2); c <= Math.min(gridSize - 1, cell1.col + 2); c++) { if (gridCells[r][c] && gridCells[r][c] !== cell1 && gridCells[r][c] !== cell2) { cellsToDestroy.push(gridCells[r][c]); } } } cell1.beingDestroyed = true; cell2.beingDestroyed = true; LK.setTimeout(function () { LK.getSound('Explosion').play(); if (cellsToDestroy.length > 0) { destroyCells(cellsToDestroy); } LK.effects.flashObject(cell1, 0xFFFFFF, 200); LK.effects.flashObject(cell2, 0xFFFFFF, 200); gridContainer.removeChild(cell1); gridContainer.removeChild(cell2); cell1.destroy(); cell2.destroy(); gridCells[cell1.row][cell1.col] = null; gridCells[cell2.row][cell2.col] = null; }, 350); } else if (cell1.isSpecial && cell1.specialType === 'bomb' && cell2.isSpecial && (cell2.specialType === 'horizontal' || cell2.specialType === 'vertical') || cell2.isSpecial && cell2.specialType === 'bomb' && cell1.isSpecial && (cell1.specialType === 'horizontal' || cell1.specialType === 'vertical')) { var bombCell = cell1.specialType === 'bomb' ? cell1 : cell2; var lineCell = cell1.specialType === 'horizontal' || cell1.specialType === 'vertical' ? cell1 : cell2; var cellsToDestroy = []; var affectedRows = []; var activatedCell = cell1; if (lineCell.specialType === 'horizontal') { for (var r = Math.max(extraRows, bombCell.row - 1); r <= Math.min(gridSize + extraRows - 1, bombCell.row + 1); r++) { affectedRows.push(r); for (var c = 0; c < gridSize; c++) { if (gridCells[r][c] && gridCells[r][c] !== bombCell && gridCells[r][c] !== lineCell) { cellsToDestroy.push(gridCells[r][c]); } } } } else { for (var r = extraRows; r < gridSize + extraRows; r++) { for (var c = Math.max(0, bombCell.col - 1); c <= Math.min(gridSize - 1, bombCell.col + 1); c++) { if (gridCells[r][c] && gridCells[r][c] !== bombCell && gridCells[r][c] !== lineCell) { cellsToDestroy.push(gridCells[r][c]); } } } } bombCell.beingDestroyed = true; lineCell.beingDestroyed = true; LK.setTimeout(function () { LK.getSound('Explosion').play(); if (cellsToDestroy.length > 0) { destroyCells(cellsToDestroy); } LK.effects.flashObject(bombCell, 0xFFFFFF, 200); LK.effects.flashObject(lineCell, 0xFFFFFF, 200); gridContainer.removeChild(bombCell); gridContainer.removeChild(lineCell); bombCell.destroy(); lineCell.destroy(); gridCells[bombCell.row][bombCell.col] = null; gridCells[lineCell.row][lineCell.col] = null; }, 350); } else if (lineSpecialCells.length === 2) { var cellsToDestroy = []; var row1, col1, row2, col2; var activatedSpecial; if (lineSpecialCells[0] === cell1) { activatedSpecial = lineSpecialCells[0]; row1 = lineSpecialCells[0].row; col1 = lineSpecialCells[0].col; } else { activatedSpecial = lineSpecialCells[1]; row1 = lineSpecialCells[1].row; col1 = lineSpecialCells[1].col; } for (var row = extraRows; row < gridSize + extraRows; row++) { if (gridCells[row][col1] && gridCells[row][col1] !== lineSpecialCells[0] && gridCells[row][col1] !== lineSpecialCells[1]) { cellsToDestroy.push(gridCells[row][col1]); } } for (var col = 0; col < gridSize; col++) { if (col !== col1 && gridCells[row1][col] && gridCells[row1][col] !== lineSpecialCells[0] && gridCells[row1][col] !== lineSpecialCells[1]) { cellsToDestroy.push(gridCells[row1][col]); } } lineSpecialCells.forEach(function (specialMeme) { specialMeme.beingDestroyed = true; }); LK.setTimeout(function () { LK.getSound('Explosion').play(); if (cellsToDestroy.length > 0) { destroyCells(cellsToDestroy); } lineSpecialCells.forEach(function (specialMeme) { LK.effects.flashObject(specialMeme, 0xFFFFFF, 200); gridContainer.removeChild(specialMeme); specialMeme.destroy(); gridCells[specialMeme.row][specialMeme.col] = null; }); }, 350); } else if (greenSpecialCell && regularCell) { if (regularCell.isSpecial && (regularCell.specialType === 'horizontal' || regularCell.specialType === 'vertical')) { var targetType = regularCell.value; var cellsToTransform = []; for (var row = extraRows; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { var cell = gridCells[row][col]; if (cell && cell.value === targetType && cell !== greenSpecialCell && cell !== regularCell && !cell.isSpecial) { cellsToTransform.push(cell); } } } greenSpecialCell.beingDestroyed = true; LK.setTimeout(function () { LK.getSound('Explosion').play(); LK.effects.flashObject(greenSpecialCell, 0xFFFFFF, 200); cellsToTransform.forEach(function (cell) { cell.isSpecial = true; cell.specialType = Math.random() < 0.5 ? 'horizontal' : 'vertical'; cell.sprite.tint = 0xFF8800; LK.effects.flashObject(cell, 0xFFFFFF, 200); LK.setTimeout(function () { cell.activateSpecialPower(); }, 100 + Math.random() * 300); }); gridContainer.removeChild(greenSpecialCell); greenSpecialCell.destroy(); gridCells[greenSpecialCell.row][greenSpecialCell.col] = null; LK.setTimeout(function () { regularCell.activateSpecialPower(); }, 500); }, 350); } else if (regularCell.isSpecial && regularCell.specialType === 'bomb') { var targetType = regularCell.value; var cellsToTransform = []; for (var row = extraRows; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { var cell = gridCells[row][col]; if (cell && cell.value === targetType && cell !== greenSpecialCell && cell !== regularCell && !cell.isSpecial) { cellsToTransform.push(cell); } } } greenSpecialCell.beingDestroyed = true; LK.setTimeout(function () { LK.getSound('Explosion').play(); LK.effects.flashObject(greenSpecialCell, 0xFFFFFF, 200); cellsToTransform.forEach(function (cell) { cell.isSpecial = true; cell.specialType = 'bomb'; cell.sprite.tint = 0x0088FF; LK.effects.flashObject(cell, 0xFFFFFF, 200); LK.setTimeout(function () { cell.activateSpecialPower(); }, 100 + Math.random() * 300); }); gridContainer.removeChild(greenSpecialCell); greenSpecialCell.destroy(); gridCells[greenSpecialCell.row][greenSpecialCell.col] = null; LK.setTimeout(function () { regularCell.activateSpecialPower(); }, 500); }, 350); } else { var targetType = regularCell.value; var cellsToDestroy = []; for (var row = extraRows; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { var cell = gridCells[row][col]; if (cell && cell.value === targetType && cell !== greenSpecialCell) { cellsToDestroy.push(cell); } } } greenSpecialCell.beingDestroyed = true; LK.setTimeout(function () { if (cellsToDestroy.length > 0) { LK.getSound('Explosion').play(); LK.effects.flashObject(greenSpecialCell, 0xFFFFFF, 200); destroyCells(cellsToDestroy); gridContainer.removeChild(greenSpecialCell); greenSpecialCell.destroy(); gridCells[greenSpecialCell.row][greenSpecialCell.col] = null; } }, 350); } } tween(cell1, { x: pos2_x, y: pos2_y }, { duration: 300 }); tween(cell2, { x: pos1_x, y: pos1_y }, { duration: 300 }); selectedCell = null; LK.setTimeout(function () { checkForAndDestroyMatches(cell1, cell2); if (!window.destructionInProgress && !window.gravityInProgress && !window.fillInProgress) { isAnimating = false; } }, 350); } function getMatches() { var matches = []; function findDirectionalMatches(isHorizontal) { var primary, secondary; var primaryMax = isHorizontal ? gridSize + extraRows : gridSize; var secondaryMax = isHorizontal ? gridSize : gridSize + extraRows; for (primary = isHorizontal ? extraRows : 0; primary < primaryMax; primary++) { if (!gridCells[primary]) { continue; } for (secondary = 0; secondary < secondaryMax;) { if (secondary > secondaryMax - 3) { secondary++; continue; } var cell1 = isHorizontal ? gridCells[primary] ? gridCells[primary][secondary] : null : gridCells[secondary] ? gridCells[secondary][primary] : null; if (!cell1 || !cell1.value) { secondary++; continue; } var currentMatchValue = cell1.value; var currentMatchCells = [cell1]; for (var k = secondary + 1; k < secondaryMax; k++) { var nextCell = isHorizontal ? gridCells[primary] ? gridCells[primary][k] : null : gridCells[k] ? gridCells[k][primary] : null; if (nextCell && nextCell.value === currentMatchValue) { currentMatchCells.push(nextCell); } else { LK.setTimeout(function () { if (!window.gravityInProgress && !window.fillInProgress) { comboInProgress = false; comboCounter = 0; } }, 500); break; } } if (currentMatchCells.length >= 3) { var validCells = currentMatchCells.filter(function (cell) { return cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell; }); if (validCells.length >= 3) { var visibleCells = validCells.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = validCells.filter(function (cell) { return cell.row < extraRows; }); if (visibleCells.length === 0 || invisibleCells.length === 0 || visibleCells.length >= 3) { validCells.isHorizontal = isHorizontal; validCells.matchType = currentMatchValue; matches.push(validCells); } } } secondary += currentMatchCells.length > 0 ? currentMatchCells.length : 1; } } } findDirectionalMatches(true); findDirectionalMatches(false); return matches; } function destroyCells(cellsToDestroy) { isAnimating = true; var destructionId = Date.now() + Math.random(); var visibleCells = cellsToDestroy.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = cellsToDestroy.filter(function (cell) { return cell.row < extraRows; }); if (visibleCells.length > 0 && invisibleCells.length > 0 && (visibleCells.length === 1 || invisibleCells.length === 1)) { isAnimating = false; return; } var visibleCellsToDestroy = cellsToDestroy.filter(function (cell) { return cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell; }); var centerCell = null; if (arguments.length > 1 && arguments[1]) { centerCell = arguments[1]; } else if (cellsToDestroy.length > 0) { centerCell = cellsToDestroy[Math.floor(cellsToDestroy.length / 2)]; } var cellsByType = {}; visibleCellsToDestroy.forEach(function (cell) { if (!cellsByType[cell.value]) { cellsByType[cell.value] = []; } cellsByType[cell.value].push(cell); }); var uniqueGroupCount = Object.keys(cellsByType).length; if (uniqueGroupCount > 0) { if (!comboInProgress) { comboCounter = uniqueGroupCount; comboInProgress = true; } else { comboCounter += uniqueGroupCount; } playComboSound(comboCounter); } function playComboSound(comboCount) { // Stop all combo sounds for (var i = 1; i <= 5; i++) { LK.getSound('Combo' + i).stop(); } // Play appropriate combo sound based on count if (comboCount >= 9) { LK.getSound('Combo5').play(); } else if (comboCount >= 6) { LK.getSound('Combo4').play(); } else if (comboCount >= 4) { LK.getSound('Combo3').play(); } else if (comboCount >= 3) { LK.getSound('Combo2').play(); } else if (comboCount >= 2) { LK.getSound('Combo1').play(); } } var specialCell = createSpecialCell(cellsByType, centerCell, visibleCellsToDestroy); if (specialCell) { visibleCellsToDestroy = visibleCellsToDestroy.filter(function (cell) { return cell !== specialCell; }); } function createSpecialCell(cellsByType, centerCell, visibleCells) { var specialCell = null; for (var type in cellsByType) { var typeCells = cellsByType[type]; var typeValue = parseInt(type); // Handle matches of 6 or more - create green special if (typeCells.length >= 6) { specialCell = chooseSpecialCell(centerCell, typeCells, typeValue); initializeSpecialCell(specialCell, 'green'); return specialCell; } // Handle matches of 5 - create bomb special else if (typeCells.length === 5) { specialCell = chooseSpecialCell(centerCell, typeCells, typeValue); initializeSpecialCell(specialCell, 'bomb'); return specialCell; } // Handle matches of 4 - create horizontal/vertical special else if (typeCells.length === 4) { var firstCell = typeCells[0]; var isHorizontalMatch = true; var isVerticalMatch = true; for (var i = 1; i < typeCells.length; i++) { if (typeCells[i].row !== firstCell.row) { isHorizontalMatch = false; } if (typeCells[i].col !== firstCell.col) { isVerticalMatch = false; } } if (isHorizontalMatch || isVerticalMatch) { specialCell = chooseSpecialCell(centerCell, typeCells, typeValue); initializeSpecialCell(specialCell, isHorizontalMatch ? 'horizontal' : 'vertical'); return specialCell; } } } return null; } function chooseSpecialCell(centerCell, typeCells, typeValue) { if (centerCell && centerCell.value === typeValue) { return centerCell; } else { return typeCells[0]; } } function initializeSpecialCell(cell, specialType) { cell.isSpecial = true; cell.specialType = specialType; cell.beingDestroyed = false; cell.updateSpecialAppearance(); } if (centerCell && visibleCellsToDestroy.length > 0) { visibleCellsToDestroy.sort(function (a, b) { var distA = Math.abs(a.row - centerCell.row) + Math.abs(a.col - centerCell.col); var distB = Math.abs(b.row - centerCell.row) + Math.abs(b.col - centerCell.col); return distA - distB; }); } var totalDestructionTime = 0; visibleCellsToDestroy.forEach(function (cell) { if (cell) { cell.beingDestroyed = true; if (cell.isSpecial) { LK.setTimeout(function () { cell.activateSpecialPower(); }, 100); } } }); if (specialCell && specialCell.isSpecial) { if (specialCell.specialType === 'bomb') { specialCell.sprite.tint = 0x0088FF; } else if (specialCell.specialType === 'green') { specialCell.sprite.tint = 0x00FF00; } else { specialCell.sprite.tint = 0xFF8800; } LK.effects.flashObject(specialCell, 0xFFFFFF, 300); } destroyVisibleCells(visibleCellsToDestroy); function destroyVisibleCells(cells) { // Play sound once for all cells rather than for each cell if (cells.length > 0) { LK.getSound('Explosion').play(); } cells.forEach(function (cell) { if (cell && cell.beingDestroyed && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) { LK.effects.flashObject(cell, 0xFFFFFF, 200); gridContainer.removeChild(cell); cell.destroy(); gridCells[cell.row][cell.col] = null; } }); } var allCellsDestroyed = true; for (var r = 0; r < gridSize + extraRows; r++) { for (var c = 0; c < gridSize; c++) { if (gridCells[r] && gridCells[r][c] && gridCells[r][c].beingDestroyed) { allCellsDestroyed = false; } } } if (allCellsDestroyed && !window.gravityInProgress && !window.fillInProgress) { applyGravity(); } } // Define global isValidCell function to fix the reference error function isValidCell(cell) { return cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell && !cell.beingDestroyed; } function applyGravity() { isAnimating = true; var cellsToFall = []; if (window.gravityInProgress) { return; } window.gravityInProgress = true; // Scan grid and find cells that need to fall processGridForGravity(cellsToFall); // Animation constants var baseDelay = 30; var constantDuration = 400; // Sort for consistent animation order cellsToFall.sort(function (a, b) { if (a.col !== b.col) { return a.col - b.col; } return b.toRow - a.toRow; }); // Start animations var longestDelay = animateFallingCells(cellsToFall, baseDelay, constantDuration); // Schedule next step LK.setTimeout(function () { window.gravityInProgress = false; if (!window.destructionInProgress) { fillEmptySpacesWithNewMemes(); } }, longestDelay + 50); } function processGridForGravity(cellsToFall) { for (var col = 0; col < gridSize; col++) { for (var row = gridSize + extraRows - 1; row >= extraRows; row--) { if (!gridCells[row][col]) { var sourceRow = row - 1; while (sourceRow >= 0 && !gridCells[sourceRow][col]) { sourceRow--; } if (sourceRow >= 0) { var cellToMove = gridCells[sourceRow][col]; if (cellToMove) { cellsToFall.push({ cell: cellToMove, fromRow: sourceRow, toRow: row, col: col }); // Update grid data gridCells[row][col] = cellToMove; gridCells[sourceRow][col] = null; cellToMove.row = row; // Make hidden cells visible if (sourceRow < extraRows) { gridContainer.addChild(cellToMove); } } } } } } } function animateFallingCells(cellsToFall, baseDelay, duration) { var longestDelay = 0; cellsToFall.forEach(function (fallInfo, index) { var delay = index * baseDelay; var newPos = getCellPosition(fallInfo.toRow, fallInfo.col); var totalTime = delay + duration; if (totalTime > longestDelay) { longestDelay = totalTime; } LK.setTimeout(function () { if (isValidCell(fallInfo.cell)) { tween(fallInfo.cell, { y: newPos.y }, { duration: duration, easing: tween.linear }); } }, delay); }); return longestDelay; } function fillEmptySpacesWithNewMemes() { if (window.fillInProgress || window.gravityInProgress) { return; } window.fillInProgress = true; // Create and add new cells var newCellsToAdd = createNewCells(); var anyNewMemeAdded = newCellsToAdd.length > 0; // Animation constants var baseDelay = 30; var constantDuration = 400; // Sort cells for consistent animation newCellsToAdd.sort(function (a, b) { if (a.col !== b.col) { return a.col - b.col; } return b.row - a.row; }); // Animate new cells var longestDelay = animateNewCells(newCellsToAdd, baseDelay, constantDuration); // Handle completion if (anyNewMemeAdded) { LK.setTimeout(function () { window.fillInProgress = false; if (window.destructionInProgress || window.gravityInProgress) { isAnimating = false; return; } processNewMatches(); }, longestDelay + 50); } else { window.fillInProgress = false; isAnimating = false; comboInProgress = false; comboCounter = 0; } } function createNewCells() { var newCells = []; for (var col = 0; col < gridSize; col++) { for (var row = 0; row < gridSize + extraRows; row++) { if (!gridCells[row][col]) { var newCell = getGridCell(); var pos = getCellPosition(row, col); // Configure new cell newCell.x = pos.x; newCell.y = pos.y - 400; // Start above grid newCell.setValue(Math.floor(Math.random() * 5) + 1); newCell.row = row; newCell.col = col; // Update grid data gridCells[row][col] = newCell; // Track for animation newCells.push({ cell: newCell, destY: pos.y, row: row, col: col }); // Add to visible container if needed if (row >= extraRows) { gridContainer.addChild(newCell); } } } } return newCells; } function animateNewCells(cells, baseDelay, duration) { var longestDelay = 0; cells.forEach(function (cellData, index) { var delay = index * baseDelay; var totalTime = delay + duration; if (totalTime > longestDelay) { longestDelay = totalTime; } LK.setTimeout(function () { if (isValidCell(cellData.cell)) { tween(cellData.cell, { y: cellData.destY }, { duration: duration, easing: tween.linear }); } }, delay); }); return longestDelay; } function processNewMatches() { // Get matches with visible cells var visibleMatchGroups = getMatches().filter(function (group) { return isValidMatchGroup(group); }); if (visibleMatchGroups.length > 0) { // Group matches by cell value type var matchesByType = groupMatchesByType(visibleMatchGroups); // Process each match type for (var type in matchesByType) { var typeGroups = matchesByType[type]; var centerCell = null; if (typeGroups.length > 0 && typeGroups[0].length > 0) { var matchGroup = typeGroups[0]; centerCell = matchGroup[Math.floor(matchGroup.length / 2)]; } // Get unique cells of this type var typeCells = getUniqueCellsFromGroups(typeGroups); if (typeCells.length) { destroyCells(typeCells, centerCell); } } if (Object.keys(matchesByType).length === 0) { isAnimating = false; } } else { isAnimating = false; } } function isValidMatchGroup(group) { var visibleCells = group.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = group.filter(function (cell) { return cell.row < extraRows; }); if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) { return false; } return visibleCells.length >= 3; } function groupMatchesByType(matches) { var matchesByType = {}; matches.forEach(function (group) { if (group.length > 0) { var type = group[0].value; if (!matchesByType[type]) { matchesByType[type] = []; } matchesByType[type].push(group); } }); return matchesByType; } function getUniqueCellsFromGroups(groups) { var cells = []; var cellTracker = {}; groups.forEach(function (group) { group.forEach(function (cell) { var cellKey = cell.row + "_" + cell.col; if (!cellTracker[cellKey] && isValidCell(cell)) { cells.push(cell); cellTracker[cellKey] = true; } }); }); return cells; } function checkForAndDestroyMatches(swappedCellA, swappedCellB) { if (window.gravityInProgress || window.fillInProgress) { return; } var allMatchGroupsOnBoard = getMatches(); if (!allMatchGroupsOnBoard.length) { return; } var relevantMatchGroups = allMatchGroupsOnBoard.filter(function (group) { var visibleCells = group.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = group.filter(function (cell) { return cell.row < extraRows; }); if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) { return false; } return group.some(function (cellInGroup) { return (cellInGroup === swappedCellA || cellInGroup === swappedCellB) && cellInGroup.row >= extraRows; }); }); if (!relevantMatchGroups.length) { return; } var matchesByType = {}; relevantMatchGroups.forEach(function (group) { if (group.length > 0) { var type = group[0].value; if (!matchesByType[type]) { matchesByType[type] = []; } matchesByType[type].push(group); } }); var uniqueCellTracker = {}; var cellsToDestroy = []; for (var type in matchesByType) { var typeGroups = matchesByType[type]; var typeCells = []; typeGroups.forEach(function (group) { group.forEach(function (cell) { if (cell.row >= extraRows) { typeCells.push(cell); } }); }); typeCells.forEach(function (cell) { var cellKey = cell.row + "_" + cell.col; if (!uniqueCellTracker[cellKey] && cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) { cellsToDestroy.push(cell); uniqueCellTracker[cellKey] = true; } }); } ; if (cellsToDestroy.length) { var centerCell = swappedCellA && relevantMatchGroups.some(function (group) { return group.includes(swappedCellA); }) ? swappedCellA : swappedCellB; destroyCells(cellsToDestroy, centerCell); LK.setTimeout(function () { if (window.gravityInProgress || window.fillInProgress) { return; } var visibleMatchGroups = getMatches().filter(function (group) { var visibleCells = group.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = group.filter(function (cell) { return cell.row < extraRows; }); if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) { return false; } return visibleCells.length >= 3; }); var newMatches = visibleMatchGroups; if (newMatches.length > 0) { var matchesByType = {}; newMatches.forEach(function (group) { if (group.length > 0) { var type = group[0].value; if (!matchesByType[type]) { matchesByType[type] = []; } matchesByType[type].push(group); } }); for (var type in matchesByType) { var typeGroups = matchesByType[type]; var newCellsToDestroy = []; var newCellTracker = {}; typeGroups.forEach(function (group) { group.forEach(function (cell) { var cellKey = cell.row + "_" + cell.col; if (!newCellTracker[cellKey] && cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) { newCellsToDestroy.push(cell); newCellTracker[cellKey] = true; } }); }); if (newCellsToDestroy.length) { var centerCell = newCellsToDestroy[Math.floor(newCellsToDestroy.length / 2)]; destroyCells(newCellsToDestroy, centerCell); } } } }, 400); } } var gridSize = 8; var extraRows = 9; var cellSpacing = 10; var cellSize = 208; var gridCells = []; var totalGridWidth = gridSize * cellSize + (gridSize - 1) * cellSpacing; var totalVisibleGridHeight = totalGridWidth; var totalGridHeight = totalVisibleGridHeight + extraRows * (cellSize + cellSpacing); var startX = (2048 - totalGridWidth) / 2 + cellSize / 2; var startY = (-1300 - totalVisibleGridHeight) / 2 + cellSize / 2 + extraRows * (cellSize + cellSpacing); function getCellPosition(row, col) { return { x: startX + col * (cellSize + cellSpacing), y: startY + row * (cellSize + cellSpacing) - extraRows * (cellSize + cellSpacing) }; } var gridContainer = new Container(); game.addChild(gridContainer); function initializeGrid() { gridCells = []; for (var row = 0; row < gridSize + extraRows; row++) { gridCells[row] = []; for (var col = 0; col < gridSize; col++) { var pos = getCellPosition(row, col); var cell = getGridCell ? getGridCell() : new GridCell(); cell.x = pos.x; cell.y = pos.y; cell.row = row; cell.col = col; var randomValue; var attempts = 0; do { randomValue = Math.floor(Math.random() * 5) + 1; attempts++; var leftMatchCount = 0; var aboveMatchCount = 0; if (col >= 2) { if (gridCells[row][col - 1].value === randomValue && gridCells[row][col - 2].value === randomValue) { leftMatchCount = 2; } } if (row >= 2) { if (gridCells[row - 1][col].value === randomValue && gridCells[row - 2][col].value === randomValue) { aboveMatchCount = 2; } } } while ((leftMatchCount >= 2 || aboveMatchCount >= 2) && attempts < 10); cell.setValue(randomValue); if (row >= extraRows) { gridContainer.addChild(cell); } gridCells[row][col] = cell; } } } initializeGrid(); function ensureNoInitialMatches() { var matches = getMatches(); if (matches.length > 0) { matches.forEach(function (group) { group.forEach(function (cell) { var currentValue = cell.value; var newValue; do { newValue = Math.floor(Math.random() * 5) + 1; } while (newValue === currentValue); cell.setValue(newValue); }); }); ensureNoInitialMatches(); } } ensureNoInitialMatches();
===================================================================
--- original.js
+++ change.js
@@ -7,110 +7,76 @@
* Classes
****/
var GridCell = Container.expand(function () {
var self = Container.call(this);
- // Define the special cell tint colors as constants
- var BOMB_TINT = 0x0088FF;
- var GREEN_TINT = 0x00FF00;
- var LINE_TINT = 0xFF8800;
- var SELECTION_TINT = 0x00FFFF;
- // Initialize method with improved structure
self.init = function () {
- // Create background only if it doesn't exist
if (!self.background) {
self.background = self.attachAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5
});
}
- // Reset all properties to default values
self.value = 0;
self.sprite = null;
self.row = -1;
self.col = -1;
self.isSpecial = false;
self.specialType = null;
- self.beingDestroyed = false;
- self.lastIntersecting = false;
- self.inMotion = false; // Add flag to track cells in motion during animations
return self;
};
- // Set value with improved appearance handling
self.setValue = function (newValue) {
- // Skip if value hasn't changed
if (self.value === newValue) {
return;
}
- // Update value
self.value = newValue;
- // Remove existing sprite
if (self.sprite) {
self.removeChild(self.sprite);
}
- // Create new sprite
var spriteId = 'meme' + newValue;
self.sprite = LK.getAsset(spriteId, {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(self.sprite);
- // Apply special effects if needed
- self.updateAppearance();
+ self.updateSpecialAppearance();
};
- // New helper method to update appearance based on special state
- self.updateAppearance = function () {
- if (!self.sprite) return;
- // Reset tint first
- self.sprite.tint = 0xFFFFFF;
- // Apply special tint if needed
- if (self.isSpecial) {
+ self.updateSpecialAppearance = function () {
+ if (self.isSpecial && self.sprite) {
if (self.specialType === 'bomb') {
- self.sprite.tint = BOMB_TINT;
+ self.sprite.tint = 0x0088FF;
} else if (self.specialType === 'green') {
- self.sprite.tint = GREEN_TINT;
+ self.sprite.tint = 0x00FF00;
} else {
- self.sprite.tint = LINE_TINT;
+ self.sprite.tint = 0xFF8800;
}
}
};
- // Activate special power with improved efficiency
self.activateSpecialPower = function () {
if (!self.isSpecial) {
return;
}
var cellsToDestroy = [];
- // Collect cells based on special type
if (self.specialType === 'horizontal') {
- // Destroy all cells in the same row
for (var row = extraRows; row < gridSize + extraRows; row++) {
if (gridCells[row][self.col] && gridCells[row][self.col] !== self) {
cellsToDestroy.push(gridCells[row][self.col]);
}
}
} else if (self.specialType === 'vertical') {
- // Destroy all cells in the same column
for (var col = 0; col < gridSize; col++) {
if (gridCells[self.row][col] && gridCells[self.row][col] !== self) {
cellsToDestroy.push(gridCells[self.row][col]);
}
}
} else if (self.specialType === 'bomb') {
- // Destroy cells in a 3x3 area
- var minRow = Math.max(extraRows, self.row - 1);
- var maxRow = Math.min(gridSize + extraRows - 1, self.row + 1);
- var minCol = Math.max(0, self.col - 1);
- var maxCol = Math.min(gridSize - 1, self.col + 1);
- for (var row = minRow; row <= maxRow; row++) {
- for (var col = minCol; col <= maxCol; col++) {
+ for (var row = Math.max(extraRows, self.row - 1); row <= Math.min(gridSize + extraRows - 1, self.row + 1); row++) {
+ for (var col = Math.max(0, self.col - 1); col <= Math.min(gridSize - 1, self.col + 1); col++) {
if (gridCells[row][col] && gridCells[row][col] !== self) {
cellsToDestroy.push(gridCells[row][col]);
}
}
}
- } else if (self.specialType === 'green') {
- // Green special power is handled elsewhere
- }
- // Process destruction if we have cells to destroy
+ } else if (self.specialType === 'green') {}
if (cellsToDestroy.length > 0) {
destroyCells(cellsToDestroy);
self.beingDestroyed = true;
LK.getSound('Explosion').play();
@@ -119,26 +85,23 @@
self.destroy();
gridCells[self.row][self.col] = null;
}
};
- // Show selection with improved animation
self.showSelection = function () {
if (self.selectionHighlight) {
return;
}
- // Create selection container
self.selectionHighlight = new Container();
var highlight = LK.getAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.15,
scaleY: 1.15,
alpha: 0.6
});
- highlight.tint = SELECTION_TINT;
+ highlight.tint = 0x00FFFF;
self.selectionHighlight.addChild(highlight);
self.addChildAt(self.selectionHighlight, 0);
- // Define pulse animation
function pulseAnimation() {
tween(highlight, {
alpha: 0.3,
scaleX: 1.2,
@@ -158,23 +121,19 @@
});
}
});
}
- // Start animation
pulseAnimation();
};
- // Hide selection with efficient cleanup
self.hideSelection = function () {
if (self.selectionHighlight) {
self.removeChild(self.selectionHighlight);
self.selectionHighlight = null;
}
};
- // Handle tap/click events
self.down = function (x, y, obj) {
handleCellTap(self);
};
- // Initialize on creation
self.init();
return self;
});
@@ -206,71 +165,67 @@
window.fillInProgress = false;
var comboCounter = 0;
var comboInProgress = false;
function handleCellTap(tappedCell) {
- // Exit early if animations are in progress
if (isAnimating || window.gravityInProgress || window.fillInProgress) {
return;
}
- // Validate tapped cell
- if (!tappedCell || !gridCells[tappedCell.row] || gridCells[tappedCell.row][tappedCell.col] !== tappedCell || tappedCell.beingDestroyed || tappedCell.inMotion) {
+ if (!isValidCell(tappedCell)) {
return;
}
- // Handle first selection
- if (selectedCell === null) {
- selectedCell = tappedCell;
- selectedCell.showSelection();
- return;
+ function isValidCell(cell) {
+ return cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell && !cell.beingDestroyed;
}
- // Validate selected cell still exists
- if (!gridCells[selectedCell.row] || gridCells[selectedCell.row][selectedCell.col] !== selectedCell) {
- // Selected cell no longer valid, use tapped cell instead
- if (selectedCell) {
- selectedCell.hideSelection();
+ if (selectedCell !== null) {
+ if (selectedCell && gridCells[selectedCell.row] && gridCells[selectedCell.row][selectedCell.col] === selectedCell) {
+ var areAdjacentCells = function areAdjacentCells(cell1, cell2) {
+ return Math.abs(cell1.row - cell2.row) === 1 && cell1.col === cell2.col || Math.abs(cell1.col - cell2.col) === 1 && cell1.row === cell2.row;
+ };
+ if (selectedCell === tappedCell) {
+ selectedCell.hideSelection();
+ selectedCell = null;
+ return;
+ }
+ if (!areAdjacentCells(selectedCell, tappedCell)) {
+ selectedCell.hideSelection();
+ selectedCell = tappedCell;
+ selectedCell.showSelection();
+ return;
+ }
+ var cell1 = selectedCell;
+ var cell2 = tappedCell;
+ cell1.hideSelection();
+ selectedCell = null;
+ var isAdjacent = Math.abs(cell1.row - cell2.row) === 1 && cell1.col === cell2.col || Math.abs(cell1.col - cell2.col) === 1 && cell1.row === cell2.row;
+ if (!isAdjacent) {
+ return;
+ }
+ } else {
+ if (selectedCell) {
+ selectedCell.hideSelection();
+ }
+ selectedCell = tappedCell;
+ selectedCell.showSelection();
+ return;
}
+ } else {
selectedCell = tappedCell;
selectedCell.showSelection();
return;
}
- // Handle tap on already selected cell (deselect)
- if (selectedCell === tappedCell) {
- selectedCell.hideSelection();
- selectedCell = null;
- return;
- }
- // Check if cells are adjacent
- var isAdjacent = Math.abs(selectedCell.row - tappedCell.row) === 1 && selectedCell.col === tappedCell.col || Math.abs(selectedCell.col - tappedCell.col) === 1 && selectedCell.row === tappedCell.row;
- // If not adjacent, select the new cell instead
- if (!isAdjacent) {
- selectedCell.hideSelection();
- selectedCell = tappedCell;
- selectedCell.showSelection();
- return;
- }
- // Set up cell swap
- var cell1 = selectedCell;
- var cell2 = tappedCell;
- // Clear selection
- cell1.hideSelection();
- selectedCell = null;
- // Begin swap animation
isAnimating = true;
- // Store original positions for animation
var pos1_x = cell1.x;
var pos1_y = cell1.y;
var pos2_x = cell2.x;
var pos2_y = cell2.y;
- // Store grid positions
var row1 = cell1.row;
var col1 = cell1.col;
var row2 = cell2.row;
var col2 = cell2.col;
- // Categorize special cell interactions
var greenSpecialCell = null;
var regularCell = null;
var lineSpecialCells = [];
var twoGreenSpecials = false;
- // Check for green special interactions
if (cell1.isSpecial && cell1.specialType === 'green' && cell2.isSpecial && cell2.specialType === 'green') {
twoGreenSpecials = true;
} else if (cell1.isSpecial && cell1.specialType === 'green') {
greenSpecialCell = cell1;
@@ -278,23 +233,20 @@
} else if (cell2.isSpecial && cell2.specialType === 'green') {
greenSpecialCell = cell2;
regularCell = cell1;
}
- // Check for line special interactions
if (cell1.isSpecial && (cell1.specialType === 'horizontal' || cell1.specialType === 'vertical')) {
lineSpecialCells.push(cell1);
}
if (cell2.isSpecial && (cell2.specialType === 'horizontal' || cell2.specialType === 'vertical')) {
lineSpecialCells.push(cell2);
}
- // Update grid references
gridCells[row1][col1] = cell2;
gridCells[row2][col2] = cell1;
cell1.row = row2;
cell1.col = col2;
cell2.row = row1;
cell2.col = col1;
- // Hide any remaining selection highlights
if (cell1.selectionHighlight) {
cell1.hideSelection();
}
if (cell2.selectionHighlight) {
@@ -538,205 +490,201 @@
}, 350);
}
function getMatches() {
var matches = [];
- // Optimized function to find matches in either horizontal or vertical direction
function findDirectionalMatches(isHorizontal) {
- var primaryCount = isHorizontal ? gridSize + extraRows : gridSize;
- var secondaryCount = isHorizontal ? gridSize : gridSize + extraRows;
- // Loop through primary dimension (rows or columns)
- for (var primary = isHorizontal ? 0 : 0; primary < primaryCount; primary++) {
- if (!gridCells[primary] && isHorizontal) {
+ var primary, secondary;
+ var primaryMax = isHorizontal ? gridSize + extraRows : gridSize;
+ var secondaryMax = isHorizontal ? gridSize : gridSize + extraRows;
+ for (primary = isHorizontal ? extraRows : 0; primary < primaryMax; primary++) {
+ if (!gridCells[primary]) {
continue;
}
- // Track current match sequence
- var currentValue = -1;
- var matchStart = 0;
- var matchLength = 0;
- // Scan through secondary dimension
- for (var secondary = 0; secondary <= secondaryCount; secondary++) {
- // Get current cell or null if beyond grid or at end of scan
- var currentCell = null;
- if (secondary < secondaryCount) {
- currentCell = isHorizontal ? gridCells[primary] ? gridCells[primary][secondary] : null : gridCells[secondary] ? gridCells[secondary][primary] : null;
+ for (secondary = 0; secondary < secondaryMax;) {
+ if (secondary > secondaryMax - 3) {
+ secondary++;
+ continue;
}
- // Check if current cell continues the match
- if (currentCell && currentCell.value && currentCell.value === currentValue) {
- matchLength++;
- } else {
- // Process completed match if long enough
- if (matchLength >= 3) {
- var matchCells = [];
- // Collect all cells in the match
- for (var i = 0; i < matchLength; i++) {
- var cell = isHorizontal ? gridCells[primary][matchStart + i] : gridCells[matchStart + i][primary];
- if (cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
- matchCells.push(cell);
+ var cell1 = isHorizontal ? gridCells[primary] ? gridCells[primary][secondary] : null : gridCells[secondary] ? gridCells[secondary][primary] : null;
+ if (!cell1 || !cell1.value) {
+ secondary++;
+ continue;
+ }
+ var currentMatchValue = cell1.value;
+ var currentMatchCells = [cell1];
+ for (var k = secondary + 1; k < secondaryMax; k++) {
+ var nextCell = isHorizontal ? gridCells[primary] ? gridCells[primary][k] : null : gridCells[k] ? gridCells[k][primary] : null;
+ if (nextCell && nextCell.value === currentMatchValue) {
+ currentMatchCells.push(nextCell);
+ } else {
+ LK.setTimeout(function () {
+ if (!window.gravityInProgress && !window.fillInProgress) {
+ comboInProgress = false;
+ comboCounter = 0;
}
+ }, 500);
+ break;
+ }
+ }
+ if (currentMatchCells.length >= 3) {
+ var validCells = currentMatchCells.filter(function (cell) {
+ return cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell;
+ });
+ if (validCells.length >= 3) {
+ var visibleCells = validCells.filter(function (cell) {
+ return cell.row >= extraRows;
+ });
+ var invisibleCells = validCells.filter(function (cell) {
+ return cell.row < extraRows;
+ });
+ if (visibleCells.length === 0 || invisibleCells.length === 0 || visibleCells.length >= 3) {
+ validCells.isHorizontal = isHorizontal;
+ validCells.matchType = currentMatchValue;
+ matches.push(validCells);
}
- // Only add valid matches with minimum length
- if (matchCells.length >= 3) {
- // Count visible and invisible cells
- var visibleCount = 0;
- var invisibleCount = 0;
- for (var i = 0; i < matchCells.length; i++) {
- if (matchCells[i].row >= extraRows) {
- visibleCount++;
- } else {
- invisibleCount++;
- }
- }
- // Add match if it satisfies visibility criteria
- if (visibleCount === 0 || invisibleCount === 0 || visibleCount >= 3) {
- matchCells.isHorizontal = isHorizontal;
- matchCells.matchType = currentValue;
- matches.push(matchCells);
- }
- }
}
- // Start new potential match
- if (currentCell && currentCell.value) {
- currentValue = currentCell.value;
- matchStart = secondary;
- matchLength = 1;
- } else {
- currentValue = -1;
- matchLength = 0;
- }
}
+ secondary += currentMatchCells.length > 0 ? currentMatchCells.length : 1;
}
}
}
- // Find matches in both directions
- findDirectionalMatches(true); // Horizontal
- findDirectionalMatches(false); // Vertical
+ findDirectionalMatches(true);
+ findDirectionalMatches(false);
return matches;
}
function destroyCells(cellsToDestroy) {
isAnimating = true;
- // Partition cells into visible and valid cells in one pass
- var visibleCellsToDestroy = [];
- var invisibleCells = [];
- var validCellMap = {};
- for (var i = 0; i < cellsToDestroy.length; i++) {
- var cell = cellsToDestroy[i];
- if (!cell || !gridCells[cell.row] || gridCells[cell.row][cell.col] !== cell) continue;
- if (cell.row >= extraRows) {
- visibleCellsToDestroy.push(cell);
- validCellMap[cell.row + "_" + cell.col] = cell;
- } else {
- invisibleCells.push(cell);
- }
- }
- // Early exit if not enough visible or invisible cells
- if (visibleCellsToDestroy.length > 0 && invisibleCells.length > 0 && (visibleCellsToDestroy.length === 1 || invisibleCells.length === 1)) {
+ var destructionId = Date.now() + Math.random();
+ var visibleCells = cellsToDestroy.filter(function (cell) {
+ return cell.row >= extraRows;
+ });
+ var invisibleCells = cellsToDestroy.filter(function (cell) {
+ return cell.row < extraRows;
+ });
+ if (visibleCells.length > 0 && invisibleCells.length > 0 && (visibleCells.length === 1 || invisibleCells.length === 1)) {
isAnimating = false;
return;
}
- // Determine center cell
+ var visibleCellsToDestroy = cellsToDestroy.filter(function (cell) {
+ return cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell;
+ });
var centerCell = null;
if (arguments.length > 1 && arguments[1]) {
centerCell = arguments[1];
} else if (cellsToDestroy.length > 0) {
centerCell = cellsToDestroy[Math.floor(cellsToDestroy.length / 2)];
}
- // Group cells by type efficiently
var cellsByType = {};
- for (var i = 0; i < visibleCellsToDestroy.length; i++) {
- var cell = visibleCellsToDestroy[i];
+ visibleCellsToDestroy.forEach(function (cell) {
if (!cellsByType[cell.value]) {
cellsByType[cell.value] = [];
}
cellsByType[cell.value].push(cell);
- }
- // Handle combo sound
+ });
var uniqueGroupCount = Object.keys(cellsByType).length;
if (uniqueGroupCount > 0) {
if (!comboInProgress) {
comboCounter = uniqueGroupCount;
comboInProgress = true;
} else {
comboCounter += uniqueGroupCount;
}
- // Stop all combo sounds before playing a new one
- LK.getSound('Combo1').stop();
- LK.getSound('Combo2').stop();
- LK.getSound('Combo3').stop();
- LK.getSound('Combo4').stop();
- LK.getSound('Combo5').stop();
- // Play the appropriate combo sound
- if (comboCounter >= 9) {
+ playComboSound(comboCounter);
+ }
+ function playComboSound(comboCount) {
+ // Stop all combo sounds
+ for (var i = 1; i <= 5; i++) {
+ LK.getSound('Combo' + i).stop();
+ }
+ // Play appropriate combo sound based on count
+ if (comboCount >= 9) {
LK.getSound('Combo5').play();
- } else if (comboCounter >= 6) {
+ } else if (comboCount >= 6) {
LK.getSound('Combo4').play();
- } else if (comboCounter >= 4) {
+ } else if (comboCount >= 4) {
LK.getSound('Combo3').play();
- } else if (comboCounter >= 3) {
+ } else if (comboCount >= 3) {
LK.getSound('Combo2').play();
- } else if (comboCounter >= 2) {
+ } else if (comboCount >= 2) {
LK.getSound('Combo1').play();
}
}
- // Process special cells
- var specialCell = null;
- for (var type in cellsByType) {
- var typeCells = cellsByType[type];
- var typeValue = parseInt(type);
- // Handle special cell creation based on match length
- if (typeCells.length >= 6) {
- specialCell = centerCell && centerCell.value === typeValue ? centerCell : typeCells[0];
- specialCell.isSpecial = true;
- specialCell.specialType = 'green';
- specialCell.beingDestroyed = false;
- delete validCellMap[specialCell.row + "_" + specialCell.col];
- break;
- } else if (typeCells.length === 5) {
- specialCell = centerCell && centerCell.value === typeValue ? centerCell : typeCells[0];
- specialCell.isSpecial = true;
- specialCell.specialType = 'bomb';
- specialCell.beingDestroyed = false;
- delete validCellMap[specialCell.row + "_" + specialCell.col];
- break;
- } else if (typeCells.length === 4) {
- // Check if cells are in same row or column
- var firstCell = typeCells[0];
- var allInSameRow = true;
- var allInSameCol = true;
- for (var i = 1; i < typeCells.length; i++) {
- if (typeCells[i].row !== firstCell.row) allInSameRow = false;
- if (typeCells[i].col !== firstCell.col) allInSameCol = false;
+ var specialCell = createSpecialCell(cellsByType, centerCell, visibleCellsToDestroy);
+ if (specialCell) {
+ visibleCellsToDestroy = visibleCellsToDestroy.filter(function (cell) {
+ return cell !== specialCell;
+ });
+ }
+ function createSpecialCell(cellsByType, centerCell, visibleCells) {
+ var specialCell = null;
+ for (var type in cellsByType) {
+ var typeCells = cellsByType[type];
+ var typeValue = parseInt(type);
+ // Handle matches of 6 or more - create green special
+ if (typeCells.length >= 6) {
+ specialCell = chooseSpecialCell(centerCell, typeCells, typeValue);
+ initializeSpecialCell(specialCell, 'green');
+ return specialCell;
}
- if (allInSameRow || allInSameCol) {
- specialCell = centerCell && centerCell.value === typeValue ? centerCell : typeCells[0];
- specialCell.isSpecial = true;
- specialCell.specialType = allInSameRow ? 'horizontal' : 'vertical';
- specialCell.beingDestroyed = false;
- delete validCellMap[specialCell.row + "_" + specialCell.col];
- break;
+ // Handle matches of 5 - create bomb special
+ else if (typeCells.length === 5) {
+ specialCell = chooseSpecialCell(centerCell, typeCells, typeValue);
+ initializeSpecialCell(specialCell, 'bomb');
+ return specialCell;
}
+ // Handle matches of 4 - create horizontal/vertical special
+ else if (typeCells.length === 4) {
+ var firstCell = typeCells[0];
+ var isHorizontalMatch = true;
+ var isVerticalMatch = true;
+ for (var i = 1; i < typeCells.length; i++) {
+ if (typeCells[i].row !== firstCell.row) {
+ isHorizontalMatch = false;
+ }
+ if (typeCells[i].col !== firstCell.col) {
+ isVerticalMatch = false;
+ }
+ }
+ if (isHorizontalMatch || isVerticalMatch) {
+ specialCell = chooseSpecialCell(centerCell, typeCells, typeValue);
+ initializeSpecialCell(specialCell, isHorizontalMatch ? 'horizontal' : 'vertical');
+ return specialCell;
+ }
+ }
}
+ return null;
}
- // Rebuild list of cells to destroy (excluding special cell)
- visibleCellsToDestroy = Object.values(validCellMap);
- // Sort cells by distance from center if needed
+ function chooseSpecialCell(centerCell, typeCells, typeValue) {
+ if (centerCell && centerCell.value === typeValue) {
+ return centerCell;
+ } else {
+ return typeCells[0];
+ }
+ }
+ function initializeSpecialCell(cell, specialType) {
+ cell.isSpecial = true;
+ cell.specialType = specialType;
+ cell.beingDestroyed = false;
+ cell.updateSpecialAppearance();
+ }
if (centerCell && visibleCellsToDestroy.length > 0) {
visibleCellsToDestroy.sort(function (a, b) {
var distA = Math.abs(a.row - centerCell.row) + Math.abs(a.col - centerCell.col);
var distB = Math.abs(b.row - centerCell.row) + Math.abs(b.col - centerCell.col);
return distA - distB;
});
}
- // Mark cells for destruction
- for (var i = 0; i < visibleCellsToDestroy.length; i++) {
- var cell = visibleCellsToDestroy[i];
- cell.beingDestroyed = true;
- if (cell.isSpecial) {
- LK.setTimeout(function () {
- cell.activateSpecialPower();
- }, 100);
+ var totalDestructionTime = 0;
+ visibleCellsToDestroy.forEach(function (cell) {
+ if (cell) {
+ cell.beingDestroyed = true;
+ if (cell.isSpecial) {
+ LK.setTimeout(function () {
+ cell.activateSpecialPower();
+ }, 100);
+ }
}
- }
- // Handle special cell appearance
+ });
if (specialCell && specialCell.isSpecial) {
if (specialCell.specialType === 'bomb') {
specialCell.sprite.tint = 0x0088FF;
} else if (specialCell.specialType === 'green') {
@@ -745,458 +693,387 @@
specialCell.sprite.tint = 0xFF8800;
}
LK.effects.flashObject(specialCell, 0xFFFFFF, 300);
}
- // Immediately destroy marked cells
- for (var i = 0; i < visibleCellsToDestroy.length; i++) {
- var cell = visibleCellsToDestroy[i];
- if (cell && cell.beingDestroyed && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
+ destroyVisibleCells(visibleCellsToDestroy);
+ function destroyVisibleCells(cells) {
+ // Play sound once for all cells rather than for each cell
+ if (cells.length > 0) {
LK.getSound('Explosion').play();
- LK.effects.flashObject(cell, 0xFFFFFF, 200);
- gridContainer.removeChild(cell);
- cell.destroy();
- gridCells[cell.row][cell.col] = null;
}
+ cells.forEach(function (cell) {
+ if (cell && cell.beingDestroyed && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
+ LK.effects.flashObject(cell, 0xFFFFFF, 200);
+ gridContainer.removeChild(cell);
+ cell.destroy();
+ gridCells[cell.row][cell.col] = null;
+ }
+ });
}
- // Apply gravity immediately after destruction
- applyGravity();
+ var allCellsDestroyed = true;
+ for (var r = 0; r < gridSize + extraRows; r++) {
+ for (var c = 0; c < gridSize; c++) {
+ if (gridCells[r] && gridCells[r][c] && gridCells[r][c].beingDestroyed) {
+ allCellsDestroyed = false;
+ }
+ }
+ }
+ if (allCellsDestroyed && !window.gravityInProgress && !window.fillInProgress) {
+ applyGravity();
+ }
}
+// Define global isValidCell function to fix the reference error
+function isValidCell(cell) {
+ return cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell && !cell.beingDestroyed;
+}
function applyGravity() {
isAnimating = true;
- // Early return if gravity is already in progress
+ var cellsToFall = [];
if (window.gravityInProgress) {
return;
}
window.gravityInProgress = true;
- var cellsToFall = [];
- // First, mark all cells in motion to prevent interaction
- for (var row = 0; row < gridSize + extraRows; row++) {
- for (var col = 0; col < gridSize; col++) {
- if (gridCells[row] && gridCells[row][col]) {
- gridCells[row][col].inMotion = true;
- }
- }
- }
- // Process column by column to ensure consistent gravity
- for (var col = 0; col < gridSize; col++) {
- var emptySpaces = [];
- // First pass: scan bottom to top to identify empty spaces
- for (var row = gridSize + extraRows - 1; row >= extraRows; row--) {
- if (!gridCells[row] || !gridCells[row][col]) {
- emptySpaces.push(row);
- } else if (emptySpaces.length > 0) {
- // Found a cell that needs to fall into an empty space below
- var targetRow = emptySpaces.shift();
- var cellToMove = gridCells[row][col];
- // Store info for animation
- cellsToFall.push({
- cell: cellToMove,
- fromRow: row,
- toRow: targetRow,
- col: col
- });
- // Update grid references immediately to prevent cells passing through each other
- gridCells[targetRow][col] = cellToMove;
- gridCells[row][col] = null;
- cellToMove.row = targetRow;
- // Add the now-empty source row back to empty spaces
- emptySpaces.push(row);
- // Sort to maintain correct falling order (higher empty spaces first)
- emptySpaces.sort(function (a, b) {
- return b - a;
- });
- }
- }
- // Second pass: handle cells from hidden area
- if (emptySpaces.length > 0 && emptySpaces[0] >= extraRows) {
- // Check hidden rows from bottom to top
- for (var hiddenRow = extraRows - 1; hiddenRow >= 0; hiddenRow--) {
- if (gridCells[hiddenRow] && gridCells[hiddenRow][col]) {
- // Move hidden cell to first visible empty space
- var targetRow = emptySpaces.shift();
- var cellToMove = gridCells[hiddenRow][col];
- // Add to visible container
- gridContainer.addChild(cellToMove);
- // Store info for animation
- cellsToFall.push({
- cell: cellToMove,
- fromRow: hiddenRow,
- toRow: targetRow,
- col: col
- });
- // Update grid references
- gridCells[targetRow][col] = cellToMove;
- gridCells[hiddenRow][col] = null;
- cellToMove.row = targetRow;
- // If we've filled all empty spaces in this column, break
- if (emptySpaces.length === 0) break;
- // Otherwise, add the now-empty source row back and resort
- emptySpaces.push(hiddenRow);
- emptySpaces.sort(function (a, b) {
- return b - a;
- });
- }
- }
- }
- }
- // Use a constant animation duration for all cells
- var animationDuration = 300;
- // Sort cells properly for natural falling animation (bottom cells first)
+ // Scan grid and find cells that need to fall
+ processGridForGravity(cellsToFall);
+ // Animation constants
+ var baseDelay = 30;
+ var constantDuration = 400;
+ // Sort for consistent animation order
cellsToFall.sort(function (a, b) {
if (a.col !== b.col) {
return a.col - b.col;
}
return b.toRow - a.toRow;
});
- // Position cells at their start position before animating
- for (var i = 0; i < cellsToFall.length; i++) {
- var fallInfo = cellsToFall[i];
- var startPos = getCellPosition(fallInfo.fromRow, fallInfo.col);
- fallInfo.cell.x = startPos.x;
- if (fallInfo.fromRow < extraRows) {
- // Position cells from hidden area just above the visible grid
- var firstVisiblePos = getCellPosition(extraRows, fallInfo.col);
- fallInfo.cell.y = firstVisiblePos.y - cellSize;
- } else {
- fallInfo.cell.y = startPos.y;
+ // Start animations
+ var longestDelay = animateFallingCells(cellsToFall, baseDelay, constantDuration);
+ // Schedule next step
+ LK.setTimeout(function () {
+ window.gravityInProgress = false;
+ if (!window.destructionInProgress) {
+ fillEmptySpacesWithNewMemes();
}
- }
- // Start all animations with proper tweening
- for (var i = 0; i < cellsToFall.length; i++) {
- var fallInfo = cellsToFall[i];
- var newPos = getCellPosition(fallInfo.toRow, fallInfo.col);
- tween(fallInfo.cell, {
- y: newPos.y
- }, {
- duration: animationDuration,
- easing: tween.easeInOutQuad,
- onComplete: function (cell) {
- return function () {
- cell.inMotion = false;
- };
- }(fallInfo.cell)
- });
- }
- // If no cells to fall, proceed immediately to filling empty spaces
- if (cellsToFall.length === 0) {
- // Clear motion flags
- for (var row = 0; row < gridSize + extraRows; row++) {
- for (var col = 0; col < gridSize; col++) {
- if (gridCells[row] && gridCells[row][col]) {
- gridCells[row][col].inMotion = false;
+ }, longestDelay + 50);
+}
+function processGridForGravity(cellsToFall) {
+ for (var col = 0; col < gridSize; col++) {
+ for (var row = gridSize + extraRows - 1; row >= extraRows; row--) {
+ if (!gridCells[row][col]) {
+ var sourceRow = row - 1;
+ while (sourceRow >= 0 && !gridCells[sourceRow][col]) {
+ sourceRow--;
}
- }
- }
- window.gravityInProgress = false;
- fillEmptySpacesWithNewMemes();
- } else {
- // Wait for animations to complete before proceeding
- LK.setTimeout(function () {
- // Clear motion flags
- for (var row = 0; row < gridSize + extraRows; row++) {
- for (var col = 0; col < gridSize; col++) {
- if (gridCells[row] && gridCells[row][col]) {
- gridCells[row][col].inMotion = false;
+ if (sourceRow >= 0) {
+ var cellToMove = gridCells[sourceRow][col];
+ if (cellToMove) {
+ cellsToFall.push({
+ cell: cellToMove,
+ fromRow: sourceRow,
+ toRow: row,
+ col: col
+ });
+ // Update grid data
+ gridCells[row][col] = cellToMove;
+ gridCells[sourceRow][col] = null;
+ cellToMove.row = row;
+ // Make hidden cells visible
+ if (sourceRow < extraRows) {
+ gridContainer.addChild(cellToMove);
+ }
}
}
}
- window.gravityInProgress = false;
- fillEmptySpacesWithNewMemes();
- }, animationDuration + 50);
+ }
}
}
+function animateFallingCells(cellsToFall, baseDelay, duration) {
+ var longestDelay = 0;
+ cellsToFall.forEach(function (fallInfo, index) {
+ var delay = index * baseDelay;
+ var newPos = getCellPosition(fallInfo.toRow, fallInfo.col);
+ var totalTime = delay + duration;
+ if (totalTime > longestDelay) {
+ longestDelay = totalTime;
+ }
+ LK.setTimeout(function () {
+ if (isValidCell(fallInfo.cell)) {
+ tween(fallInfo.cell, {
+ y: newPos.y
+ }, {
+ duration: duration,
+ easing: tween.linear
+ });
+ }
+ }, delay);
+ });
+ return longestDelay;
+}
function fillEmptySpacesWithNewMemes() {
- // Early return if operations are already in progress
if (window.fillInProgress || window.gravityInProgress) {
return;
}
window.fillInProgress = true;
- var newCellsToAdd = [];
- // First mark all cells in motion to prevent interaction
- for (var row = 0; row < gridSize + extraRows; row++) {
- for (var col = 0; col < gridSize; col++) {
- if (gridCells[row] && gridCells[row][col]) {
- gridCells[row][col].inMotion = true;
- }
+ // Create and add new cells
+ var newCellsToAdd = createNewCells();
+ var anyNewMemeAdded = newCellsToAdd.length > 0;
+ // Animation constants
+ var baseDelay = 30;
+ var constantDuration = 400;
+ // Sort cells for consistent animation
+ newCellsToAdd.sort(function (a, b) {
+ if (a.col !== b.col) {
+ return a.col - b.col;
}
+ return b.row - a.row;
+ });
+ // Animate new cells
+ var longestDelay = animateNewCells(newCellsToAdd, baseDelay, constantDuration);
+ // Handle completion
+ if (anyNewMemeAdded) {
+ LK.setTimeout(function () {
+ window.fillInProgress = false;
+ if (window.destructionInProgress || window.gravityInProgress) {
+ isAnimating = false;
+ return;
+ }
+ processNewMatches();
+ }, longestDelay + 50);
+ } else {
+ window.fillInProgress = false;
+ isAnimating = false;
+ comboInProgress = false;
+ comboCounter = 0;
}
- // Process column by column for consistent filling
+}
+function createNewCells() {
+ var newCells = [];
for (var col = 0; col < gridSize; col++) {
- // Count empty spaces in this column
- var emptyCount = 0;
for (var row = 0; row < gridSize + extraRows; row++) {
if (!gridCells[row][col]) {
- emptyCount++;
- }
- }
- // Fill empty spaces starting from the top
- var nextRowToFill = 0;
- for (var row = 0; row < gridSize + extraRows; row++) {
- if (!gridCells[row][col]) {
var newCell = getGridCell();
var pos = getCellPosition(row, col);
- // Calculate starting position above the grid
- var startPosition = extraRows - emptyCount + nextRowToFill;
- var startY = startPosition < 0 ? pos.y - Math.abs(startPosition) * (cellSize + cellSpacing) : getCellPosition(startPosition, col).y;
- // Position new cell above the grid for animation
+ // Configure new cell
newCell.x = pos.x;
- newCell.y = startY;
- newCell.inMotion = true;
- // Generate random value while avoiding potential matches
- var randomValue;
- var attempts = 0;
- var leftMatches = 0;
- var aboveMatches = 0;
- do {
- randomValue = Math.floor(Math.random() * 5) + 1;
- attempts++;
- // Check horizontal matches
- if (col >= 2 && gridCells[row][col - 1] && gridCells[row][col - 2] && gridCells[row][col - 1].value === randomValue && gridCells[row][col - 2].value === randomValue) {
- leftMatches = 2;
- } else {
- leftMatches = 0;
- }
- // Check vertical matches
- if (row >= 2 && gridCells[row - 1] && gridCells[row - 2] && gridCells[row - 1][col] && gridCells[row - 2][col] && gridCells[row - 1][col].value === randomValue && gridCells[row - 2][col].value === randomValue) {
- aboveMatches = 2;
- } else {
- aboveMatches = 0;
- }
- } while ((leftMatches >= 2 || aboveMatches >= 2) && attempts < 5);
- // Set values and update grid reference
- newCell.setValue(randomValue);
+ newCell.y = pos.y - 400; // Start above grid
+ newCell.setValue(Math.floor(Math.random() * 5) + 1);
newCell.row = row;
newCell.col = col;
+ // Update grid data
gridCells[row][col] = newCell;
- newCellsToAdd.push({
+ // Track for animation
+ newCells.push({
cell: newCell,
destY: pos.y,
row: row,
- col: col,
- startY: startY
+ col: col
});
- // Only add to visible container if in visible area
+ // Add to visible container if needed
if (row >= extraRows) {
gridContainer.addChild(newCell);
}
- nextRowToFill++;
}
}
}
- // Use a constant animation duration with staggered timing
- var animationDuration = 300;
- var staggerDelay = 30; // Small delay between cells in same column
- // Sort cells for natural falling appearance (top to bottom in each column)
- newCellsToAdd.sort(function (a, b) {
- if (a.col !== b.col) {
- return a.col - b.col;
+ return newCells;
+}
+function animateNewCells(cells, baseDelay, duration) {
+ var longestDelay = 0;
+ cells.forEach(function (cellData, index) {
+ var delay = index * baseDelay;
+ var totalTime = delay + duration;
+ if (totalTime > longestDelay) {
+ longestDelay = totalTime;
}
- return a.row - b.row; // Top to bottom within column
- });
- // Start animations with proper delays for natural falling
- var maxDelay = 0;
- var lastCol = -1;
- var colDelay = 0;
- for (var i = 0; i < newCellsToAdd.length; i++) {
- var cellData = newCellsToAdd[i];
- // Reset column delay when moving to a new column
- if (cellData.col !== lastCol) {
- colDelay = 0;
- lastCol = cellData.col;
- }
- // Set cell to starting position
- cellData.cell.y = cellData.startY;
- // Calculate delay and update maximum
- var thisDelay = colDelay;
- maxDelay = Math.max(maxDelay, thisDelay);
- // Start animation with delay
- LK.setTimeout(function (data, delay) {
- return function () {
- tween(data.cell, {
- y: data.destY
+ LK.setTimeout(function () {
+ if (isValidCell(cellData.cell)) {
+ tween(cellData.cell, {
+ y: cellData.destY
}, {
- duration: animationDuration,
- easing: tween.easeOutBounce,
- onComplete: function (cell) {
- return function () {
- cell.inMotion = false;
- };
- }(data.cell)
+ duration: duration,
+ easing: tween.linear
});
- };
- }(cellData, thisDelay), thisDelay);
- // Increment delay for next cell in this column
- colDelay += staggerDelay;
- }
- // If no new cells, reset states immediately
- if (newCellsToAdd.length === 0) {
- // Clear motion flags
- for (var row = 0; row < gridSize + extraRows; row++) {
- for (var col = 0; col < gridSize; col++) {
- if (gridCells[row] && gridCells[row][col]) {
- gridCells[row][col].inMotion = false;
- }
}
- }
- window.fillInProgress = false;
- isAnimating = false;
- comboInProgress = false;
- comboCounter = 0;
- return;
- }
- // Check for matches after animation completes
- LK.setTimeout(function () {
- // Clear motion flags
- for (var row = 0; row < gridSize + extraRows; row++) {
- for (var col = 0; col < gridSize; col++) {
- if (gridCells[row] && gridCells[row][col]) {
- gridCells[row][col].inMotion = false;
- }
+ }, delay);
+ });
+ return longestDelay;
+}
+function processNewMatches() {
+ // Get matches with visible cells
+ var visibleMatchGroups = getMatches().filter(function (group) {
+ return isValidMatchGroup(group);
+ });
+ if (visibleMatchGroups.length > 0) {
+ // Group matches by cell value type
+ var matchesByType = groupMatchesByType(visibleMatchGroups);
+ // Process each match type
+ for (var type in matchesByType) {
+ var typeGroups = matchesByType[type];
+ var centerCell = null;
+ if (typeGroups.length > 0 && typeGroups[0].length > 0) {
+ var matchGroup = typeGroups[0];
+ centerCell = matchGroup[Math.floor(matchGroup.length / 2)];
}
+ // Get unique cells of this type
+ var typeCells = getUniqueCellsFromGroups(typeGroups);
+ if (typeCells.length) {
+ destroyCells(typeCells, centerCell);
+ }
}
- window.fillInProgress = false;
- if (window.destructionInProgress || window.gravityInProgress) {
+ if (Object.keys(matchesByType).length === 0) {
isAnimating = false;
- return;
}
- // Get only valid, visible matches
- var matches = getMatches();
- var visibleMatchGroups = [];
- for (var i = 0; i < matches.length; i++) {
- var group = matches[i];
- var visibleCount = 0;
- var invisibleCount = 0;
- for (var j = 0; j < group.length; j++) {
- if (group[j].row >= extraRows) {
- visibleCount++;
- } else {
- invisibleCount++;
- }
+ } else {
+ isAnimating = false;
+ }
+}
+function isValidMatchGroup(group) {
+ var visibleCells = group.filter(function (cell) {
+ return cell.row >= extraRows;
+ });
+ var invisibleCells = group.filter(function (cell) {
+ return cell.row < extraRows;
+ });
+ if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) {
+ return false;
+ }
+ return visibleCells.length >= 3;
+}
+function groupMatchesByType(matches) {
+ var matchesByType = {};
+ matches.forEach(function (group) {
+ if (group.length > 0) {
+ var type = group[0].value;
+ if (!matchesByType[type]) {
+ matchesByType[type] = [];
}
- // Only include groups with enough visible cells
- if (visibleCount >= 3 || visibleCount > 0 && invisibleCount > 0 && visibleCount >= 3) {
- visibleMatchGroups.push(group);
- }
+ matchesByType[type].push(group);
}
- if (visibleMatchGroups.length > 0) {
- // Process matches by cell type
- var cellsByType = {};
- var processedCells = {};
- // Group cells by type
- for (var i = 0; i < visibleMatchGroups.length; i++) {
- var group = visibleMatchGroups[i];
- if (group.length === 0) continue;
- var type = group[0].value;
- if (!cellsByType[type]) {
- cellsByType[type] = [];
- }
- // Add unique cells
- for (var j = 0; j < group.length; j++) {
- var cell = group[j];
- var cellKey = cell.row + "_" + cell.col;
- if (!processedCells[cellKey] && cell.row >= extraRows && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
- cellsByType[type].push(cell);
- processedCells[cellKey] = true;
- }
- }
+ });
+ return matchesByType;
+}
+function getUniqueCellsFromGroups(groups) {
+ var cells = [];
+ var cellTracker = {};
+ groups.forEach(function (group) {
+ group.forEach(function (cell) {
+ var cellKey = cell.row + "_" + cell.col;
+ if (!cellTracker[cellKey] && isValidCell(cell)) {
+ cells.push(cell);
+ cellTracker[cellKey] = true;
}
- // Process each type group
- for (var type in cellsByType) {
- var cells = cellsByType[type];
- if (cells.length === 0) continue;
- // Use middle cell as center
- var centerCell = cells[Math.floor(cells.length / 2)];
- destroyCells(cells, centerCell);
- }
- } else {
- // No matches, end animation state
- isAnimating = false;
- comboInProgress = false;
- comboCounter = 0;
- }
- }, animationDuration + Math.max(maxDelay, 0) + 50);
+ });
+ });
+ return cells;
}
function checkForAndDestroyMatches(swappedCellA, swappedCellB) {
- // Don't process if animations are in progress
if (window.gravityInProgress || window.fillInProgress) {
return;
}
- // Get all match groups
var allMatchGroupsOnBoard = getMatches();
if (!allMatchGroupsOnBoard.length) {
return;
}
- // Find matches that contain the swapped cells and have enough visible cells
- var relevantMatchGroups = [];
- var cellsInSwap = [swappedCellA, swappedCellB];
- for (var i = 0; i < allMatchGroupsOnBoard.length; i++) {
- var group = allMatchGroupsOnBoard[i];
- var visibleCount = 0;
- var invisibleCount = 0;
- var containsSwappedCell = false;
- // Count visible cells and check for swapped cells in one pass
- for (var j = 0; j < group.length; j++) {
- var cell = group[j];
- if (cell.row >= extraRows) {
- visibleCount++;
- // Check if this cell is one of the swapped cells
- if (cell === swappedCellA || cell === swappedCellB) {
- containsSwappedCell = true;
- }
- } else {
- invisibleCount++;
- }
+ var relevantMatchGroups = allMatchGroupsOnBoard.filter(function (group) {
+ var visibleCells = group.filter(function (cell) {
+ return cell.row >= extraRows;
+ });
+ var invisibleCells = group.filter(function (cell) {
+ return cell.row < extraRows;
+ });
+ if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) {
+ return false;
}
- // Include group if it has enough visible cells and contains a swapped cell
- if (containsSwappedCell && (visibleCount >= 3 || !(visibleCount > 0 && invisibleCount > 0 && visibleCount < 3))) {
- relevantMatchGroups.push(group);
- }
- }
+ return group.some(function (cellInGroup) {
+ return (cellInGroup === swappedCellA || cellInGroup === swappedCellB) && cellInGroup.row >= extraRows;
+ });
+ });
if (!relevantMatchGroups.length) {
return;
}
- // Process matches efficiently
- var cellsByType = {};
- var uniqueCellTracker = {};
- // Group cells by type in one pass
- for (var i = 0; i < relevantMatchGroups.length; i++) {
- var group = relevantMatchGroups[i];
- if (group.length === 0) continue;
- var type = group[0].value;
- if (!cellsByType[type]) {
- cellsByType[type] = [];
+ var matchesByType = {};
+ relevantMatchGroups.forEach(function (group) {
+ if (group.length > 0) {
+ var type = group[0].value;
+ if (!matchesByType[type]) {
+ matchesByType[type] = [];
+ }
+ matchesByType[type].push(group);
}
- // Add unique cells directly
- for (var j = 0; j < group.length; j++) {
- var cell = group[j];
- if (cell.row < extraRows) continue;
+ });
+ var uniqueCellTracker = {};
+ var cellsToDestroy = [];
+ for (var type in matchesByType) {
+ var typeGroups = matchesByType[type];
+ var typeCells = [];
+ typeGroups.forEach(function (group) {
+ group.forEach(function (cell) {
+ if (cell.row >= extraRows) {
+ typeCells.push(cell);
+ }
+ });
+ });
+ typeCells.forEach(function (cell) {
var cellKey = cell.row + "_" + cell.col;
- if (!uniqueCellTracker[cellKey] && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
- cellsByType[type].push(cell);
+ if (!uniqueCellTracker[cellKey] && cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
+ cellsToDestroy.push(cell);
uniqueCellTracker[cellKey] = true;
}
- }
+ });
}
- // Collect all cells to destroy
- var cellsToDestroy = [];
- for (var type in cellsByType) {
- var typeCells = cellsByType[type];
- cellsToDestroy = cellsToDestroy.concat(typeCells);
- }
+ ;
if (cellsToDestroy.length) {
- // Determine center cell for special piece creation
- var centerCell = null;
- // Prioritize swapped cells that are part of a match
- if (swappedCellA && uniqueCellTracker[swappedCellA.row + "_" + swappedCellA.col]) {
- centerCell = swappedCellA;
- } else if (swappedCellB && uniqueCellTracker[swappedCellB.row + "_" + swappedCellB.col]) {
- centerCell = swappedCellB;
- }
- // Destroy matched cells
+ var centerCell = swappedCellA && relevantMatchGroups.some(function (group) {
+ return group.includes(swappedCellA);
+ }) ? swappedCellA : swappedCellB;
destroyCells(cellsToDestroy, centerCell);
- // Reset combo at the end of all cascade matches
- comboInProgress = false;
- comboCounter = 0;
+ LK.setTimeout(function () {
+ if (window.gravityInProgress || window.fillInProgress) {
+ return;
+ }
+ var visibleMatchGroups = getMatches().filter(function (group) {
+ var visibleCells = group.filter(function (cell) {
+ return cell.row >= extraRows;
+ });
+ var invisibleCells = group.filter(function (cell) {
+ return cell.row < extraRows;
+ });
+ if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) {
+ return false;
+ }
+ return visibleCells.length >= 3;
+ });
+ var newMatches = visibleMatchGroups;
+ if (newMatches.length > 0) {
+ var matchesByType = {};
+ newMatches.forEach(function (group) {
+ if (group.length > 0) {
+ var type = group[0].value;
+ if (!matchesByType[type]) {
+ matchesByType[type] = [];
+ }
+ matchesByType[type].push(group);
+ }
+ });
+ for (var type in matchesByType) {
+ var typeGroups = matchesByType[type];
+ var newCellsToDestroy = [];
+ var newCellTracker = {};
+ typeGroups.forEach(function (group) {
+ group.forEach(function (cell) {
+ var cellKey = cell.row + "_" + cell.col;
+ if (!newCellTracker[cellKey] && cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
+ newCellsToDestroy.push(cell);
+ newCellTracker[cellKey] = true;
+ }
+ });
+ });
+ if (newCellsToDestroy.length) {
+ var centerCell = newCellsToDestroy[Math.floor(newCellsToDestroy.length / 2)];
+ destroyCells(newCellsToDestroy, centerCell);
+ }
+ }
+ }
+ }, 400);
}
}
var gridSize = 8;
var extraRows = 9;
la figura de una casa color blanca simple para una interfaz. In-Game asset. 2d. High contrast. No shadows
haz el fondo color morado
circular check logo. In-Game asset. 2d. High contrast. No shadows
Cuadrado con los bordes redondeado negro. In-Game asset. 2d. High contrast. No shadows
hazlo un gris claro
Que sea blanco
Que sea blanco