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
User prompt
repite para la interacción con bomb
User prompt
si se cambia de posición un meme especial verde con un line-clearing transformara todos los memes de ese tipo en line-clearing (aleatorio horizontal/vertical) y consecutivamente activarlos
User prompt
si se cambia de posición 2 bombas se activa una habilidad especial que rompe en 5*5
User prompt
si se cambia de posición un line-clearing con una bomba se activa una habilidad especial que rompe 3 linea o columna
User prompt
arregla el siguiente caso: se combinan dos line-clearing, se hace la habilidad en conjunta en ambas. Haz que solo el meme especial movido por el jugador sea la que se active la super habilidad para evitar casos donde se limpie 2 columnas o 2 filas
User prompt
arregla el siguiente caso: se combinan dos line-clearing, se hace la habilidad en conjunta en ambas. Haz que solo el meme especial movido por el jugador sea la que se active para evitar casos donde se limpie 2 columnas o 2 filas
User prompt
haz que solo se active el meme especial que se movio
User prompt
si se cambia de posición 2 memes que rompen linea/columna se activa una habilidad especial que rompe linea y columna en conjunto
User prompt
crea un nuevo meme especial. Este se crea cuando se combinan 6 o más memes y tiene un tinte verde. Su habilidad se activa cuando se cambia de posición con otro meme, este destruira todos los memes del que se cambio de posición que esten en pantalla
User prompt
crea un nuevo meme especial este se crea cuando se combinan 5 memes y tiene un tinte azul. Su habilidad es romper los memes adyacentes como si fuera una bomba.
User prompt
mejora la logica de bomb ya que genera muchos errores en la caida de nuevos memes dejando espacios vacios sin motivo
User prompt
mejora la bomba para que se mantenga despues de la ruptura y una vez caiga activar su habilidad
User prompt
crea un nuevo meme especial con un tinte verde que se crea al combinar 6 o más memes del mismo tipo. Este al moverlo de lugar con un meme, rompera todos los memes de ese tipo en pantalla
User prompt
crea un nuevo meme especial con un tinte verde que se crea al combinar 6 o más. Este al moverlo de lugar con un meme, rompera todos los memes de ese tipo en pantalla
User prompt
crea un nuevo meme especial este se crea cuando se combinan 5 memes y tiene un tinte azul. Su habilidad es romper los memes adyacentes como si fuera una bomba. se activara dos veces, uno en su lugar y otro cuando cae
User prompt
El meme especial se activa solo cuando se rompe ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
El meme especial se activa solo cuando se junta 3 o más memes de su mismo tipo
User prompt
El meme especial se activa solo cuando se junta con memes de su mismo tipo
User prompt
El meme especial se activa solo cuando se combina con memes de su mismo tipo
User prompt
aarregla lo siguiente. toma a cada tipo de memes como un individuo diferente para evitar casos como el siguiente: Se combinaron 4 memes del mismo tipo pero como el movimiento conbino otros 3 no se creo el meme especial porque toma como si fueran 7 memes en vez de 4 del mismo tipo y 3 de otro. Esto también para habilitar la ruptura simultanea de los grupos
User prompt
arregla el bug que no permite mover las especiales
/**** * 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; // 'horizontal' or 'vertical' 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); // Apply orange tint if this is a special meme if (self.isSpecial) { self.sprite.tint = 0xFF8800; // Orange tint } }; self.activateSpecialPower = function () { if (!self.isSpecial) { return; } var cellsToDestroy = []; if (self.specialType === 'horizontal') { // Destroy all cells in the same column 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 row for (var col = 0; col < gridSize; col++) { if (gridCells[self.row][col] && gridCells[self.row][col] !== self) { cellsToDestroy.push(gridCells[self.row][col]); } } } // Destroy collected cells if (cellsToDestroy.length > 0) { destroyCells(cellsToDestroy); // Also destroy this special meme 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(); // Create pulsating highlight effect var highlight = LK.getAsset('cuadricula', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.15, scaleY: 1.15, alpha: 0.6 }); highlight.tint = 0x00FFFF; // Cyan highlight self.selectionHighlight.addChild(highlight); self.addChildAt(self.selectionHighlight, 0); // Create pulsating animation 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; function handleCellTap(tappedCell) { if (isAnimating || window.gravityInProgress || window.fillInProgress) { return; } if (!tappedCell || !gridCells[tappedCell.row] || gridCells[tappedCell.row][tappedCell.col] !== tappedCell || tappedCell.beingDestroyed) { return; } // Check if the tapped cell is a special meme and we have a previously selected cell if (selectedCell !== null && selectedCell !== tappedCell && tappedCell.isSpecial) { // Check if we're trying to swap (adjacent cells) 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 (isAdjacent) { // Allow swapping special memes like normal memes var cell1 = selectedCell; var cell2 = tappedCell; // Hide selection before swap cell1.hideSelection(); selectedCell = null; // Proceed with swap logic (this will be handled by the code below) } else if (selectedCell.value === tappedCell.value) { // Activate special power tappedCell.activateSpecialPower(); // Clear selection selectedCell.hideSelection(); selectedCell = null; return; } else { // Not the same type, just switch selection selectedCell.hideSelection(); selectedCell = tappedCell; selectedCell.showSelection(); return; } } // Check if the selected cell is a special meme and we're tapping a regular cell if (selectedCell !== null && selectedCell !== tappedCell && selectedCell.isSpecial) { // Check if we're trying to swap (adjacent cells) 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 (isAdjacent) { // Allow swapping special memes like normal memes var cell1 = selectedCell; var cell2 = tappedCell; // Hide selection before swap cell1.hideSelection(); selectedCell = null; // Proceed with swap logic (this will be handled by the code below) } else if (selectedCell.value === tappedCell.value) { // Activate special power selectedCell.activateSpecialPower(); // Clear selection selectedCell.hideSelection(); selectedCell = null; return; } else { // Not the same type, just switch selection selectedCell.hideSelection(); selectedCell = tappedCell; selectedCell.showSelection(); return; } } // If we already have a selected cell if (selectedCell !== null) { // If it's valid if (selectedCell && gridCells[selectedCell.row] && gridCells[selectedCell.row][selectedCell.col] === selectedCell) { // If we tap the same cell, deselect it if (selectedCell === tappedCell) { selectedCell.hideSelection(); selectedCell = null; return; } // Check if they're 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 (!isAdjacent) { // Not adjacent, switch selection selectedCell.hideSelection(); selectedCell = tappedCell; selectedCell.showSelection(); return; } // They are adjacent, continue with swap var cell1 = selectedCell; var cell2 = tappedCell; // Hide selection before swap 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 { // Invalid selected cell, select the new one if (selectedCell) { selectedCell.hideSelection(); } selectedCell = tappedCell; selectedCell.showSelection(); return; } } else { // No selection yet, select this cell 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; gridCells[row1][col1] = cell2; gridCells[row2][col2] = cell1; cell1.row = row2; cell1.col = col2; cell2.row = row1; cell2.col = col1; // Make sure any selection highlights are removed if (cell1.selectionHighlight) { cell1.hideSelection(); } if (cell2.selectionHighlight) { cell2.hideSelection(); } 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 { 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; }); // Either all cells are visible, or all cells are invisible, or there are at least 3 visible cells if (visibleCells.length === 0 || invisibleCells.length === 0 || visibleCells.length >= 3) { // Make sure all cells in a match group have the same value var allSameValue = true; var firstValue = validCells[0].value; for (var i = 1; i < validCells.length; i++) { if (validCells[i].value !== firstValue) { allSameValue = false; break; } } if (allSameValue) { matches.push(validCells); } } } } secondary += currentMatchCells.length > 0 ? currentMatchCells.length : 1; } } } findDirectionalMatches(true); findDirectionalMatches(false); return matches; } function destroyCells(cellsToDestroy) { isAnimating = true; // Create a unique ID for this destruction process var destructionId = Date.now() + Math.random(); // Check if match crosses visible/invisible boundary var visibleCells = cellsToDestroy.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = cellsToDestroy.filter(function (cell) { return cell.row < extraRows; }); // If mixed visibility and only one cell is visible, don't destroy any 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; }); // Find the center cell (the one that triggered the match) var centerCell = null; // If we have the cells from a swap, use one of those as the center if (arguments.length > 1 && arguments[1]) { centerCell = arguments[1]; } else if (cellsToDestroy.length > 0) { // Otherwise use the middle cell of the match centerCell = cellsToDestroy[Math.floor(cellsToDestroy.length / 2)]; } // Group cells by meme type var cellsByType = {}; visibleCellsToDestroy.forEach(function (cell) { if (!cellsByType[cell.value]) { cellsByType[cell.value] = []; } cellsByType[cell.value].push(cell); }); // Check if any type has exactly 4 memes to create a special orange meme var specialCell = null; var isHorizontalMatch = false; var isVerticalMatch = false; for (var memeType in cellsByType) { var sameCells = cellsByType[memeType]; // Only consider groups of exactly 4 of the same type if (sameCells.length === 4) { // Determine if the match is horizontal or vertical var allInSameRow = true; var allInSameCol = true; var firstCell = sameCells[0]; for (var i = 1; i < sameCells.length; i++) { if (sameCells[i].row !== firstCell.row) { allInSameRow = false; } if (sameCells[i].col !== firstCell.col) { allInSameCol = false; } } isHorizontalMatch = allInSameRow; isVerticalMatch = allInSameCol; // Create special meme only if it's a clean horizontal or vertical match if (isHorizontalMatch || isVerticalMatch) { // Use center cell or the second cell in the match for the special meme specialCell = centerCell && centerCell.value == memeType ? centerCell : sameCells[Math.floor(sameCells.length / 2)]; specialCell.isSpecial = true; specialCell.specialType = isHorizontalMatch ? 'horizontal' : 'vertical'; specialCell.beingDestroyed = false; // Remove special cell from cells to destroy visibleCellsToDestroy = visibleCellsToDestroy.filter(function (cell) { return cell !== specialCell; }); // We found our special match, so break out of the loop break; } } } // Sort cells by distance from center cell for ripple effect 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 delay = 0; var delayIncrement = 100; var totalDestructionTime = visibleCellsToDestroy.length * delayIncrement; // Mark cells as being destroyed to prevent them from being part of new matches visibleCellsToDestroy.forEach(function (cell) { if (cell) { cell.beingDestroyed = true; } }); // If we have a special meme, tint it orange if (specialCell && specialCell.isSpecial) { specialCell.sprite.tint = 0xFF8800; // Orange tint LK.effects.flashObject(specialCell, 0xFFFFFF, 300); } visibleCellsToDestroy.forEach(function (cell) { LK.setTimeout(function () { if (cell && cell.beingDestroyed && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) { LK.getSound('Explosion').play(); LK.effects.flashObject(cell, 0xFFFFFF, 200); gridContainer.removeChild(cell); cell.destroy(); gridCells[cell.row][cell.col] = null; } }, delay); delay += delayIncrement; }); // After all cells in this group are destroyed, check if we need to apply gravity LK.setTimeout(function () { // Check if all destructions are complete before applying gravity 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; } } } // Only the last destruction process should trigger gravity if (allCellsDestroyed && !window.gravityInProgress && !window.fillInProgress) { applyGravity(); } }, totalDestructionTime + 50); } function applyGravity() { isAnimating = true; var cellsToFall = []; if (window.gravityInProgress) { return; } window.gravityInProgress = true; 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 }); gridCells[row][col] = cellToMove; gridCells[sourceRow][col] = null; cellToMove.row = row; if (sourceRow < extraRows) { gridContainer.addChild(cellToMove); } } } } } } var longestDelay = 0; var baseDelay = 30; var constantDuration = 400; cellsToFall.sort(function (a, b) { if (a.col !== b.col) { return a.col - b.col; } return b.toRow - a.toRow; }); cellsToFall.forEach(function (fallInfo, index) { var delay = index * baseDelay; var newPos = getCellPosition(fallInfo.toRow, fallInfo.col); var totalTime = delay + constantDuration; if (totalTime > longestDelay) { longestDelay = totalTime; } LK.setTimeout(function () { if (fallInfo.cell && gridCells[fallInfo.cell.row] && gridCells[fallInfo.cell.row][fallInfo.cell.col] === fallInfo.cell) { tween(fallInfo.cell, { y: newPos.y }, { duration: constantDuration, easing: tween.linear }); } }, delay); }); LK.setTimeout(function () { window.gravityInProgress = false; if (!window.destructionInProgress) { fillEmptySpacesWithNewMemes(); } }, longestDelay + 50); } function fillEmptySpacesWithNewMemes() { if (window.fillInProgress || window.gravityInProgress) { return; } window.fillInProgress = true; var anyNewMemeAdded = false; var newCellsToAdd = []; for (var col = 0; col < gridSize; col++) { for (var row = 0; row < gridSize + extraRows; row++) { if (!gridCells[row][col]) { anyNewMemeAdded = true; var newCell = getGridCell(); var pos = getCellPosition(row, col); newCell.x = pos.x; newCell.y = pos.y - 400; var randomValue = Math.floor(Math.random() * 5) + 1; newCell.setValue(randomValue); newCell.row = row; newCell.col = col; gridCells[row][col] = newCell; newCellsToAdd.push({ cell: newCell, destY: pos.y, row: row, col: col }); if (row >= extraRows) { gridContainer.addChild(newCell); } } } } var longestDelay = 0; var baseDelay = 30; var constantDuration = 400; newCellsToAdd.sort(function (a, b) { if (a.col !== b.col) { return a.col - b.col; } return b.row - a.row; }); newCellsToAdd.forEach(function (cellData, index) { var delay = index * baseDelay; var totalTime = delay + constantDuration; if (totalTime > longestDelay) { longestDelay = totalTime; } LK.setTimeout(function () { if (cellData.cell && gridCells[cellData.row] && gridCells[cellData.row][cellData.col] === cellData.cell) { tween(cellData.cell, { y: cellData.destY }, { duration: constantDuration, easing: tween.linear }); } }, delay); }); if (anyNewMemeAdded) { LK.setTimeout(function () { window.fillInProgress = false; if (window.destructionInProgress || window.gravityInProgress) { isAnimating = false; return; } var visibleMatchGroups = getMatches().filter(function (group) { // Check if the match has cells in both visible and invisible areas var visibleCells = group.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = group.filter(function (cell) { return cell.row < extraRows; }); // Don't count groups with both visible and invisible cells unless there are at least 3 visible cells if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) { return false; } return visibleCells.length >= 3; // At least 3 visible cells make a valid visible match }); var newMatches = visibleMatchGroups; if (newMatches.length > 0) { var newCellsToDestroy = []; var newCellTracker = {}; newMatches.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) { // Find a central cell for the auto-match after gravity var centerCell = null; if (newMatches.length > 0 && newMatches[0].length > 0) { // Pick the center of the first match group var matchGroup = newMatches[0]; centerCell = matchGroup[Math.floor(matchGroup.length / 2)]; } destroyCells(newCellsToDestroy, centerCell); } else { isAnimating = false; } } else { isAnimating = false; } }, longestDelay + 50); } else { window.fillInProgress = false; isAnimating = false; } } function checkForAndDestroyMatches(swappedCellA, swappedCellB) { // Check if any special memes are in a match with same type after falling for (var row = extraRows; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { var cell = gridCells[row] ? gridCells[row][col] : null; if (cell && cell.isSpecial) { // Check adjacent cells for matches with same type var adjacentCells = []; // Check cell above if (row > 0 && gridCells[row - 1] && gridCells[row - 1][col] && gridCells[row - 1][col].value === cell.value) { adjacentCells.push(gridCells[row - 1][col]); } // Check cell below if (row < gridSize + extraRows - 1 && gridCells[row + 1] && gridCells[row + 1][col] && gridCells[row + 1][col].value === cell.value) { adjacentCells.push(gridCells[row + 1][col]); } // Check cell left if (col > 0 && gridCells[row][col - 1] && gridCells[row][col - 1].value === cell.value) { adjacentCells.push(gridCells[row][col - 1]); } // Check cell right if (col < gridSize - 1 && gridCells[row][col + 1] && gridCells[row][col + 1].value === cell.value) { adjacentCells.push(gridCells[row][col + 1]); } // If at least one adjacent cell matches, activate special power if (adjacentCells.length > 0) { cell.activateSpecialPower(); } } } } if (window.gravityInProgress || window.fillInProgress) { return; } var allMatchGroupsOnBoard = getMatches(); if (!allMatchGroupsOnBoard.length) { return; } var relevantMatchGroups = allMatchGroupsOnBoard.filter(function (group) { // Check if the match has cells in both visible and invisible areas var visibleCells = group.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = group.filter(function (cell) { return cell.row < extraRows; }); // Don't count groups with both visible and invisible cells unless there are at least 3 visible cells if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) { return false; } // Only include groups where at least one of the swapped cells is in the group // and the swapped cell is in the visible part of the grid return group.some(function (cellInGroup) { return (cellInGroup === swappedCellA || cellInGroup === swappedCellB) && cellInGroup.row >= extraRows; }); }); if (!relevantMatchGroups.length) { return; } var uniqueCellTracker = {}; var cellsToDestroy = []; relevantMatchGroups.forEach(function (group) { group.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) { // Pass the swapped cell that created the match as the center for the ripple effect 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) { // Check if the match has cells in both visible and invisible areas var visibleCells = group.filter(function (cell) { return cell.row >= extraRows; }); var invisibleCells = group.filter(function (cell) { return cell.row < extraRows; }); // Don't count groups with both visible and invisible cells unless there are at least 3 visible cells if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) { return false; } return visibleCells.length >= 3; // At least 3 visible cells make a valid visible match }); var newMatches = visibleMatchGroups; if (newMatches.length > 0) { var newCellsToDestroy = []; var newCellTracker = {}; newMatches.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) { destroyCells(newCellsToDestroy); } } }, 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();
/****
* 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; // 'horizontal' or 'vertical'
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);
// Apply orange tint if this is a special meme
if (self.isSpecial) {
self.sprite.tint = 0xFF8800; // Orange tint
}
};
self.activateSpecialPower = function () {
if (!self.isSpecial) {
return;
}
var cellsToDestroy = [];
if (self.specialType === 'horizontal') {
// Destroy all cells in the same column
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 row
for (var col = 0; col < gridSize; col++) {
if (gridCells[self.row][col] && gridCells[self.row][col] !== self) {
cellsToDestroy.push(gridCells[self.row][col]);
}
}
}
// Destroy collected cells
if (cellsToDestroy.length > 0) {
destroyCells(cellsToDestroy);
// Also destroy this special meme
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();
// Create pulsating highlight effect
var highlight = LK.getAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.15,
scaleY: 1.15,
alpha: 0.6
});
highlight.tint = 0x00FFFF; // Cyan highlight
self.selectionHighlight.addChild(highlight);
self.addChildAt(self.selectionHighlight, 0);
// Create pulsating animation
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;
function handleCellTap(tappedCell) {
if (isAnimating || window.gravityInProgress || window.fillInProgress) {
return;
}
if (!tappedCell || !gridCells[tappedCell.row] || gridCells[tappedCell.row][tappedCell.col] !== tappedCell || tappedCell.beingDestroyed) {
return;
}
// Check if the tapped cell is a special meme and we have a previously selected cell
if (selectedCell !== null && selectedCell !== tappedCell && tappedCell.isSpecial) {
// Check if we're trying to swap (adjacent cells)
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 (isAdjacent) {
// Allow swapping special memes like normal memes
var cell1 = selectedCell;
var cell2 = tappedCell;
// Hide selection before swap
cell1.hideSelection();
selectedCell = null;
// Proceed with swap logic (this will be handled by the code below)
} else if (selectedCell.value === tappedCell.value) {
// Activate special power
tappedCell.activateSpecialPower();
// Clear selection
selectedCell.hideSelection();
selectedCell = null;
return;
} else {
// Not the same type, just switch selection
selectedCell.hideSelection();
selectedCell = tappedCell;
selectedCell.showSelection();
return;
}
}
// Check if the selected cell is a special meme and we're tapping a regular cell
if (selectedCell !== null && selectedCell !== tappedCell && selectedCell.isSpecial) {
// Check if we're trying to swap (adjacent cells)
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 (isAdjacent) {
// Allow swapping special memes like normal memes
var cell1 = selectedCell;
var cell2 = tappedCell;
// Hide selection before swap
cell1.hideSelection();
selectedCell = null;
// Proceed with swap logic (this will be handled by the code below)
} else if (selectedCell.value === tappedCell.value) {
// Activate special power
selectedCell.activateSpecialPower();
// Clear selection
selectedCell.hideSelection();
selectedCell = null;
return;
} else {
// Not the same type, just switch selection
selectedCell.hideSelection();
selectedCell = tappedCell;
selectedCell.showSelection();
return;
}
}
// If we already have a selected cell
if (selectedCell !== null) {
// If it's valid
if (selectedCell && gridCells[selectedCell.row] && gridCells[selectedCell.row][selectedCell.col] === selectedCell) {
// If we tap the same cell, deselect it
if (selectedCell === tappedCell) {
selectedCell.hideSelection();
selectedCell = null;
return;
}
// Check if they're 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 (!isAdjacent) {
// Not adjacent, switch selection
selectedCell.hideSelection();
selectedCell = tappedCell;
selectedCell.showSelection();
return;
}
// They are adjacent, continue with swap
var cell1 = selectedCell;
var cell2 = tappedCell;
// Hide selection before swap
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 {
// Invalid selected cell, select the new one
if (selectedCell) {
selectedCell.hideSelection();
}
selectedCell = tappedCell;
selectedCell.showSelection();
return;
}
} else {
// No selection yet, select this cell
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;
gridCells[row1][col1] = cell2;
gridCells[row2][col2] = cell1;
cell1.row = row2;
cell1.col = col2;
cell2.row = row1;
cell2.col = col1;
// Make sure any selection highlights are removed
if (cell1.selectionHighlight) {
cell1.hideSelection();
}
if (cell2.selectionHighlight) {
cell2.hideSelection();
}
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 {
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;
});
// Either all cells are visible, or all cells are invisible, or there are at least 3 visible cells
if (visibleCells.length === 0 || invisibleCells.length === 0 || visibleCells.length >= 3) {
// Make sure all cells in a match group have the same value
var allSameValue = true;
var firstValue = validCells[0].value;
for (var i = 1; i < validCells.length; i++) {
if (validCells[i].value !== firstValue) {
allSameValue = false;
break;
}
}
if (allSameValue) {
matches.push(validCells);
}
}
}
}
secondary += currentMatchCells.length > 0 ? currentMatchCells.length : 1;
}
}
}
findDirectionalMatches(true);
findDirectionalMatches(false);
return matches;
}
function destroyCells(cellsToDestroy) {
isAnimating = true;
// Create a unique ID for this destruction process
var destructionId = Date.now() + Math.random();
// Check if match crosses visible/invisible boundary
var visibleCells = cellsToDestroy.filter(function (cell) {
return cell.row >= extraRows;
});
var invisibleCells = cellsToDestroy.filter(function (cell) {
return cell.row < extraRows;
});
// If mixed visibility and only one cell is visible, don't destroy any
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;
});
// Find the center cell (the one that triggered the match)
var centerCell = null;
// If we have the cells from a swap, use one of those as the center
if (arguments.length > 1 && arguments[1]) {
centerCell = arguments[1];
} else if (cellsToDestroy.length > 0) {
// Otherwise use the middle cell of the match
centerCell = cellsToDestroy[Math.floor(cellsToDestroy.length / 2)];
}
// Group cells by meme type
var cellsByType = {};
visibleCellsToDestroy.forEach(function (cell) {
if (!cellsByType[cell.value]) {
cellsByType[cell.value] = [];
}
cellsByType[cell.value].push(cell);
});
// Check if any type has exactly 4 memes to create a special orange meme
var specialCell = null;
var isHorizontalMatch = false;
var isVerticalMatch = false;
for (var memeType in cellsByType) {
var sameCells = cellsByType[memeType];
// Only consider groups of exactly 4 of the same type
if (sameCells.length === 4) {
// Determine if the match is horizontal or vertical
var allInSameRow = true;
var allInSameCol = true;
var firstCell = sameCells[0];
for (var i = 1; i < sameCells.length; i++) {
if (sameCells[i].row !== firstCell.row) {
allInSameRow = false;
}
if (sameCells[i].col !== firstCell.col) {
allInSameCol = false;
}
}
isHorizontalMatch = allInSameRow;
isVerticalMatch = allInSameCol;
// Create special meme only if it's a clean horizontal or vertical match
if (isHorizontalMatch || isVerticalMatch) {
// Use center cell or the second cell in the match for the special meme
specialCell = centerCell && centerCell.value == memeType ? centerCell : sameCells[Math.floor(sameCells.length / 2)];
specialCell.isSpecial = true;
specialCell.specialType = isHorizontalMatch ? 'horizontal' : 'vertical';
specialCell.beingDestroyed = false;
// Remove special cell from cells to destroy
visibleCellsToDestroy = visibleCellsToDestroy.filter(function (cell) {
return cell !== specialCell;
});
// We found our special match, so break out of the loop
break;
}
}
}
// Sort cells by distance from center cell for ripple effect
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 delay = 0;
var delayIncrement = 100;
var totalDestructionTime = visibleCellsToDestroy.length * delayIncrement;
// Mark cells as being destroyed to prevent them from being part of new matches
visibleCellsToDestroy.forEach(function (cell) {
if (cell) {
cell.beingDestroyed = true;
}
});
// If we have a special meme, tint it orange
if (specialCell && specialCell.isSpecial) {
specialCell.sprite.tint = 0xFF8800; // Orange tint
LK.effects.flashObject(specialCell, 0xFFFFFF, 300);
}
visibleCellsToDestroy.forEach(function (cell) {
LK.setTimeout(function () {
if (cell && cell.beingDestroyed && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
LK.getSound('Explosion').play();
LK.effects.flashObject(cell, 0xFFFFFF, 200);
gridContainer.removeChild(cell);
cell.destroy();
gridCells[cell.row][cell.col] = null;
}
}, delay);
delay += delayIncrement;
});
// After all cells in this group are destroyed, check if we need to apply gravity
LK.setTimeout(function () {
// Check if all destructions are complete before applying gravity
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;
}
}
}
// Only the last destruction process should trigger gravity
if (allCellsDestroyed && !window.gravityInProgress && !window.fillInProgress) {
applyGravity();
}
}, totalDestructionTime + 50);
}
function applyGravity() {
isAnimating = true;
var cellsToFall = [];
if (window.gravityInProgress) {
return;
}
window.gravityInProgress = true;
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
});
gridCells[row][col] = cellToMove;
gridCells[sourceRow][col] = null;
cellToMove.row = row;
if (sourceRow < extraRows) {
gridContainer.addChild(cellToMove);
}
}
}
}
}
}
var longestDelay = 0;
var baseDelay = 30;
var constantDuration = 400;
cellsToFall.sort(function (a, b) {
if (a.col !== b.col) {
return a.col - b.col;
}
return b.toRow - a.toRow;
});
cellsToFall.forEach(function (fallInfo, index) {
var delay = index * baseDelay;
var newPos = getCellPosition(fallInfo.toRow, fallInfo.col);
var totalTime = delay + constantDuration;
if (totalTime > longestDelay) {
longestDelay = totalTime;
}
LK.setTimeout(function () {
if (fallInfo.cell && gridCells[fallInfo.cell.row] && gridCells[fallInfo.cell.row][fallInfo.cell.col] === fallInfo.cell) {
tween(fallInfo.cell, {
y: newPos.y
}, {
duration: constantDuration,
easing: tween.linear
});
}
}, delay);
});
LK.setTimeout(function () {
window.gravityInProgress = false;
if (!window.destructionInProgress) {
fillEmptySpacesWithNewMemes();
}
}, longestDelay + 50);
}
function fillEmptySpacesWithNewMemes() {
if (window.fillInProgress || window.gravityInProgress) {
return;
}
window.fillInProgress = true;
var anyNewMemeAdded = false;
var newCellsToAdd = [];
for (var col = 0; col < gridSize; col++) {
for (var row = 0; row < gridSize + extraRows; row++) {
if (!gridCells[row][col]) {
anyNewMemeAdded = true;
var newCell = getGridCell();
var pos = getCellPosition(row, col);
newCell.x = pos.x;
newCell.y = pos.y - 400;
var randomValue = Math.floor(Math.random() * 5) + 1;
newCell.setValue(randomValue);
newCell.row = row;
newCell.col = col;
gridCells[row][col] = newCell;
newCellsToAdd.push({
cell: newCell,
destY: pos.y,
row: row,
col: col
});
if (row >= extraRows) {
gridContainer.addChild(newCell);
}
}
}
}
var longestDelay = 0;
var baseDelay = 30;
var constantDuration = 400;
newCellsToAdd.sort(function (a, b) {
if (a.col !== b.col) {
return a.col - b.col;
}
return b.row - a.row;
});
newCellsToAdd.forEach(function (cellData, index) {
var delay = index * baseDelay;
var totalTime = delay + constantDuration;
if (totalTime > longestDelay) {
longestDelay = totalTime;
}
LK.setTimeout(function () {
if (cellData.cell && gridCells[cellData.row] && gridCells[cellData.row][cellData.col] === cellData.cell) {
tween(cellData.cell, {
y: cellData.destY
}, {
duration: constantDuration,
easing: tween.linear
});
}
}, delay);
});
if (anyNewMemeAdded) {
LK.setTimeout(function () {
window.fillInProgress = false;
if (window.destructionInProgress || window.gravityInProgress) {
isAnimating = false;
return;
}
var visibleMatchGroups = getMatches().filter(function (group) {
// Check if the match has cells in both visible and invisible areas
var visibleCells = group.filter(function (cell) {
return cell.row >= extraRows;
});
var invisibleCells = group.filter(function (cell) {
return cell.row < extraRows;
});
// Don't count groups with both visible and invisible cells unless there are at least 3 visible cells
if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) {
return false;
}
return visibleCells.length >= 3; // At least 3 visible cells make a valid visible match
});
var newMatches = visibleMatchGroups;
if (newMatches.length > 0) {
var newCellsToDestroy = [];
var newCellTracker = {};
newMatches.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) {
// Find a central cell for the auto-match after gravity
var centerCell = null;
if (newMatches.length > 0 && newMatches[0].length > 0) {
// Pick the center of the first match group
var matchGroup = newMatches[0];
centerCell = matchGroup[Math.floor(matchGroup.length / 2)];
}
destroyCells(newCellsToDestroy, centerCell);
} else {
isAnimating = false;
}
} else {
isAnimating = false;
}
}, longestDelay + 50);
} else {
window.fillInProgress = false;
isAnimating = false;
}
}
function checkForAndDestroyMatches(swappedCellA, swappedCellB) {
// Check if any special memes are in a match with same type after falling
for (var row = extraRows; row < gridSize + extraRows; row++) {
for (var col = 0; col < gridSize; col++) {
var cell = gridCells[row] ? gridCells[row][col] : null;
if (cell && cell.isSpecial) {
// Check adjacent cells for matches with same type
var adjacentCells = [];
// Check cell above
if (row > 0 && gridCells[row - 1] && gridCells[row - 1][col] && gridCells[row - 1][col].value === cell.value) {
adjacentCells.push(gridCells[row - 1][col]);
}
// Check cell below
if (row < gridSize + extraRows - 1 && gridCells[row + 1] && gridCells[row + 1][col] && gridCells[row + 1][col].value === cell.value) {
adjacentCells.push(gridCells[row + 1][col]);
}
// Check cell left
if (col > 0 && gridCells[row][col - 1] && gridCells[row][col - 1].value === cell.value) {
adjacentCells.push(gridCells[row][col - 1]);
}
// Check cell right
if (col < gridSize - 1 && gridCells[row][col + 1] && gridCells[row][col + 1].value === cell.value) {
adjacentCells.push(gridCells[row][col + 1]);
}
// If at least one adjacent cell matches, activate special power
if (adjacentCells.length > 0) {
cell.activateSpecialPower();
}
}
}
}
if (window.gravityInProgress || window.fillInProgress) {
return;
}
var allMatchGroupsOnBoard = getMatches();
if (!allMatchGroupsOnBoard.length) {
return;
}
var relevantMatchGroups = allMatchGroupsOnBoard.filter(function (group) {
// Check if the match has cells in both visible and invisible areas
var visibleCells = group.filter(function (cell) {
return cell.row >= extraRows;
});
var invisibleCells = group.filter(function (cell) {
return cell.row < extraRows;
});
// Don't count groups with both visible and invisible cells unless there are at least 3 visible cells
if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) {
return false;
}
// Only include groups where at least one of the swapped cells is in the group
// and the swapped cell is in the visible part of the grid
return group.some(function (cellInGroup) {
return (cellInGroup === swappedCellA || cellInGroup === swappedCellB) && cellInGroup.row >= extraRows;
});
});
if (!relevantMatchGroups.length) {
return;
}
var uniqueCellTracker = {};
var cellsToDestroy = [];
relevantMatchGroups.forEach(function (group) {
group.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) {
// Pass the swapped cell that created the match as the center for the ripple effect
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) {
// Check if the match has cells in both visible and invisible areas
var visibleCells = group.filter(function (cell) {
return cell.row >= extraRows;
});
var invisibleCells = group.filter(function (cell) {
return cell.row < extraRows;
});
// Don't count groups with both visible and invisible cells unless there are at least 3 visible cells
if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) {
return false;
}
return visibleCells.length >= 3; // At least 3 visible cells make a valid visible match
});
var newMatches = visibleMatchGroups;
if (newMatches.length > 0) {
var newCellsToDestroy = [];
var newCellTracker = {};
newMatches.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) {
destroyCells(newCellsToDestroy);
}
}
}, 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();
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