Code edit (1 edits merged)
Please save this source code
User prompt
desplaza los grid 500 pixees arriba
User prompt
los nuevos memes fueron agregados abajo no arriba
User prompt
agrega 9 filas superiores de memes, manten la posición de las actuales
User prompt
agrega 9 filas superiores sin modificar la posición actual e las cuadriculas
User prompt
agrega 9 filas superiores pero que estos no les afecte la ruptura por caída y no sean movible. Dale un tinte oscuro si se encuentran en estas capas
User prompt
haz que la velocidad de caida sea constante y no dependa de la distancia ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que los nuevos memes pre establecidos sean visibles
User prompt
agrega el mismo dilei a a caida de los memes actuales. haz que empiecen a caer los nuevos memes en esa columna una vez el meme de la parte superior empiece este a punto de finalizar
User prompt
agrega un dilei a la aparición de nuevos memes. Este funciona de la siguiente manera: Es propia de cada columna. va en orden de abajo arriba. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
agrega un dilei individual a la aparición de los nuevos memes ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
agrega un pequeño diley a la entrada de los memes ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Haz que los nuevos memes caigan una vez finalicen de caer los memes en la cuadricula ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que los nuevos memes empiecena salir una vez caigan los memes actuales
User prompt
haz que las proximas 9 filas de nuevos memes ya este precargado para hacer más sutil su integración
User prompt
haz que la velocidad de caida de los memes actuales con los nuevos sean lás mismas, crea un método para hacer más fluido la entrada. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que la velocidad de caida de los memes actuales con los nuevos sean lás mismas, crea un método para hacer más fluido la entrada.
User prompt
sincroniza la caída de los memes actuales con los nuevos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que no se pueda mover manualmente mientras estan en gravedad
User prompt
haz que no se pueda mover manualmente mientras estan en gravedad
User prompt
haz que las roturas por gravedad empiecen una vez finalicen las caidas
User prompt
si se empieza una nueva roptura de meme que no continue con el delay del anterior
User prompt
haz que a medida que se rompen caigan nuevos memes
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(cell1).to({' Line Number: 138
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(cell1, {' Line Number: 138
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var GridCell = Container.expand(function () { var self = Container.call(this); // Method to initialize or reset a cell self.init = function () { // Create the background square for the cell if it doesn't exist if (!self.background) { self.background = self.attachAsset('cuadricula', { anchorX: 0.5, anchorY: 0.5 }); } // Initialize or reset properties self.value = 0; self.sprite = null; self.row = -1; self.col = -1; return self; // Enable chaining }; // Method to set value and corresponding sprite self.setValue = function (newValue) { // Skip if same value if (self.value === newValue) { return; } self.value = newValue; // Remove previous sprite if exists if (self.sprite) { self.removeChild(self.sprite); } // Create new sprite based on value var spriteId = 'meme' + newValue; self.sprite = LK.getAsset(spriteId, { anchorX: 0.5, anchorY: 0.5 }); self.addChild(self.sprite); }; // Handle tap event self.down = function (x, y, obj) { handleCellTap(self); }; // Initialize the cell self.init(); return self; }); /**** * Initialize Game ****/ // Factory function to get a GridCell (from pool or new) // Grid configuration var game = new LK.Game({ backgroundColor: 0xF4FFFF }); /**** * Game Code ****/ // Cell pool for object reuse // Grid configuration var cellPool = []; // Factory function to get a GridCell (from pool or new) function getGridCell() { if (cellPool.length > 0) { return cellPool.pop().init(); // Reuse a cell from the pool } return new GridCell(); // Create a new cell } // Function to return a cell to the pool function recycleGridCell(cell) { if (cell) { cellPool.push(cell); // Add to pool for later reuse } } var selectedCell = null; function handleCellTap(tappedCell) { // Case 1: No cell selected yet - select this one if (selectedCell === null) { selectedCell = tappedCell; LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash yellow quickly return; } var cell1 = selectedCell; var cell2 = tappedCell; // Case 2: Tapped the already selected cell - deselect it if (cell1 === cell2) { selectedCell = null; // Deselect return; } // Case 3: Check for adjacency (vertical or horizontal) 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) { // Case 4: Non-adjacent cell - select the new cell instead selectedCell = tappedCell; LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash the new selection return; } // Case 5: Adjacent cell - perform the swap // 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 original grid indices var row1 = cell1.row; var col1 = cell1.col; var row2 = cell2.row; var col2 = cell2.col; // Swap cells in the gridCells array gridCells[row1][col1] = cell2; gridCells[row2][col2] = cell1; // Swap row/col properties on the cell objects cell1.row = row2; cell1.col = col2; cell2.row = row1; cell2.col = col1; // Animate the visual swap of positions with enhanced motion // For cell1: add scaling and rotation effect tween(cell1).to({ x: pos2_x, y: pos2_y, scale: { x: 1.15, y: 1.15 }, rotation: 0.1 }, { duration: 250, easing: tween.easeInOut, onFinish: function onFinish() { tween(cell1).to({ scale: { x: 1, y: 1 }, rotation: 0 }, { duration: 150, easing: tween.easeOut }); } }); // For cell2: add scaling and counter-rotation tween(cell2).to({ x: pos1_x, y: pos1_y, scale: { x: 1.15, y: 1.15 }, rotation: -0.1 }, { duration: 250, easing: tween.easeInOut, onFinish: function onFinish() { tween(cell2).to({ scale: { x: 1, y: 1 }, rotation: 0 }, { duration: 150, easing: tween.easeOut }); } }); selectedCell = null; // Reset selection after swap // Schedule the match check and destruction slightly after the animation completes LK.setTimeout(function () { checkForAndDestroyMatches(cell1, cell2); // Pass the swapped cells // Future enhancement: After destruction, new cells might fall, // and new matches could form. This would require a loop of: // check/destroy -> fill -> check/destroy ... until no more matches. // For now, we just check once after the swap. }, 350); // Animation is 300ms, add a small buffer of 50ms } // Helper functions for match detection and destruction function getMatches() { var matches = []; // Helper function to find matches in a specific direction function findDirectionalMatches(isHorizontal) { var primary, secondary; for (primary = 0; primary < gridSize; primary++) { for (secondary = 0; secondary < gridSize;) { // Skip if not enough cells left for a match of 3 if (secondary > gridSize - 3) { secondary++; continue; } // Get current cell based on direction var cell1 = isHorizontal ? gridCells[primary][secondary] : gridCells[secondary][primary]; if (!cell1) { // Skip empty cells secondary++; continue; } var currentMatchValue = cell1.value; var currentMatchCells = [cell1]; // Check subsequent cells for matches for (var k = secondary + 1; k < gridSize; k++) { var nextCell = isHorizontal ? gridCells[primary][k] : gridCells[k][primary]; if (nextCell && nextCell.value === currentMatchValue) { currentMatchCells.push(nextCell); } else { break; // End of current potential match } } // Add to matches if we found 3 or more if (currentMatchCells.length >= 3) { matches.push(currentMatchCells); } // Move index forward based on match length secondary += currentMatchCells.length > 0 ? currentMatchCells.length : 1; } } } // Find horizontal matches findDirectionalMatches(true); // Find vertical matches findDirectionalMatches(false); return matches; } function destroyCells(cellsToDestroy) { // Process each cell with a slight delay for more satisfying destruction var delay = 0; var delayIncrement = 100; // 100ms delay between each meme destruction cellsToDestroy.forEach(function (cell) { // Schedule destruction with increasing delay LK.setTimeout(function () { // Defensive checks: ensure cell exists and is the one we expect in the grid if (cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) { // Play explosion sound LK.getSound('Explosion').play(); // Enhanced visual effects for cell destruction // First expand and brighten tween(cell).to({ scale: { x: 1.3, y: 1.3 }, alpha: 0.9 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { // Then flash and fade out LK.effects.flashObject(cell, 0xFFFFFF, 150); tween(cell).to({ scale: { x: 0.1, y: 0.1 }, alpha: 0 }, { duration: 180, easing: tween.easeIn, onFinish: function onFinish() { // Remove from display gridContainer.removeChild(cell); cell.destroy(); // Destroy the cell object (releases resources) gridCells[cell.row][cell.col] = null; // Mark as empty in the logical grid } }); } }); } }, delay); // Increase delay for next cell delay += delayIncrement; }); // After destroying cells, make memes fall to fill empty spaces // Wait until all cells are destroyed LK.setTimeout(function () { applyGravity(); }, delay + 50); } // Function to make memes fall down to fill empty spaces function applyGravity() { // Loop through each column for (var col = 0; col < gridSize; col++) { // Start from the bottom row and work upwards for (var row = gridSize - 1; row >= 0; row--) { // If current cell is empty if (!gridCells[row][col]) { // Look for the nearest non-empty cell above var sourceRow = row - 1; while (sourceRow >= 0 && !gridCells[sourceRow][col]) { sourceRow--; } // If we found a cell to move down if (sourceRow >= 0) { var cellToMove = gridCells[sourceRow][col]; // Update grid array gridCells[row][col] = cellToMove; gridCells[sourceRow][col] = null; // Update cell's logical position cellToMove.row = row; // Animate the fall with improved motion and visual feedback var newPos = getCellPosition(row, col); // Flash briefly to highlight the movement LK.effects.flashObject(cellToMove, 0xFFFFFF, 100); // First slightly overshoot the target tween(cellToMove).to({ y: newPos.y + 15, scale: { x: 0.9, y: 1.1 } }, { duration: 280, easing: tween.easeIn, onFinish: function onFinish() { // Then bounce back to normal position and scale tween(cellToMove).to({ y: newPos.y, scale: { x: 1, y: 1 } }, { duration: 120, easing: tween.bounceOut }); } }); } } } } // After gravity, add new memes to fill the top LK.setTimeout(function () { fillEmptySpacesFromTop(); }, 350); } // Function to create new memes for empty spaces at the top of each column function fillEmptySpacesFromTop() { var anyNewMemes = false; // Loop through each column for (var col = 0; col < gridSize; col++) { // Start from the top row for (var row = 0; row < gridSize; row++) { // If this cell is empty, fill it with a new meme if (!gridCells[row][col]) { anyNewMemes = true; // Create a new cell var cell = getGridCell(); // Position calculation for the new cell var pos = getCellPosition(row, col); cell.x = pos.x; // Start above the grid (off-screen) cell.y = startY - cellSize * 2; // Assign row and column cell.row = row; cell.col = col; // Random value 1-5 var randomValue = Math.floor(Math.random() * 5) + 1; cell.setValue(randomValue); // Add to grid gridContainer.addChild(cell); gridCells[row][col] = cell; // Animate falling from above with improved animation // Start with a small scale and expand while falling cell.scale.x = 0.3; cell.scale.y = 0.3; cell.alpha = 0.7; // First tween - fall down with scaling effect tween(cell).to({ y: pos.y, scale: { x: 1.2, y: 1.2 }, alpha: 1 }, { duration: 400, easing: tween.elasticOut, onFinish: function onFinish() { // Second tween - bounce back to normal size tween(cell).to({ scale: { x: 1, y: 1 } }, { duration: 150, easing: tween.bounceOut }); } }); } } } // If we added new memes, check for matches after they've landed if (anyNewMemes) { LK.setTimeout(function () { var newMatches = getMatches(); 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]) { newCellsToDestroy.push(cell); newCellTracker[cellKey] = true; } }); }); if (newCellsToDestroy.length) { destroyCells(newCellsToDestroy); } } }, 550); } } function checkForAndDestroyMatches(swappedCellA, swappedCellB) { // Get all potential matches on the board var allMatchGroupsOnBoard = getMatches(); // Quick return if no matches if (!allMatchGroupsOnBoard.length) { return; // No matches found anywhere, nothing to do } // Filter to only match groups containing one of the swapped cells var relevantMatchGroups = allMatchGroupsOnBoard.filter(function (group) { // Check if any cell in the group is one of our swapped cells return group.some(function (cellInGroup) { return cellInGroup === swappedCellA || cellInGroup === swappedCellB; }); }); // Quick return if no relevant matches if (!relevantMatchGroups.length) { return; // No matches involving the swapped cells were found } // Create array of unique cells to destroy var uniqueCellTracker = {}; var cellsToDestroy = []; // Collect all cells from relevant groups, avoiding duplicates relevantMatchGroups.forEach(function (group) { group.forEach(function (cell) { // Create a unique key for each cell var cellKey = cell.row + "_" + cell.col; // Only add if we haven't seen this cell yet if (!uniqueCellTracker[cellKey]) { cellsToDestroy.push(cell); uniqueCellTracker[cellKey] = true; } }); }); // Destroy cells if we found any if (cellsToDestroy.length) { destroyCells(cellsToDestroy); // Wait for gravity animation to complete, then check for new matches // Allow more time for sequential destruction and gravity to complete LK.setTimeout(function () { // Check for new matches caused by gravity var newMatches = getMatches(); if (newMatches.length > 0) { // Get all cells from all new match groups var newCellsToDestroy = []; var newCellTracker = {}; newMatches.forEach(function (group) { group.forEach(function (cell) { var cellKey = cell.row + "_" + cell.col; if (!newCellTracker[cellKey]) { newCellsToDestroy.push(cell); newCellTracker[cellKey] = true; } }); }); // Destroy these new matches if (newCellsToDestroy.length) { destroyCells(newCellsToDestroy); } } }, 1200); // Increased wait time to accommodate sequential destruction and new memes falling // Here you could add scoring or other effects if needed // e.g., LK.setScore(LK.getScore() + cellsToDestroy.length * 10); } } // Game configuration var gridSize = 8; var cellSpacing = 10; var cellSize = 208; // Width/height of the cell background increased by 30% var gridCells = []; // Calculate layout var totalGridWidth = gridSize * cellSize + (gridSize - 1) * cellSpacing; var totalGridHeight = totalGridWidth; // Grid is square // Center the grid on screen var startX = (2048 - totalGridWidth) / 2 + cellSize / 2; var startY = (2732 - totalGridHeight) / 2 + cellSize / 2; // Position calculation helper function getCellPosition(row, col) { return { x: startX + col * (cellSize + cellSpacing), y: startY + row * (cellSize + cellSpacing) }; } // Create grid container var gridContainer = new Container(); game.addChild(gridContainer); // Create and initialize the grid function initializeGrid() { // Clear existing grid if any gridCells = []; // Create grid cells for (var row = 0; row < gridSize; row++) { gridCells[row] = []; for (var col = 0; col < gridSize; col++) { // Get cell position var pos = getCellPosition(row, col); // Create new cell (using pool if implemented) var cell = getGridCell ? getGridCell() : new GridCell(); // Position cell cell.x = pos.x; cell.y = pos.y; // Assign row and column cell.row = row; cell.col = col; // Generate random value (1-5), but avoid creating initial matches var randomValue; var attempts = 0; do { randomValue = Math.floor(Math.random() * 5) + 1; attempts++; // Check left and above for potential matches var leftMatchCount = 0; var aboveMatchCount = 0; // Check left if (col >= 2) { if (gridCells[row][col - 1].value === randomValue && gridCells[row][col - 2].value === randomValue) { leftMatchCount = 2; } } // Check above if (row >= 2) { if (gridCells[row - 1][col].value === randomValue && gridCells[row - 2][col].value === randomValue) { aboveMatchCount = 2; } } // If no potential matches or too many attempts, exit loop } while ((leftMatchCount >= 2 || aboveMatchCount >= 2) && attempts < 10); cell.setValue(randomValue); // Add to grid gridContainer.addChild(cell); gridCells[row][col] = cell; } } } // Initialize the grid initializeGrid(); // Check for any initial matches and correct them function ensureNoInitialMatches() { var matches = getMatches(); if (matches.length > 0) { // Replace cells in matches with new random values matches.forEach(function (group) { group.forEach(function (cell) { // Get current value var currentValue = cell.value; var newValue; // Find a new value that doesn't cause a match do { newValue = Math.floor(Math.random() * 5) + 1; } while (newValue === currentValue); // Set the new value cell.setValue(newValue); }); }); // Check again recursively if we still have matches ensureNoInitialMatches(); } } // Make sure grid starts with no matches ensureNoInitialMatches();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var GridCell = Container.expand(function () {
var self = Container.call(this);
// Method to initialize or reset a cell
self.init = function () {
// Create the background square for the cell if it doesn't exist
if (!self.background) {
self.background = self.attachAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Initialize or reset properties
self.value = 0;
self.sprite = null;
self.row = -1;
self.col = -1;
return self; // Enable chaining
};
// Method to set value and corresponding sprite
self.setValue = function (newValue) {
// Skip if same value
if (self.value === newValue) {
return;
}
self.value = newValue;
// Remove previous sprite if exists
if (self.sprite) {
self.removeChild(self.sprite);
}
// Create new sprite based on value
var spriteId = 'meme' + newValue;
self.sprite = LK.getAsset(spriteId, {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(self.sprite);
};
// Handle tap event
self.down = function (x, y, obj) {
handleCellTap(self);
};
// Initialize the cell
self.init();
return self;
});
/****
* Initialize Game
****/
// Factory function to get a GridCell (from pool or new)
// Grid configuration
var game = new LK.Game({
backgroundColor: 0xF4FFFF
});
/****
* Game Code
****/
// Cell pool for object reuse
// Grid configuration
var cellPool = [];
// Factory function to get a GridCell (from pool or new)
function getGridCell() {
if (cellPool.length > 0) {
return cellPool.pop().init(); // Reuse a cell from the pool
}
return new GridCell(); // Create a new cell
}
// Function to return a cell to the pool
function recycleGridCell(cell) {
if (cell) {
cellPool.push(cell); // Add to pool for later reuse
}
}
var selectedCell = null;
function handleCellTap(tappedCell) {
// Case 1: No cell selected yet - select this one
if (selectedCell === null) {
selectedCell = tappedCell;
LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash yellow quickly
return;
}
var cell1 = selectedCell;
var cell2 = tappedCell;
// Case 2: Tapped the already selected cell - deselect it
if (cell1 === cell2) {
selectedCell = null; // Deselect
return;
}
// Case 3: Check for adjacency (vertical or horizontal)
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) {
// Case 4: Non-adjacent cell - select the new cell instead
selectedCell = tappedCell;
LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash the new selection
return;
}
// Case 5: Adjacent cell - perform the swap
// 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 original grid indices
var row1 = cell1.row;
var col1 = cell1.col;
var row2 = cell2.row;
var col2 = cell2.col;
// Swap cells in the gridCells array
gridCells[row1][col1] = cell2;
gridCells[row2][col2] = cell1;
// Swap row/col properties on the cell objects
cell1.row = row2;
cell1.col = col2;
cell2.row = row1;
cell2.col = col1;
// Animate the visual swap of positions with enhanced motion
// For cell1: add scaling and rotation effect
tween(cell1).to({
x: pos2_x,
y: pos2_y,
scale: {
x: 1.15,
y: 1.15
},
rotation: 0.1
}, {
duration: 250,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cell1).to({
scale: {
x: 1,
y: 1
},
rotation: 0
}, {
duration: 150,
easing: tween.easeOut
});
}
});
// For cell2: add scaling and counter-rotation
tween(cell2).to({
x: pos1_x,
y: pos1_y,
scale: {
x: 1.15,
y: 1.15
},
rotation: -0.1
}, {
duration: 250,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cell2).to({
scale: {
x: 1,
y: 1
},
rotation: 0
}, {
duration: 150,
easing: tween.easeOut
});
}
});
selectedCell = null; // Reset selection after swap
// Schedule the match check and destruction slightly after the animation completes
LK.setTimeout(function () {
checkForAndDestroyMatches(cell1, cell2); // Pass the swapped cells
// Future enhancement: After destruction, new cells might fall,
// and new matches could form. This would require a loop of:
// check/destroy -> fill -> check/destroy ... until no more matches.
// For now, we just check once after the swap.
}, 350); // Animation is 300ms, add a small buffer of 50ms
}
// Helper functions for match detection and destruction
function getMatches() {
var matches = [];
// Helper function to find matches in a specific direction
function findDirectionalMatches(isHorizontal) {
var primary, secondary;
for (primary = 0; primary < gridSize; primary++) {
for (secondary = 0; secondary < gridSize;) {
// Skip if not enough cells left for a match of 3
if (secondary > gridSize - 3) {
secondary++;
continue;
}
// Get current cell based on direction
var cell1 = isHorizontal ? gridCells[primary][secondary] : gridCells[secondary][primary];
if (!cell1) {
// Skip empty cells
secondary++;
continue;
}
var currentMatchValue = cell1.value;
var currentMatchCells = [cell1];
// Check subsequent cells for matches
for (var k = secondary + 1; k < gridSize; k++) {
var nextCell = isHorizontal ? gridCells[primary][k] : gridCells[k][primary];
if (nextCell && nextCell.value === currentMatchValue) {
currentMatchCells.push(nextCell);
} else {
break; // End of current potential match
}
}
// Add to matches if we found 3 or more
if (currentMatchCells.length >= 3) {
matches.push(currentMatchCells);
}
// Move index forward based on match length
secondary += currentMatchCells.length > 0 ? currentMatchCells.length : 1;
}
}
}
// Find horizontal matches
findDirectionalMatches(true);
// Find vertical matches
findDirectionalMatches(false);
return matches;
}
function destroyCells(cellsToDestroy) {
// Process each cell with a slight delay for more satisfying destruction
var delay = 0;
var delayIncrement = 100; // 100ms delay between each meme destruction
cellsToDestroy.forEach(function (cell) {
// Schedule destruction with increasing delay
LK.setTimeout(function () {
// Defensive checks: ensure cell exists and is the one we expect in the grid
if (cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
// Play explosion sound
LK.getSound('Explosion').play();
// Enhanced visual effects for cell destruction
// First expand and brighten
tween(cell).to({
scale: {
x: 1.3,
y: 1.3
},
alpha: 0.9
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
// Then flash and fade out
LK.effects.flashObject(cell, 0xFFFFFF, 150);
tween(cell).to({
scale: {
x: 0.1,
y: 0.1
},
alpha: 0
}, {
duration: 180,
easing: tween.easeIn,
onFinish: function onFinish() {
// Remove from display
gridContainer.removeChild(cell);
cell.destroy(); // Destroy the cell object (releases resources)
gridCells[cell.row][cell.col] = null; // Mark as empty in the logical grid
}
});
}
});
}
}, delay);
// Increase delay for next cell
delay += delayIncrement;
});
// After destroying cells, make memes fall to fill empty spaces
// Wait until all cells are destroyed
LK.setTimeout(function () {
applyGravity();
}, delay + 50);
}
// Function to make memes fall down to fill empty spaces
function applyGravity() {
// Loop through each column
for (var col = 0; col < gridSize; col++) {
// Start from the bottom row and work upwards
for (var row = gridSize - 1; row >= 0; row--) {
// If current cell is empty
if (!gridCells[row][col]) {
// Look for the nearest non-empty cell above
var sourceRow = row - 1;
while (sourceRow >= 0 && !gridCells[sourceRow][col]) {
sourceRow--;
}
// If we found a cell to move down
if (sourceRow >= 0) {
var cellToMove = gridCells[sourceRow][col];
// Update grid array
gridCells[row][col] = cellToMove;
gridCells[sourceRow][col] = null;
// Update cell's logical position
cellToMove.row = row;
// Animate the fall with improved motion and visual feedback
var newPos = getCellPosition(row, col);
// Flash briefly to highlight the movement
LK.effects.flashObject(cellToMove, 0xFFFFFF, 100);
// First slightly overshoot the target
tween(cellToMove).to({
y: newPos.y + 15,
scale: {
x: 0.9,
y: 1.1
}
}, {
duration: 280,
easing: tween.easeIn,
onFinish: function onFinish() {
// Then bounce back to normal position and scale
tween(cellToMove).to({
y: newPos.y,
scale: {
x: 1,
y: 1
}
}, {
duration: 120,
easing: tween.bounceOut
});
}
});
}
}
}
}
// After gravity, add new memes to fill the top
LK.setTimeout(function () {
fillEmptySpacesFromTop();
}, 350);
}
// Function to create new memes for empty spaces at the top of each column
function fillEmptySpacesFromTop() {
var anyNewMemes = false;
// Loop through each column
for (var col = 0; col < gridSize; col++) {
// Start from the top row
for (var row = 0; row < gridSize; row++) {
// If this cell is empty, fill it with a new meme
if (!gridCells[row][col]) {
anyNewMemes = true;
// Create a new cell
var cell = getGridCell();
// Position calculation for the new cell
var pos = getCellPosition(row, col);
cell.x = pos.x;
// Start above the grid (off-screen)
cell.y = startY - cellSize * 2;
// Assign row and column
cell.row = row;
cell.col = col;
// Random value 1-5
var randomValue = Math.floor(Math.random() * 5) + 1;
cell.setValue(randomValue);
// Add to grid
gridContainer.addChild(cell);
gridCells[row][col] = cell;
// Animate falling from above with improved animation
// Start with a small scale and expand while falling
cell.scale.x = 0.3;
cell.scale.y = 0.3;
cell.alpha = 0.7;
// First tween - fall down with scaling effect
tween(cell).to({
y: pos.y,
scale: {
x: 1.2,
y: 1.2
},
alpha: 1
}, {
duration: 400,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Second tween - bounce back to normal size
tween(cell).to({
scale: {
x: 1,
y: 1
}
}, {
duration: 150,
easing: tween.bounceOut
});
}
});
}
}
}
// If we added new memes, check for matches after they've landed
if (anyNewMemes) {
LK.setTimeout(function () {
var newMatches = getMatches();
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]) {
newCellsToDestroy.push(cell);
newCellTracker[cellKey] = true;
}
});
});
if (newCellsToDestroy.length) {
destroyCells(newCellsToDestroy);
}
}
}, 550);
}
}
function checkForAndDestroyMatches(swappedCellA, swappedCellB) {
// Get all potential matches on the board
var allMatchGroupsOnBoard = getMatches();
// Quick return if no matches
if (!allMatchGroupsOnBoard.length) {
return; // No matches found anywhere, nothing to do
}
// Filter to only match groups containing one of the swapped cells
var relevantMatchGroups = allMatchGroupsOnBoard.filter(function (group) {
// Check if any cell in the group is one of our swapped cells
return group.some(function (cellInGroup) {
return cellInGroup === swappedCellA || cellInGroup === swappedCellB;
});
});
// Quick return if no relevant matches
if (!relevantMatchGroups.length) {
return; // No matches involving the swapped cells were found
}
// Create array of unique cells to destroy
var uniqueCellTracker = {};
var cellsToDestroy = [];
// Collect all cells from relevant groups, avoiding duplicates
relevantMatchGroups.forEach(function (group) {
group.forEach(function (cell) {
// Create a unique key for each cell
var cellKey = cell.row + "_" + cell.col;
// Only add if we haven't seen this cell yet
if (!uniqueCellTracker[cellKey]) {
cellsToDestroy.push(cell);
uniqueCellTracker[cellKey] = true;
}
});
});
// Destroy cells if we found any
if (cellsToDestroy.length) {
destroyCells(cellsToDestroy);
// Wait for gravity animation to complete, then check for new matches
// Allow more time for sequential destruction and gravity to complete
LK.setTimeout(function () {
// Check for new matches caused by gravity
var newMatches = getMatches();
if (newMatches.length > 0) {
// Get all cells from all new match groups
var newCellsToDestroy = [];
var newCellTracker = {};
newMatches.forEach(function (group) {
group.forEach(function (cell) {
var cellKey = cell.row + "_" + cell.col;
if (!newCellTracker[cellKey]) {
newCellsToDestroy.push(cell);
newCellTracker[cellKey] = true;
}
});
});
// Destroy these new matches
if (newCellsToDestroy.length) {
destroyCells(newCellsToDestroy);
}
}
}, 1200); // Increased wait time to accommodate sequential destruction and new memes falling
// Here you could add scoring or other effects if needed
// e.g., LK.setScore(LK.getScore() + cellsToDestroy.length * 10);
}
}
// Game configuration
var gridSize = 8;
var cellSpacing = 10;
var cellSize = 208; // Width/height of the cell background increased by 30%
var gridCells = [];
// Calculate layout
var totalGridWidth = gridSize * cellSize + (gridSize - 1) * cellSpacing;
var totalGridHeight = totalGridWidth; // Grid is square
// Center the grid on screen
var startX = (2048 - totalGridWidth) / 2 + cellSize / 2;
var startY = (2732 - totalGridHeight) / 2 + cellSize / 2;
// Position calculation helper
function getCellPosition(row, col) {
return {
x: startX + col * (cellSize + cellSpacing),
y: startY + row * (cellSize + cellSpacing)
};
}
// Create grid container
var gridContainer = new Container();
game.addChild(gridContainer);
// Create and initialize the grid
function initializeGrid() {
// Clear existing grid if any
gridCells = [];
// Create grid cells
for (var row = 0; row < gridSize; row++) {
gridCells[row] = [];
for (var col = 0; col < gridSize; col++) {
// Get cell position
var pos = getCellPosition(row, col);
// Create new cell (using pool if implemented)
var cell = getGridCell ? getGridCell() : new GridCell();
// Position cell
cell.x = pos.x;
cell.y = pos.y;
// Assign row and column
cell.row = row;
cell.col = col;
// Generate random value (1-5), but avoid creating initial matches
var randomValue;
var attempts = 0;
do {
randomValue = Math.floor(Math.random() * 5) + 1;
attempts++;
// Check left and above for potential matches
var leftMatchCount = 0;
var aboveMatchCount = 0;
// Check left
if (col >= 2) {
if (gridCells[row][col - 1].value === randomValue && gridCells[row][col - 2].value === randomValue) {
leftMatchCount = 2;
}
}
// Check above
if (row >= 2) {
if (gridCells[row - 1][col].value === randomValue && gridCells[row - 2][col].value === randomValue) {
aboveMatchCount = 2;
}
}
// If no potential matches or too many attempts, exit loop
} while ((leftMatchCount >= 2 || aboveMatchCount >= 2) && attempts < 10);
cell.setValue(randomValue);
// Add to grid
gridContainer.addChild(cell);
gridCells[row][col] = cell;
}
}
}
// Initialize the grid
initializeGrid();
// Check for any initial matches and correct them
function ensureNoInitialMatches() {
var matches = getMatches();
if (matches.length > 0) {
// Replace cells in matches with new random values
matches.forEach(function (group) {
group.forEach(function (cell) {
// Get current value
var currentValue = cell.value;
var newValue;
// Find a new value that doesn't cause a match
do {
newValue = Math.floor(Math.random() * 5) + 1;
} while (newValue === currentValue);
// Set the new value
cell.setValue(newValue);
});
});
// Check again recursively if we still have matches
ensureNoInitialMatches();
}
}
// Make sure grid starts with no matches
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