User prompt
elimina el codigo para el cambio de memes
User prompt
No se puede cambiar los memes despues del primer movimiento. Los memes se hacen más chiquitos como si se cambiaran y a pesar de tocar otro este no se cambia si no que repite lo anteriormente dicho
User prompt
El bug continua, busca una alternativa para poder seguir haciendo cambios de posición
User prompt
Arregla el bug que hace que despues del primero cambio dejan de hacer cambios de lugar
User prompt
arregla el bug que no permite cambiar posición despues de la primera vez
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'outBack')' in or related to this line: 'tween(self.sprite, {' Line Number: 54
User prompt
optimiza el codigo
User prompt
Please fix the bug: 'TypeError: easing is not a function' in or related to this line: 'scoreText.setText("Score: " + LK.getScore());' Line Number: 479 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'outBack')' in or related to this line: 'tween(self.sprite, {' Line Number: 55
User prompt
Please fix the bug: 'TypeError: easing is not a function' in or related to this line: 'scoreText.setText("Score: " + LK.getScore());' Line Number: 479
User prompt
Mejora el codigo
User prompt
cuando se rompan los memes haz que los memes superiores bajen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
arregla el bug que hace que se destruyan todos los memes del mismo tipo, haz que simplemente sean los adyacentes del movido
User prompt
si se juntan 3 memes del mismo tipo (vertical u horizontal) tras mover, se destruirán
User prompt
cuando se toque un meme, y posteriormente uno de sus memes adyacentes (vertical y horizontal), cambiaran de posición ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cuando se toque un meme, y posteriormente uno de sus memes adyacentes (vertical y horizontal), cambiaran de posición
User prompt
crea un grid 9*9 en el centro de la pantalla con un espaciado de 10 pixeles entre cada uno. Haz que cada grid tenga un valor y un sprite diferente del 1 a 5 aleatoriamente
User prompt
Cuando se toque un meme y consecutivamente uno de los memes de sus costados laterales y superiores, se cambiaran de posición ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cuando se toque un meme y consecutivamente uno de los memes de sus costados laterales y superiores, se cambiaran de posición ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que al tocar un meme y presionar uno de los memes de sus costados laterales y superiores cambien de posición ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Optimiza el codigo
User prompt
Optimiza el código
User prompt
Elimina todos los comentarios // del codigo
User prompt
Crea un objeto llamado meme, haz que aleatoriamente tenga un valor entre 1 a 5, según su valor sera el diseño. Haz que aparezcan en todas las cadriculas
User prompt
Crea un objeto llamado meme, haz que aleatoriamente tenga un valor entre 1 a 5, según su valor sera el diseño. Haz que aparezcan random en las cuadriculas
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var GridCell = Container.expand(function () {
var self = Container.call(this);
// Create the background square for the cell
var background = self.attachAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5
});
// Add a slight shadow/glow effect to background for depth
background.alpha = 0.8;
// Initialize properties
self.value = 0;
self.sprite = null;
self.row = -1; // Initialize row property
self.col = -1; // Initialize col property
// Method to set value and corresponding sprite
self.setValue = function (newValue) {
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,
scaleX: 0.9,
// Slightly smaller than cell for nicer look
scaleY: 0.9 // Slightly smaller than cell for nicer look
});
// Add sprite with a little animation for new cells
self.addChild(self.sprite);
self.sprite.alpha = 0;
self.sprite.scaleX = 0.5;
self.sprite.scaleY = 0.5;
// Animate in with a little bounce effect
tween(self.sprite, {
alpha: 1,
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 200,
easing: 'easeOutBack'
});
};
// Visual feedback on tap/touch
self.down = function (x, y, obj) {
// Add small scale effect on tap
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onComplete: function onComplete() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
handleCellTap(self);
};
return self;
});
/****
* Initialize Game
****/
// Grid configuration
var game = new LK.Game({
backgroundColor: 0xF4FFFF
});
/****
* Game Code
****/
// Grid configuration
var selectedCell = null;
function handleCellTap(tappedCell) {
// Check if animations are in progress
if (animationInProgress) {
return; // Ignore taps during animations
}
if (selectedCell === null) {
selectedCell = tappedCell;
// Visual feedback for selection
tween(selectedCell.sprite, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150
});
LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash yellow quickly
} else {
var cell1 = selectedCell;
var cell2 = tappedCell;
if (cell1 === cell2) {
// Tapped the same selected cell again - deselect
tween(selectedCell.sprite, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150
});
selectedCell = null; // Deselect
} else {
// 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) {
// Reset selection effect
tween(selectedCell.sprite, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150
});
animationInProgress = true; // Prevent new selections during animation
// 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
tween(cell1, {
x: pos2_x,
y: pos2_y
}, {
duration: 300,
onComplete: function onComplete() {
// First part of animation complete
}
});
tween(cell2, {
x: pos1_x,
y: pos1_y
}, {
duration: 300,
onComplete: function onComplete() {
// Schedule the match check and destruction after animation completes
LK.setTimeout(function () {
// checkForAndDestroyMatches now returns true if matches were found
var matchesFound = checkForAndDestroyMatches(cell1, cell2);
// If no matches found, the cells will be swapped back in checkForAndDestroyMatches
// Re-enable selections after a short delay
LK.setTimeout(function () {
animationInProgress = false;
}, matchesFound ? 1000 : 350); // Longer delay if matches were found and refill happens
}, 50);
}
});
selectedCell = null; // Reset selection after swap
} else {
// Reset previous selection effect
tween(selectedCell.sprite, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150
});
// Tapped a non-adjacent cell. Treat this as a new selection.
selectedCell = tappedCell;
// Visual feedback for new selection
tween(selectedCell.sprite, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150
});
LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash the new selection
}
}
}
}
// Helper functions for match detection and destruction
function getMatches() {
var matches = [];
var r, c, k, cell1, nextCell, currentMatchValue, currentMatchCells;
// Horizontal matches
for (r = 0; r < gridSize; r++) {
for (c = 0; c < gridSize;) {
// c is incremented based on match length or by 1
if (c > gridSize - 3) {
// Optimization: not enough cells left for a match of 3
c++;
continue;
}
cell1 = gridCells[r][c];
if (!cell1) {
// Skip empty cells
c++;
continue;
}
currentMatchValue = cell1.value;
currentMatchCells = [cell1];
for (k = c + 1; k < gridSize; k++) {
nextCell = gridCells[r][k];
if (nextCell && nextCell.value === currentMatchValue) {
currentMatchCells.push(nextCell);
} else {
break; // End of current potential match
}
}
if (currentMatchCells.length >= 3) {
matches.push(currentMatchCells);
}
c += currentMatchCells.length > 0 ? currentMatchCells.length : 1; // Advance index
}
}
// Vertical matches
for (c = 0; c < gridSize; c++) {
for (r = 0; r < gridSize;) {
// r is incremented based on match length or by 1
if (r > gridSize - 3) {
// Optimization: not enough cells left for a match of 3
r++;
continue;
}
cell1 = gridCells[r][c];
if (!cell1) {
// Skip empty cells
r++;
continue;
}
currentMatchValue = cell1.value;
currentMatchCells = [cell1];
for (k = r + 1; k < gridSize; k++) {
nextCell = gridCells[k][c];
if (nextCell && nextCell.value === currentMatchValue) {
currentMatchCells.push(nextCell);
} else {
break; // End of current potential match
}
}
if (currentMatchCells.length >= 3) {
matches.push(currentMatchCells);
}
r += currentMatchCells.length > 0 ? currentMatchCells.length : 1; // Advance index
}
}
return matches;
}
function destroyCells(cellsToDestroy) {
cellsToDestroy.forEach(function (cell) {
// 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) {
// Animate the cell before removing it
tween(cell.sprite, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 200,
onComplete: function onComplete() {
gridContainer.removeChild(cell); // Remove from display
cell.destroy(); // Destroy the cell object (releases resources)
gridCells[cell.row][cell.col] = null; // Mark as empty in the logical grid
}
});
}
});
}
function refillGrid() {
// First move existing cells down to fill gaps
var hasMoved = false;
// Process each column
for (var col = 0; col < gridSize; col++) {
// Start from the bottom row and move up
for (var row = gridSize - 1; row > 0; row--) {
if (gridCells[row][col] === null) {
// Find the closest non-null cell above
var sourceRow = row - 1;
while (sourceRow >= 0 && gridCells[sourceRow][col] === null) {
sourceRow--;
}
if (sourceRow >= 0) {
// Move this cell down to the empty space
var movingCell = gridCells[sourceRow][col];
var targetY = startY + row * (cellSize + cellSpacing);
// Update the grid references
gridCells[row][col] = movingCell;
gridCells[sourceRow][col] = null;
// Update the cell's internal coordinates
movingCell.row = row;
// Animate the move
tween(movingCell, {
y: targetY
}, {
duration: 300
});
hasMoved = true;
}
}
}
}
// Create new cells for any remaining empty spaces at the top
for (var col = 0; col < gridSize; col++) {
for (var row = 0; row < gridSize; row++) {
if (gridCells[row][col] === null) {
// Create a new cell
var newCell = new GridCell();
// Position cell (start above the grid and animate down)
newCell.x = startX + col * (cellSize + cellSpacing);
newCell.y = startY + (row - 3) * (cellSize + cellSpacing); // Start above grid
// Assign coordinates
newCell.row = row;
newCell.col = col;
// Generate random value
var randomValue = Math.floor(Math.random() * 5) + 1;
newCell.setValue(randomValue);
// Add to grid and animate down
gridContainer.addChild(newCell);
gridCells[row][col] = newCell;
// Animate falling into place
tween(newCell, {
y: startY + row * (cellSize + cellSpacing)
}, {
duration: 300,
delay: 100
});
hasMoved = true;
}
}
}
return hasMoved;
}
function checkForAndDestroyMatches(swappedCellA, swappedCellB) {
var allMatchGroupsOnBoard = getMatches(); // Get all potential matches on the board
if (allMatchGroupsOnBoard.length === 0) {
return false; // No matches found anywhere, nothing to do
}
var relevantMatchGroups = [];
// If swapped cells are provided, only check matches involving them
if (swappedCellA && swappedCellB) {
// Filter allMatchGroupsOnBoard to find groups containing one of the swapped cells
allMatchGroupsOnBoard.forEach(function (group) {
var groupIsRelevant = false;
for (var i = 0; i < group.length; i++) {
var cellInGroup = group[i];
// Check if the current cell in the group is one of the cells that was moved
if (cellInGroup === swappedCellA || cellInGroup === swappedCellB) {
groupIsRelevant = true;
break; // Found a swapped cell in this group, so the group is relevant
}
}
if (groupIsRelevant) {
relevantMatchGroups.push(group);
}
});
// If this was a move that didn't create a match, swap cells back
if (relevantMatchGroups.length === 0) {
// Swap back the cells in the grid array
var row1 = swappedCellA.row;
var col1 = swappedCellA.col;
var row2 = swappedCellB.row;
var col2 = swappedCellB.col;
// Swap cells in the gridCells array
gridCells[row1][col1] = swappedCellB;
gridCells[row2][col2] = swappedCellA;
// Swap row/col properties on the cell objects
swappedCellA.row = row2;
swappedCellA.col = col2;
swappedCellB.row = row1;
swappedCellB.col = col1;
// Animate the swap back
tween(swappedCellA, {
x: startX + col2 * (cellSize + cellSpacing),
y: startY + row2 * (cellSize + cellSpacing)
}, {
duration: 300
});
tween(swappedCellB, {
x: startX + col1 * (cellSize + cellSpacing),
y: startY + row1 * (cellSize + cellSpacing)
}, {
duration: 300
});
return false;
}
} else {
// If no specific cells provided, check all matches (for cascade effects)
relevantMatchGroups = allMatchGroupsOnBoard;
}
// Proceed with destroying cells from the relevant match groups
var cellsToDestroy = [];
var uniqueCellTracker = {}; // To ensure each cell is added only once
relevantMatchGroups.forEach(function (group) {
// Calculate points for this match
var matchPoints = group.length * 10;
// Bonus points for matches larger than 3
if (group.length > 3) {
matchPoints += (group.length - 3) * 10;
}
// Update score
LK.setScore(LK.getScore() + matchPoints);
// Add cells to destroy list
group.forEach(function (cell) {
// Create a unique key for each cell using its row and column
var cellKey = cell.row + "_" + cell.col;
if (!uniqueCellTracker[cellKey]) {
cellsToDestroy.push(cell);
uniqueCellTracker[cellKey] = true;
}
});
});
if (cellsToDestroy.length > 0) {
destroyCells(cellsToDestroy);
// After a short delay to allow destruction animations to complete,
// refill the grid and check for new matches
LK.setTimeout(function () {
refillGrid();
// Check for cascading matches after refill (with a delay)
LK.setTimeout(function () {
checkForAndDestroyMatches();
}, 500);
}, 300);
return true;
}
return false;
}
// Game variables
var gridSize = 9;
var cellSpacing = 10;
var cellSize = 160; // Width/height of the cell background
var gridCells = [];
// Calculate total grid width and height
var totalGridWidth = gridSize * cellSize + (gridSize - 1) * cellSpacing;
var totalGridHeight = totalGridWidth; // Grid is square
// Calculate starting position to center the grid
var startX = (2048 - totalGridWidth) / 2 + cellSize / 2;
var startY = (2732 - totalGridHeight) / 2 + cellSize / 2;
// Set up score display
var scoreText = new Text2("Score: 0", {
size: 80,
fill: 0x333333
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 1024; // Center horizontally
scoreText.y = 50; // Top padding
LK.gui.top.addChild(scoreText);
// Create grid container
var gridContainer = new Container();
game.addChild(gridContainer);
// Add game update listener to handle score display updates
LK.on('tick', function () {
// Update score display
scoreText.setText("Score: " + LK.getScore());
});
// Flag to track if animations are in progress
var animationInProgress = false;
// Initialize score to 0
LK.setScore(0);
// Create grid cells
for (var row = 0; row < gridSize; row++) {
gridCells[row] = [];
for (var col = 0; col < gridSize; col++) {
// Create new cell
var cell = new GridCell();
// Position cell
cell.x = startX + col * (cellSize + cellSpacing);
cell.y = startY + row * (cellSize + cellSpacing);
// Assign row and column to the cell
cell.row = row;
cell.col = col;
// Generate random value between 1 and 5
var randomValue = Math.floor(Math.random() * 5) + 1;
cell.setValue(randomValue);
// Add to grid container and store reference
gridContainer.addChild(cell);
gridCells[row][col] = cell;
}
}
// Check and clear any initial matches that might exist on the grid
LK.setTimeout(function () {
checkForAndDestroyMatches();
}, 500); ===================================================================
--- original.js
+++ change.js
@@ -12,8 +12,10 @@
var background = self.attachAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5
});
+ // Add a slight shadow/glow effect to background for depth
+ background.alpha = 0.8;
// Initialize properties
self.value = 0;
self.sprite = null;
self.row = -1; // Initialize row property
@@ -28,13 +30,45 @@
// Create new sprite based on value
var spriteId = 'meme' + newValue;
self.sprite = LK.getAsset(spriteId, {
anchorX: 0.5,
- anchorY: 0.5
+ anchorY: 0.5,
+ scaleX: 0.9,
+ // Slightly smaller than cell for nicer look
+ scaleY: 0.9 // Slightly smaller than cell for nicer look
});
+ // Add sprite with a little animation for new cells
self.addChild(self.sprite);
+ self.sprite.alpha = 0;
+ self.sprite.scaleX = 0.5;
+ self.sprite.scaleY = 0.5;
+ // Animate in with a little bounce effect
+ tween(self.sprite, {
+ alpha: 1,
+ scaleX: 0.9,
+ scaleY: 0.9
+ }, {
+ duration: 200,
+ easing: 'easeOutBack'
+ });
};
+ // Visual feedback on tap/touch
self.down = function (x, y, obj) {
+ // Add small scale effect on tap
+ tween(self, {
+ scaleX: 0.95,
+ scaleY: 0.95
+ }, {
+ duration: 100,
+ onComplete: function onComplete() {
+ tween(self, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 100
+ });
+ }
+ });
handleCellTap(self);
};
return self;
});
@@ -50,24 +84,48 @@
/****
* Game Code
****/
// Grid configuration
-var cellsPendingPhysicalDestruction = [];
var selectedCell = null;
function handleCellTap(tappedCell) {
+ // Check if animations are in progress
+ if (animationInProgress) {
+ return; // Ignore taps during animations
+ }
if (selectedCell === null) {
selectedCell = tappedCell;
+ // Visual feedback for selection
+ tween(selectedCell.sprite, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 150
+ });
LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash yellow quickly
} else {
var cell1 = selectedCell;
var cell2 = tappedCell;
if (cell1 === cell2) {
- // Tapped the same selected cell again
+ // Tapped the same selected cell again - deselect
+ tween(selectedCell.sprite, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 150
+ });
selectedCell = null; // Deselect
} else {
// 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) {
+ // Reset selection effect
+ tween(selectedCell.sprite, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 150
+ });
+ animationInProgress = true; // Prevent new selections during animation
// Store original positions for animation
var pos1_x = cell1.x;
var pos1_y = cell1.y;
var pos2_x = cell2.x;
@@ -89,46 +147,54 @@
tween(cell1, {
x: pos2_x,
y: pos2_y
}, {
- duration: 300
+ duration: 300,
+ onComplete: function onComplete() {
+ // First part of animation complete
+ }
});
tween(cell2, {
x: pos1_x,
y: pos1_y
}, {
- duration: 300
+ duration: 300,
+ onComplete: function onComplete() {
+ // Schedule the match check and destruction after animation completes
+ LK.setTimeout(function () {
+ // checkForAndDestroyMatches now returns true if matches were found
+ var matchesFound = checkForAndDestroyMatches(cell1, cell2);
+ // If no matches found, the cells will be swapped back in checkForAndDestroyMatches
+ // Re-enable selections after a short delay
+ LK.setTimeout(function () {
+ animationInProgress = false;
+ }, matchesFound ? 1000 : 350); // Longer delay if matches were found and refill happens
+ }, 50);
+ }
});
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
} else {
+ // Reset previous selection effect
+ tween(selectedCell.sprite, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 150
+ });
// Tapped a non-adjacent cell. Treat this as a new selection.
selectedCell = tappedCell;
+ // Visual feedback for new selection
+ tween(selectedCell.sprite, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 150
+ });
LK.effects.flashObject(selectedCell.sprite, 0xFFFF00, 150); // Flash the new selection
}
}
}
}
-// Function to actually remove cells from display and destroy them
-function actuallyDestroyCells(arrayOfCells) {
- arrayOfCells.forEach(function (cell) {
- if (cell && cell.parent) {
- // Check if cell exists and is still attached
- gridContainer.removeChild(cell);
- }
- if (cell) {
- // Check if cell exists before destroying
- cell.destroy();
- }
- });
-}
// Helper functions for match detection and destruction
function getMatches() {
var matches = [];
var r, c, k, cell1, nextCell, currentMatchValue, currentMatchCells;
@@ -195,152 +261,187 @@
}
}
return matches;
}
-// Function to animate falling cells and trigger further checks
-function animateFallingCellsAndTriggerCascade() {
- var cellsToShiftVisualOnly = [];
- var gridUpdates = []; // To store { cell, oldRow, oldCol, newRow, newCol }
- for (var c = 0; c < gridSize; c++) {
- // Iterate columns
- var emptySlotsInColumn = 0;
- for (var r = gridSize - 1; r >= 0; r--) {
- // Iterate rows from bottom up
- if (gridCells[r][c] === null) {
- emptySlotsInColumn++;
- } else if (emptySlotsInColumn > 0) {
- var cellToMove = gridCells[r][c];
- var newLogicalRow = r + emptySlotsInColumn;
- var targetY = startY + newLogicalRow * (cellSize + cellSpacing);
- cellsToShiftVisualOnly.push({
- cell: cellToMove,
- targetY: targetY
- });
- // Store details needed to update the logical grid
- gridUpdates.push({
- cell: cellToMove,
- oldRow: r,
- oldCol: c,
- newRow: newLogicalRow,
- newCol: c
- });
- }
+function destroyCells(cellsToDestroy) {
+ cellsToDestroy.forEach(function (cell) {
+ // 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) {
+ // Animate the cell before removing it
+ tween(cell.sprite, {
+ alpha: 0,
+ scaleX: 0,
+ scaleY: 0
+ }, {
+ duration: 200,
+ onComplete: function onComplete() {
+ gridContainer.removeChild(cell); // Remove from display
+ cell.destroy(); // Destroy the cell object (releases resources)
+ gridCells[cell.row][cell.col] = null; // Mark as empty in the logical grid
+ }
+ });
}
- }
- // Apply logical grid updates *before* animation starts
- // First, clear old positions of moving cells to avoid overwriting during update
- gridUpdates.forEach(function (op) {
- gridCells[op.oldRow][op.oldCol] = null;
});
- // Then, place cells in their new logical positions and update their row property
- gridUpdates.forEach(function (op) {
- op.cell.row = op.newRow; // Update cell's internal knowledge of its row
- gridCells[op.newRow][op.newCol] = op.cell;
- });
- if (cellsToShiftVisualOnly.length === 0) {
- // No cells are moving, meaning falling is complete for this cascade step, or no fall was needed.
- if (cellsPendingPhysicalDestruction.length > 0) {
- actuallyDestroyCells(cellsPendingPhysicalDestruction);
- cellsPendingPhysicalDestruction = []; // Clear the list
+}
+function refillGrid() {
+ // First move existing cells down to fill gaps
+ var hasMoved = false;
+ // Process each column
+ for (var col = 0; col < gridSize; col++) {
+ // Start from the bottom row and move up
+ for (var row = gridSize - 1; row > 0; row--) {
+ if (gridCells[row][col] === null) {
+ // Find the closest non-null cell above
+ var sourceRow = row - 1;
+ while (sourceRow >= 0 && gridCells[sourceRow][col] === null) {
+ sourceRow--;
+ }
+ if (sourceRow >= 0) {
+ // Move this cell down to the empty space
+ var movingCell = gridCells[sourceRow][col];
+ var targetY = startY + row * (cellSize + cellSpacing);
+ // Update the grid references
+ gridCells[row][col] = movingCell;
+ gridCells[sourceRow][col] = null;
+ // Update the cell's internal coordinates
+ movingCell.row = row;
+ // Animate the move
+ tween(movingCell, {
+ y: targetY
+ }, {
+ duration: 300
+ });
+ hasMoved = true;
+ }
+ }
}
- // Check for new matches on the entire board.
- // Use LK.setTimeout to ensure this check happens after current execution context unwinds.
- LK.setTimeout(function () {
- checkForAndDestroyMatches(null, null); // Check entire board for new matches
- }, 50); // A small delay
- return;
}
- var animationsInProgressCount = cellsToShiftVisualOnly.length;
- cellsToShiftVisualOnly.forEach(function (shiftOp) {
- tween(shiftOp.cell, {
- y: shiftOp.targetY
- }, {
- duration: 300,
- // Animation duration
- easing: tween.easeOut,
- // A smooth easing for falling
- onFinish: function onFinish() {
- animationsInProgressCount--;
- if (animationsInProgressCount === 0) {
- // All falling animations for this step are done
- if (cellsPendingPhysicalDestruction.length > 0) {
- actuallyDestroyCells(cellsPendingPhysicalDestruction);
- cellsPendingPhysicalDestruction = []; // Clear the list
- }
- // Now, check for new matches formed by the fallen cells
- LK.setTimeout(function () {
- checkForAndDestroyMatches(null, null); // Recursive call for cascades
- }, 50); // A small delay
- }
+ // Create new cells for any remaining empty spaces at the top
+ for (var col = 0; col < gridSize; col++) {
+ for (var row = 0; row < gridSize; row++) {
+ if (gridCells[row][col] === null) {
+ // Create a new cell
+ var newCell = new GridCell();
+ // Position cell (start above the grid and animate down)
+ newCell.x = startX + col * (cellSize + cellSpacing);
+ newCell.y = startY + (row - 3) * (cellSize + cellSpacing); // Start above grid
+ // Assign coordinates
+ newCell.row = row;
+ newCell.col = col;
+ // Generate random value
+ var randomValue = Math.floor(Math.random() * 5) + 1;
+ newCell.setValue(randomValue);
+ // Add to grid and animate down
+ gridContainer.addChild(newCell);
+ gridCells[row][col] = newCell;
+ // Animate falling into place
+ tween(newCell, {
+ y: startY + row * (cellSize + cellSpacing)
+ }, {
+ duration: 300,
+ delay: 100
+ });
+ hasMoved = true;
}
- });
- });
+ }
+ }
+ return hasMoved;
}
function checkForAndDestroyMatches(swappedCellA, swappedCellB) {
- var allMatchGroupsOnBoard = getMatches();
+ var allMatchGroupsOnBoard = getMatches(); // Get all potential matches on the board
+ if (allMatchGroupsOnBoard.length === 0) {
+ return false; // No matches found anywhere, nothing to do
+ }
var relevantMatchGroups = [];
- if (swappedCellA === null && swappedCellB === null) {
- // Full board check for cascades
- relevantMatchGroups = allMatchGroupsOnBoard;
- } else {
- // Initial check after a swap
+ // If swapped cells are provided, only check matches involving them
+ if (swappedCellA && swappedCellB) {
+ // Filter allMatchGroupsOnBoard to find groups containing one of the swapped cells
allMatchGroupsOnBoard.forEach(function (group) {
var groupIsRelevant = false;
for (var i = 0; i < group.length; i++) {
var cellInGroup = group[i];
+ // Check if the current cell in the group is one of the cells that was moved
if (cellInGroup === swappedCellA || cellInGroup === swappedCellB) {
groupIsRelevant = true;
- break;
+ break; // Found a swapped cell in this group, so the group is relevant
}
}
if (groupIsRelevant) {
relevantMatchGroups.push(group);
}
});
+ // If this was a move that didn't create a match, swap cells back
+ if (relevantMatchGroups.length === 0) {
+ // Swap back the cells in the grid array
+ var row1 = swappedCellA.row;
+ var col1 = swappedCellA.col;
+ var row2 = swappedCellB.row;
+ var col2 = swappedCellB.col;
+ // Swap cells in the gridCells array
+ gridCells[row1][col1] = swappedCellB;
+ gridCells[row2][col2] = swappedCellA;
+ // Swap row/col properties on the cell objects
+ swappedCellA.row = row2;
+ swappedCellA.col = col2;
+ swappedCellB.row = row1;
+ swappedCellB.col = col1;
+ // Animate the swap back
+ tween(swappedCellA, {
+ x: startX + col2 * (cellSize + cellSpacing),
+ y: startY + row2 * (cellSize + cellSpacing)
+ }, {
+ duration: 300
+ });
+ tween(swappedCellB, {
+ x: startX + col1 * (cellSize + cellSpacing),
+ y: startY + row1 * (cellSize + cellSpacing)
+ }, {
+ duration: 300
+ });
+ return false;
+ }
+ } else {
+ // If no specific cells provided, check all matches (for cascade effects)
+ relevantMatchGroups = allMatchGroupsOnBoard;
}
- if (relevantMatchGroups.length === 0) {
- // No new matches found in this pass.
- // If this is part of a cascade that just finished falling and found no new matches,
- // animateFallingCellsAndTriggerCascade's "no cells to shift" or "onFinish" paths
- // would have handled cleanup and this recursive call. So, simply returning is fine.
- return;
- }
- var cellsToMarkInThisPass = [];
- var uniqueCellTracker = {}; // To avoid processing a cell multiple times if in multiple groups
+ // Proceed with destroying cells from the relevant match groups
+ var cellsToDestroy = [];
+ var uniqueCellTracker = {}; // To ensure each cell is added only once
relevantMatchGroups.forEach(function (group) {
+ // Calculate points for this match
+ var matchPoints = group.length * 10;
+ // Bonus points for matches larger than 3
+ if (group.length > 3) {
+ matchPoints += (group.length - 3) * 10;
+ }
+ // Update score
+ LK.setScore(LK.getScore() + matchPoints);
+ // Add cells to destroy list
group.forEach(function (cell) {
+ // Create a unique key for each cell using its row and column
var cellKey = cell.row + "_" + cell.col;
- // Cell must exist in the grid logically (not already nullified by a previous step in the same destruction event)
- // and not yet tracked for this specific pass of marking.
- if (gridCells[cell.row] && gridCells[cell.row][cell.col] === cell && !uniqueCellTracker[cellKey]) {
- cellsToMarkInThisPass.push(cell);
+ if (!uniqueCellTracker[cellKey]) {
+ cellsToDestroy.push(cell);
uniqueCellTracker[cellKey] = true;
}
});
});
- if (cellsToMarkInThisPass.length > 0) {
- // These are newly identified cells to be destroyed (or marked for destruction)
- cellsToMarkInThisPass.forEach(function (cell) {
- // Add to global list for eventual physical destruction, if not already there from this destruction event
- if (!cellsPendingPhysicalDestruction.includes(cell)) {
- cellsPendingPhysicalDestruction.push(cell);
- }
- gridCells[cell.row][cell.col] = null; // Mark as empty in the logical grid
- });
- // Since new cells were marked (and thus logically removed from grid), trigger falling and subsequent checks
- animateFallingCellsAndTriggerCascade();
- } else if (relevantMatchGroups.length > 0 && cellsPendingPhysicalDestruction.length > 0) {
- // No *new* cells were marked in this pass (cellsToMarkInThisPass is empty),
- // BUT there were relevantMatchGroups (meaning matches exist, likely on already nulled spots)
- // AND there are cells pending physical destruction from previous steps of this same destruction event.
- // This implies we're in a complex cascade state. We should still trigger the falling/cleanup mechanism.
- animateFallingCellsAndTriggerCascade();
+ if (cellsToDestroy.length > 0) {
+ destroyCells(cellsToDestroy);
+ // After a short delay to allow destruction animations to complete,
+ // refill the grid and check for new matches
+ LK.setTimeout(function () {
+ refillGrid();
+ // Check for cascading matches after refill (with a delay)
+ LK.setTimeout(function () {
+ checkForAndDestroyMatches();
+ }, 500);
+ }, 300);
+ return true;
}
- // If relevantMatchGroups.length > 0, but cellsToMarkInThisPass is 0, AND cellsPendingPhysicalDestruction is 0,
- // it implies a very specific state where matches are found on already nulled spots from a *fully completed previous destruction event*.
- // This case should be rare and ideally covered by the general flow. If it's problematic,
- // the condition `cellsPendingPhysicalDestruction.length > 0` in the else-if ensures we only proceed if there's an active destruction event.
+ return false;
}
+// Game variables
var gridSize = 9;
var cellSpacing = 10;
var cellSize = 160; // Width/height of the cell background
var gridCells = [];
@@ -349,11 +450,29 @@
var totalGridHeight = totalGridWidth; // Grid is square
// Calculate starting position to center the grid
var startX = (2048 - totalGridWidth) / 2 + cellSize / 2;
var startY = (2732 - totalGridHeight) / 2 + cellSize / 2;
+// Set up score display
+var scoreText = new Text2("Score: 0", {
+ size: 80,
+ fill: 0x333333
+});
+scoreText.anchor.set(0.5, 0);
+scoreText.x = 1024; // Center horizontally
+scoreText.y = 50; // Top padding
+LK.gui.top.addChild(scoreText);
// Create grid container
var gridContainer = new Container();
game.addChild(gridContainer);
+// Add game update listener to handle score display updates
+LK.on('tick', function () {
+ // Update score display
+ scoreText.setText("Score: " + LK.getScore());
+});
+// Flag to track if animations are in progress
+var animationInProgress = false;
+// Initialize score to 0
+LK.setScore(0);
// Create grid cells
for (var row = 0; row < gridSize; row++) {
gridCells[row] = [];
for (var col = 0; col < gridSize; col++) {
@@ -371,5 +490,9 @@
// Add to grid container and store reference
gridContainer.addChild(cell);
gridCells[row][col] = cell;
}
-}
\ No newline at end of file
+}
+// Check and clear any initial matches that might exist on the grid
+LK.setTimeout(function () {
+ checkForAndDestroyMatches();
+}, 500);
\ No newline at end of file
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