User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'indexOf')' in or related to this line: 'if (child.textElement.text.indexOf('Change') >= 0 || child.textElement.text.indexOf('Changer') >= 0 || child.textElement.text.indexOf('Cambiar') >= 0 || child.textElement.text.indexOf('Cambia') >= 0 || child.textElement.text.indexOf('Schimbă') >= 0 || child.textElement.text.indexOf('Zmień') >= 0 || child.textElement.text.indexOf('Αλλαγή') >= 0 || child.textElement.text.indexOf('Spielsprache') >= 0 || child.textElement.text.indexOf('更改') >= 0 || child.textElement.text.indexOf('ゲーム言語') >= 0) {' Line Number: 1227
User prompt
Ajoute une fonctionnalité qui permet aux joueurs de changer la langue du jeu (par exemple si un joueur qui ne parle pas le français souhaite jouer et comprendre le jeu), la langue par défaut du jeu est le français, Mais le joueur doit pouvoir la changer pour sa propre langue en se rendant sur un écran de paramètre de choix de la langue du jeu, ce paramètre est accessible en appuyant sur un bouton rouge a texte blanc "Change the Game Language", disponible dans L'ui du jeu, le joueur peut personnalisé la langue du jeu , dans une liste de langues supportes par le jeu, Voici la liste : 1) anglais 2) allemand 3) japonais 4) italien 5) espagnol 6) chinois 7) grec 8) français 9) Roumain 10) Polonais (On pourra ajouter plus de langues supportés à la liste par la suite), le joueur peut changer la langue du jeu, quand il le veut avec la langue qu'il veut gratuitement, Cela assure que chaque joueur, même parlant une langue étrangère au français, puisse jouer au jeu dans sa propre langue La traduction du jeu traduit : Tout les textes du jeu (ui, menus, écrans etc..) dans la langue visé Le joueur sélectionne la langue dans laquelle il veut traduire le jeu, en appuyant sur un bouton "choice", affiche en face de chaque langue de la liste dans l'écran de paramètres des langues ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Je veux personnalisé le fond du jeu avec mon propre asset
User prompt
Please fix the bug: 'Uncaught TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 1011
User prompt
Please fix the bug: 'Uncaught ReferenceError: triggerLicoriceExplosion is not defined' in or related to this line: 'triggerLicoriceExplosion(self.row, self.col);' Line Number: 264
User prompt
Please fix the bug: 'TypeError: flower.moveTo is not a function' in or related to this line: 'flower.moveTo(flower.x, targetY, 300, function () {' Line Number: 666
User prompt
Ajoute une fonctionnalité de combo, Qui se déclenche lorsque le joueur réussit à associer 4 fleurs du même type , Une boule de réglisse s'affiche donc a l'écran dans la grille, et le joueur peut la faire exploser en appuyant dessus, Quand il le fait, toute une colonne de fleurs disparaît, et le jeu associe les fleurs alentour automatiquement pendant 8 secondes ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Fait en sorte que le bouton de reset se situe en haut a droite de l'écran du jeu
User prompt
Fait en sorte que le joueur puisse reset sa progression au niveau 1 en appuyant sur un boutton rouge "reset"
User prompt
Ajoute la musique du jeu en loop sur le jeu quand le joueur joue
User prompt
Fait en sorte que le joueur monte au niveau 2 quand il a finis 5 déplacements de disparition de fleurs ,puis après a chaque niveau supérieur il doit faire disparaitre 3 fleurs de plus que le niveau d'avant pour monter au niveau d'après
User prompt
Fait en sorte que le joueur puisse échanger les places des fleurs pour déplacer les fleurs
User prompt
Please fix the bug: 'Set is not a constructor' in or related to this line: 'var invalidTypes = new Set();' Line Number: 343
Code edit (1 edits merged)
Please save this source code
User prompt
Flowers Pop
Initial prompt
Crée ce jeu : **Titre du jeu** : *Flowers Pop* **Genre** : Jeu de réflexion / Match-3 **Description pour la création** : Dans *Flowers Pop*, le joueur doit associer des fleurs identiques pour les faire disparaître du plateau et gagner des points. ### Mécaniques du jeu : 1. **Plateau de jeu** : - Un plateau rempli aléatoirement de fleurs est généré au début de chaque niveau. - Les types de fleurs présents sont : **Tulipe**, **Coquelicot**, **Rose**, **Violette**, **Muguet**, **Yasmin** et **Lilas**. 2. **Règles d’association** : - Le joueur doit aligner **au moins 3 fleurs identiques** horizontalement ou verticalement pour les faire disparaître. - Quand les fleurs disparaissent, les fleurs du dessus tombent pour remplir les vides, et de nouvelles fleurs apparaissent en haut du plateau. 3. **Déplacements** : - Le joueur dispose de **50 déplacements maximum** par niveau. - À chaque mouvement (échanger deux fleurs voisines), 1 déplacement est consommé. 4. **Conditions de victoire** : - Le but est de **faire disparaître toutes les fleurs du plateau** avant d'avoir utilisé les 50 déplacements. 5. **Conditions de défaite** : - Si le joueur utilise ses 50 déplacements sans avoir éliminé toutes les fleurs, il doit **recommencer le jeu depuis le premier niveau**. 6. **Progression** : - Quand il n'y a plus aucune fleur sur le plateau, le joueur passe au **niveau suivant**. - À chaque nouveau niveau, un nouveau plateau de fleurs est généré automatiquement. 7. **Score** : - Chaque association de fleurs donne des points. (Exemple : +10 points par trio, +20 points pour 4 fleurs associées, etc.) 8. **Objectif final** : - Aller le plus loin possible en passant de niveau en niveau sans perdre. ### Contrôles : - Cliquer ou glisser pour échanger deux fleurs voisines. ### Détails graphiques : - Fleurs colorées et reconnaissables facilement. - Effets visuels quand les fleurs disparaissent. - Affichage du score et du nombre de déplacements restants en haut de l'écran. --- **Résumé rapide pour Upit** : > Créer un jeu d'association nommé *Flowers Pop* : > Associer 3 fleurs du même type pour les faire disparaître. Types de fleurs : tulipe, coquelicot, rose, violette, muguet, yasmin, lilas. > Plateau généré automatiquement à chaque niveau. > 50 déplacements maximum. > Si toutes les fleurs disparaissent avant d’avoir utilisé 50 déplacements, le joueur passe au niveau suivant. > Sinon, il recommence le jeu au niveau 1.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, currentLevel: 1 }); /**** * Classes ****/ var Flower = Container.expand(function (type) { var self = Container.call(this); self.type = type; self.isMatched = false; self.isMoving = false; // Create flower asset based on type var flowerGraphics = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.9, scaleY: 0.9 }); // Method to handle selection/deselection visual effect self.setSelected = function (selected) { if (selected) { tween(flowerGraphics, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200, easing: tween.easeOut }); } else { tween(flowerGraphics, { scaleX: 0.9, scaleY: 0.9 }, { duration: 200, easing: tween.easeOut }); } }; // Method to handle match animation self.animateMatch = function (callback) { self.isMatched = true; tween(flowerGraphics, { alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { if (callback) { callback(); } } }); }; // Method to move flower to a new position self.moveTo = function (newX, newY, duration, callback) { self.isMoving = true; tween(self, { x: newX, y: newY }, { duration: duration || 300, easing: tween.easeOut, onFinish: function onFinish() { self.isMoving = false; if (callback) { callback(); } } }); }; // Event handlers self.down = function (x, y, obj) { // Handle touch/click in game logic if (!self.isMatched && !self.isMoving && !gameOver) { selectFlower(self); } }; return self; }); var GameBoard = Container.expand(function (rows, cols, cellSize) { var self = Container.call(this); self.rows = rows; self.cols = cols; self.cellSize = cellSize; self.boardWidth = cols * cellSize; self.boardHeight = rows * cellSize; self.grid = []; // Create board background var boardBackground = self.attachAsset('board', { anchorX: 0.5, anchorY: 0.5, width: self.boardWidth, height: self.boardHeight }); // Initialize grid with cells self.initializeGrid = function () { // Create grid cells for (var row = 0; row < rows; row++) { self.grid[row] = []; for (var col = 0; col < cols; col++) { // Create cell background var cell = LK.getAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: cellSize - 10, height: cellSize - 10 }); // Position cell cell.x = col * cellSize - self.boardWidth / 2 + cellSize / 2; cell.y = row * cellSize - self.boardHeight / 2 + cellSize / 2; self.addChild(cell); self.grid[row][col] = null; // Will hold flower references } } }; // Add a flower to the grid at specified position self.addFlower = function (flower, row, col) { if (row >= 0 && row < rows && col >= 0 && col < cols) { self.grid[row][col] = flower; flower.row = row; flower.col = col; // Position flower in grid flower.x = col * cellSize - self.boardWidth / 2 + cellSize / 2; flower.y = row * cellSize - self.boardHeight / 2 + cellSize / 2; self.addChild(flower); return true; } return false; }; // Remove a flower from the grid self.removeFlower = function (row, col) { if (row >= 0 && row < rows && col >= 0 && col < cols) { var flower = self.grid[row][col]; if (flower) { self.grid[row][col] = null; return flower; } } return null; }; // Swap two flowers in the grid self.swapFlowers = function (row1, col1, row2, col2, animate, callback) { if (row1 < 0 || row1 >= rows || col1 < 0 || col1 >= cols || row2 < 0 || row2 >= rows || col2 < 0 || col2 >= cols) { return false; } var flower1 = self.grid[row1][col1]; var flower2 = self.grid[row2][col2]; if (!flower1 || !flower2) { return false; } // Update grid references self.grid[row1][col1] = flower2; self.grid[row2][col2] = flower1; // Update flower position properties flower1.row = row2; flower1.col = col2; flower2.row = row1; flower2.col = col1; if (animate) { // Calculate target positions var pos1 = { x: col2 * cellSize - self.boardWidth / 2 + cellSize / 2, y: row2 * cellSize - self.boardHeight / 2 + cellSize / 2 }; var pos2 = { x: col1 * cellSize - self.boardWidth / 2 + cellSize / 2, y: row1 * cellSize - self.boardHeight / 2 + cellSize / 2 }; // Animate the swap flower1.moveTo(pos1.x, pos1.y, 200); flower2.moveTo(pos2.x, pos2.y, 200, callback); } else { // Instantly swap positions flower1.x = col2 * cellSize - self.boardWidth / 2 + cellSize / 2; flower1.y = row2 * cellSize - self.boardHeight / 2 + cellSize / 2; flower2.x = col1 * cellSize - self.boardWidth / 2 + cellSize / 2; flower2.y = row1 * cellSize - self.boardHeight / 2 + cellSize / 2; if (callback) { callback(); } } return true; }; // Get flower at specific grid position self.getFlower = function (row, col) { if (row >= 0 && row < rows && col >= 0 && col < cols) { return self.grid[row][col]; } return null; }; // Check if coordinates are adjacent self.areAdjacent = function (row1, col1, row2, col2) { var rowDiff = Math.abs(row1 - row2); var colDiff = Math.abs(col1 - col2); // Adjacent if exactly one coordinate differs by 1 and the other is the same return rowDiff === 1 && colDiff === 0 || rowDiff === 0 && colDiff === 1; }; return self; }); // LicoriceBall class for combo feature var LicoriceBall = Container.expand(function (row, col) { var self = Container.call(this); self.row = row; self.col = col; self.isExploded = false; // Attach a licorice ball asset (use a unique color/shape for now) var licoriceGraphics = self.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 90, height: 90, color: 0x222222, tint: 0x222222 }); // Add a visual cue (e.g. a white "O" text) var licoriceText = new Text2('🍬', { size: 60, fill: 0xffffff }); licoriceText.anchor.set(0.5, 0.5); self.addChild(licoriceText); // Animate appearance licoriceGraphics.scaleX = 0.2; licoriceGraphics.scaleY = 0.2; tween(licoriceGraphics, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.bounceOut }); // Handle explosion on tap self.down = function (x, y, obj) { if (!self.isExploded && !isProcessingMatches && !gameOver) { self.isExploded = true; triggerLicoriceExplosion(self.row, self.col); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4CAF50 }); /**** * Game Code ****/ // Add custom background var customBackground = LK.getAsset('customBackground', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732 }); customBackground.x = 2048 / 2; customBackground.y = 2732 / 2; game.addChild(customBackground); // Language system var SUPPORTED_LANGUAGES = [{ code: 'fr', name: 'Français' }, { code: 'en', name: 'English' }, { code: 'de', name: 'Deutsch' }, { code: 'ja', name: '日本語' }, { code: 'it', name: 'Italiano' }, { code: 'es', name: 'Español' }, { code: 'zh', name: '中文' }, { code: 'el', name: 'Ελληνικά' }, { code: 'ro', name: 'Română' }, { code: 'pl', name: 'Polski' }]; var TRANSLATIONS = { fr: { score: 'Score: ', moves: 'Mouvements: ', level: 'Niveau: ', reset: 'RESET', changeLanguage: 'Changer la langue', chooseLanguage: 'Choisissez votre langue', choice: 'Choisir', back: 'Retour' }, en: { score: 'Score: ', moves: 'Moves: ', level: 'Level: ', reset: 'RESET', changeLanguage: 'Change the Game Language', chooseLanguage: 'Choose your language', choice: 'Choice', back: 'Back' }, de: { score: 'Punkte: ', moves: 'Züge: ', level: 'Level: ', reset: 'RESET', changeLanguage: 'Spielsprache ändern', chooseLanguage: 'Wählen Sie Ihre Sprache', choice: 'Wählen', back: 'Zurück' }, ja: { score: 'スコア: ', moves: '手数: ', level: 'レベル: ', reset: 'リセット', changeLanguage: 'ゲーム言語を変更', chooseLanguage: '言語を選択してください', choice: '選択', back: '戻る' }, it: { score: 'Punteggio: ', moves: 'Mosse: ', level: 'Livello: ', reset: 'RESET', changeLanguage: 'Cambia lingua del gioco', chooseLanguage: 'Scegli la tua lingua', choice: 'Scegli', back: 'Indietro' }, es: { score: 'Puntuación: ', moves: 'Movimientos: ', level: 'Nivel: ', reset: 'RESET', changeLanguage: 'Cambiar idioma del juego', chooseLanguage: 'Elige tu idioma', choice: 'Elegir', back: 'Volver' }, zh: { score: '分数: ', moves: '步数: ', level: '等级: ', reset: '重置', changeLanguage: '更改游戏语言', chooseLanguage: '选择您的语言', choice: '选择', back: '返回' }, el: { score: 'Σκορ: ', moves: 'Κινήσεις: ', level: 'Επίπεδο: ', reset: 'ΕΠΑΝΑΦΟΡΑ', changeLanguage: 'Αλλαγή γλώσσας παιχνιδιού', chooseLanguage: 'Επιλέξτε τη γλώσσα σας', choice: 'Επιλογή', back: 'Πίσω' }, ro: { score: 'Scor: ', moves: 'Mișcări: ', level: 'Nivel: ', reset: 'RESET', changeLanguage: 'Schimbă limba jocului', chooseLanguage: 'Alege limba ta', choice: 'Alege', back: 'Înapoi' }, pl: { score: 'Wynik: ', moves: 'Ruchy: ', level: 'Poziom: ', reset: 'RESET', changeLanguage: 'Zmień język gry', chooseLanguage: 'Wybierz swój język', choice: 'Wybierz', back: 'Wstecz' } }; var currentLanguage = storage.language || 'fr'; var languageMenuOpen = false; var languageMenuContainer = null; function getText(key) { return TRANSLATIONS[currentLanguage][key] || TRANSLATIONS['fr'][key] || key; } // Game constants var ROWS = 7; var COLS = 7; var CELL_SIZE = 100; var FLOWER_TYPES = ['tulip', 'poppy', 'rose', 'violet', 'lily', 'jasmine', 'lilac']; var MAX_MOVES = 50; // Game state variables var gameBoard; var selectedFlower = null; var movesLeft = MAX_MOVES; var currentScore = 0; var currentLevel = storage.currentLevel || 1; var highScore = storage.highScore || 0; var remainingFlowers = ROWS * COLS; var isProcessingMatches = false; var gameOver = false; var matchCounter = 0; var matchesRequiredForNextLevel = 5; // UI elements var scoreText; var movesText; var levelText; // Initialize game function initGame() { // Create game board gameBoard = new GameBoard(ROWS, COLS, CELL_SIZE); gameBoard.x = 2048 / 2; gameBoard.y = 2732 / 2; game.addChild(gameBoard); // Initialize the grid cells gameBoard.initializeGrid(); // Populate the board with flowers populateBoard(); // Create UI createUI(); // Set initial game state movesLeft = MAX_MOVES; currentScore = 0; remainingFlowers = ROWS * COLS; gameOver = false; matchCounter = 0; matchesRequiredForNextLevel = 5 + (currentLevel - 1) * 3; // 5 for level 1, +3 for each level // Update UI updateUI(); // Play background music LK.playMusic('bgmusic'); // Play background music LK.playMusic('bgmusic'); } // Create UI elements function createUI() { // Create score text scoreText = new Text2(getText('score') + '0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); // Anchored to top-right LK.gui.topRight.addChild(scoreText); // Create moves text movesText = new Text2(getText('moves') + movesLeft, { size: 60, fill: 0xFFFFFF }); movesText.anchor.set(0, 0); // Anchored to top-left // Don't place in top-left corner due to platform menu icon movesText.x = 120; LK.gui.topLeft.addChild(movesText); // Create level text levelText = new Text2(getText('level') + currentLevel + ' (' + matchCounter + '/' + matchesRequiredForNextLevel + ')', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); // Create language button var languageButton = new Container(); var languageBackground = languageButton.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 300, height: 60, tint: 0xFF0000 }); var languageText = new Text2(getText('changeLanguage'), { size: 35, fill: 0xFFFFFF }); languageText.anchor.set(0.5, 0.5); languageButton.addChild(languageText); languageButton.x = 0; languageButton.y = 120; LK.gui.top.addChild(languageButton); // Add event handler to language button languageButton.down = function (x, y, obj) { if (!languageMenuOpen) { showLanguageMenu(); } }; // Store reference for updates languageButton.textElement = languageText; // Create reset button var resetButton = new Container(); var resetBackground = resetButton.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 120, height: 60, tint: 0xFF0000 }); var resetText = new Text2(getText('reset'), { size: 40, fill: 0xFFFFFF }); resetText.anchor.set(0.5, 0.5); resetButton.addChild(resetText); resetButton.x = -150; resetButton.y = 50; LK.gui.topRight.addChild(resetButton); // Store reference for updates resetButton.textElement = resetText; // Add event handler to reset button resetButton.down = function (x, y, obj) { // Reset level to 1 currentLevel = 1; storage.currentLevel = 1; // Reset match counter and requirements matchCounter = 0; matchesRequiredForNextLevel = 5; // Reset game state and board gameOver = true; // To stop game processing temporarily // Clear the board for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS; col++) { var flower = gameBoard.removeFlower(row, col); if (flower) { flower.destroy(); } } } // Reset and restart the game initGame(); }; } // Update UI elements function updateUI() { scoreText.setText(getText('score') + currentScore); movesText.setText(getText('moves') + movesLeft); levelText.setText(getText('level') + currentLevel + ' (' + matchCounter + '/' + matchesRequiredForNextLevel + ')'); LK.setScore(currentScore); } // Populate the board with flowers function populateBoard() { // Create flowers and ensure no initial matches for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS; col++) { addNewFlower(row, col); } } // Check and resolve any initial matches var initialMatches = findAllMatches(); while (initialMatches.length > 0) { // If we have initial matches, regenerate those flowers for (var i = 0; i < initialMatches.length; i++) { var matchedFlower = gameBoard.removeFlower(initialMatches[i].row, initialMatches[i].col); if (matchedFlower) { matchedFlower.destroy(); addNewFlower(initialMatches[i].row, initialMatches[i].col); } } initialMatches = findAllMatches(); } } // Add a new flower at the specified position function addNewFlower(row, col) { // Choose a random flower type that doesn't create a match var validTypes = getValidFlowerTypes(row, col); var randomType = validTypes[Math.floor(Math.random() * validTypes.length)]; // Create a new flower and add it to the board var flower = new Flower(randomType); gameBoard.addFlower(flower, row, col); return flower; } // Get valid flower types that don't create a match at position function getValidFlowerTypes(row, col) { var invalidTypes = {}; // Use a regular object instead of Set // Check horizontal matches to avoid if (col >= 2) { var flower1 = gameBoard.getFlower(row, col - 1); var flower2 = gameBoard.getFlower(row, col - 2); if (flower1 && flower2 && flower1.type === flower2.type) { invalidTypes[flower1.type] = true; // Mark type as invalid } } // Check vertical matches to avoid if (row >= 2) { var flower1 = gameBoard.getFlower(row - 1, col); var flower2 = gameBoard.getFlower(row - 2, col); if (flower1 && flower2 && flower1.type === flower2.type) { invalidTypes[flower1.type] = true; // Mark type as invalid } } // Return valid types (all types minus invalid ones) return FLOWER_TYPES.filter(function (type) { return !invalidTypes[type]; // Check if type is in invalidTypes object }); } // Handle flower selection function selectFlower(flower) { if (isProcessingMatches || gameOver) { return; } if (selectedFlower === null) { // First selection selectedFlower = flower; selectedFlower.setSelected(true); LK.getSound('swap').play(); } else if (selectedFlower === flower) { // Deselect selectedFlower.setSelected(false); selectedFlower = null; } else { // Second selection - check if adjacent if (gameBoard.areAdjacent(selectedFlower.row, selectedFlower.col, flower.row, flower.col)) { // Try to swap trySwapFlowers(selectedFlower, flower); } else { // Not adjacent, switch selection selectedFlower.setSelected(false); selectedFlower = flower; selectedFlower.setSelected(true); LK.getSound('swap').play(); } } } // Try to swap flowers and check for matches function trySwapFlowers(flower1, flower2) { // Swap flowers var row1 = flower1.row; var col1 = flower1.col; var row2 = flower2.row; var col2 = flower2.col; // Deselect first flower flower1.setSelected(false); selectedFlower = null; // Swap to check for matches gameBoard.swapFlowers(row1, col1, row2, col2, true, function () { // Check for matches after swap var matches = findAllMatches(); if (matches.length > 0) { // Valid move - process matches decreaseMoves(); processMatches(matches); } else { // Invalid move - swap back LK.getSound('invalid').play(); gameBoard.swapFlowers(row2, col2, row1, col1, true); } }); } // Decrease moves and check game over function decreaseMoves() { movesLeft--; updateUI(); // Check if game is over if (movesLeft <= 0 && remainingFlowers > 0) { endGame(false); } } // Process all matches function processMatches(matches) { if (matches.length === 0) { return; } isProcessingMatches = true; // Calculate score based on match length var matchScore = 0; var matchCounts = {}; // Group matches by type matches.forEach(function (match) { var flower = gameBoard.getFlower(match.row, match.col); if (flower) { if (!matchCounts[flower.type]) { matchCounts[flower.type] = 0; } matchCounts[flower.type]++; } }); // Calculate score based on matches // Track licorice ball spawn positions var licoriceToSpawn = []; Object.keys(matchCounts).forEach(function (type) { var count = matchCounts[type]; if (count >= 5) { matchScore += count * 15; LK.getSound('match5').play(); } else if (count === 4) { matchScore += count * 10; LK.getSound('match4').play(); // Find the 4-in-a-row and mark for licorice ball spawn // Horizontal for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS - 3; col++) { var f1 = gameBoard.getFlower(row, col); var f2 = gameBoard.getFlower(row, col + 1); var f3 = gameBoard.getFlower(row, col + 2); var f4 = gameBoard.getFlower(row, col + 3); if (f1 && f2 && f3 && f4 && f1.type === type && f2.type === type && f3.type === type && f4.type === type) { // Place licorice ball at the second or third flower (centered) licoriceToSpawn.push({ row: row, col: col + 1 }); } } } // Vertical for (var col = 0; col < COLS; col++) { for (var row = 0; row < ROWS - 3; row++) { var f1 = gameBoard.getFlower(row, col); var f2 = gameBoard.getFlower(row + 1, col); var f3 = gameBoard.getFlower(row + 2, col); var f4 = gameBoard.getFlower(row + 3, col); if (f1 && f2 && f3 && f4 && f1.type === type && f2.type === type && f3.type === type && f4.type === type) { licoriceToSpawn.push({ row: row + 1, col: col }); } } } } else { matchScore += count * 5; LK.getSound('match3').play(); } // Count this as a successful match for level progression matchCounter++; }); // Update score currentScore += matchScore; remainingFlowers -= matches.length; // Animate matches and remove flowers var animationsCompleted = 0; matches.forEach(function (match) { var flower = gameBoard.getFlower(match.row, match.col); if (flower) { gameBoard.removeFlower(match.row, match.col); flower.animateMatch(function () { flower.destroy(); animationsCompleted++; // When all animations complete, make flowers fall and check for new matches if (animationsCompleted === matches.length) { // Spawn licorice balls if needed if (typeof licoriceToSpawn !== "undefined" && licoriceToSpawn.length > 0) { for (var i = 0; i < licoriceToSpawn.length; i++) { var pos = licoriceToSpawn[i]; // Only spawn if cell is empty (flower was matched) if (!gameBoard.getFlower(pos.row, pos.col)) { var licorice = new LicoriceBall(pos.row, pos.col); // Place licorice ball in grid (so it can be found for explosion) gameBoard.grid[pos.row][pos.col] = licorice; // Position licorice ball licorice.x = pos.col * CELL_SIZE - gameBoard.boardWidth / 2 + CELL_SIZE / 2; licorice.y = pos.row * CELL_SIZE - gameBoard.boardHeight / 2 + CELL_SIZE / 2; gameBoard.addChild(licorice); } } } updateUI(); makeFlowersFall(function () { fillEmptySpaces(function () { // Check for new matches after filling var newMatches = findAllMatches(); if (newMatches.length > 0) { processMatches(newMatches); } else { isProcessingMatches = false; // Check if player reached required match count if (matchCounter >= matchesRequiredForNextLevel) { // Level completed endGame(true); } else if (remainingFlowers <= 0) { // All flowers cleared (alternative win condition) endGame(true); } } }); }); } }); } }); } // Make flowers fall to fill empty spaces function makeFlowersFall(callback) { var animationsInProgress = 0; // Process columns bottom to top for (var col = 0; col < COLS; col++) { var emptySpaces = 0; // Process rows bottom to top for (var row = ROWS - 1; row >= 0; row--) { var flower = gameBoard.getFlower(row, col); if (!flower) { emptySpaces++; } else if (emptySpaces > 0) { // Move flower down by the number of empty spaces var newRow = row + emptySpaces; animationsInProgress++; // Update grid reference gameBoard.grid[row][col] = null; gameBoard.grid[newRow][col] = flower; // Update flower position properties flower.row = newRow; // Animate the fall var targetY = newRow * CELL_SIZE - gameBoard.boardHeight / 2 + CELL_SIZE / 2; if (typeof flower.moveTo === "function") { flower.moveTo(flower.x, targetY, 300, function () { animationsInProgress--; if (animationsInProgress === 0 && callback) { callback(); } }); } else { // Fallback for objects without moveTo (e.g. LicoriceBall) flower.y = targetY; animationsInProgress--; if (animationsInProgress === 0 && callback) { callback(); } } } } } if (animationsInProgress === 0 && callback) { callback(); } } // Fill empty spaces at the top with new flowers function fillEmptySpaces(callback) { var animationsInProgress = 0; for (var col = 0; col < COLS; col++) { // Find empty spaces at the top for (var row = 0; row < ROWS; row++) { if (!gameBoard.getFlower(row, col)) { // Create a new flower above the board var flower = new Flower(FLOWER_TYPES[Math.floor(Math.random() * FLOWER_TYPES.length)]); gameBoard.addFlower(flower, row, col); // Position it above the board flower.y -= (row + 1) * CELL_SIZE; // Animate it falling down animationsInProgress++; remainingFlowers++; var targetY = row * CELL_SIZE - gameBoard.boardHeight / 2 + CELL_SIZE / 2; flower.moveTo(flower.x, targetY, 300, function () { animationsInProgress--; if (animationsInProgress === 0 && callback) { callback(); } }); } } } if (animationsInProgress === 0 && callback) { callback(); } } // Find all matching flowers on the board function findAllMatches() { var matches = []; var visited = {}; // Check horizontal matches for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS - 2; col++) { var flower1 = gameBoard.getFlower(row, col); var flower2 = gameBoard.getFlower(row, col + 1); var flower3 = gameBoard.getFlower(row, col + 2); if (flower1 && flower2 && flower3 && flower1.type === flower2.type && flower2.type === flower3.type) { // Add match if not already added var key1 = row + "," + col; var key2 = row + "," + (col + 1); var key3 = row + "," + (col + 2); if (!visited[key1]) { matches.push({ row: row, col: col }); visited[key1] = true; } if (!visited[key2]) { matches.push({ row: row, col: col + 1 }); visited[key2] = true; } if (!visited[key3]) { matches.push({ row: row, col: col + 2 }); visited[key3] = true; } } } } // Check vertical matches for (var row = 0; row < ROWS - 2; row++) { for (var col = 0; col < COLS; col++) { var flower1 = gameBoard.getFlower(row, col); var flower2 = gameBoard.getFlower(row + 1, col); var flower3 = gameBoard.getFlower(row + 2, col); if (flower1 && flower2 && flower3 && flower1.type === flower2.type && flower2.type === flower3.type) { // Add match if not already added var key1 = row + "," + col; var key2 = row + 1 + "," + col; var key3 = row + 2 + "," + col; if (!visited[key1]) { matches.push({ row: row, col: col }); visited[key1] = true; } if (!visited[key2]) { matches.push({ row: row + 1, col: col }); visited[key2] = true; } if (!visited[key3]) { matches.push({ row: row + 2, col: col }); visited[key3] = true; } } } } return matches; } // Check if any valid moves exist function hasValidMoves() { // Check each position for potential swaps that create matches for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS; col++) { // Check right swap if (col < COLS - 1) { // Simulate swap right var flower1 = gameBoard.getFlower(row, col); var flower2 = gameBoard.getFlower(row, col + 1); if (flower1 && flower2) { // Swap gameBoard.swapFlowers(row, col, row, col + 1, false); // Check for matches var matches = findAllMatches(); // Swap back gameBoard.swapFlowers(row, col + 1, row, col, false); if (matches.length > 0) { return true; } } } // Check down swap if (row < ROWS - 1) { // Simulate swap down var flower1 = gameBoard.getFlower(row, col); var flower2 = gameBoard.getFlower(row + 1, col); if (flower1 && flower2) { // Swap gameBoard.swapFlowers(row, col, row + 1, col, false); // Check for matches var matches = findAllMatches(); // Swap back gameBoard.swapFlowers(row + 1, col, row, col, false); if (matches.length > 0) { return true; } } } } } return false; } // End the game function endGame(success) { gameOver = true; if (success) { // Level completed currentLevel++; storage.currentLevel = currentLevel; // Reset match counter and increase requirements for next level matchCounter = 0; matchesRequiredForNextLevel = 5 + (currentLevel - 1) * 3; // 5 for level 1, +3 for each level // Update high score if (currentScore > highScore) { highScore = currentScore; storage.highScore = highScore; } // Show you win screen LK.getSound('levelup').play(); LK.showYouWin(); } else { // Game over - ran out of moves currentLevel = 1; storage.currentLevel = currentLevel; // Update high score if (currentScore > highScore) { highScore = currentScore; storage.highScore = highScore; } // Show game over screen LK.showGameOver(); } } // Initialize the game initGame(); // Main game update loop game.update = function () { // If no valid moves exist, shuffle the board if (!isProcessingMatches && !gameOver && !hasValidMoves()) { // Shuffle the board var allFlowers = []; // Collect all flowers for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS; col++) { var flower = gameBoard.removeFlower(row, col); if (flower) { flower.destroy(); } } } // Repopulate the board populateBoard(); } }; // Handle touch/mouse input on game board game.down = function (x, y, obj) { // This is handled in the Flower class }; game.move = function (x, y, obj) { // Handle dragging of selected flower if (selectedFlower && !isProcessingMatches && !gameOver) { // Get position in gameBoard coordinates var localPos = gameBoard.toLocal({ x: x, y: y }); // Calculate which cell the player is hovering over var hoverCol = Math.floor((localPos.x + gameBoard.boardWidth / 2) / CELL_SIZE); var hoverRow = Math.floor((localPos.y + gameBoard.boardHeight / 2) / CELL_SIZE); // Check if it's a valid cell and adjacent to the original position if (hoverRow >= 0 && hoverRow < ROWS && hoverCol >= 0 && hoverCol < COLS && gameBoard.areAdjacent(selectedFlower.row, selectedFlower.col, hoverRow, hoverCol)) { // Get the flower at the hover position var targetFlower = gameBoard.getFlower(hoverRow, hoverCol); if (targetFlower && targetFlower !== selectedFlower) { // Try to swap the flowers trySwapFlowers(selectedFlower, targetFlower); } } } }; game.up = function (x, y, obj) { // No global up handling needed }; // Show language selection menu function showLanguageMenu() { if (languageMenuOpen) return; languageMenuOpen = true; // Create language menu container languageMenuContainer = new Container(); // Create background overlay var overlay = languageMenuContainer.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, tint: 0x000000, alpha: 0.8 }); // Create menu background var menuBackground = languageMenuContainer.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 1200, height: 1800, tint: 0xFFFFFF }); // Create title var titleText = new Text2(getText('chooseLanguage'), { size: 80, fill: 0x000000 }); titleText.anchor.set(0.5, 0.5); titleText.y = -700; languageMenuContainer.addChild(titleText); // Create language buttons var buttonStartY = -500; var buttonSpacing = 120; for (var i = 0; i < SUPPORTED_LANGUAGES.length; i++) { var lang = SUPPORTED_LANGUAGES[i]; var langButton = new Container(); // Button background var buttonBg = langButton.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 800, height: 100, tint: currentLanguage === lang.code ? 0x00FF00 : 0x808080 }); // Language name var langName = new Text2(lang.name, { size: 50, fill: 0x000000 }); langName.anchor.set(0, 0.5); langName.x = -300; langButton.addChild(langName); // Choice button var choiceButton = new Container(); var choiceBg = choiceButton.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 80, tint: 0x0066CC }); var choiceText = new Text2(getText('choice'), { size: 40, fill: 0xFFFFFF }); choiceText.anchor.set(0.5, 0.5); choiceButton.addChild(choiceText); choiceButton.x = 250; // Add choice button event choiceButton.languageCode = lang.code; choiceButton.down = function (x, y, obj) { selectLanguage(this.languageCode); }; langButton.addChild(choiceButton); langButton.y = buttonStartY + i * buttonSpacing; languageMenuContainer.addChild(langButton); } // Create back button var backButton = new Container(); var backBg = backButton.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5, width: 300, height: 100, tint: 0xFF0000 }); var backText = new Text2(getText('back'), { size: 50, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); backButton.addChild(backText); backButton.y = 700; backButton.down = function (x, y, obj) { hideLanguageMenu(); }; languageMenuContainer.addChild(backButton); // Position and add to game languageMenuContainer.x = 2048 / 2; languageMenuContainer.y = 2732 / 2; game.addChild(languageMenuContainer); } // Hide language menu function hideLanguageMenu() { if (languageMenuContainer) { languageMenuContainer.destroy(); languageMenuContainer = null; } languageMenuOpen = false; } // Select a language function selectLanguage(languageCode) { currentLanguage = languageCode; storage.language = languageCode; // Update all UI text updateAllUIText(); // Hide language menu hideLanguageMenu(); } // Update all UI text with current language function updateAllUIText() { // Update main UI updateUI(); // Update button texts var topContainer = LK.gui.top; for (var i = 0; i < topContainer.children.length; i++) { var child = topContainer.children[i]; if (child.textElement && child.textElement.text) { if (child.textElement.text.indexOf('Change') >= 0 || child.textElement.text.indexOf('Changer') >= 0 || child.textElement.text.indexOf('Cambiar') >= 0 || child.textElement.text.indexOf('Cambia') >= 0 || child.textElement.text.indexOf('Schimbă') >= 0 || child.textElement.text.indexOf('Zmień') >= 0 || child.textElement.text.indexOf('Αλλαγή') >= 0 || child.textElement.text.indexOf('Spielsprache') >= 0 || child.textElement.text.indexOf('更改') >= 0 || child.textElement.text.indexOf('ゲーム言語') >= 0) { child.textElement.setText(getText('changeLanguage')); } } } var topRightContainer = LK.gui.topRight; for (var i = 0; i < topRightContainer.children.length; i++) { var child = topRightContainer.children[i]; if (child.textElement && child.textElement.text) { if (child.textElement.text === 'RESET' || child.textElement.text === 'リセット' || child.textElement.text === 'ΕΠΑΝΑΦΟΡΑ' || child.textElement.text === '重置') { child.textElement.setText(getText('reset')); } } } } // Trigger the licorice explosion: remove all flowers in the column, trigger combo mode for 8 seconds function triggerLicoriceExplosion(row, col) { if (gameOver || isProcessingMatches) return; isProcessingMatches = true; // Remove all flowers in the column (except LicoriceBall itself) for (var r = 0; r < ROWS; r++) { var obj = gameBoard.getFlower(r, col); if (obj && !(obj instanceof LicoriceBall)) { gameBoard.removeFlower(r, col); if (typeof obj.animateMatch === "function") { obj.animateMatch(function () { obj.destroy(); }); } else { obj.destroy(); } remainingFlowers--; } } // Remove the LicoriceBall itself var licorice = gameBoard.getFlower(row, col); if (licorice && licorice instanceof LicoriceBall) { gameBoard.removeFlower(row, col); licorice.destroy(); } // Combo mode: for 8 seconds, after each match, auto-match adjacent flowers var comboEndTime = Date.now() + 8000; var originalProcessMatches = processMatches; var comboActive = true; // Helper to auto-match adjacent flowers after each match function comboProcessMatches(matches) { originalProcessMatches(matches); // After normal match processing, auto-match adjacent flowers if combo is still active if (comboActive && !gameOver) { LK.setTimeout(function () { var newMatches = []; // Find all adjacent pairs and add to matches for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS; col++) { var f = gameBoard.getFlower(row, col); if (!f || f instanceof LicoriceBall) continue; // Check right var fRight = gameBoard.getFlower(row, col + 1); if (fRight && fRight.type === f.type && !(fRight instanceof LicoriceBall)) { newMatches.push({ row: row, col: col }); newMatches.push({ row: row, col: col + 1 }); } // Check down var fDown = gameBoard.getFlower(row + 1, col); if (fDown && fDown.type === f.type && !(fDown instanceof LicoriceBall)) { newMatches.push({ row: row, col: col }); newMatches.push({ row: row + 1, col: col }); } } } // Remove duplicates var seen = {}; var uniqueMatches = []; for (var i = 0; i < newMatches.length; i++) { var key = newMatches[i].row + "," + newMatches[i].col; if (!seen[key]) { uniqueMatches.push(newMatches[i]); seen[key] = true; } } if (uniqueMatches.length > 0 && comboActive) { comboProcessMatches(uniqueMatches); } else { isProcessingMatches = false; } }, 350); // Wait for match animation } else { isProcessingMatches = false; } } // Override processMatches for combo mode processMatches = comboProcessMatches; // End combo mode after 8 seconds LK.setTimeout(function () { comboActive = false; processMatches = originalProcessMatches; isProcessingMatches = false; }, 8000); // After explosion, let flowers fall and fill, then check for matches makeFlowersFall(function () { fillEmptySpaces(function () { var matches = findAllMatches(); if (matches.length > 0) { processMatches(matches); } else { isProcessingMatches = false; } }); }); }
===================================================================
--- original.js
+++ change.js
@@ -1199,18 +1199,18 @@
// Update button texts
var topContainer = LK.gui.top;
for (var i = 0; i < topContainer.children.length; i++) {
var child = topContainer.children[i];
- if (child.textElement) {
+ if (child.textElement && child.textElement.text) {
if (child.textElement.text.indexOf('Change') >= 0 || child.textElement.text.indexOf('Changer') >= 0 || child.textElement.text.indexOf('Cambiar') >= 0 || child.textElement.text.indexOf('Cambia') >= 0 || child.textElement.text.indexOf('Schimbă') >= 0 || child.textElement.text.indexOf('Zmień') >= 0 || child.textElement.text.indexOf('Αλλαγή') >= 0 || child.textElement.text.indexOf('Spielsprache') >= 0 || child.textElement.text.indexOf('更改') >= 0 || child.textElement.text.indexOf('ゲーム言語') >= 0) {
child.textElement.setText(getText('changeLanguage'));
}
}
}
var topRightContainer = LK.gui.topRight;
for (var i = 0; i < topRightContainer.children.length; i++) {
var child = topRightContainer.children[i];
- if (child.textElement) {
+ if (child.textElement && child.textElement.text) {
if (child.textElement.text === 'RESET' || child.textElement.text === 'リセット' || child.textElement.text === 'ΕΠΑΝΑΦΟΡΑ' || child.textElement.text === '重置') {
child.textElement.setText(getText('reset'));
}
}