User prompt
arregla contador, no dura realmente 10 segundos, usa delta time
User prompt
el contador parece no tardar realmente 10 segundos, esta acelerado
User prompt
haz que el fast mode empiece con un contador de 10 segundos a medida que el record aumenta el tiempo disminuye a minimo 4 segundos
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Timeout.tick error: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'self.timerText.style.fill = 0xFFFFFF; // White normally' Line Number: 315
User prompt
caracteristicas de fast mode: Habra un contador de 3 segundos, cuando este llegue a 0 se pierde, la unica forma de reiniciarlo es rompiendo memes āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que todos los memeas sean especiales random
User prompt
haz que todos los memes sean verdes āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
arregla el bug que hace que no aparezcan nuevos memes despues de usar la habilidad verde
User prompt
arregla el bug que hace que no aparezcan nuevos memes despues de usar la habilidad verde
User prompt
caracteristicas de classic mode: Solo se pueden mover los memes si se rompen, de no romperse volveran a su posicioĢn
User prompt
arregla el siguiente error: despues de mover un meme y que se regrese a su posicioĢn no se puede seleccionar ningun otro meme para mover
User prompt
arregla el bug que no permite mover ningun meme despues de que el meme regrese a su posicioĢn
User prompt
caracteristicas de classic mode: Solo se pueden mover los memes si se rompen, de no romperse volveran a su posicioĢn
User prompt
caracteristicas de classic mode: Solo se pueden mover los memes si se rompen, de no romperse volveran a su posicioĢn
User prompt
crea dos botones en el menu Classic mode y Fast mode, luego especificaremos la caracteristicas de cada uno
User prompt
Crea un menu inicial separado del juego
User prompt
el juego no se inicia
User prompt
Agrega un menu inicial
User prompt
agrega un sistema de puntos
User prompt
agrega una variable GameStart, cuando este es verdadero el juego comienza y se inicia la posicioĢn aleatoria de los memes
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'visible')' in or related to this line: 'gridContainer.visible = false;' Line Number: 278
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'visible')' in or related to this line: 'gridContainer.visible = false;' Line Number: 276
User prompt
crea un menu inicial
User prompt
Crea un menu inicial
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var GridCell = Container.expand(function () {
var self = Container.call(this);
self.init = function () {
if (!self.background) {
self.background = self.attachAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.value = 0;
self.sprite = null;
self.row = -1;
self.col = -1;
self.isSpecial = false;
self.specialType = null;
return self;
};
self.setValue = function (newValue) {
if (self.value === newValue) {
return;
}
self.value = newValue;
if (self.sprite) {
self.removeChild(self.sprite);
}
var spriteId = 'meme' + newValue;
self.sprite = LK.getAsset(spriteId, {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(self.sprite);
// Apply tint if this is a special meme
if (self.isSpecial) {
if (self.specialType === 'bomb') {
self.sprite.tint = 0x0088FF; // Blue tint for bomb special meme
} else if (self.specialType === 'green') {
self.sprite.tint = 0x00FF00; // Green tint for swap-destroy special meme
} else {
self.sprite.tint = 0xFF8800; // Orange tint for horizontal/vertical special meme
}
}
};
self.activateSpecialPower = function () {
if (!self.isSpecial) {
return;
}
var cellsToDestroy = [];
var bonusPoints = 0;
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]);
}
}
// Award bonus points for horizontal special activation
bonusPoints = 100;
} 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]);
}
}
// Award bonus points for vertical special activation
bonusPoints = 100;
} else if (self.specialType === 'bomb') {
// Destroy adjacent cells (bomb effect)
for (var row = Math.max(extraRows, self.row - 1); row <= Math.min(gridSize + extraRows - 1, self.row + 1); row++) {
for (var col = Math.max(0, self.col - 1); col <= Math.min(gridSize - 1, self.col + 1); col++) {
if (gridCells[row][col] && gridCells[row][col] !== self) {
cellsToDestroy.push(gridCells[row][col]);
}
}
}
// Award bonus points for bomb special activation
bonusPoints = 150;
} else if (self.specialType === 'green') {
// Green special meme power is activated when swapped, not when destroyed
// The power is implemented in handleCellTap function
// Award bonus points for green special activation (though it should be handled elsewhere)
bonusPoints = 200;
}
// Award special activation bonus points
if (bonusPoints > 0) {
updateScore(bonusPoints);
// Show floating score text for special activation
var scorePopup = new Text2("+" + bonusPoints, {
size: 60,
fill: 0xFFFF00
});
scorePopup.anchor.set(0.5, 0.5);
scorePopup.x = self.x;
scorePopup.y = self.y;
game.addChild(scorePopup);
// Animate score popup
tween(scorePopup, {
y: scorePopup.y - 80,
alpha: 0
}, {
duration: 800,
onComplete: function onComplete() {
game.removeChild(scorePopup);
scorePopup.destroy();
}
});
}
// 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;
});
var MenuScreen = Container.expand(function () {
var self = Container.call(this);
// Create title
var title = new Text2("Meme Match", {
size: 120,
fill: 0x000000
});
title.anchor.set(0.5, 0);
title.x = 2048 / 2;
title.y = 300;
self.addChild(title);
// Create Classic mode button
var classicButton = new Container();
var classicButtonBg = LK.getAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 1.5
});
classicButtonBg.tint = 0x00AA00;
var classicText = new Text2("CLASSIC MODE", {
size: 70,
fill: 0xFFFFFF
});
classicText.anchor.set(0.5, 0.5);
classicButton.addChild(classicButtonBg);
classicButton.addChild(classicText);
classicButton.x = 2048 / 2;
classicButton.y = 2732 / 2 - 200;
self.addChild(classicButton);
// Create Fast mode button
var fastButton = new Container();
var fastButtonBg = LK.getAsset('cuadricula', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 1.5
});
fastButtonBg.tint = 0x0088FF;
var fastText = new Text2("FAST MODE", {
size: 70,
fill: 0xFFFFFF
});
fastText.anchor.set(0.5, 0.5);
fastButton.addChild(fastButtonBg);
fastButton.addChild(fastText);
fastButton.x = 2048 / 2;
fastButton.y = 2732 / 2 + 100;
self.addChild(fastButton);
// Add button interactions
classicButton.interactive = true;
classicButton.down = function (x, y, obj) {
LK.effects.flashObject(classicButtonBg, 0xFFFFFF, 200);
LK.setTimeout(function () {
self.startGame('classic');
}, 300);
};
fastButton.interactive = true;
fastButton.down = function (x, y, obj) {
LK.effects.flashObject(fastButtonBg, 0xFFFFFF, 200);
LK.setTimeout(function () {
self.startGame('fast');
}, 300);
};
// Function to start the game
self.startGame = function (mode) {
game.gameMode = mode || 'classic';
game.removeChild(self);
game.initializeGame();
};
return self;
});
var TimerDisplay = Container.expand(function () {
var self = Container.call(this);
// Create timer text
self.timerText = new Text2("3", {
size: 100,
fill: 0xFF0000
});
self.timerText.style = self.timerText.style || {};
self.timerText.anchor.set(0.5, 0.5);
self.addChild(self.timerText);
// Initialize timer properties
self.maxTime = 10; // 10 seconds default for Fast Mode
self.currentTime = self.maxTime;
self.active = false;
self.warningThreshold = 1; // Flashing warning when 1 second left
self.lastWholeSecond = Math.ceil(self.currentTime);
self.baseMaxTime = 10; // Store the base maximum time
self.minMaxTime = 4; // Minimum timer value is 4 seconds
// Start the timer
self.start = function () {
self.active = true;
self.currentTime = self.maxTime;
self.lastWholeSecond = Math.ceil(self.currentTime);
self.updateDisplay();
};
// Stop the timer
self.stop = function () {
self.active = false;
};
// Calculate max time based on score
self.calculateMaxTime = function () {
// As score increases, time decreases, with a minimum of 4 seconds
// Formula: Start with 10 seconds, subtract 0.01 seconds per point, but never go below 4 seconds
var calculatedTime = self.baseMaxTime - score * 0.01;
return Math.max(self.minMaxTime, calculatedTime);
};
// Reset timer back to max
self.reset = function () {
// Update maxTime based on current score
self.maxTime = self.calculateMaxTime();
self.currentTime = self.maxTime;
self.lastWholeSecond = Math.ceil(self.currentTime);
self.updateDisplay();
// Flash effect to indicate reset
LK.effects.flashObject(self.timerText, 0x00FF00, 200);
};
// Update timer display
self.updateDisplay = function () {
var displayTime = Math.ceil(self.currentTime);
self.timerText.setText(displayTime.toString());
// Change color based on time remaining
if (displayTime <= self.warningThreshold) {
self.timerText.style.fill = 0xFF0000; // Red when low time
// Pulse animation for urgency when time is low
if (!self.pulsing) {
self.pulsing = true;
self.startPulseAnimation();
}
} else {
self.timerText.style.fill = 0xFFFFFF; // White normally
self.stopPulseAnimation();
}
};
// Pulse animation for low time warning
self.startPulseAnimation = function () {
tween.stop(self.timerText);
self.doPulse();
};
self.doPulse = function () {
if (!self.pulsing) return;
tween(self.timerText, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onComplete: function onComplete() {
tween(self.timerText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn,
onComplete: self.doPulse
});
}
});
};
self.stopPulseAnimation = function () {
self.pulsing = false;
tween.stop(self.timerText);
tween(self.timerText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
};
// Update method called every frame
self.update = function (deltaTime) {
if (!self.active) return;
// Use deltaTime for accurate timing regardless of frame rate
var seconds = deltaTime ? deltaTime / 1000 : 1 / 60;
self.currentTime -= seconds;
// Check if we crossed a whole second boundary for display update
var currentWholeSecond = Math.ceil(self.currentTime);
if (currentWholeSecond !== self.lastWholeSecond) {
self.lastWholeSecond = currentWholeSecond;
self.updateDisplay();
}
// Check if time is up
if (self.currentTime <= 0) {
self.currentTime = 0;
self.active = false;
self.onTimeUp && self.onTimeUp();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xF4FFFF
});
/****
* Game Code
****/
// Game state and initialization
var menuScreen;
var gameInitialized = false;
var score = 0;
var scoreText;
var gridContainer;
var gameMode = 'classic'; // Track current game mode
// Initialize the menu
function initializeMenu() {
menuScreen = new MenuScreen();
game.addChild(menuScreen);
}
// Initialize the game
game.initializeGame = function () {
// Initialize score system
score = 0;
// Create and position score text
initializeScore();
// Create grid container if it doesn't exist
if (!gridContainer) {
gridContainer = new Container();
game.addChild(gridContainer);
} else {
// Clear existing grid container
while (gridContainer.children.length > 0) {
var child = gridContainer.children[0];
gridContainer.removeChild(child);
child.destroy();
}
}
// Add mode indicator text
var modeText = new Text2(game.gameMode === 'classic' ? "Classic Mode" : "Fast Mode", {
size: 60,
fill: game.gameMode === 'classic' ? 0x00AA00 : 0x0088FF
});
modeText.anchor.set(0.5, 0);
modeText.x = 2048 / 2;
modeText.y = 180;
game.addChild(modeText);
// Initialize timer for Fast mode
if (game.gameMode === 'fast') {
if (!game.timer) {
game.timer = new TimerDisplay();
game.timer.x = 2048 / 2;
game.timer.y = 2732 - 120;
game.addChild(game.timer);
game.timer.onTimeUp = function () {
// Game over when time runs out
LK.effects.flashScreen(0xFF0000, 500);
LK.showGameOver();
};
} else {
// Reset existing timer
game.timer.reset();
}
// Calculate initial timer value based on score before starting
game.timer.maxTime = game.timer.calculateMaxTime();
// Start timer
game.timer.start();
} else if (game.timer) {
// Remove timer if not in Fast mode
game.timer.stop();
game.removeChild(game.timer);
game.timer = null;
}
// Initialize the game grid
initializeGrid();
ensureNoInitialMatches();
// Main game update loop
game.update = function (deltaTime) {
// Update timer in Fast mode
if (game.gameMode === 'fast' && game.timer) {
game.timer.update(deltaTime);
}
};
gameInitialized = true;
};
// Create and position score text
function initializeScore() {
scoreText = new Text2("Score: 0", {
size: 80,
fill: 0x000000
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 2048 / 2;
scoreText.y = 100;
game.addChild(scoreText);
}
// Update score display
function updateScore(points) {
score += points;
scoreText.setText("Score: " + score);
}
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;
// Track combo counts for sound effects
var comboCounter = 0;
var comboInProgress = 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;
}
// Special memes need to be matched with other memes to be activated, so we don't check for special activation here
// 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;
// Store original positions and grid coordinates
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;
// Check if cells are special memes
var greenSpecialCell = null;
var regularCell = null;
var lineSpecialCells = [];
var twoGreenSpecials = false;
// Check for two green special memes
if (cell1.isSpecial && cell1.specialType === 'green' && cell2.isSpecial && cell2.specialType === 'green') {
twoGreenSpecials = true;
}
// Check for green special meme
else if (cell1.isSpecial && cell1.specialType === 'green') {
greenSpecialCell = cell1;
regularCell = cell2;
} else if (cell2.isSpecial && cell2.specialType === 'green') {
greenSpecialCell = cell2;
regularCell = cell1;
}
// Check for line-clearing special memes (horizontal/vertical)
if (cell1.isSpecial && (cell1.specialType === 'horizontal' || cell1.specialType === 'vertical')) {
lineSpecialCells.push(cell1);
}
if (cell2.isSpecial && (cell2.specialType === 'horizontal' || cell2.specialType === 'vertical')) {
lineSpecialCells.push(cell2);
}
gridCells[row1][col1] = cell2;
gridCells[row2][col2] = cell1;
cell1.row = row2;
cell1.col = col2;
cell2.row = row1;
cell2.col = col1;
// Make sure any selection highlights are removed
if (cell1.selectionHighlight) {
cell1.hideSelection();
}
if (cell2.selectionHighlight) {
cell2.hideSelection();
}
// Check for special combinations: two green special memes, two bombs, line-clearing + bomb, or two line special memes
if (twoGreenSpecials) {
// Two green special memes combination - destroys all visible memes
var cellsToDestroy = [];
// Collect all visible cells on the board
for (var row = extraRows; row < gridSize + extraRows; row++) {
for (var col = 0; col < gridSize; col++) {
if (gridCells[row][col] && gridCells[row][col] !== cell1 && gridCells[row][col] !== cell2) {
cellsToDestroy.push(gridCells[row][col]);
}
}
}
// Award massive bonus for two green special meme combination
updateScore(1000);
// Show mega score popup
var megaScorePopup = new Text2("+1000", {
size: 100,
fill: 0x00FF00
});
megaScorePopup.anchor.set(0.5, 0.5);
megaScorePopup.x = 2048 / 2;
megaScorePopup.y = 2732 / 2;
game.addChild(megaScorePopup);
// Animate mega score popup
tween(megaScorePopup, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 1000,
onComplete: function onComplete() {
game.removeChild(megaScorePopup);
megaScorePopup.destroy();
}
});
// Mark special memes for destruction
cell1.beingDestroyed = true;
cell2.beingDestroyed = true;
// Schedule destruction after the swap animation completes
LK.setTimeout(function () {
LK.getSound('Explosion').play();
// Flash screen effect for this powerful combination
LK.effects.flashScreen(0x00FF00, 500);
// Destroy the collected cells
if (cellsToDestroy.length > 0) {
destroyCells(cellsToDestroy);
}
// Destroy the special memes
LK.effects.flashObject(cell1, 0xFFFFFF, 200);
LK.effects.flashObject(cell2, 0xFFFFFF, 200);
gridContainer.removeChild(cell1);
gridContainer.removeChild(cell2);
cell1.destroy();
cell2.destroy();
gridCells[cell1.row][cell1.col] = null;
gridCells[cell2.row][cell2.col] = null;
}, 250);
} else if (cell1.isSpecial && cell1.specialType === 'bomb' && cell2.isSpecial && cell2.specialType === 'bomb') {
// Two bomb special memes combination - creates a 5x5 explosion
var cellsToDestroy = [];
// Determine which cell was moved by the player
var activatedCell = cell1;
// Create a 5x5 area effect centered on the first bomb
for (var r = Math.max(extraRows, cell1.row - 2); r <= Math.min(gridSize + extraRows - 1, cell1.row + 2); r++) {
for (var c = Math.max(0, cell1.col - 2); c <= Math.min(gridSize - 1, cell1.col + 2); c++) {
if (gridCells[r][c] && gridCells[r][c] !== cell1 && gridCells[r][c] !== cell2) {
cellsToDestroy.push(gridCells[r][c]);
}
}
}
// Mark special memes for destruction
cell1.beingDestroyed = true;
cell2.beingDestroyed = true;
// Schedule destruction after the swap animation completes
LK.setTimeout(function () {
LK.getSound('Explosion').play();
// Destroy the collected cells
if (cellsToDestroy.length > 0) {
destroyCells(cellsToDestroy);
}
// Destroy the special memes
LK.effects.flashObject(cell1, 0xFFFFFF, 200);
LK.effects.flashObject(cell2, 0xFFFFFF, 200);
gridContainer.removeChild(cell1);
gridContainer.removeChild(cell2);
cell1.destroy();
cell2.destroy();
gridCells[cell1.row][cell1.col] = null;
gridCells[cell2.row][cell2.col] = null;
}, 250);
} else if (cell1.isSpecial && cell1.specialType === 'bomb' && cell2.isSpecial && (cell2.specialType === 'horizontal' || cell2.specialType === 'vertical') || cell2.isSpecial && cell2.specialType === 'bomb' && cell1.isSpecial && (cell1.specialType === 'horizontal' || cell1.specialType === 'vertical')) {
// Line-clearing + bomb special combination
var bombCell = cell1.specialType === 'bomb' ? cell1 : cell2;
var lineCell = cell1.specialType === 'horizontal' || cell1.specialType === 'vertical' ? cell1 : cell2;
var cellsToDestroy = [];
var affectedRows = [];
// Determine which cell was moved by the player
var activatedCell = cell1;
// Enhanced effect: destroy 3 rows or columns based on the line special type
if (lineCell.specialType === 'horizontal') {
// Destroy 3 rows centered on the bomb's row
for (var r = Math.max(extraRows, bombCell.row - 1); r <= Math.min(gridSize + extraRows - 1, bombCell.row + 1); r++) {
affectedRows.push(r);
for (var c = 0; c < gridSize; c++) {
if (gridCells[r][c] && gridCells[r][c] !== bombCell && gridCells[r][c] !== lineCell) {
cellsToDestroy.push(gridCells[r][c]);
}
}
}
} else {
// vertical
// Destroy 3 columns centered on the bomb's column
for (var r = extraRows; r < gridSize + extraRows; r++) {
for (var c = Math.max(0, bombCell.col - 1); c <= Math.min(gridSize - 1, bombCell.col + 1); c++) {
if (gridCells[r][c] && gridCells[r][c] !== bombCell && gridCells[r][c] !== lineCell) {
cellsToDestroy.push(gridCells[r][c]);
}
}
}
}
// Mark special memes for destruction
bombCell.beingDestroyed = true;
lineCell.beingDestroyed = true;
// Schedule destruction after the swap animation completes
LK.setTimeout(function () {
LK.getSound('Explosion').play();
// Destroy the collected cells
if (cellsToDestroy.length > 0) {
destroyCells(cellsToDestroy);
}
// Destroy the special memes
LK.effects.flashObject(bombCell, 0xFFFFFF, 200);
LK.effects.flashObject(lineCell, 0xFFFFFF, 200);
gridContainer.removeChild(bombCell);
gridContainer.removeChild(lineCell);
bombCell.destroy();
lineCell.destroy();
gridCells[bombCell.row][bombCell.col] = null;
gridCells[lineCell.row][lineCell.col] = null;
}, 250);
}
// Check if two line special memes were swapped (horizontal and vertical)
else if (lineSpecialCells.length === 2) {
var cellsToDestroy = [];
// Collect cells in both row and column
var row1, col1, row2, col2;
var activatedSpecial;
// Determine which special meme was moved by the player (based on original positions)
if (lineSpecialCells[0] === cell1) {
activatedSpecial = lineSpecialCells[0];
row1 = lineSpecialCells[0].row;
col1 = lineSpecialCells[0].col;
} else {
activatedSpecial = lineSpecialCells[1];
row1 = lineSpecialCells[1].row;
col1 = lineSpecialCells[1].col;
}
// Add cells from the activated special's row or column
for (var row = extraRows; row < gridSize + extraRows; row++) {
// Add cells from column
if (gridCells[row][col1] && gridCells[row][col1] !== lineSpecialCells[0] && gridCells[row][col1] !== lineSpecialCells[1]) {
cellsToDestroy.push(gridCells[row][col1]);
}
}
// Add cells from the activated special's row
for (var col = 0; col < gridSize; col++) {
// Add cells from row
if (col !== col1 && gridCells[row1][col] && gridCells[row1][col] !== lineSpecialCells[0] && gridCells[row1][col] !== lineSpecialCells[1]) {
cellsToDestroy.push(gridCells[row1][col]);
}
}
// Mark special memes for destruction
lineSpecialCells.forEach(function (specialMeme) {
specialMeme.beingDestroyed = true;
});
// Schedule destruction after the swap animation completes
LK.setTimeout(function () {
LK.getSound('Explosion').play();
// Destroy the collected cells
if (cellsToDestroy.length > 0) {
destroyCells(cellsToDestroy);
}
// Destroy the special memes
lineSpecialCells.forEach(function (specialMeme) {
LK.effects.flashObject(specialMeme, 0xFFFFFF, 200);
gridContainer.removeChild(specialMeme);
specialMeme.destroy();
gridCells[specialMeme.row][specialMeme.col] = null;
});
}, 250);
}
// Check if greenSpecialCell was swapped with a line-clearing special meme or bomb
else if (greenSpecialCell && regularCell) {
// Check if regularCell is a line-clearing special meme
if (regularCell.isSpecial && (regularCell.specialType === 'horizontal' || regularCell.specialType === 'vertical')) {
var targetType = regularCell.value;
var cellsToTransform = [];
// Find all cells with the same type as the swapped line-clearing meme
for (var row = extraRows; row < gridSize + extraRows; row++) {
for (var col = 0; col < gridSize; col++) {
var cell = gridCells[row][col];
if (cell && cell.value === targetType && cell !== greenSpecialCell && cell !== regularCell && !cell.isSpecial) {
cellsToTransform.push(cell);
}
}
}
// Mark special memes for destruction
greenSpecialCell.beingDestroyed = true;
// Schedule transformation and activation after the swap animation completes
LK.setTimeout(function () {
LK.getSound('Explosion').play();
LK.effects.flashObject(greenSpecialCell, 0xFFFFFF, 200);
// Transform all cells of the same type into line-clearing memes
cellsToTransform.forEach(function (cell) {
cell.isSpecial = true;
// Randomly assign horizontal or vertical
cell.specialType = Math.random() < 0.5 ? 'horizontal' : 'vertical';
// Apply tint
cell.sprite.tint = 0xFF8800; // Orange tint for line special memes
LK.effects.flashObject(cell, 0xFFFFFF, 200);
// Activate each special meme with a slight delay
LK.setTimeout(function () {
cell.activateSpecialPower();
}, 100 + Math.random() * 300);
});
// Remove the green special meme
gridContainer.removeChild(greenSpecialCell);
greenSpecialCell.destroy();
gridCells[greenSpecialCell.row][greenSpecialCell.col] = null;
// Activate the original line-clearing meme last
LK.setTimeout(function () {
regularCell.activateSpecialPower();
}, 500);
}, 250);
} else if (regularCell.isSpecial && regularCell.specialType === 'bomb') {
// Green special + bomb special interaction
var targetType = regularCell.value;
var cellsToTransform = [];
// Find all cells with the same type as the bomb meme
for (var row = extraRows; row < gridSize + extraRows; row++) {
for (var col = 0; col < gridSize; col++) {
var cell = gridCells[row][col];
if (cell && cell.value === targetType && cell !== greenSpecialCell && cell !== regularCell && !cell.isSpecial) {
cellsToTransform.push(cell);
}
}
}
// Mark green special meme for destruction
greenSpecialCell.beingDestroyed = true;
// Schedule transformation and activation after swap animation
LK.setTimeout(function () {
LK.getSound('Explosion').play();
LK.effects.flashObject(greenSpecialCell, 0xFFFFFF, 200);
// Transform all cells of same type into bomb memes
cellsToTransform.forEach(function (cell) {
cell.isSpecial = true;
cell.specialType = 'bomb';
// Apply blue tint for bomb memes
cell.sprite.tint = 0x0088FF;
LK.effects.flashObject(cell, 0xFFFFFF, 200);
// Activate each bomb with slight delay
LK.setTimeout(function () {
cell.activateSpecialPower();
}, 100 + Math.random() * 300);
});
// Remove the green special meme
gridContainer.removeChild(greenSpecialCell);
greenSpecialCell.destroy();
gridCells[greenSpecialCell.row][greenSpecialCell.col] = null;
// Activate the original bomb last
LK.setTimeout(function () {
regularCell.activateSpecialPower();
}, 500);
}, 250);
} else {
var targetType = regularCell.value;
var cellsToDestroy = [];
// Find all cells with the same type as the swapped meme
for (var row = extraRows; row < gridSize + extraRows; row++) {
for (var col = 0; col < gridSize; col++) {
var cell = gridCells[row][col];
if (cell && cell.value === targetType && cell !== greenSpecialCell) {
cellsToDestroy.push(cell);
}
}
}
// Also destroy the green special meme itself
greenSpecialCell.beingDestroyed = true;
// Schedule destruction after the swap animation completes
LK.setTimeout(function () {
if (cellsToDestroy.length > 0) {
LK.getSound('Explosion').play();
LK.effects.flashObject(greenSpecialCell, 0xFFFFFF, 200);
destroyCells(cellsToDestroy);
gridContainer.removeChild(greenSpecialCell);
greenSpecialCell.destroy();
gridCells[greenSpecialCell.row][greenSpecialCell.col] = null;
}
}, 250);
}
}
tween(cell1, {
x: pos2_x,
y: pos2_y
}, {
duration: 200
});
tween(cell2, {
x: pos1_x,
y: pos1_y
}, {
duration: 200
});
selectedCell = null;
LK.setTimeout(function () {
checkForAndDestroyMatches(cell1, cell2);
if (!window.destructionInProgress && !window.gravityInProgress && !window.fillInProgress) {
isAnimating = false;
}
}, 250);
}
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 {
// If no new matches found, reset combo counter
LK.setTimeout(function () {
if (!window.gravityInProgress && !window.fillInProgress) {
comboInProgress = false;
comboCounter = 0;
}
}, 500);
break;
}
}
if (currentMatchCells.length >= 3) {
var validCells = currentMatchCells.filter(function (cell) {
return cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell;
});
if (validCells.length >= 3) {
var visibleCells = validCells.filter(function (cell) {
return cell.row >= extraRows;
});
var invisibleCells = validCells.filter(function (cell) {
return cell.row < extraRows;
});
// 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) {
// Add isHorizontal and matchType to the match data
validCells.isHorizontal = isHorizontal;
validCells.matchType = currentMatchValue;
matches.push(validCells);
}
}
}
secondary += currentMatchCells.length > 0 ? currentMatchCells.length : 1;
}
}
}
findDirectionalMatches(true);
findDirectionalMatches(false);
return matches;
}
function destroyCells(cellsToDestroy) {
isAnimating = true;
// 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;
}
// Calculate points for destroyed cells - only count visible cells
var basePoints = visibleCells.length * 10;
var visibleCellsToDestroy = cellsToDestroy.filter(function (cell) {
return cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell;
});
// Reset timer in Fast mode when cells are destroyed
if (game.gameMode === 'fast' && game.timer && visibleCellsToDestroy.length > 0) {
game.timer.reset();
}
// 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);
});
// Count unique groups for combo sound
var uniqueGroupCount = Object.keys(cellsByType).length;
if (uniqueGroupCount > 0) {
// Increment combo counter only if this is part of a continuous combo
if (!comboInProgress) {
comboCounter = uniqueGroupCount;
comboInProgress = true;
} else {
comboCounter += uniqueGroupCount;
}
// Calculate score multiplier based on combo count
var comboMultiplier = 1;
if (comboCounter >= 9) {
comboMultiplier = 5;
} else if (comboCounter >= 6) {
comboMultiplier = 4;
} else if (comboCounter >= 4) {
comboMultiplier = 3;
} else if (comboCounter >= 3) {
comboMultiplier = 2;
} else if (comboCounter >= 2) {
comboMultiplier = 1.5;
}
// Award points with combo multiplier
var pointsToAdd = Math.floor(basePoints * comboMultiplier);
updateScore(pointsToAdd);
// Show floating score text at center cell if available
if (centerCell && centerCell.row >= extraRows) {
var scorePopup = new Text2("+" + pointsToAdd, {
size: 60,
fill: 0xFF8800
});
scorePopup.anchor.set(0.5, 0.5);
scorePopup.x = centerCell.x;
scorePopup.y = centerCell.y;
game.addChild(scorePopup);
// Animate score popup
tween(scorePopup, {
y: scorePopup.y - 80,
alpha: 0
}, {
duration: 800,
onComplete: function onComplete() {
game.removeChild(scorePopup);
scorePopup.destroy();
}
});
}
// Stop any currently playing combo sounds before playing a new one
LK.getSound('Combo1').stop();
LK.getSound('Combo2').stop();
LK.getSound('Combo3').stop();
LK.getSound('Combo4').stop();
LK.getSound('Combo5').stop();
if (comboCounter >= 9) {
LK.getSound('Combo5').play();
} else if (comboCounter >= 6) {
LK.getSound('Combo4').play();
} else if (comboCounter >= 4) {
LK.getSound('Combo3').play();
} else if (comboCounter >= 3) {
LK.getSound('Combo2').play();
} else if (comboCounter >= 2) {
LK.getSound('Combo1').play();
}
}
var specialCell = null;
var isHorizontalMatch = false;
var isVerticalMatch = false;
for (var type in cellsByType) {
var typeCells = cellsByType[type];
if (typeCells.length >= 6) {
// Create green special meme for 6 or more matches
if (centerCell && centerCell.value === parseInt(type)) {
specialCell = centerCell;
} else {
specialCell = typeCells[0];
}
specialCell.isSpecial = true;
specialCell.specialType = 'green';
specialCell.beingDestroyed = false;
// Award bonus points for creating a green special meme
updateScore(100);
// Remove special cell from cells to destroy
visibleCellsToDestroy = visibleCellsToDestroy.filter(function (cell) {
return cell !== specialCell;
});
break; // Only create one special meme
} else if (typeCells.length === 5) {
// Create bomb special meme (blue)
if (centerCell && centerCell.value === parseInt(type)) {
specialCell = centerCell;
} else {
specialCell = typeCells[0];
}
specialCell.isSpecial = true;
specialCell.specialType = 'bomb';
specialCell.beingDestroyed = false;
// Award bonus points for creating a bomb special meme
updateScore(75);
// Remove special cell from cells to destroy
visibleCellsToDestroy = visibleCellsToDestroy.filter(function (cell) {
return cell !== specialCell;
});
break; // Only create one special meme
} else if (typeCells.length === 4) {
// Determine if match is horizontal or vertical
var allInSameRow = true;
var allInSameCol = true;
var firstCell = typeCells[0];
for (var i = 1; i < typeCells.length; i++) {
if (typeCells[i].row !== firstCell.row) {
allInSameRow = false;
}
if (typeCells[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 if it matches the type, otherwise use the first cell of this type
if (centerCell && centerCell.value === parseInt(type)) {
specialCell = centerCell;
} else {
specialCell = typeCells[0];
}
specialCell.isSpecial = true;
specialCell.specialType = isHorizontalMatch ? 'horizontal' : 'vertical';
specialCell.beingDestroyed = false;
// Award bonus points for creating a line-clearing special meme
updateScore(50);
// Remove special cell from cells to destroy
visibleCellsToDestroy = visibleCellsToDestroy.filter(function (cell) {
return cell !== specialCell;
});
break; // Only create one special meme
}
}
}
// 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 = 50;
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;
// Check if any of these cells are matched with a special meme
if (cell.isSpecial) {
// Special meme is being destroyed, activate its power
LK.setTimeout(function () {
cell.activateSpecialPower();
}, 100);
}
}
});
// If we have a special meme, apply the appropriate tint
if (specialCell && specialCell.isSpecial) {
if (specialCell.specialType === 'bomb') {
specialCell.sprite.tint = 0x0088FF; // Blue tint for bomb
} else if (specialCell.specialType === 'green') {
specialCell.sprite.tint = 0x00FF00; // Green tint for swap-destroy special meme
} else {
specialCell.sprite.tint = 0xFF8800; // Orange tint for others
}
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 = 15;
var constantDuration = 250;
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 = 15;
var constantDuration = 250;
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) {
// Group by meme type
var matchesByType = {};
newMatches.forEach(function (group) {
if (group.length > 0) {
var type = group[0].value;
if (!matchesByType[type]) {
matchesByType[type] = [];
}
matchesByType[type].push(group);
}
});
var newCellsToDestroy = [];
var newCellTracker = {};
// Process each type separately
for (var type in matchesByType) {
var typeGroups = matchesByType[type];
// Find a central cell for this type
var centerCell = null;
if (typeGroups.length > 0 && typeGroups[0].length > 0) {
// Pick the center of the first match group of this type
var matchGroup = typeGroups[0];
centerCell = matchGroup[Math.floor(matchGroup.length / 2)];
}
// Collect all cells of this type
var typeCells = [];
typeGroups.forEach(function (group) {
group.forEach(function (cell) {
var cellKey = cell.row + "_" + cell.col;
if (!newCellTracker[cellKey] && cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
typeCells.push(cell);
newCellTracker[cellKey] = true;
}
});
});
// Destroy cells of this type
if (typeCells.length) {
destroyCells(typeCells, centerCell);
}
}
if (Object.keys(matchesByType).length === 0) {
isAnimating = false;
}
} else {
isAnimating = false;
}
}, longestDelay + 50);
} else {
window.fillInProgress = false;
isAnimating = false;
// Reset combo tracking when no more matches are being created
comboInProgress = false;
comboCounter = 0;
}
}
// Handle game over events to return to menu
game.onGameOver = function () {
LK.setTimeout(function () {
// Clear the game board
while (gridContainer.children.length > 0) {
var child = gridContainer.children[0];
gridContainer.removeChild(child);
child.destroy();
}
if (scoreText) {
game.removeChild(scoreText);
scoreText = null;
}
// Show menu
initializeMenu();
}, 500);
};
function checkForAndDestroyMatches(swappedCellA, swappedCellB) {
if (window.gravityInProgress || window.fillInProgress) {
return;
}
var allMatchGroupsOnBoard = getMatches();
if (!allMatchGroupsOnBoard.length) {
// In Classic Mode, if no matches are found after a swap, revert the swap
if (game.gameMode === 'classic' && swappedCellA && swappedCellB) {
// Get original positions
var pos1_x = swappedCellA.x;
var pos1_y = swappedCellA.y;
var pos2_x = swappedCellB.x;
var pos2_y = swappedCellB.y;
var row1 = swappedCellA.row;
var col1 = swappedCellA.col;
var row2 = swappedCellB.row;
var col2 = swappedCellB.col;
// Swap back in grid data
gridCells[row1][col1] = swappedCellA;
gridCells[row2][col2] = swappedCellB;
swappedCellA.row = row1;
swappedCellA.col = col1;
swappedCellB.row = row2;
swappedCellB.col = col2;
// Animate swap back
tween(swappedCellA, {
x: pos2_x,
y: pos2_y
}, {
duration: 200
});
tween(swappedCellB, {
x: pos1_x,
y: pos1_y
}, {
duration: 200,
onComplete: function onComplete() {
isAnimating = false;
}
});
}
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;
}
return group.some(function (cellInGroup) {
return (cellInGroup === swappedCellA || cellInGroup === swappedCellB) && cellInGroup.row >= extraRows;
});
});
if (!relevantMatchGroups.length) {
// In Classic Mode, if matches exist but none involve the swapped cells, revert the swap
if (game.gameMode === 'classic' && swappedCellA && swappedCellB) {
// Get original positions
var pos1_x = swappedCellA.x;
var pos1_y = swappedCellA.y;
var pos2_x = swappedCellB.x;
var pos2_y = swappedCellB.y;
var row1 = swappedCellA.row;
var col1 = swappedCellA.col;
var row2 = swappedCellB.row;
var col2 = swappedCellB.col;
// Swap back in grid data
gridCells[row1][col1] = swappedCellA;
gridCells[row2][col2] = swappedCellB;
swappedCellA.row = row1;
swappedCellA.col = col1;
swappedCellB.row = row2;
swappedCellB.col = col2;
// Animate swap back
tween(swappedCellA, {
x: pos2_x,
y: pos2_y
}, {
duration: 200
});
tween(swappedCellB, {
x: pos1_x,
y: pos1_y
}, {
duration: 200,
onComplete: function onComplete() {
isAnimating = false;
}
});
}
return;
}
// Group by meme type
var matchesByType = {};
relevantMatchGroups.forEach(function (group) {
if (group.length > 0) {
var type = group[0].value;
if (!matchesByType[type]) {
matchesByType[type] = [];
}
matchesByType[type].push(group);
}
});
var uniqueCellTracker = {};
var cellsToDestroy = [];
// Process each type separately
for (var type in matchesByType) {
var typeGroups = matchesByType[type];
// Flatten all groups of this type
var typeCells = [];
typeGroups.forEach(function (group) {
group.forEach(function (cell) {
if (cell.row >= extraRows) {
typeCells.push(cell);
}
});
});
// Add each cell of this type to cellsToDestroy
typeCells.forEach(function (cell) {
var cellKey = cell.row + "_" + cell.col;
if (!uniqueCellTracker[cellKey] && cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
cellsToDestroy.push(cell);
uniqueCellTracker[cellKey] = true;
}
});
}
;
if (cellsToDestroy.length) {
// 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) {
// Group by meme type
var matchesByType = {};
newMatches.forEach(function (group) {
if (group.length > 0) {
var type = group[0].value;
if (!matchesByType[type]) {
matchesByType[type] = [];
}
matchesByType[type].push(group);
}
});
// Process each type separately
for (var type in matchesByType) {
var typeGroups = matchesByType[type];
var newCellsToDestroy = [];
var newCellTracker = {};
// Collect all cells of this type
typeGroups.forEach(function (group) {
group.forEach(function (cell) {
var cellKey = cell.row + "_" + cell.col;
if (!newCellTracker[cellKey] && cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell) {
newCellsToDestroy.push(cell);
newCellTracker[cellKey] = true;
}
});
});
if (newCellsToDestroy.length) {
// Find center cell of this type
var centerCell = newCellsToDestroy[Math.floor(newCellsToDestroy.length / 2)];
destroyCells(newCellsToDestroy, centerCell);
}
}
}
}, 400);
}
}
var gridSize = 8;
var extraRows = 9;
var cellSpacing = 10;
var cellSize = 208;
var gridCells = [];
var totalGridWidth = gridSize * cellSize + (gridSize - 1) * cellSpacing;
var totalVisibleGridHeight = totalGridWidth;
var totalGridHeight = totalVisibleGridHeight + extraRows * (cellSize + cellSpacing);
var startX = (2048 - totalGridWidth) / 2 + cellSize / 2;
var startY = (-1300 - totalVisibleGridHeight) / 2 + cellSize / 2 + extraRows * (cellSize + cellSpacing);
function getCellPosition(row, col) {
return {
x: startX + col * (cellSize + cellSpacing),
y: startY + row * (cellSize + cellSpacing) - extraRows * (cellSize + cellSpacing)
};
}
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;
}
}
}
// Initialize menu instead of directly starting the game
initializeMenu();
function ensureNoInitialMatches() {
var matches = getMatches();
if (matches.length > 0) {
matches.forEach(function (group) {
group.forEach(function (cell) {
var currentValue = cell.value;
var newValue;
do {
newValue = Math.floor(Math.random() * 5) + 1;
} while (newValue === currentValue);
cell.setValue(newValue);
});
});
ensureNoInitialMatches();
}
}
ensureNoInitialMatches(); ===================================================================
--- original.js
+++ change.js
@@ -347,13 +347,13 @@
duration: 100
});
};
// Update method called every frame
- self.update = function () {
+ self.update = function (deltaTime) {
if (!self.active) return;
- // Use LK.deltaTime instead of assuming fixed framerate
- // deltaTime is in milliseconds, convert to seconds
- self.currentTime -= 1 / 60 * (1000 / 16.67); // Normalize to 60fps equivalent
+ // Use deltaTime for accurate timing regardless of frame rate
+ var seconds = deltaTime ? deltaTime / 1000 : 1 / 60;
+ self.currentTime -= seconds;
// Check if we crossed a whole second boundary for display update
var currentWholeSecond = Math.ceil(self.currentTime);
if (currentWholeSecond !== self.lastWholeSecond) {
self.lastWholeSecond = currentWholeSecond;
@@ -447,12 +447,12 @@
// Initialize the game grid
initializeGrid();
ensureNoInitialMatches();
// Main game update loop
- game.update = function () {
+ game.update = function (deltaTime) {
// Update timer in Fast mode
if (game.gameMode === 'fast' && game.timer) {
- game.timer.update();
+ game.timer.update(deltaTime);
}
};
gameInitialized = true;
};
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