User prompt
arregla el bug que hace que se siga viendo BGmeme al salir de los modos de juego
User prompt
haz que bgmemes no aparezca en menu de incio
User prompt
haz que bgmemes desaparezca al cambiar de menus
User prompt
agrega una transición al cambiar de menus ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
agrega una pequeña transición rapida al cambiar de menus ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bgmemes se sigue viendo al cambiar de menu
User prompt
haz que al romper un memes salgan partículas con velocidad aleatoria, direcciónes aleatorias, muy corta duración y que cambien con colores rgb ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
dale un poco más de diley a las ropturas
Code edit (1 edits merged)
Please save this source code
User prompt
aumenta el dilei de los combos y disminuye el de las habilidades
User prompt
aumenta el diley de roptura de los memes en habilidades especiales y combos
Code edit (1 edits merged)
Please save this source code
User prompt
Agrega detras de los las cuadriculas de memes, en los modos de juegos, un bgmemes con el asset Bg3 con la transparencia al 0.5
User prompt
Agrega detras de los memes en los modos de juegos un bgmemes con el asset Bg3 con la transparencia al 0.5
User prompt
Agrega un fondo negro con 0.7 de transparencia detras de llos memes
User prompt
haz que el tamaño de los objetos que posean el asset button sea modificable en el codigo
User prompt
agrega detrás de las cuadriculas de memes un bgmemes con el asset button con transparencia al 0.3
User prompt
haz que al juntar la habilidad verde con roja o azul, se haga un efecto domino donde se activan las habilidades una por una en vez de todas a la vez
User prompt
crea un sistema para priorizar las flag. Primero se espera que caigan por gravedad, luego que se activen las habilidades y al final que se rompan por combinación
User prompt
crea un sistema para priorizar las flag. Primero se espera que caigan por gravedad, luego que se activen las habilidades y al final que se rompan por combinación
User prompt
agrega nuevas flag, haz que la habilidad especial no se roma al juntarlo y que al finalizar la animación de caida que se active su habilidad como prioridad
User prompt
haz que los memes especiales tengan un pequeño diley en activar sus habilidades
User prompt
baja los botones del menu 400 pixeles
User prompt
Haz que al tener seleccionado un meme si puntero es mayor a 100 pixeles (en cualquier posicion vertical y horizontal) cambia su posición con el meme de dicho lado
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'var cell = gridCells[row][col];' Line Number: 2869
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScoreClassic: 0, highScoreFast: 0, highScoreSeek: 0 }); /**** * Classes ****/ var CosmeticsScreen = Container.expand(function () { var self = Container.call(this); var title = new Text2("Cosmetics", { size: 150, fill: 0x000000 }); title.anchor.set(0.5, 0); title.x = 2048 / 2; title.y = 300; self.addChild(title); title.y = 200; self.cosmeticsGrid = new Container(); self.addChild(self.cosmeticsGrid); var cosmeticSets = [{ id: 1, name: "Default", memePrefix: 'meme' }, { id: 2, name: "Variant 1", memePrefix: 'meme1-2' }, { id: 3, name: "Variant 2", memePrefix: 'meme1-3' }]; var cardWidth = 550; var cardHeight = 680; var cardsPerRow = 3; var cardSpacing = 50; var startX = (2048 - (cardsPerRow * cardWidth + (cardsPerRow - 1) * cardSpacing)) / 2 + cardWidth / 2; var startY = 700; cosmeticSets.forEach(function (set, index) { var row = Math.floor(index / cardsPerRow); var col = index % cardsPerRow; var card = new Container(); card.x = startX + col * (cardWidth + cardSpacing); card.y = startY + row * (cardHeight + 80); var cardShadow = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.6, scaleY: 3.6 }); cardShadow.tint = 0x000000; cardShadow.alpha = 0.3; cardShadow.x = 10; cardShadow.y = 10; var cardBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 3.5 }); cardBg.tint = 0xFFFFFF; var nameText = new Text2(set.name, { size: 70, fill: 0x000000 }); nameText.anchor.set(0.5, 0); nameText.y = -cardHeight / 2 + 80; var setLabel = new Text2("MEME SET", { size: 40, fill: 0x555555 }); setLabel.anchor.set(0.5, 1); setLabel.y = cardHeight / 2 - 40; function animateCard() { tween(card, { y: card.y - 10 }, { duration: 800, easing: tween.easeInOutQuad, onComplete: function onComplete() { tween(card, { y: card.y + 10 }, { duration: 800, easing: tween.easeInOutQuad, onComplete: animateCard }); } }); } LK.setTimeout(animateCard, Math.random() * 1000); var previewContainer = new Container(); var previewSize = 120; var previewSpacing = 20; var previewScale = 0.6; var previewsPerRow = 3; var previewGridWidth = previewsPerRow * previewSize + (previewsPerRow - 1) * previewSpacing; var previewStartX = -previewGridWidth / 2 + previewSize / 2; var previewStartY = -40; for (var i = 1; i <= 5; i++) { var row = Math.floor((i - 1) / previewsPerRow); var col = (i - 1) % previewsPerRow; var preview; if (set.id === 1) { preview = LK.getAsset('meme' + i, { anchorX: 0.5, anchorY: 0.5, scaleX: previewScale, scaleY: previewScale }); } else if (set.id === 2) { preview = LK.getAsset('meme' + i + '-2', { anchorX: 0.5, anchorY: 0.5, scaleX: previewScale, scaleY: previewScale }); } else { preview = LK.getAsset('meme' + i + '-3', { anchorX: 0.5, anchorY: 0.5, scaleX: previewScale, scaleY: previewScale }); } preview.x = previewStartX + col * (previewSize + previewSpacing); preview.y = previewStartY + row * (previewSize + previewSpacing); var previewBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6, alpha: 0.1 }); previewBg.tint = 0x888888; previewBg.x = preview.x; previewBg.y = preview.y; previewContainer.addChild(previewBg); previewContainer.addChild(preview); } var statusOverlay = new Container(); card.statusOverlay = statusOverlay; var isSelected = set.id === 1; // Default always to set 1 if (isSelected) { var _pulseBorder = function pulseBorder() { tween(selectedBorder, { alpha: 0.2 }, { duration: 700, easing: tween.easeInOutQuad, onComplete: function onComplete() { tween(selectedBorder, { alpha: 0.5 }, { duration: 700, easing: tween.easeInOutQuad, onComplete: _pulseBorder }); } }); }; var selectedBorder = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.6, scaleY: 3.6 }); selectedBorder.tint = 0x00FF00; selectedBorder.alpha = 0.5; _pulseBorder(); var checkmark = LK.getAsset('check', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); checkmark.x = cardWidth / 2 - 70; checkmark.y = -cardHeight / 2 + 70; card.addChildAt(selectedBorder, 0); statusOverlay.addChild(checkmark); } card.addChild(cardShadow); card.addChild(cardBg); card.addChild(nameText); card.addChild(setLabel); card.addChild(previewContainer); card.addChild(statusOverlay); card.interactive = true; card.setId = set.id; card.isUnlocked = true; card.price = set.price; card.down = function (x, y, obj) { LK.effects.flashObject(cardBg, 0xFFFFFF, 200); LK.getSound('ButtonSound').play(); // No storage for selected set self.cosmeticsGrid.children.forEach(function (otherCard) { otherCard.children.forEach(function (child) { if (child.tint === 0x00FF00 && child !== cardBg) { otherCard.removeChild(child); } }); if (otherCard.statusOverlay) { while (otherCard.statusOverlay.children.length > 0) { otherCard.statusOverlay.removeChild(otherCard.statusOverlay.children[0]); } } }); var selectedBorder = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.6, scaleY: 3.6 }); selectedBorder.tint = 0x00FF00; var checkmark = LK.getAsset('check', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); checkmark.x = cardWidth / 2 - 70; checkmark.y = -cardHeight / 2 + 70; checkmark.isCheckmark = true; card.addChildAt(selectedBorder, 0); statusOverlay.addChild(checkmark); }; self.cosmeticsGrid.addChild(card); }); var backButton = createButton("BACK TO MENU", 0xFF5500, 3, 1.5, function () { if (transitionInProgress) return; showTransition(function () { game.removeChild(self); initializeMenu(); }); }, 2048 / 2, 2732 - 200); self.addChild(backButton); return self; }); 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; if (game && game.gameMode === 'seekmode' && game.seekModeForceSeekSprite) { spriteId = 'seek'; } else { // Default to meme set 1 var selectedSet = 1; if (selectedSet === 1) { spriteId = 'meme' + newValue; } else if (selectedSet === 2) { spriteId = 'meme' + newValue + '-2'; } else if (selectedSet === 3) { spriteId = 'meme' + newValue + '-3'; } else { spriteId = 'meme' + newValue; } } self.sprite = LK.getAsset(spriteId, { anchorX: 0.5, anchorY: 0.5 }); var padding = 20; var maxWidth = cellSize - padding * 2; var maxHeight = cellSize - padding * 2; var scaleX = maxWidth / self.sprite.width; var scaleY = maxHeight / self.sprite.height; var scale = Math.min(scaleX, scaleY); self.sprite.scale.set(scale, scale); self.addChild(self.sprite); if (self.isSpecial) { if (self.specialType === 'bomb') { self.sprite.tint = 0x0088FF; } else if (self.specialType === 'green') { self.sprite.tint = 0x00FF00; } else { self.sprite.tint = 0xFF8800; } } }; self.activateSpecialPower = function () { if (!self.isSpecial) { return; } var cellsToDestroy = []; var bonusPoints = 0; if (self.specialType === 'horizontal') { for (var row = extraRows; row < gridSize + extraRows; row++) { if (gridCells[row][self.col] && gridCells[row][self.col] !== self) { cellsToDestroy.push(gridCells[row][self.col]); } } bonusPoints = 100; } else if (self.specialType === 'vertical') { for (var col = 0; col < gridSize; col++) { if (gridCells[self.row][col] && gridCells[self.row][col] !== self) { cellsToDestroy.push(gridCells[self.row][col]); } } bonusPoints = 100; } else if (self.specialType === 'bomb') { 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]); } } } bonusPoints = 150; } else if (self.specialType === 'green') { self.value = 99; // Ensure green special always has value 99 bonusPoints = 200; } // No score pop-up needed if (cellsToDestroy.length > 0) { destroyCells(cellsToDestroy); 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(); var highlight = LK.getAsset('cuadricula', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.15, scaleY: 1.15, alpha: 0.6 }); highlight.tint = 0x00FFFF; self.selectionHighlight.addChild(highlight); self.addChildAt(self.selectionHighlight, 0); 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 MemeParticle = Container.expand(function () { var self = Container.call(this); self.init = function (textureId) { self.textureId = textureId; if (self.sprite) { self.removeChild(self.sprite); } self.sprite = self.attachAsset(self.textureId, { anchorX: 0.5, anchorY: 0.5 }); self.alpha = 0.8; self.scale.set(0.5); self.speedX = (Math.random() - 0.5) * 1; self.speedY = 0.5 + Math.random() * 0.5; self.rotationSpeed = (Math.random() - 0.5) * 0.05; return self; }; self.update = function () { self.x += self.speedX; self.y += self.speedY; self.rotation += self.rotationSpeed; if (self.y > 2732 + 100 || self.x < -100 || self.x > 2048 + 100) { self.destroy(); } }; return self; }); var MenuScreen = Container.expand(function () { var self = Container.call(this); var title = self.attachAsset('titulo', { anchorX: 0.5, anchorY: 0, scaleX: 3, scaleY: 3 }); title.x = 2048 / 2; title.y = 300; function pulseTitle() { tween(title, { scaleX: 3.2, scaleY: 3.4, y: 200 }, { duration: 400, easing: tween.easeOutQuad, onFinish: function onFinish() { tween(title, { scaleX: 3.5, scaleY: 2.7, y: 350 }, { duration: 300, easing: tween.easeInQuad, onFinish: function onFinish() { tween(title, { rotation: -0.05, scaleX: 3.1, scaleY: 3.2, y: 320 }, { duration: 180, easing: tween.easeOutQuad, onFinish: function onFinish() { tween(title, { rotation: 0.05, scaleX: 3.2, scaleY: 3.1 }, { duration: 180, easing: tween.easeInOutQuad, onFinish: function onFinish() { tween(title, { rotation: 0, scaleX: 3, scaleY: 3, y: 300 }, { duration: 250, easing: tween.easeOutElastic, onFinish: function onFinish() { LK.setTimeout(pulseTitle, 800); } }); } }); } }); } }); } }); } pulseTitle(); // First column var classicButton = createButton("ZEN MODE", 0x00AA00, 3, 1.5, function () { self.startGame('classic'); }, 2048 / 4, 2732 / 2 + 400); self.addChild(classicButton); var seekModeButton = createButton("SEEK MODE", 0xDD5500, 3, 1.5, function () { self.startGame('seekmode'); }, 2048 / 4, 2732 / 2 + 700); self.addChild(seekModeButton); var fastButton = createButton("FAST MODE", 0x0088FF, 3, 1.5, function () { self.startGame('fast'); }, 2048 / 4, 2732 / 2 + 1000); self.addChild(fastButton); // Second column var cosmeticsButton = createButton("COSMETICS", 0x9932CC, 3, 1.5, function () { game.removeChild(self); showCosmeticsScreen(); }, 2048 * 3 / 4, 2732 / 2 + 400); self.addChild(cosmeticsButton); var recordsButton = createButton("RECORDS", 0xFFA500, 3, 1.5, function () { game.removeChild(self); showRecordsScreen(); }, 2048 * 3 / 4, 2732 / 2 + 700); self.addChild(recordsButton); var settingsButton = createButton("SETTINGS", 0x800080, 3, 1.5, function () { game.removeChild(self); showSettingsScreen(); }, 2048 * 3 / 4, 2732 / 2 + 1000); self.addChild(settingsButton); self.startGame = function (mode) { if (transitionInProgress) return; showTransition(function () { game.gameMode = mode || 'classic'; game.removeChild(self); game.initializeGame(); }); }; self.particleContainer = new Container(); self.addChildAt(self.particleContainer, 0); self.memeParticles = ['meme1', 'meme2', 'meme3', 'meme4', 'meme5', 'meme1-2', 'meme2-2', 'meme3-2', 'meme4-2', 'meme5-2', 'meme1-3', 'meme2-3', 'meme3-3', 'meme4-3', 'meme5-3']; self.particleTimer = LK.setInterval(function () { self.emitParticle(); }, 500); self.emitParticle = function () { var randomMemeId = self.memeParticles[Math.floor(Math.random() * self.memeParticles.length)]; var particle = new MemeParticle().init(randomMemeId); particle.x = Math.random() * 2048; particle.y = -50; self.particleContainer.addChild(particle); }; self.update = function () { self.particleContainer.children.forEach(function (particle) { if (particle && particle.update) { particle.update(); } }); }; self.destroy = function () { LK.clearInterval(self.particleTimer); self.particleTimer = null; self.particleContainer.destroy({ children: true }); self.particleContainer = null; Container.prototype.destroy.call(self); }; return self; }); var PauseButton = Container.expand(function () { var self = Container.call(this); var pauseIcon = self.attachAsset('Pause', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, // 0.8 * 1.5 = 1.2 scaleY: 1.2 }); var background = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.05, // 0.7 * 1.5 = 1.05 scaleY: 1.05 }); background.tint = 0x444444; background.alpha = 0.7; self.addChildAt(background, 0); self.down = function (x, y, obj) { LK.effects.flashObject(self, 0xFFFFFF, 200); LK.getSound('ButtonSound').play(); showPausePopup(); }; return self; }); var PausePopup = Container.expand(function () { var self = Container.call(this); var popupBg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 3.5, scaleY: 4.5 }); popupBg.tint = 0x222222; popupBg.alpha = 0.9; var popupTitle = new Text2("PAUSED", { size: 100, fill: 0xFFFFFF }); popupTitle.anchor.set(0.5, 0); popupTitle.y = -250; self.addChild(popupTitle); var continueButton = createButton("CONTINUE", 0x00AA00, 2.5, 1.2, function () { game.removeChild(self); }, 0, -20); self.addChild(continueButton); var surrenderButton = createButton("SURRENDER", 0xFF0000, 2.5, 1.2, function () { game.removeChild(self); game.onGameOver(); }, 0, 200); self.addChild(surrenderButton); return self; }); var RecordsScreen = Container.expand(function () { var self = Container.call(this); // Create title var title = new Text2("High Scores", { size: 150, fill: 0x000000 }); title.anchor.set(0.5, 0); title.x = 2048 / 2; title.y = 300; self.addChild(title); // Refresh high scores when shown self.refreshHighScores = function () { // Clear existing score texts if any if (self.classicScoreText) { self.removeChild(self.classicScoreText); self.classicScoreText = null; } if (self.fastScoreText) { self.removeChild(self.fastScoreText); self.fastScoreText = null; } if (self.seekScoreText) { self.removeChild(self.seekScoreText); self.seekScoreText = null; } // Create mode buttons with high scores function createModeButton(modeName, score, color, posY) { var button = new Container(); var buttonBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 4, scaleY: 1.5 }); buttonBg.tint = color; var modeText = new Text2(modeName, { size: 90, fill: 0xFFFFFF }); modeText.anchor.set(0.5, 0); modeText.y = -100; var scoreText = new Text2(score.toString(), { size: 70, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.y = 10; button.addChild(buttonBg); button.addChild(modeText); button.addChild(scoreText); button.x = 2048 / 2; button.y = posY; return button; } self.addChild(createModeButton("Zen Mode", highScoreClassic, 0x00AA00, 800)); self.addChild(createModeButton("Fast Mode", highScoreFast, 0x0088FF, 1100)); self.addChild(createModeButton("Seek Mode", highScoreSeek, 0xDD5500, 1400)); }; // Refresh scores when created self.refreshHighScores(); // Back button var backButton = createButton("BACK TO MENU", 0xFF5500, 3, 1.5, function () { if (transitionInProgress) return; showTransition(function () { game.removeChild(self); initializeMenu(); }); }, 2048 / 2, 2732 - 200); self.addChild(backButton); return self; }); var SeekMode = Container.expand(function () { var self = Container.call(this); // Similar to classic mode logic var gridContainer = new Container(); self.addChild(gridContainer); return self; }); var SettingsScreen = Container.expand(function () { var self = Container.call(this); var title = new Text2("Settings", { size: 150, fill: 0x000000 }); title.anchor.set(0.5, 0); title.x = 2048 / 2; title.y = 300; self.addChild(title); var resetButton = createButton("RESET PROGRESS", 0xFF0000, 3.7, 1.5, function () { // Show confirmation popup var confirmPopup = new Container(); // Enlarged popup background var popupBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 5.5, scaleY: 5.7 }); popupBg.tint = 0x222222; popupBg.alpha = 0.9; var popupTitle = new Text2("Reset all progress?", { size: 80, fill: 0xFFFFFF }); popupTitle.anchor.set(0.5, 0); popupTitle.y = -440; var popupText = new Text2("This will reset all high scores\nThis cannot be undone.", { size: 60, fill: 0xFFFFFF }); popupText.anchor.set(0.5, 0); popupText.y = -300; // Confirm and Cancel buttons, separated vertically var confirmButton = createButton("CONFIRM", 0xFF0000, 2.5, 1.2, function () { // Reset high scores highScoreClassic = 0; highScoreFast = 0; highScoreSeek = 0; storage.highScoreClassic = 0; storage.highScoreFast = 0; storage.highScoreSeek = 0; // Show confirmation message var messagePopup = new Container(); var messageBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 5.5, scaleY: 1.5 }); messageBg.tint = 0x00AA00; var messageText = new Text2("Progress reset successfully", { size: 80, fill: 0xFFFFFF }); messageText.anchor.set(0.5, 0.5); messagePopup.addChild(messageBg); messagePopup.addChild(messageText); messagePopup.x = 2048 / 2; messagePopup.y = 2732 / 2; game.addChild(messagePopup); // Remove message after 2 seconds LK.setTimeout(function () { game.removeChild(messagePopup); }, 2000); // Remove confirmation popup game.removeChild(confirmPopup); }, 0, 60); var cancelButton = createButton("CANCEL", 0x00AA00, 2.5, 1.2, function () { game.removeChild(confirmPopup); }, 0, 280); // Increased vertical separation confirmPopup.addChild(popupBg); confirmPopup.addChild(popupTitle); confirmPopup.addChild(popupText); confirmPopup.addChild(confirmButton); confirmPopup.addChild(cancelButton); confirmPopup.x = 2048 / 2; confirmPopup.y = 2732 / 2; game.addChild(confirmPopup); }, 2048 / 2, 2732 / 2); self.addChild(resetButton); var backButton = createButton("BACK TO MENU", 0xFF5500, 3, 1.5, function () { if (transitionInProgress) return; showTransition(function () { game.removeChild(self); initializeMenu(); }); }, 2048 / 2, 2732 - 200); self.addChild(backButton); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Add background asset to the game scene var backgroundAsset = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChildAt(backgroundAsset, 0); // --- Smoothly tween background color forever --- var colorTweenTargets = [0xffb347, 0x7ec8e3, 0x8aff80, 0xff80c0, 0xf9ff80, 0x80ffd9, 0xd1b3ff, 0xffffff, 0xffe066, 0x6ec6ff, 0xff6ec7, 0x6effb3, 0xff6666, 0x66ffea, 0x9d66ff, 0x66ff66, 0xffe6b3, 0xb3e6ff, 0xe6b3ff, 0xb3ffb3]; var currentColorIndex = 0; function tweenBackgroundToNextColor() { var nextIndex = (currentColorIndex + 1) % colorTweenTargets.length; var nextColor = colorTweenTargets[nextIndex]; tween(backgroundAsset, { tint: nextColor }, { duration: 14000, // much slower and smoother (was 7000) easing: tween.easeInOutQuad, onFinish: function onFinish() { currentColorIndex = nextIndex; tweenBackgroundToNextColor(); } }); } // Start the color tween loop backgroundAsset.tint = colorTweenTargets[0]; tweenBackgroundToNextColor(); // Game state and initialization var menuScreen; var cosmeticsScreen; var recordsScreen; var settingsScreen; var pausePopup; 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; var saveScoreInterval; // Interval for saving classic mode high score var seekMode; // Reference to seek mode instance // Game tracks scores in local variables, no global persistence var highScoreClassic = typeof storage.highScoreClassic === "number" ? storage.highScoreClassic : 0; // Zen Mode high score var highScoreFast = typeof storage.highScoreFast === "number" ? storage.highScoreFast : 0; // Fast Mode high score var highScoreSeek = typeof storage.highScoreSeek === "number" ? storage.highScoreSeek : 0; // Seek Mode high score // --- SEEK MODE: Block meme movement for 5 seconds and show countdown --- var seekModeBlockActive = false; var seekModeBlockTimer = null; var seekModeBlockSeconds = 5; var seekModeBlockText = null; // --- SEEK MODE: Combo tracking and visualization --- var seekModeComboCount = 0; var seekModeComboText = null; var seekModeShowAllTimer = null; // Function to show settings screen function showSettingsScreen() { if (transitionInProgress) return; showTransition(function () { // Remove bgmemes if it exists when leaving game modes if (game.bgmemes) { if (game.bgmemes.parent) { game.bgmemes.parent.removeChild(game.bgmemes); } if (game.bgmemes.destroy) { game.bgmemes.destroy(); } game.bgmemes = null; } if (!settingsScreen) { settingsScreen = new SettingsScreen(); } game.addChild(settingsScreen); }); } // Create a reusable button function function createButton(text, bgColor, width, height, callback, buttonX, buttonY) { var button = new Container(); var buttonBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: width || 3, scaleY: height || 1.5 }); buttonBg.tint = bgColor || 0x00AA00; var buttonText = new Text2(text, { size: 70, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); button.addChild(buttonBg); button.addChild(buttonText); // Add button interaction button.interactive = true; button.down = function (x, y, obj) { LK.effects.flashObject(buttonBg, 0xFFFFFF, 200); LK.getSound('ButtonSound').play(); if (callback) { LK.setTimeout(function () { callback(); }, 300); } }; // Store references for later access button.background = buttonBg; button.label = buttonText; // Set position if provided if (buttonX !== undefined) { button.x = buttonX; } if (buttonY !== undefined) { button.y = buttonY; } return button; } // Centralized initialization function for adding elements to the game function initializeGameElements() { // --- Agrega fondo bgmemes detrás de la cuadricula en modos de juego --- if ((game.gameMode === 'classic' || game.gameMode === 'fast' || game.gameMode === 'seekmode') && !game.bgmemes) { // Crea el asset Bg3 con transparencia 0.5 y lo coloca detrás de la cuadricula var bgmemes = LK.getAsset('Bg3', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 + 100, scaleX: 2.2, scaleY: 2.2 }); bgmemes.alpha = 0.5; game.bgmemes = bgmemes; // Asegura que esté detrás de la cuadricula game.addChildAt(bgmemes, 1); } // Create and add grid container if it doesn't exist if (!gridContainer) { gridContainer = new Container(); game.addChild(gridContainer); } // Create score text for all modes if (!scoreText) { scoreText = new Text2("Score: 0", { size: 120, fill: 0x222222 }); scoreText.anchor.set(0.5, 0); scoreText.x = 2048 / 2; scoreText.y = 80; game.addChild(scoreText); } // Create timer text for fast mode if needed if (game.gameMode === 'fast' && !timerText) { timerText = new Text2("Time: " + timerSeconds.toFixed(1), { size: 140, fill: 0xFF0000 }); timerText.anchor.set(0.5, 1); timerText.x = 2048 / 2; timerText.y = 2732 - 100; game.addChild(timerText); } // Add mode indicator text var modeTextContent = "Zen Mode"; var modeTextColor = 0x00AA00; if (game.gameMode === 'fast') { modeTextContent = "Fast Mode"; modeTextColor = 0x0088FF; } else if (game.gameMode === 'seekmode') { modeTextContent = "Seek Mode"; modeTextColor = 0xDD5500; } game.modeText = new Text2(modeTextContent, { size: 80, fill: modeTextColor }); game.modeText.anchor.set(0.5, 0); game.modeText.x = 2048 / 2; game.modeText.y = 180; game.addChild(game.modeText); // Add pause button to the top right corner in zen mode and seek mode if (game.gameMode === 'classic' || game.gameMode === 'seekmode') { game.pauseButton = new PauseButton(); // Add a 20px margin from the top and right edges game.pauseButton.x = 2048 - 100 - 45; game.pauseButton.y = 100 + 45; game.pauseButton.interactive = true; game.addChild(game.pauseButton); } } // Function to show pause popup function showPausePopup() { if (!pausePopup) { pausePopup = new PausePopup(); pausePopup.x = 2048 / 2; pausePopup.y = 2732 / 2; } game.addChild(pausePopup); // Fast Mode doesn't have pause functionality, so no need to pause the timer } // Show records screen function showRecordsScreen() { if (transitionInProgress) return; showTransition(function () { // Remove bgmemes if it exists when leaving game modes if (game.bgmemes) { if (game.bgmemes.parent) { game.bgmemes.parent.removeChild(game.bgmemes); } if (game.bgmemes.destroy) { game.bgmemes.destroy(); } game.bgmemes = null; } if (!recordsScreen) { recordsScreen = new RecordsScreen(); } // Make sure to refresh high scores every time the screen is shown if (recordsScreen.refreshHighScores) { recordsScreen.refreshHighScores(); } game.addChild(recordsScreen); }); } // Show cosmetics screen function showCosmeticsScreen() { if (transitionInProgress) return; showTransition(function () { // Remove bgmemes if it exists when leaving game modes if (game.bgmemes) { if (game.bgmemes.parent) { game.bgmemes.parent.removeChild(game.bgmemes); } if (game.bgmemes.destroy) { game.bgmemes.destroy(); } game.bgmemes = null; } if (!cosmeticsScreen) { cosmeticsScreen = new CosmeticsScreen(); } game.addChild(cosmeticsScreen); }); } // Initialize the menu // --- TRANSICIÓN DE MENÚ (FADE IN/OUT) --- var transitionOverlay = null; var transitionInProgress = false; function showTransition(callback) { if (transitionInProgress) return; transitionInProgress = true; if (!transitionOverlay) { transitionOverlay = LK.getAsset('transicion', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 1, scaleY: 1 }); transitionOverlay.alpha = 0; transitionOverlay.zIndex = 99999; } if (!game.children.includes(transitionOverlay)) { game.addChild(transitionOverlay); } // Fade in transitionOverlay.alpha = 0; tween(transitionOverlay, { alpha: 1 }, { duration: 350, easing: tween.easeInOutQuad, onFinish: function onFinish() { if (typeof callback === "function") callback(); // Fade out tween(transitionOverlay, { alpha: 0 }, { duration: 350, easing: tween.easeInOutQuad, onFinish: function onFinish() { if (transitionOverlay && transitionOverlay.parent) { game.removeChild(transitionOverlay); } transitionInProgress = false; } }); } }); } function initializeMenu() { if (transitionInProgress) return; showTransition(function () { // Remove bgmemes if it exists when leaving game modes if (game.bgmemes) { if (game.bgmemes.parent) { game.bgmemes.parent.removeChild(game.bgmemes); } if (game.bgmemes.destroy) { game.bgmemes.destroy(); } game.bgmemes = null; } if (!menuScreen) { menuScreen = new MenuScreen(); } game.addChild(menuScreen); }); } // Function to periodically save high score and manage music function startPeriodicSave() { // Clear any existing save interval if (saveScoreInterval) { LK.clearInterval(saveScoreInterval); saveScoreInterval = null; } // Save high score every second if it's better saveScoreInterval = LK.setInterval(function () { if (game.gameMode === 'classic' && score > highScoreClassic) { highScoreClassic = score; storage.highScoreClassic = highScoreClassic; } else if (game.gameMode === 'seekmode' && score > highScoreSeek) { highScoreSeek = score; storage.highScoreSeek = highScoreSeek; } }, 1000); // Start background music startBackgroundMusic(); } // Function to manage background music function startBackgroundMusic() { // Clear existing music interval if it exists if (game.musicInterval) { LK.clearInterval(game.musicInterval); game.musicInterval = null; } // Array of available music tracks var musicTracks = ['Backgroundmusic', 'backgroundmusic2']; // Function to play a random track function playRandomTrack() { var randomIndex = Math.floor(Math.random() * musicTracks.length); var selectedTrack = musicTracks[randomIndex]; // Play the selected track LK.playMusic(selectedTrack); console.log("Now playing: " + selectedTrack); } // Play initial track playRandomTrack(); // Set interval to change music every 1 minute and 20 seconds (80000 ms) game.musicInterval = LK.setInterval(playRandomTrack, 80000); } // Initialize the game game.initializeGame = function () { // Initialize score system score = 0; // Clear existing grid container if it exists if (gridContainer) { while (gridContainer.children.length > 0) { var child = gridContainer.children[0]; gridContainer.removeChild(child); child.destroy(); } } // 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; if (timerText) { timerText.setText("Time: " + maxTimer.toFixed(1)); } // Start timer countdown startTimer(); } // Centralize initialization of all game elements initializeGameElements(); // Initialize score initializeScore(); // Initialize the game grid initializeGrid(); ensureNoInitialMatches(); gameInitialized = true; // Start periodic save of high score for classic mode startPeriodicSave(); // --- SEEK MODE: Block meme movement for 5 seconds and show countdown --- if (game.gameMode === 'seekmode') { // Block meme movement seekModeBlockActive = true; seekModeBlockSeconds = 5; // Reset combo counter seekModeComboCount = 0; // Remove previous combo text if any if (seekModeComboText) { game.removeChild(seekModeComboText); seekModeComboText.destroy(); seekModeComboText = null; } // Remove previous block text if any if (seekModeBlockText) { game.removeChild(seekModeBlockText); seekModeBlockText.destroy(); seekModeBlockText = null; } // Create and show countdown text at bottom center, but a bit higher to leave space for combo text below seekModeBlockText = new Text2("Wait: " + seekModeBlockSeconds, { size: 120, fill: 0xDD5500, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); seekModeBlockText.anchor.set(0.5, 1); seekModeBlockText.x = 2048 / 2; seekModeBlockText.y = 2732 - 220; // Move up to leave space for combo text below game.addChild(seekModeBlockText); // Start countdown timer if (seekModeBlockTimer) { LK.clearInterval(seekModeBlockTimer); seekModeBlockTimer = null; } seekModeBlockTimer = LK.setInterval(function () { seekModeBlockSeconds--; if (seekModeBlockText) { seekModeBlockText.setText("Wait: " + seekModeBlockSeconds); } if (seekModeBlockSeconds <= 0) { seekModeBlockActive = false; if (seekModeBlockTimer) { LK.clearInterval(seekModeBlockTimer); seekModeBlockTimer = null; } if (seekModeBlockText) { game.removeChild(seekModeBlockText); seekModeBlockText.destroy(); seekModeBlockText = null; } // --- Set all current memes to use the 'seek' sprite --- for (var row = 0; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { var cell = gridCells[row][col]; if (cell && cell.sprite) { // Remove old sprite cell.removeChild(cell.sprite); // Attach new 'seek' sprite cell.sprite = LK.getAsset('seek', { anchorX: 0.5, anchorY: 0.5 }); // Scale to fit cell var padding = 20; var maxWidth = cellSize - padding * 2; var maxHeight = cellSize - padding * 2; var scaleX = maxWidth / cell.sprite.width; var scaleY = maxHeight / cell.sprite.height; var scale = Math.min(scaleX, scaleY); cell.sprite.scale.set(scale, scale); cell.addChild(cell.sprite); } } } // --- Mark that new memes should use 'seek' sprite --- game.seekModeForceSeekSprite = true; // Create combo counter text seekModeComboCount = 0; if (seekModeComboText) { game.removeChild(seekModeComboText); seekModeComboText.destroy(); } seekModeComboText = new Text2("Combos: 0/3", { size: 120, fill: 0xDD5500, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); seekModeComboText.anchor.set(0.5, 0); seekModeComboText.x = 2048 / 2; seekModeComboText.y = 2732 - 120; // Place just below the wait text game.addChild(seekModeComboText); } }, 1000); } else { // Clean up if not in seek mode seekModeBlockActive = false; if (seekModeBlockTimer) { LK.clearInterval(seekModeBlockTimer); seekModeBlockTimer = null; } if (seekModeBlockText) { game.removeChild(seekModeBlockText); seekModeBlockText.destroy(); seekModeBlockText = null; } // --- FIX: Reset seekModeForceSeekSprite so memes use correct sprite on re-enter --- game.seekModeForceSeekSprite = false; } }; // Create and position score text function initializeScore() { score = 0; if (scoreText) { scoreText.setText("Score: 0"); } } // Update score and score text function updateScore(points) { if (typeof points === "number" && points > 0) { score += points; if (scoreText) { 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) { // Bloquea romper y mover memes durante el periodo visible en seekmode if (isAnimating || window.gravityInProgress || window.fillInProgress || pausePopup && game.children.includes(pausePopup) || game.gameMode === 'seekmode' && (seekModeBlockActive || game.seekModeForceSeekSprite && seekModeComboText && seekModeComboText.text && seekModeComboText.text.indexOf('MEMES VISIBLE') === 0)) { return; } if (!tappedCell || !gridCells[tappedCell.row] || gridCells[tappedCell.row][tappedCell.col] !== tappedCell || tappedCell.beingDestroyed) { return; } 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; } // Assign a unique value to green special so it doesn't break when combined if (greenSpecialCell) { greenSpecialCell.value = 99; // Use a value outside the normal meme range (1-5) } if (twoGreenSpecials) { cell1.value = 99; cell2.value = 99; } // 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 || cell1.value === 99) { 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 && nextCell.value !== 99) { 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(); } // Award points for visible matches var pointsToAdd = 0; var visibleCellsToDestroy = cellsToDestroy.filter(function (cell) { return cell.row >= extraRows && cell && gridCells[cell.row] && gridCells[cell.row][cell.col] === cell; }); if (visibleCellsToDestroy.length > 0) { // 10 points per cell, bonus for combos pointsToAdd = visibleCellsToDestroy.length * 10; if (visibleCellsToDestroy.length >= 4) { pointsToAdd += 10; } if (visibleCellsToDestroy.length >= 5) { pointsToAdd += 20; } if (visibleCellsToDestroy.length >= 6) { pointsToAdd += 30; } updateScore(pointsToAdd); } // 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; } // Update seek mode combo counter if we're in seek mode if (game && game.gameMode === 'seekmode' && !seekModeBlockActive && game.seekModeForceSeekSprite) { seekModeComboCount++; // Create or update combo text if (!seekModeComboText) { seekModeComboText = new Text2("Combos: " + seekModeComboCount + "/3", { size: 120, fill: 0xDD5500, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); seekModeComboText.anchor.set(0.5, 0); seekModeComboText.x = 2048 / 2; seekModeComboText.y = 2732 - 120; // Place just below the wait text game.addChild(seekModeComboText); } else { seekModeComboText.setText("Combos: " + seekModeComboCount + "/3"); } // Check if we've reached 3 combos if (seekModeComboCount >= 3) { // Reset combo counter seekModeComboCount = 0; // Show all memes for 3 seconds for (var row = 0; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { var cell = gridCells[row][col]; if (cell && cell.sprite) { // Remove old seek sprite cell.removeChild(cell.sprite); // Attach original meme sprite based on value var selectedSet = 1; var spriteId; if (selectedSet === 1) { spriteId = 'meme' + cell.value; } else if (selectedSet === 2) { spriteId = 'meme' + cell.value + '-2'; } else if (selectedSet === 3) { spriteId = 'meme' + cell.value + '-3'; } else { spriteId = 'meme' + cell.value; } cell.sprite = LK.getAsset(spriteId, { anchorX: 0.5, anchorY: 0.5 }); // Scale to fit cell var padding = 20; var maxWidth = cellSize - padding * 2; var maxHeight = cellSize - padding * 2; var scaleX = maxWidth / cell.sprite.width; var scaleY = maxHeight / cell.sprite.height; var scale = Math.min(scaleX, scaleY); cell.sprite.scale.set(scale, scale); cell.addChild(cell.sprite); if (cell.isSpecial) { if (cell.specialType === 'bomb') { cell.sprite.tint = 0x0088FF; } else if (cell.specialType === 'green') { cell.sprite.tint = 0x00FF00; } else { cell.sprite.tint = 0xFF8800; } } } } } // Display countdown text if (seekModeComboText) { seekModeComboText.setText("MEMES VISIBLE: 3"); if (seekModeComboText.style) { seekModeComboText.style.size = 120; seekModeComboText.style.fill = 0xDD5500; seekModeComboText.style.font = "'GillSans-Bold',Impact,'Arial Black',Tahoma"; } seekModeComboText.y = 2732 - 120; // Ensure position is below wait text } // Start countdown var showAllSeconds = 3; var countdownInterval = LK.setInterval(function () { showAllSeconds--; if (seekModeComboText) { seekModeComboText.setText("MEMES VISIBLE: " + showAllSeconds); if (seekModeComboText.style) { seekModeComboText.style.size = 120; seekModeComboText.style.fill = 0xDD5500; seekModeComboText.style.font = "'GillSans-Bold',Impact,'Arial Black',Tahoma"; } seekModeComboText.y = 2732 - 120; // Ensure position is below wait text } if (showAllSeconds <= 0) { // Clear interval LK.clearInterval(countdownInterval); // Set all memes back to seek sprite for (var row = 0; row < gridSize + extraRows; row++) { for (var col = 0; col < gridSize; col++) { var cell = gridCells[row][col]; if (cell && cell.sprite) { // Remove old sprite cell.removeChild(cell.sprite); // Attach new 'seek' sprite cell.sprite = LK.getAsset('seek', { anchorX: 0.5, anchorY: 0.5 }); // Scale to fit cell var padding = 20; var maxWidth = cellSize - padding * 2; var maxHeight = cellSize - padding * 2; var scaleX = maxWidth / cell.sprite.width; var scaleY = maxHeight / cell.sprite.height; var scale = Math.min(scaleX, scaleY); cell.sprite.scale.set(scale, scale); cell.addChild(cell.sprite); // Preserve special tints if needed if (cell.isSpecial) { if (cell.specialType === 'bomb') { cell.sprite.tint = 0x0088FF; } else if (cell.specialType === 'green') { cell.sprite.tint = 0x00FF00; } else { cell.sprite.tint = 0xFF8800; } } } } } // Reset combo text if (seekModeComboText) { seekModeComboText.setText("Combos: 0/3"); if (seekModeComboText.style) { seekModeComboText.style.size = 120; seekModeComboText.style.fill = 0xDD5500; seekModeComboText.style.font = "'GillSans-Bold',Impact,'Arial Black',Tahoma"; } seekModeComboText.y = 2732 - 120; // Ensure position is below wait text } } }, 1000); } } // 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) { // Check if a special ability is currently being used before creating a green special var specialAbilityInUse = false; // Loop through all cells to check if any special is activated for (var r = 0; r < gridSize + extraRows; r++) { for (var c = 0; c < gridSize; c++) { if (gridCells[r] && gridCells[r][c] && gridCells[r][c].isSpecial && gridCells[r][c].beingDestroyed) { specialAbilityInUse = true; break; } } if (specialAbilityInUse) { break; } } // Only create a green special meme if no other special ability is in use if (!specialAbilityInUse) { // 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.value = 99; // Assign unique value for green special specialCell.value = 99; // Assign unique value for green special 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); // --- PARTICULAS DE MEME AL ROMPER --- for (var p = 0; p < 8; p++) { var particula = LK.getAsset('particula', { anchorX: 0.5, anchorY: 0.5, x: cell.x, y: cell.y }); // Color RGB aleatorio var r = Math.floor(Math.random() * 256); var g = Math.floor(Math.random() * 256); var b = Math.floor(Math.random() * 256); particula.tint = r << 16 | g << 8 | b; particula.alpha = 0.85; // Velocidad y dirección aleatoria var angle = Math.random() * Math.PI * 2; var speed = 7 + Math.random() * 7; particula._vx = Math.cos(angle) * speed; particula._vy = Math.sin(angle) * speed; // Animación de movimiento y desvanecimiento var duration = 220 + Math.random() * 120; var startX = particula.x; var startY = particula.y; var endX = startX + particula._vx * (duration / 16); var endY = startY + particula._vy * (duration / 16); tween(particula, { x: endX, y: endY, alpha: 0 }, { duration: duration, easing: tween.linear, onFinish: function (pt) { return function () { if (pt.parent) pt.parent.removeChild(pt); if (pt.destroy) pt.destroy(); }; }(particula) }); // Añadir la partícula al mismo contenedor que la celda if (gridContainer) gridContainer.addChild(particula); } // --- FIN PARTICULAS --- 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 = 25; 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); // Calculate duration based on distance var distance = Math.abs(newPos.y - fallInfo.cell.y); var duration = 100 + distance * 0.35; // Reduced base time + smaller distance multiplier for faster falls var totalTime = delay + duration; 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: duration, 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); timerInterval = null; } // 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; } // Only set timer to max when initializing new game, not when resuming if (!game.timerInitialized) { timerSeconds = maxTimer; game.timerInitialized = true; } // Update timer display initially if (timerText) { timerText.setText("Time: " + timerSeconds.toFixed(1)); } // Start countdown timer with decimals (100ms interval) timerInterval = LK.setInterval(function () { timerSeconds -= 0.1; timerSeconds = Math.max(0, parseFloat(timerSeconds.toFixed(1))); // Fix floating point issues // Update timer display if (timerText) { timerText.setText("Time: " + timerSeconds.toFixed(1)); } // Check for game over if (timerSeconds <= 0) { // Stop timer LK.clearInterval(timerInterval); timerInterval = null; // Instead of showing game over screen, trigger the custom game over game.onGameOver(); } }, 100); } 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 timerSeconds = maxTimer; if (timerText) { timerText.setText("Time: " + timerSeconds.toFixed(1)); } } } // Handle game over events to return to menu game.onGameOver = function () { // Save high score one last time if it's better if (game.gameMode === 'classic' && score > highScoreClassic) { highScoreClassic = score; storage.highScoreClassic = highScoreClassic; } else if (game.gameMode === 'fast' && score > highScoreFast) { highScoreFast = score; storage.highScoreFast = highScoreFast; } else if (game.gameMode === 'seekmode' && score > highScoreSeek) { highScoreSeek = score; storage.highScoreSeek = highScoreSeek; } // Stop timer if running if (timerInterval) { LK.clearInterval(timerInterval); timerInterval = null; } // Clean up seek mode block timer and text seekModeBlockActive = false; if (seekModeBlockTimer) { LK.clearInterval(seekModeBlockTimer); seekModeBlockTimer = null; } if (seekModeBlockText) { game.removeChild(seekModeBlockText); seekModeBlockText.destroy(); seekModeBlockText = null; } // Clean up seek mode combo counter and show-all timer if (seekModeComboText) { game.removeChild(seekModeComboText); seekModeComboText.destroy(); seekModeComboText = null; } if (seekModeShowAllTimer) { LK.clearTimeout(seekModeShowAllTimer); seekModeShowAllTimer = null; } seekModeComboCount = 0; // --- FIX: Reset seekModeForceSeekSprite so memes use correct sprite after game over --- game.seekModeForceSeekSprite = false; // Stop periodic save interval if (saveScoreInterval) { LK.clearInterval(saveScoreInterval); saveScoreInterval = null; } // Clear music interval if (game.musicInterval) { LK.clearInterval(game.musicInterval); game.musicInterval = null; // Stop any currently playing music LK.stopMusic(); } // Remove bgmemes if it exists when leaving game modes if (game.bgmemes) { if (game.bgmemes.parent) { game.bgmemes.parent.removeChild(game.bgmemes); } if (game.bgmemes.destroy) { game.bgmemes.destroy(); } game.bgmemes = null; } // For Fast Mode, show a custom high score popup instead of the game over screen if (game.gameMode === 'fast') { // Create popup container var popupContainer = new Container(); // Create popup background var popupBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 4, scaleY: 4.5 }); popupBg.tint = 0x0088FF; // Blue tint for Fast Mode // Create popup title var popupTitle = new Text2("GAME OVER", { size: 100, fill: 0xFFFFFF }); popupTitle.anchor.set(0.5, 0); popupTitle.y = -350; // Show current score in Fast Mode game over popup var currentScoreText = new Text2("Score: " + score, { size: 90, fill: 0xffffff }); currentScoreText.anchor.set(0.5, 0); currentScoreText.y = -200; // Show high score var highScoreText = new Text2("High Score: " + highScoreFast, { size: 90, fill: 0xFFFF00 }); highScoreText.anchor.set(0.5, 0); highScoreText.y = -100; // Update high score if needed if (score > highScoreFast) { highScoreFast = score; highScoreText.setText("High Score: " + score + " (New!)"); } // Create button to return to menu var menuButton = new Container(); var menuButtonBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 1.5 }); menuButtonBg.tint = 0xFF5500; var menuButtonText = new Text2("BACK TO MENU", { size: 70, fill: 0xFFFFFF }); menuButtonText.anchor.set(0.5, 0.5); menuButton.addChild(menuButtonBg); menuButton.addChild(menuButtonText); menuButton.y = 250; // Add all elements to popup popupContainer.addChild(popupBg); popupContainer.addChild(popupTitle); popupContainer.addChild(highScoreText); popupContainer.addChild(currentScoreText); popupContainer.addChild(menuButton); // Position popup in center of screen popupContainer.x = 2048 / 2; popupContainer.y = 2732 / 2; game.addChild(popupContainer); // Add button interaction menuButton.interactive = true; menuButton.down = function (x, y, obj) { LK.effects.flashObject(menuButtonBg, 0xFFFFFF, 200); // 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; } // Remove popup game.removeChild(popupContainer); // Clean up any game UI elements if (game.modeText) { game.removeChild(game.modeText); game.modeText = null; } if (game.pauseButton) { game.removeChild(game.pauseButton); game.pauseButton = null; } game.timerInitialized = false; // Show menu initializeMenu(); }; } else { // For Classic Mode, use the standard game over screen 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; } // Clean up any game UI elements if (game.modeText) { game.removeChild(game.modeText); game.modeText = null; } if (game.pauseButton) { game.removeChild(game.pauseButton); game.pauseButton = null; } game.timerInitialized = false; // 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 = 7; var extraRows = 9; var cellSpacing = 12; var cellSize = 240; 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 = (-1600 - 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; } } } // --- PUNTERO DRAG --- // Puntero visual que sigue el dedo mientras está presionado var pointerActive = false; var pointerSprite = LK.getAsset('Puntero', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); pointerSprite.visible = false; pointerSprite.zIndex = 9999; // Asegura que esté encima game.addChild(pointerSprite); // Evento down: activa el puntero y lo posiciona game.down = function (x, y, obj) { pointerActive = true; pointerSprite.visible = true; pointerSprite.x = x; pointerSprite.y = y; if (typeof handleCellTap === "function") { // Si hay una celda debajo, permite la selección normal // (esto mantiene la funcionalidad original) // handleCellTap puede ser llamada aquí si se desea } }; // Evento move: si está activo, sigue el dedo game.move = function (x, y, obj) { if (pointerActive) { pointerSprite.x = x; pointerSprite.y = y; // --- SWAP POR ARRASTRE --- if (selectedCell && gridCells[selectedCell.row] && gridCells[selectedCell.row][selectedCell.col] === selectedCell) { // Calcula la posición central de la celda seleccionada var cellPos = getCellPosition(selectedCell.row, selectedCell.col); var dx = x - cellPos.x; var dy = y - cellPos.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 100) { // Determina la dirección principal (horizontal o vertical) var dir; if (Math.abs(dx) > Math.abs(dy)) { dir = dx > 0 ? "right" : "left"; } else { dir = dy > 0 ? "down" : "up"; } var targetRow = selectedCell.row; var targetCol = selectedCell.col; if (dir === "right" && selectedCell.col < gridSize - 1) { targetCol++; } else if (dir === "left" && selectedCell.col > 0) { targetCol--; } else if (dir === "down" && selectedCell.row < gridSize + extraRows - 1) { targetRow++; } else if (dir === "up" && selectedCell.row > 0) { targetRow--; } else { // No hay celda adyacente válida return; } var targetCell = gridCells[targetRow][targetCol]; // Solo intercambia si la celda destino existe y no está siendo destruida if (targetCell && !targetCell.beingDestroyed) { // Llama a la lógica de swap como si se hubiera hecho tap en la celda adyacente handleCellTap(targetCell); } } } } }; // Evento up: desactiva el puntero game.up = function (x, y, obj) { pointerActive = false; pointerSprite.visible = false; }; // 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
@@ -859,8 +859,18 @@
// Function to show settings screen
function showSettingsScreen() {
if (transitionInProgress) return;
showTransition(function () {
+ // Remove bgmemes if it exists when leaving game modes
+ if (game.bgmemes) {
+ if (game.bgmemes.parent) {
+ game.bgmemes.parent.removeChild(game.bgmemes);
+ }
+ if (game.bgmemes.destroy) {
+ game.bgmemes.destroy();
+ }
+ game.bgmemes = null;
+ }
if (!settingsScreen) {
settingsScreen = new SettingsScreen();
}
game.addChild(settingsScreen);
@@ -908,9 +918,8 @@
}
// Centralized initialization function for adding elements to the game
function initializeGameElements() {
// --- Agrega fondo bgmemes detrás de la cuadricula en modos de juego ---
- // Solo agrega bgmemes si NO estamos en el menú de inicio
if ((game.gameMode === 'classic' || game.gameMode === 'fast' || game.gameMode === 'seekmode') && !game.bgmemes) {
// Crea el asset Bg3 con transparencia 0.5 y lo coloca detrás de la cuadricula
var bgmemes = LK.getAsset('Bg3', {
anchorX: 0.5,
@@ -993,8 +1002,18 @@
// Show records screen
function showRecordsScreen() {
if (transitionInProgress) return;
showTransition(function () {
+ // Remove bgmemes if it exists when leaving game modes
+ if (game.bgmemes) {
+ if (game.bgmemes.parent) {
+ game.bgmemes.parent.removeChild(game.bgmemes);
+ }
+ if (game.bgmemes.destroy) {
+ game.bgmemes.destroy();
+ }
+ game.bgmemes = null;
+ }
if (!recordsScreen) {
recordsScreen = new RecordsScreen();
}
// Make sure to refresh high scores every time the screen is shown
@@ -1007,8 +1026,18 @@
// Show cosmetics screen
function showCosmeticsScreen() {
if (transitionInProgress) return;
showTransition(function () {
+ // Remove bgmemes if it exists when leaving game modes
+ if (game.bgmemes) {
+ if (game.bgmemes.parent) {
+ game.bgmemes.parent.removeChild(game.bgmemes);
+ }
+ if (game.bgmemes.destroy) {
+ game.bgmemes.destroy();
+ }
+ game.bgmemes = null;
+ }
if (!cosmeticsScreen) {
cosmeticsScreen = new CosmeticsScreen();
}
game.addChild(cosmeticsScreen);
@@ -1063,8 +1092,18 @@
}
function initializeMenu() {
if (transitionInProgress) return;
showTransition(function () {
+ // Remove bgmemes if it exists when leaving game modes
+ if (game.bgmemes) {
+ if (game.bgmemes.parent) {
+ game.bgmemes.parent.removeChild(game.bgmemes);
+ }
+ if (game.bgmemes.destroy) {
+ game.bgmemes.destroy();
+ }
+ game.bgmemes = null;
+ }
if (!menuScreen) {
menuScreen = new MenuScreen();
}
game.addChild(menuScreen);
@@ -2584,8 +2623,18 @@
game.musicInterval = null;
// Stop any currently playing music
LK.stopMusic();
}
+ // Remove bgmemes if it exists when leaving game modes
+ if (game.bgmemes) {
+ if (game.bgmemes.parent) {
+ game.bgmemes.parent.removeChild(game.bgmemes);
+ }
+ if (game.bgmemes.destroy) {
+ game.bgmemes.destroy();
+ }
+ game.bgmemes = null;
+ }
// For Fast Mode, show a custom high score popup instead of the game over screen
if (game.gameMode === 'fast') {
// Create popup container
var popupContainer = new Container();
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