User prompt
mueve time text abajo, aumenta su tamaño y haz que baje con desimales incluidos para dar una sensación de adrenalina ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
haz que tarde muchisimo más en ir disminuyendo el máximo del contador de manera exponencial
User prompt
haz que tarde más en ir disminuyendo el maximo del contador
User prompt
haz que tarde más en ir disminuyendo el tiempo maximo
User prompt
Mientras más score se tenga el contador ira disminuyendo su maximo de 10 a 9, 8, etc hasta un minimo de 3
User prompt
agrega a fast mode un contador de 10 segundos cuando rompa memes este se reinicia a su maximo
User prompt
cuando combine memes que se reinicie a su maximo
User prompt
cuando rompa memes que se reinicie a su maximo
User prompt
agrega a fast mode un contador de 10 segundos
User prompt
Please fix the bug: 'Timeout.tick error: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'timerText.style.fill = 0x00FF00; // Green flash for bonus time' Line Number: 1392
User prompt
Please fix the bug: 'Timeout.tick error: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'timerText.style.fill = 0x0088FF; // Blue for normal' Line Number: 356
User prompt
características de fast mode: Habrá un contador de 10 segundos, cuando este llegue a 0 se pierde, la única forma de volver a conseguir el máximo es rompiendo memes. Mientras más score tengas el contador pasara de máximo 10 a 9 a 8, etc hasta un mínimo de 3. Si se hace un combo grande se agrega un extra de tiempo según el combo, pudiendo superar el máximo
User prompt
caracteristicas de fast mode: Habrá un contador de 10 segundos, cuando este llegue a 0 se pierde, la única forma de reiniciarlo es rompiendo memes. Mientras más score tenga el contador pasara de 10 a 9 a 8 etc hasta minimo de 3. SI se hace un combo grande se agrega un extra de tiempo segun el combo
User prompt
arregla la habilidad verde, no permite la caida de memes
User prompt
caracteristicas de classic mode: Solo se pueden mover los memes si se rompen, de no romperse volveran a su posición
User prompt
caracteristica de classic mode: Solo se pueden mover los memes si se rompen, de no romperse volverán a su posición
User prompt
Please fix the bug: 'Uncaught ReferenceError: pos2_x is not defined' in or related to this line: 'tween(cell1, {' Line Number: 808
User prompt
arregla la mecánica de regresar de posición los memes debido a los multiples errores
User prompt
arregla el bug que hace que no se pueda cambiar de posición con el de la izquierda cuando el meme regresa a su posición
User prompt
haz que el contador empiece en 10 y a medida que el record aumenta este disminuye hasta un minimo de 3 segundos
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
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
User prompt
arrefla el contador
User prompt
arregla contador, no dura realmente 10 segundos, usa delta time
/****
* 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;
});
/****
* 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
var timerText;
var timerSeconds = 10; // 10 seconds timer for Fast Mode
var timerInterval;
// 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') {
// Clear any existing timer
if (timerInterval) {
LK.clearInterval(timerInterval);
timerInterval = null;
}
// Calculate initial max timer value based on score
var maxTimer = 10;
// Use exponential thresholds for slower decrease
if (score >= 100) {
maxTimer = 9;
}
if (score >= 500) {
maxTimer = 8;
}
if (score >= 1000) {
maxTimer = 7;
}
if (score >= 3500) {
maxTimer = 6;
}
if (score >= 10000) {
maxTimer = 5;
}
if (score >= 25000) {
maxTimer = 4;
}
if (score >= 50000) {
maxTimer = 3;
}
// Reset timer value
timerSeconds = maxTimer;
// Create timer text if it doesn't exist
if (!timerText) {
timerText = new Text2("Time: " + maxTimer, {
size: 120,
fill: 0xFF0000
});
timerText.anchor.set(0.5, 0);
timerText.x = 2048 / 2;
timerText.y = 350;
game.addChild(timerText);
} else {
timerText.setText("Time: " + maxTimer);
}
// Start timer countdown
startTimer();
}
// Initialize the game grid
initializeGrid();
ensureNoInitialMatches();
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;
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;
}
// Reset timer if we're in Fast Mode and destroying visible cells
if (game.gameMode === 'fast' && visibleCells.length > 0) {
resetTimer();
}
// 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;
});
// 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;
}
}
// Timer management functions
function startTimer() {
// Clear any existing timer
if (timerInterval) {
LK.clearInterval(timerInterval);
}
// Calculate initial max timer value based on score
// This ensures proper timer initialization when starting a game with existing score
var maxTimer = 10;
// Use exponential thresholds for slower decrease
if (score >= 100) {
maxTimer = 9;
}
if (score >= 500) {
maxTimer = 8;
}
if (score >= 1000) {
maxTimer = 7;
}
if (score >= 3500) {
maxTimer = 6;
}
if (score >= 10000) {
maxTimer = 5;
}
if (score >= 25000) {
maxTimer = 4;
}
if (score >= 50000) {
maxTimer = 3;
}
timerSeconds = maxTimer;
// Update timer display initially
if (timerText) {
timerText.setText("Time: " + timerSeconds);
}
// Start countdown timer with decimals for more tension
var timerDecimal = timerSeconds * 10; // Convert to tenths of a second
timerInterval = LK.setInterval(function () {
timerDecimal--;
// Update timer display with decimal precision
if (timerText) {
var seconds = Math.floor(timerDecimal / 10);
var decimal = timerDecimal % 10;
timerText.setText("Time: " + seconds + "." + decimal);
}
// Check for game over
if (timerDecimal <= 0) {
// Stop timer
LK.clearInterval(timerInterval);
timerInterval = null;
// Trigger game over
LK.showGameOver();
}
}, 100); // Update every 100ms for smoother countdown
}
function resetTimer() {
// Only reset timer in Fast Mode
if (game.gameMode === 'fast') {
// Calculate max timer value based on score
// Start with 10 seconds, decrease as score increases, minimum of 3 seconds
var maxTimer = 10;
// Use exponential thresholds for slower decrease
if (score >= 100) {
maxTimer = 9;
}
if (score >= 500) {
maxTimer = 8;
}
if (score >= 1000) {
maxTimer = 7;
}
if (score >= 3500) {
maxTimer = 6;
}
if (score >= 10000) {
maxTimer = 5;
}
if (score >= 25000) {
maxTimer = 4;
}
if (score >= 50000) {
maxTimer = 3;
}
// Set timer to calculated max (with decimals)
timerSeconds = maxTimer;
if (timerText) {
timerText.setText("Time: " + Math.floor(timerSeconds) + ".0");
// Add animation when timer resets for more visual impact
tween(timerText, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOutQuad,
onComplete: function onComplete() {
tween(timerText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeInQuad
});
}
});
}
}
}
// Handle game over events to return to menu
game.onGameOver = function () {
// Stop timer if running
if (timerInterval) {
LK.clearInterval(timerInterval);
timerInterval = null;
}
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;
}
if (timerText) {
game.removeChild(timerText);
timerText = null;
}
// Show menu
initializeMenu();
}, 500);
};
function checkForAndDestroyMatches(swappedCellA, swappedCellB) {
if (window.gravityInProgress || window.fillInProgress) {
return;
}
var allMatchGroupsOnBoard = getMatches();
if (!allMatchGroupsOnBoard.length) {
return;
}
var relevantMatchGroups = allMatchGroupsOnBoard.filter(function (group) {
// Check if the match has cells in both visible and invisible areas
var visibleCells = group.filter(function (cell) {
return cell.row >= extraRows;
});
var invisibleCells = group.filter(function (cell) {
return cell.row < extraRows;
});
// Don't count groups with both visible and invisible cells unless there are at least 3 visible cells
if (visibleCells.length > 0 && invisibleCells.length > 0 && visibleCells.length < 3) {
return false;
}
return group.some(function (cellInGroup) {
return (cellInGroup === swappedCellA || cellInGroup === swappedCellB) && cellInGroup.row >= extraRows;
});
});
if (!relevantMatchGroups.length) {
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
@@ -311,40 +311,40 @@
}
// Calculate initial max timer value based on score
var maxTimer = 10;
// Use exponential thresholds for slower decrease
- if (score >= 1000) {
+ if (score >= 100) {
maxTimer = 9;
}
- if (score >= 5000) {
+ if (score >= 500) {
maxTimer = 8;
}
- if (score >= 20000) {
+ if (score >= 1000) {
maxTimer = 7;
}
- if (score >= 70000) {
+ if (score >= 3500) {
maxTimer = 6;
}
- if (score >= 200000) {
+ if (score >= 10000) {
maxTimer = 5;
}
- if (score >= 500000) {
+ if (score >= 25000) {
maxTimer = 4;
}
- if (score >= 1000000) {
+ if (score >= 50000) {
maxTimer = 3;
}
// Reset timer value
timerSeconds = maxTimer;
// Create timer text if it doesn't exist
if (!timerText) {
timerText = new Text2("Time: " + maxTimer, {
- size: 80,
+ size: 120,
fill: 0xFF0000
});
timerText.anchor.set(0.5, 0);
timerText.x = 2048 / 2;
- timerText.y = 250;
+ timerText.y = 350;
game.addChild(timerText);
} else {
timerText.setText("Time: " + maxTimer);
}
@@ -1340,77 +1340,97 @@
}
if (score >= 500) {
maxTimer = 8;
}
- if (score >= 2000) {
+ if (score >= 1000) {
maxTimer = 7;
}
- if (score >= 7000) {
+ if (score >= 3500) {
maxTimer = 6;
}
- if (score >= 20000) {
+ if (score >= 10000) {
maxTimer = 5;
}
- if (score >= 50000) {
+ if (score >= 25000) {
maxTimer = 4;
}
- if (score >= 100000) {
+ if (score >= 50000) {
maxTimer = 3;
}
timerSeconds = maxTimer;
// Update timer display initially
if (timerText) {
timerText.setText("Time: " + timerSeconds);
}
- // Start countdown timer
+ // Start countdown timer with decimals for more tension
+ var timerDecimal = timerSeconds * 10; // Convert to tenths of a second
timerInterval = LK.setInterval(function () {
- timerSeconds--;
- // Update timer display
+ timerDecimal--;
+ // Update timer display with decimal precision
if (timerText) {
- timerText.setText("Time: " + timerSeconds);
+ var seconds = Math.floor(timerDecimal / 10);
+ var decimal = timerDecimal % 10;
+ timerText.setText("Time: " + seconds + "." + decimal);
}
// Check for game over
- if (timerSeconds <= 0) {
+ if (timerDecimal <= 0) {
// Stop timer
LK.clearInterval(timerInterval);
timerInterval = null;
// Trigger game over
LK.showGameOver();
}
- }, 1000);
+ }, 100); // Update every 100ms for smoother countdown
}
function resetTimer() {
// Only reset timer in Fast Mode
if (game.gameMode === 'fast') {
// Calculate max timer value based on score
// Start with 10 seconds, decrease as score increases, minimum of 3 seconds
var maxTimer = 10;
// Use exponential thresholds for slower decrease
- if (score >= 1000) {
+ if (score >= 100) {
maxTimer = 9;
}
- if (score >= 5000) {
+ if (score >= 500) {
maxTimer = 8;
}
- if (score >= 20000) {
+ if (score >= 1000) {
maxTimer = 7;
}
- if (score >= 70000) {
+ if (score >= 3500) {
maxTimer = 6;
}
- if (score >= 200000) {
+ if (score >= 10000) {
maxTimer = 5;
}
- if (score >= 500000) {
+ if (score >= 25000) {
maxTimer = 4;
}
- if (score >= 1000000) {
+ if (score >= 50000) {
maxTimer = 3;
}
- // Set timer to calculated max
+ // Set timer to calculated max (with decimals)
timerSeconds = maxTimer;
if (timerText) {
- timerText.setText("Time: " + timerSeconds);
+ timerText.setText("Time: " + Math.floor(timerSeconds) + ".0");
+ // Add animation when timer resets for more visual impact
+ tween(timerText, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 200,
+ easing: tween.easeOutQuad,
+ onComplete: function onComplete() {
+ tween(timerText, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200,
+ easing: tween.easeInQuad
+ });
+ }
+ });
}
}
}
// Handle game over events to return to menu
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