User prompt
3. Levelde tüm bloklar biterse kazandın yazısı ama hamlelerim onlardan önce biterse game over yazısı gelsin
User prompt
10 hamle hakki verelim level 3 icin
User prompt
yol acik oldugu icin spawnlanma serbest olmali
User prompt
3.level icin en ust 2 row yerine en alt 2 row bloklu olsun
User prompt
en alt 2 row bloklu gem olsun
User prompt
En ust satirda bloklanan taslarin ustune yeni gem dustu bunun icin gravity ayari yap eger en ustte bloklanan gem varsa yol kapansin yeni taslar spawnlanmasin
User prompt
Blocked gem'lerin uzerine asla gem cikmasin.
User prompt
Blocked Gem'lerin uzerine normal gem olmasin asla eger blocked gem unblocked olduysa asset yok olsun normale donsun
User prompt
en ust 2 satir komple bloklu taslardan olussun, bloklanan taslar icin ayri bir asset olusturalim
User prompt
bloklanmis taslar ayni satirda olsun leveli gecme kosulu blocklanmis taslarin hepsini acmak olsun
User prompt
bloklanma tarzi bu sekil olmamali sadece taslarin uzerinde bloklansin
User prompt
3. levelde eslestirme yapilamiyor sadece 5-6 gem bloklu olmali
User prompt
3. level oynanabilir degil duzelt lutfen
User prompt
3. levelde taslarin bir kismi bloklu olsun tahta gibi bir kilitle bunun yaninda tas eslesdikce taslar serbest hale gelsin ancak 1 yaninda eslestirme yapilmasi sart
User prompt
Kazandikdan sonra bir sonraki levele gecis yada menuye donus butonu koyulsun
User prompt
make 23 move for 2nd level and collect green gem for 2nd level
User prompt
create 2nd and 3rd lv similliar to 1st level
User prompt
make 19 moves instead of 15
User prompt
for first level 15 moves we should have
User prompt
Collect some blue gems with match 30 gems needs to be collected for succesfull completion
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'isUnlocked')' in or related to this line: 'if (clickedButton.isUnlocked) {' Line Number: 157
User prompt
i cant click to first level to open
User prompt
integration failed fix
User prompt
I CANT CLICK THE 1ST LEVEL TO OPEN
User prompt
1st level should be open ↪💡 Consider importing and using the following plugins: @upit/storage.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { unlockedLevel: 1 }); /**** * Classes ****/ var Gem = Container.expand(function (gemType, gridX, gridY, isBlocked) { var self = Container.call(this); self.gemType = gemType; self.gridX = gridX; self.gridY = gridY; self.isSpecial = false; self.specialType = 'normal'; // 'normal', 'striped_horizontal', 'striped_vertical', 'rainbow' self.isAnimating = false; self.isSelected = false; self.isBlocked = isBlocked || false; var gemAsset = self.attachAsset(gemType, { anchorX: 0.5, anchorY: 0.5 }); // Apply blocked visual directly to the gem if (self.isBlocked) { self.removeChild(gemAsset); gemAsset = self.attachAsset('blocked_gem', { anchorX: 0.5, anchorY: 0.5 }); } self.setSpecial = function (type) { self.isSpecial = true; self.specialType = type; if (type === 'striped_horizontal' || type === 'striped_vertical') { self.removeChild(gemAsset); gemAsset = self.attachAsset('striped_gem', { anchorX: 0.5, anchorY: 0.5 }); if (type === 'striped_horizontal') { gemAsset.rotation = Math.PI / 2; } } else if (type === 'rainbow') { self.removeChild(gemAsset); gemAsset = self.attachAsset('rainbow_gem', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'bomb') { self.removeChild(gemAsset); gemAsset = self.attachAsset('bomb_gem', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'target') { self.removeChild(gemAsset); gemAsset = self.attachAsset('target_gem', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'line_cleaner') { self.removeChild(gemAsset); gemAsset = self.attachAsset('line_cleaner', { anchorX: 0.5, anchorY: 0.5 }); } }; self.highlight = function () { self.isSelected = true; gemAsset.alpha = 0.7; }; self.unhighlight = function () { self.isSelected = false; gemAsset.alpha = 1.0; }; self.unblock = function () { if (self.isBlocked) { self.isBlocked = false; // Completely remove the blocked gem asset self.removeChild(gemAsset); // Create new gem asset with original gem type gemAsset = self.attachAsset(self.gemType, { anchorX: 0.5, anchorY: 0.5 }); // Reset any visual properties to ensure clean state gemAsset.alpha = 1.0; gemAsset.tint = 0xffffff; gemAsset.scaleX = 1.0; gemAsset.scaleY = 1.0; // Animate restoration of gem's original appearance tween(gemAsset, { scaleX: 1.2, scaleY: 1.2 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(gemAsset, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeIn }); } }); } }; self.down = function (x, y, obj) { if (!self.isAnimating && !self.isBlocked) { handleGemSelect(self); } }; return self; }); var MenuState = Container.expand(function () { var self = Container.call(this); // Create menu background var menuBg = self.attachAsset('board_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 1.3, scaleY: 1.7 }); menuBg.tint = 0x2c2c54; // Title text var titleText = new Text2('MATCH-3 PUZZLE', { size: 120, fill: '#ffffff' }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; self.addChild(titleText); // Subtitle var subtitleText = new Text2('Select Level', { size: 80, fill: '#ffaa00' }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 1024; subtitleText.y = 550; self.addChild(subtitleText); // Level buttons array self.levelButtons = []; // Create level buttons (1-10) for (var i = 1; i <= 10; i++) { var unlockedLevel = storage.unlockedLevel || 1; var isUnlocked = i <= unlockedLevel; var buttonBg = LK.getAsset(isUnlocked ? 'gem_blue' : 'gem_red', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); var levelText = new Text2(i.toString(), { size: 60, fill: isUnlocked ? '#ffffff' : '#888888' }); levelText.anchor.set(0.5, 0.5); var button = new Container(); button.addChild(buttonBg); button.addChild(levelText); // Position buttons in 2 rows of 5 var col = (i - 1) % 5; var row = Math.floor((i - 1) / 5); button.x = 400 + col * 250; button.y = 800 + row * 200; button.levelNumber = i; button.buttonBg = buttonBg; button.isUnlocked = isUnlocked; // Button interaction button.down = function (x, y, obj) { // Use 'this' to reference the button that was clicked if (this.isUnlocked) { var level = this.levelNumber; startGame(level); } }; self.levelButtons.push(button); self.addChild(button); } return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ var gameState = 'menu'; // 'menu' or 'playing' var currentLevel = 1; var menuScreen = null; function startGame(level) { gameState = 'playing'; currentLevel = level; // Remove menu screen if (menuScreen) { menuScreen.destroy(); menuScreen = null; } // Reset game variables based on level if (level === 1) { movesLeft = 19; targetBlueGems = 30; targetGreenGems = 0; } else if (level === 2) { movesLeft = 23; targetBlueGems = 0; targetGreenGems = 35; } else if (level === 3) { movesLeft = 10; targetBlueGems = 40; targetGreenGems = 0; } else { movesLeft = Math.max(10, 20 - level); targetBlueGems = 25 + level * 5; targetGreenGems = 0; } currentScore = 0; cascadeDepth = 0; blueGemsCollected = 0; greenGemsCollected = 0; selectedGem = null; isProcessing = false; // Update UI movesText.setText('Moves: ' + movesLeft); scoreText.setText('Score: ' + currentScore); levelText.setText('Level: ' + currentLevel); blueGemsText.setText('Blue Gems: ' + blueGemsCollected + '/' + targetBlueGems); greenGemsText.setText('Green Gems: ' + greenGemsCollected + '/' + targetGreenGems); // Show game UI scoreText.visible = true; movesText.visible = true; levelText.visible = true; blueGemsText.visible = currentLevel === 1 || currentLevel > 3; greenGemsText.visible = currentLevel === 2; // For level 3, show blocked gems objective if (currentLevel === 3) { blueGemsText.setText('Unblock All Gems!'); blueGemsText.visible = true; } boardBg.visible = true; // Initialize grid for gameplay initializeGrid(); } function showMenu() { gameState = 'menu'; // Hide game UI scoreText.visible = false; movesText.visible = false; levelText.visible = false; blueGemsText.visible = false; greenGemsText.visible = false; boardBg.visible = false; // Clear any existing gems for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x] && grid[x][y]) { if (grid[x][y].parent) { grid[x][y].destroy(); } grid[x][y] = null; } } } // Show menu menuScreen = new MenuState(); game.addChild(menuScreen); } var GRID_SIZE = 6; var GEM_SIZE = 200; var BOARD_SIZE = GRID_SIZE * GEM_SIZE; var BOARD_OFFSET_X = (2048 - BOARD_SIZE) / 2; var BOARD_OFFSET_Y = (2732 - BOARD_SIZE) / 2 - 200; var gemTypes = ['gem_red', 'gem_blue', 'gem_green', 'gem_yellow', 'gem_purple', 'gem_orange']; var grid = []; var selectedGem = null; var isProcessing = false; var movesLeft = 30; var currentScore = 0; var cascadeDepth = 0; var blueGemsCollected = 0; var targetBlueGems = 30; var greenGemsCollected = 0; var targetGreenGems = 0; // Initialize UI var scoreText = new Text2('Score: 0', { size: 60, fill: '#ffffff' }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var movesText = new Text2('Moves: 30', { size: 60, fill: '#ffffff' }); movesText.anchor.set(0.5, 0); movesText.y = 80; LK.gui.top.addChild(movesText); var levelText = new Text2('Level: 1', { size: 60, fill: '#ffffff' }); levelText.anchor.set(0.5, 0); levelText.y = 160; LK.gui.top.addChild(levelText); var blueGemsText = new Text2('Blue Gems: 0/30', { size: 60, fill: '#4da6ff' }); blueGemsText.anchor.set(0.5, 0); blueGemsText.y = 240; LK.gui.top.addChild(blueGemsText); var greenGemsText = new Text2('Green Gems: 0/0', { size: 60, fill: '#44dd44' }); greenGemsText.anchor.set(0.5, 0); greenGemsText.y = 300; LK.gui.top.addChild(greenGemsText); // Create board background var boardBg = game.attachAsset('board_bg', { anchorX: 0.5, anchorY: 0.5, x: BOARD_OFFSET_X + BOARD_SIZE / 2, y: BOARD_OFFSET_Y + BOARD_SIZE / 2 }); // Initialize grid function initializeGrid() { grid = []; for (var x = 0; x < GRID_SIZE; x++) { grid[x] = []; for (var y = 0; y < GRID_SIZE; y++) { grid[x][y] = null; } } // Fill grid with gems, ensuring no initial matches for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { var validTypes = gemTypes.slice(); // Remove types that would create horizontal matches if (x >= 2 && grid[x - 1][y] && grid[x - 2][y] && grid[x - 1][y].gemType === grid[x - 2][y].gemType) { var typeToRemove = grid[x - 1][y].gemType; var index = validTypes.indexOf(typeToRemove); if (index > -1) validTypes.splice(index, 1); } // Remove types that would create vertical matches if (y >= 2 && grid[x][y - 1] && grid[x][y - 2] && grid[x][y - 1].gemType === grid[x][y - 2].gemType) { var typeToRemove = grid[x][y - 1].gemType; var index = validTypes.indexOf(typeToRemove); if (index > -1) validTypes.splice(index, 1); } // Use different gem types for each level to adjust difficulty var availableTypes; if (currentLevel === 1) { availableTypes = gemTypes.slice(0, 4); // 4 types for level 1 } else if (currentLevel === 2) { availableTypes = gemTypes.slice(0, 5); // 5 types for level 2 } else if (currentLevel === 3) { availableTypes = gemTypes.slice(0, 6); // All 6 types for level 3 } else { availableTypes = gemTypes; // All types for higher levels } var filteredValidTypes = validTypes.filter(function (type) { return availableTypes.indexOf(type) !== -1; }); if (filteredValidTypes.length === 0) filteredValidTypes = availableTypes.slice(0, 2); var randomType = filteredValidTypes[Math.floor(Math.random() * filteredValidTypes.length)]; // For level 3, add some blocked gems var isBlocked = false; if (currentLevel === 3) { // Add blocked gems in bottom 2 rows (rows 4 and 5) if (y === 4 || y === 5) { isBlocked = true; } } var gem = new Gem(randomType, x, y, isBlocked); gem.x = BOARD_OFFSET_X + x * GEM_SIZE + GEM_SIZE / 2; gem.y = BOARD_OFFSET_Y + y * GEM_SIZE + GEM_SIZE / 2; grid[x][y] = gem; game.addChild(gem); } } } function handleGemSelect(gem) { if (isProcessing) return; if (selectedGem === null) { selectedGem = gem; gem.highlight(); } else if (selectedGem === gem) { selectedGem.unhighlight(); selectedGem = null; } else { // Check if either gem is blocked - cannot swap with blocked gems if (selectedGem.isBlocked || gem.isBlocked) { selectedGem.unhighlight(); selectedGem = null; return; } // Check if gems are adjacent var dx = Math.abs(selectedGem.gridX - gem.gridX); var dy = Math.abs(selectedGem.gridY - gem.gridY); if (dx === 1 && dy === 0 || dx === 0 && dy === 1) { // Swap gems swapGems(selectedGem, gem); } selectedGem.unhighlight(); selectedGem = null; } } function swapGems(gem1, gem2) { if (movesLeft <= 0) return; // Don't allow swapping with blocked gems if (gem1.isBlocked || gem2.isBlocked) { return; } isProcessing = true; // Check if both gems are special - create super combo if (gem1.isSpecial && gem2.isSpecial) { movesLeft--; movesText.setText('Moves: ' + movesLeft); LK.setTimeout(function () { activateSpecialCombo(gem1, gem2); LK.setTimeout(function () { applyGravity(); }, 500); }, 100); return; } // Check if either gem is special and activate it var specialActivated = false; if (gem1.isSpecial) { specialActivated = true; movesLeft--; movesText.setText('Moves: ' + movesLeft); LK.setTimeout(function () { activateSpecialGem(gem1); LK.setTimeout(function () { applyGravity(); }, 500); }, 100); return; } if (gem2.isSpecial) { specialActivated = true; movesLeft--; movesText.setText('Moves: ' + movesLeft); LK.setTimeout(function () { activateSpecialGem(gem2); LK.setTimeout(function () { applyGravity(); }, 500); }, 100); return; } // Store original positions var tempX = gem1.gridX; var tempY = gem1.gridY; // Temporarily swap gems to check for matches gem1.gridX = gem2.gridX; gem1.gridY = gem2.gridY; gem2.gridX = tempX; gem2.gridY = tempY; grid[gem1.gridX][gem1.gridY] = gem1; grid[gem2.gridX][gem2.gridY] = gem2; // Check if this swap creates any matches var testMatches = findMatches(); // If no matches, revert the swap and don't continue if (testMatches.length === 0) { // Revert grid positions to original gem1.gridX = tempX; gem1.gridY = tempY; gem2.gridX = gem2.gridX; gem2.gridY = gem2.gridY; grid[gem1.gridX][gem1.gridY] = gem1; grid[gem2.gridX][gem2.gridY] = gem2; isProcessing = false; return; } // Update grid positions (already done above for testing) // Animate swap var targetX1 = BOARD_OFFSET_X + gem1.gridX * GEM_SIZE + GEM_SIZE / 2; var targetY1 = BOARD_OFFSET_Y + gem1.gridY * GEM_SIZE + GEM_SIZE / 2; var targetX2 = BOARD_OFFSET_X + gem2.gridX * GEM_SIZE + GEM_SIZE / 2; var targetY2 = BOARD_OFFSET_Y + gem2.gridY * GEM_SIZE + GEM_SIZE / 2; gem1.isAnimating = true; gem2.isAnimating = true; tween(gem1, { x: targetX1, y: targetY1 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { gem1.isAnimating = false; checkSwapComplete(); } }); tween(gem2, { x: targetX2, y: targetY2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { gem2.isAnimating = false; checkSwapComplete(); } }); } var swapCompleteCount = 0; function checkSwapComplete() { swapCompleteCount++; if (swapCompleteCount === 2) { swapCompleteCount = 0; // Check for matches var matches = findMatches(); if (matches.length > 0) { movesLeft--; movesText.setText('Moves: ' + movesLeft); processMatches(matches); } else { // No matches, just end processing since swap was invalid isProcessing = false; } } } function findMatches() { var matches = []; var visited = []; // Initialize visited array for (var x = 0; x < GRID_SIZE; x++) { visited[x] = []; for (var y = 0; y < GRID_SIZE; y++) { visited[x][y] = false; } } // Find horizontal matches for (var y = 0; y < GRID_SIZE; y++) { for (var x = 0; x < GRID_SIZE - 2; x++) { if (grid[x][y] && grid[x + 1][y] && grid[x + 2][y] && !grid[x][y].isBlocked && !grid[x + 1][y].isBlocked && !grid[x + 2][y].isBlocked && grid[x][y].gemType === grid[x + 1][y].gemType && grid[x + 1][y].gemType === grid[x + 2][y].gemType) { var matchGroup = []; var currentX = x; while (currentX < GRID_SIZE && grid[currentX][y] && grid[currentX][y].gemType === grid[x][y].gemType) { if (!visited[currentX][y]) { matchGroup.push(grid[currentX][y]); visited[currentX][y] = true; } currentX++; } if (matchGroup.length >= 3) { matches.push(matchGroup); } } } } // Find vertical matches for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE - 2; y++) { if (grid[x][y] && grid[x][y + 1] && grid[x][y + 2] && !grid[x][y].isBlocked && !grid[x][y + 1].isBlocked && !grid[x][y + 2].isBlocked && grid[x][y].gemType === grid[x][y + 1].gemType && grid[x][y + 1].gemType === grid[x][y + 2].gemType) { var matchGroup = []; var currentY = y; while (currentY < GRID_SIZE && grid[x][currentY] && grid[x][currentY].gemType === grid[x][y].gemType) { if (!visited[x][currentY]) { matchGroup.push(grid[x][currentY]); visited[x][currentY] = true; } currentY++; } if (matchGroup.length >= 3) { matches.push(matchGroup); } } } } // Find 2x2 square matches for (var x = 0; x < GRID_SIZE - 1; x++) { for (var y = 0; y < GRID_SIZE - 1; y++) { if (grid[x][y] && grid[x + 1][y] && grid[x][y + 1] && grid[x + 1][y + 1]) { var gemType = grid[x][y].gemType; if (grid[x + 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x + 1][y + 1].gemType === gemType && !visited[x][y] && !visited[x + 1][y] && !visited[x][y + 1] && !visited[x + 1][y + 1]) { var squareMatch = [grid[x][y], grid[x + 1][y], grid[x][y + 1], grid[x + 1][y + 1]]; matches.push(squareMatch); for (var i = 0; i < squareMatch.length; i++) { visited[squareMatch[i].gridX][squareMatch[i].gridY] = true; } } } } } // Find L and T shaped matches for (var x = 1; x < GRID_SIZE - 1; x++) { for (var y = 1; y < GRID_SIZE - 1; y++) { if (grid[x][y]) { var centerGem = grid[x][y]; var gemType = centerGem.gemType; // Check L shapes (4 possible orientations) // L shape: top-left if (grid[x - 1][y] && grid[x][y - 1] && grid[x - 1][y - 1] && grid[x - 1][y].gemType === gemType && grid[x][y - 1].gemType === gemType && grid[x - 1][y - 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x][y - 1] && !visited[x - 1][y - 1]) { var lMatch = [centerGem, grid[x - 1][y], grid[x][y - 1], grid[x - 1][y - 1]]; matches.push(lMatch); for (var i = 0; i < lMatch.length; i++) { visited[lMatch[i].gridX][lMatch[i].gridY] = true; } } // L shape: top-right if (grid[x + 1][y] && grid[x][y - 1] && grid[x + 1][y - 1] && grid[x + 1][y].gemType === gemType && grid[x][y - 1].gemType === gemType && grid[x + 1][y - 1].gemType === gemType && !visited[x][y] && !visited[x + 1][y] && !visited[x][y - 1] && !visited[x + 1][y - 1]) { var lMatch = [centerGem, grid[x + 1][y], grid[x][y - 1], grid[x + 1][y - 1]]; matches.push(lMatch); for (var i = 0; i < lMatch.length; i++) { visited[lMatch[i].gridX][lMatch[i].gridY] = true; } } // L shape: bottom-left if (grid[x - 1][y] && grid[x][y + 1] && grid[x - 1][y + 1] && grid[x - 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x - 1][y + 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x][y + 1] && !visited[x - 1][y + 1]) { var lMatch = [centerGem, grid[x - 1][y], grid[x][y + 1], grid[x - 1][y + 1]]; matches.push(lMatch); for (var i = 0; i < lMatch.length; i++) { visited[lMatch[i].gridX][lMatch[i].gridY] = true; } } // L shape: bottom-right if (grid[x + 1][y] && grid[x][y + 1] && grid[x + 1][y + 1] && grid[x + 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x + 1][y + 1].gemType === gemType && !visited[x][y] && !visited[x + 1][y] && !visited[x][y + 1] && !visited[x + 1][y + 1]) { var lMatch = [centerGem, grid[x + 1][y], grid[x][y + 1], grid[x + 1][y + 1]]; matches.push(lMatch); for (var i = 0; i < lMatch.length; i++) { visited[lMatch[i].gridX][lMatch[i].gridY] = true; } } // Check T shapes (4 possible orientations) // T shape: horizontal top if (grid[x - 1][y] && grid[x + 1][y] && grid[x][y - 1] && grid[x - 1][y].gemType === gemType && grid[x + 1][y].gemType === gemType && grid[x][y - 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x + 1][y] && !visited[x][y - 1]) { var tMatch = [centerGem, grid[x - 1][y], grid[x + 1][y], grid[x][y - 1]]; matches.push(tMatch); for (var i = 0; i < tMatch.length; i++) { visited[tMatch[i].gridX][tMatch[i].gridY] = true; } } // T shape: horizontal bottom if (grid[x - 1][y] && grid[x + 1][y] && grid[x][y + 1] && grid[x - 1][y].gemType === gemType && grid[x + 1][y].gemType === gemType && grid[x][y + 1].gemType === gemType && !visited[x][y] && !visited[x - 1][y] && !visited[x + 1][y] && !visited[x][y + 1]) { var tMatch = [centerGem, grid[x - 1][y], grid[x + 1][y], grid[x][y + 1]]; matches.push(tMatch); for (var i = 0; i < tMatch.length; i++) { visited[tMatch[i].gridX][tMatch[i].gridY] = true; } } // T shape: vertical left if (grid[x][y - 1] && grid[x][y + 1] && grid[x - 1][y] && grid[x][y - 1].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x - 1][y].gemType === gemType && !visited[x][y] && !visited[x][y - 1] && !visited[x][y + 1] && !visited[x - 1][y]) { var tMatch = [centerGem, grid[x][y - 1], grid[x][y + 1], grid[x - 1][y]]; matches.push(tMatch); for (var i = 0; i < tMatch.length; i++) { visited[tMatch[i].gridX][tMatch[i].gridY] = true; } } // T shape: vertical right if (grid[x][y - 1] && grid[x][y + 1] && grid[x + 1][y] && grid[x][y - 1].gemType === gemType && grid[x][y + 1].gemType === gemType && grid[x + 1][y].gemType === gemType && !visited[x][y] && !visited[x][y - 1] && !visited[x][y + 1] && !visited[x + 1][y]) { var tMatch = [centerGem, grid[x][y - 1], grid[x][y + 1], grid[x + 1][y]]; matches.push(tMatch); for (var i = 0; i < tMatch.length; i++) { visited[tMatch[i].gridX][tMatch[i].gridY] = true; } } } } } return matches; } function processMatches(matches) { cascadeDepth++; var totalScore = 0; var specialGems = []; for (var i = 0; i < matches.length; i++) { var match = matches[i]; var matchScore = match.length * 10 * cascadeDepth; totalScore += matchScore; // Create special gems for larger matches if (match.length === 4) { // Check if it's a 2x2 square var isSquare = false; var isLOrT = false; if (match.length === 4) { // Sort gems by position to check square pattern var sortedMatch = match.slice().sort(function (a, b) { if (a.gridX !== b.gridX) return a.gridX - b.gridX; return a.gridY - b.gridY; }); // Check if it forms a 2x2 square if (sortedMatch[0].gridX === sortedMatch[1].gridX - 1 && sortedMatch[0].gridY === sortedMatch[2].gridY - 1 && sortedMatch[1].gridX === sortedMatch[3].gridX && sortedMatch[2].gridY === sortedMatch[3].gridY && sortedMatch[0].gridX === sortedMatch[2].gridX && sortedMatch[1].gridY === sortedMatch[0].gridY) { isSquare = true; } // Check if it's an L or T shape (4 gems in specific patterns) // L/T shapes will have gems that don't form a straight line var minX = Math.min(match[0].gridX, match[1].gridX, match[2].gridX, match[3].gridX); var maxX = Math.max(match[0].gridX, match[1].gridX, match[2].gridX, match[3].gridX); var minY = Math.min(match[0].gridY, match[1].gridY, match[2].gridY, match[3].gridY); var maxY = Math.max(match[0].gridY, match[1].gridY, match[2].gridY, match[3].gridY); // If it spans more than 1 row AND more than 1 column, it's likely L or T if (maxX - minX > 0 && maxY - minY > 0 && !isSquare) { isLOrT = true; } } if (isSquare) { // Create target gem for 2x2 square var specialGem = match[0]; specialGem.setSpecial('target'); specialGems.push(specialGem); } else if (isLOrT) { // Create bomb gem for L and T shapes var specialGem = match[0]; specialGem.setSpecial('bomb'); specialGems.push(specialGem); } else { // For 4-gem straight line matches, create line cleaner var specialGem = match[0]; specialGem.setSpecial('line_cleaner'); specialGems.push(specialGem); } } else if (match.length >= 5) { // Create rainbow gem var specialGem = match[0]; specialGem.setSpecial('rainbow'); specialGems.push(specialGem); } // Remove matched gems (except special gems) with crystal crack effects for (var j = 0; j < match.length; j++) { var gem = match[j]; if (specialGems.indexOf(gem) === -1) { // Track blue gem collection if (gem.gemType === 'gem_blue') { blueGemsCollected++; blueGemsText.setText('Blue Gems: ' + blueGemsCollected + '/' + targetBlueGems); } // Track green gem collection if (gem.gemType === 'gem_green') { greenGemsCollected++; greenGemsText.setText('Green Gems: ' + greenGemsCollected + '/' + targetGreenGems); } if (grid[gem.gridX] && grid[gem.gridX][gem.gridY]) { grid[gem.gridX][gem.gridY] = null; } // Add crystal crack effect LK.setTimeout(function (targetGem) { return function () { tween(targetGem, { scaleX: 1.3, scaleY: 1.3, alpha: 0.8, tint: 0xffffff }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(targetGem, { scaleX: 0.1, scaleY: 0.1, alpha: 0, rotation: Math.PI * 0.5, tint: 0xaaaaaa }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { if (targetGem.parent) { targetGem.destroy(); } } }); } }); }; }(gem), j * 20); } } } currentScore += totalScore; scoreText.setText('Score: ' + currentScore); LK.getSound('match').play(); // Apply gravity and cascade // Unblock adjacent gems for (var i = 0; i < matches.length; i++) { var match = matches[i]; for (var j = 0; j < match.length; j++) { var gem = match[j]; // Check all adjacent positions and unblock them for (var dx = -1; dx <= 1; dx++) { for (var dy = -1; dy <= 1; dy++) { if (dx === 0 && dy === 0) continue; var adjX = gem.gridX + dx; var adjY = gem.gridY + dy; if (adjX >= 0 && adjX < GRID_SIZE && adjY >= 0 && adjY < GRID_SIZE) { if (grid[adjX][adjY] && grid[adjX][adjY].isBlocked) { grid[adjX][adjY].unblock(); } } } } } } LK.setTimeout(function () { applyGravity(); }, 200); } function applyGravity() { var gemsToAnimate = []; // Move gems down for (var x = 0; x < GRID_SIZE; x++) { var writeIndex = GRID_SIZE - 1; for (var y = GRID_SIZE - 1; y >= 0; y--) { if (grid[x][y] !== null) { if (grid[x][y].isBlocked) { // Blocked gems stay in place writeIndex--; } else { if (y !== writeIndex) { grid[x][writeIndex] = grid[x][y]; grid[x][y] = null; grid[x][writeIndex].gridY = writeIndex; var targetY = BOARD_OFFSET_Y + writeIndex * GEM_SIZE + GEM_SIZE / 2; gemsToAnimate.push({ gem: grid[x][writeIndex], targetY: targetY }); } writeIndex--; } } } // Check if spawning path is clear - only blocked gems at the spawn positions matter var canSpawnNewGems = true; // Check if any of the positions we need to fill have blocked gems for (var checkY = 0; checkY <= writeIndex; checkY++) { if (grid[x][checkY] && grid[x][checkY].isBlocked) { canSpawnNewGems = false; break; } } // Only spawn new gems if the actual spawn positions are clear if (canSpawnNewGems) { for (var y = 0; y <= writeIndex; y++) { var availableTypes; if (currentLevel === 1) { availableTypes = gemTypes.slice(0, 4); // 4 types for level 1 } else if (currentLevel === 2) { availableTypes = gemTypes.slice(0, 5); // 5 types for level 2 } else if (currentLevel === 3) { availableTypes = gemTypes.slice(0, 6); // All 6 types for level 3 } else { availableTypes = gemTypes; // All types for higher levels } var randomType = availableTypes[Math.floor(Math.random() * availableTypes.length)]; var newGem = new Gem(randomType, x, y); newGem.x = BOARD_OFFSET_X + x * GEM_SIZE + GEM_SIZE / 2; newGem.y = BOARD_OFFSET_Y + y * GEM_SIZE + GEM_SIZE / 2 - (writeIndex - y + 1) * GEM_SIZE; grid[x][y] = newGem; game.addChild(newGem); var targetY = BOARD_OFFSET_Y + y * GEM_SIZE + GEM_SIZE / 2; gemsToAnimate.push({ gem: newGem, targetY: targetY }); } } } // Animate falling gems var animationCount = 0; for (var i = 0; i < gemsToAnimate.length; i++) { var animData = gemsToAnimate[i]; animData.gem.isAnimating = true; tween(animData.gem, { y: animData.targetY }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { animationCount++; if (animationCount === gemsToAnimate.length) { checkForCascade(); } } }); } if (gemsToAnimate.length === 0) { checkForCascade(); } } function activateSpecialGem(gem) { if (!gem.isSpecial) return false; var gemsToRemove = []; if (gem.specialType === 'striped_horizontal') { // Enhanced horizontal striped effect - sweeping motion tween(gem, { scaleX: 8, scaleY: 1.5, tint: 0xffff00, alpha: 0.7 }, { duration: 350, easing: tween.easeOut }); // Remove entire row for (var x = 0; x < GRID_SIZE; x++) { if (grid[x][gem.gridY] && grid[x][gem.gridY] !== gem) { gemsToRemove.push(grid[x][gem.gridY]); } } } else if (gem.specialType === 'striped_vertical') { // Enhanced vertical striped effect - sweeping motion tween(gem, { scaleX: 1.5, scaleY: 8, tint: 0xffff00, alpha: 0.7 }, { duration: 350, easing: tween.easeOut }); // Remove entire column for (var y = 0; y < GRID_SIZE; y++) { if (grid[gem.gridX][y] && grid[gem.gridX][y] !== gem) { gemsToRemove.push(grid[gem.gridX][y]); } } } else if (gem.specialType === 'rainbow') { // Enhanced rainbow effect - color cycling shimmer tween(gem, { scaleX: 2.5, scaleY: 2.5, tint: 0xff00ff }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(gem, { tint: 0x00ffff }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(gem, { tint: 0xffff00 }, { duration: 200, easing: tween.easeInOut }); } }); } }); // Remove all gems of the same type as the first regular gem found var targetType = null; for (var x = 0; x < GRID_SIZE && !targetType; x++) { for (var y = 0; y < GRID_SIZE && !targetType; y++) { if (grid[x][y] && !grid[x][y].isSpecial && grid[x][y] !== gem) { targetType = grid[x][y].gemType; } } } if (targetType) { for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] && grid[x][y].gemType === targetType && grid[x][y] !== gem) { gemsToRemove.push(grid[x][y]); } } } } } else if (gem.specialType === 'bomb') { // Add explosion flash effect for bomb LK.effects.flashScreen(0xff8800, 600); // Enhanced bomb visual effect - pulsing explosion tween(gem, { scaleX: 4, scaleY: 4, rotation: Math.PI * 2, tint: 0xff4400 }, { duration: 400, easing: tween.easeOut }); // Remove 3x3 area around the bomb for (var dx = -1; dx <= 1; dx++) { for (var dy = -1; dy <= 1; dy++) { var targetX = gem.gridX + dx; var targetY = gem.gridY + dy; if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) { if (grid[targetX][targetY] && grid[targetX][targetY] !== gem) { gemsToRemove.push(grid[targetX][targetY]); } } } } } else if (gem.specialType === 'target') { // Enhanced target effect - bullseye pulsing tween(gem, { scaleX: 2.5, scaleY: 2.5, tint: 0xff0000 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(gem, { scaleX: 1.5, scaleY: 1.5, tint: 0xffffff }, { duration: 150, easing: tween.easeInOut, onFinish: function onFinish() { tween(gem, { scaleX: 2, scaleY: 2, tint: 0xff0000 }, { duration: 150, easing: tween.easeInOut }); } }); } }); // Remove single target gem (the gem itself) // Target gem destroys only itself when activated } else if (gem.specialType === 'line_cleaner') { // Enhanced line cleaner effect - crosshair targeting tween(gem, { scaleX: 3, scaleY: 3, tint: 0x00ff00, rotation: Math.PI / 4 }, { duration: 300, easing: tween.easeOut }); // Determine if it was a horizontal or vertical line and clear that line // Check adjacent gems to determine orientation var isHorizontal = false; var isVertical = false; // Check horizontal neighbors if (gem.gridX > 0 && grid[gem.gridX - 1][gem.gridY] && grid[gem.gridX - 1][gem.gridY].gemType === gem.gemType || gem.gridX < GRID_SIZE - 1 && grid[gem.gridX + 1][gem.gridY] && grid[gem.gridX + 1][gem.gridY].gemType === gem.gemType) { isHorizontal = true; } // Check vertical neighbors if (gem.gridY > 0 && grid[gem.gridX][gem.gridY - 1] && grid[gem.gridX][gem.gridY - 1].gemType === gem.gemType || gem.gridY < GRID_SIZE - 1 && grid[gem.gridX][gem.gridY + 1] && grid[gem.gridX][gem.gridY + 1].gemType === gem.gemType) { isVertical = true; } if (isHorizontal && !isVertical) { // Clear entire row for (var x = 0; x < GRID_SIZE; x++) { if (grid[x][gem.gridY] && grid[x][gem.gridY] !== gem) { gemsToRemove.push(grid[x][gem.gridY]); } } } else if (isVertical && !isHorizontal) { // Clear entire column for (var y = 0; y < GRID_SIZE; y++) { if (grid[gem.gridX][y] && grid[gem.gridX][y] !== gem) { gemsToRemove.push(grid[gem.gridX][y]); } } } else { // Default to clearing row if unclear for (var x = 0; x < GRID_SIZE; x++) { if (grid[x][gem.gridY] && grid[x][gem.gridY] !== gem) { gemsToRemove.push(grid[x][gem.gridY]); } } } } // Remove the special gem itself gemsToRemove.push(gem); // Add explosion effect tween(gem, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, easing: tween.easeOut }); // Remove all targeted gems with crystal crack effects and staggered timing for (var i = 0; i < gemsToRemove.length; i++) { var gemToRemove = gemsToRemove[i]; // Track blue gem collection if (gemToRemove.gemType === 'gem_blue') { blueGemsCollected++; blueGemsText.setText('Blue Gems: ' + blueGemsCollected + '/' + targetBlueGems); } // Track green gem collection if (gemToRemove.gemType === 'gem_green') { greenGemsCollected++; greenGemsText.setText('Green Gems: ' + greenGemsCollected + '/' + targetGreenGems); } if (grid[gemToRemove.gridX] && grid[gemToRemove.gridX][gemToRemove.gridY]) { grid[gemToRemove.gridX][gemToRemove.gridY] = null; } // Add crystal crack effect with delay for cascade visual LK.setTimeout(function (targetGem) { return function () { // First stage - crystal stress effect tween(targetGem, { scaleX: 1.2, scaleY: 1.2, alpha: 0.9, tint: 0xffffff }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { // Second stage - crack and shatter tween(targetGem, { scaleX: 0.1, scaleY: 0.1, alpha: 0, rotation: Math.PI, tint: 0xcccccc }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { if (targetGem.parent) { targetGem.destroy(); } } }); } }); }; }(gemToRemove), i * 50); } // Add score for special activation var bonusScore = gemsToRemove.length * 20; currentScore += bonusScore; scoreText.setText('Score: ' + currentScore); return true; } function showWinScreen() { gameState = 'win'; // Hide game UI scoreText.visible = false; movesText.visible = false; levelText.visible = false; blueGemsText.visible = false; greenGemsText.visible = false; boardBg.visible = false; // Create win screen background var winBg = game.attachAsset('board_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 1.3, scaleY: 1.7 }); winBg.tint = 0x2c5422; // Congratulations text var winText = new Text2('LEVEL COMPLETED!', { size: 100, fill: '#ffffff' }); winText.anchor.set(0.5, 0.5); winText.x = 1024; winText.y = 800; game.addChild(winText); // Score text var finalScoreText = new Text2('Final Score: ' + currentScore, { size: 80, fill: '#ffaa00' }); finalScoreText.anchor.set(0.5, 0.5); finalScoreText.x = 1024; finalScoreText.y = 950; game.addChild(finalScoreText); // Next Level button var nextLevelButton = new Container(); var nextLevelBg = LK.getAsset('gem_green', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var nextLevelText = new Text2('NEXT LEVEL', { size: 50, fill: '#ffffff' }); nextLevelText.anchor.set(0.5, 0.5); nextLevelButton.addChild(nextLevelBg); nextLevelButton.addChild(nextLevelText); nextLevelButton.x = 750; nextLevelButton.y = 1150; nextLevelButton.down = function (x, y, obj) { // Clean up win screen winBg.destroy(); winText.destroy(); finalScoreText.destroy(); nextLevelButton.destroy(); menuButton.destroy(); // Start next level if (currentLevel < 10) { startGame(currentLevel + 1); } else { showMenu(); } }; // Menu button var menuButton = new Container(); var menuBg = LK.getAsset('gem_blue', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var menuText = new Text2('MENU', { size: 50, fill: '#ffffff' }); menuText.anchor.set(0.5, 0.5); menuButton.addChild(menuBg); menuButton.addChild(menuText); menuButton.x = 1298; menuButton.y = 1150; menuButton.down = function (x, y, obj) { // Clean up win screen winBg.destroy(); winText.destroy(); finalScoreText.destroy(); nextLevelButton.destroy(); menuButton.destroy(); // Return to menu showMenu(); }; game.addChild(nextLevelButton); game.addChild(menuButton); // Hide next level button if it's the last level if (currentLevel >= 10) { nextLevelText.setText('ALL LEVELS\nCOMPLETED!'); nextLevelBg.tint = 0x666666; } } function checkForCascade() { var matches = findMatches(); if (matches.length > 0) { LK.getSound('cascade').play(); processMatches(matches); } else { cascadeDepth = 0; isProcessing = false; // Check for level 3 special win condition (all blocked gems unblocked) if (currentLevel === 3) { var blockedGemsRemaining = 0; for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x] && grid[x][y] && grid[x][y].isBlocked) { blockedGemsRemaining++; } } } if (blockedGemsRemaining === 0) { // Level 3 completed - all blocked gems unblocked! var unlockedLevel = storage.unlockedLevel || 1; if (currentLevel >= unlockedLevel && currentLevel < 10) { storage.unlockedLevel = currentLevel + 1; } LK.showYouWin(); return; } // Check for game over in level 3 - if moves exhausted but blocks remain if (movesLeft <= 0) { LK.showGameOver(); return; } } else { // Check for blue gem completion for other levels if (blueGemsCollected >= targetBlueGems && targetBlueGems > 0) { // Level completed - blue gems collected! var unlockedLevel = storage.unlockedLevel || 1; if (currentLevel >= unlockedLevel && currentLevel < 10) { storage.unlockedLevel = currentLevel + 1; } showWinScreen(); return; } // Check for green gem completion if (greenGemsCollected >= targetGreenGems && targetGreenGems > 0) { // Level completed - green gems collected! var unlockedLevel = storage.unlockedLevel || 1; if (currentLevel >= unlockedLevel && currentLevel < 10) { storage.unlockedLevel = currentLevel + 1; } showWinScreen(); return; } // Check for game over in other levels if (movesLeft <= 0) { LK.setTimeout(function () { showMenu(); }, 1000); } } } } // Start with menu instead of initializing grid directly showMenu(); game.update = function () { // Update gem animations for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x] && grid[x][y] && grid[x][y].isAnimating) { grid[x][y].isAnimating = false; } } } }; function activateSpecialCombo(gem1, gem2) { var gemsToRemove = []; var comboScore = 0; // Add dramatic visual effect for combo tween(gem1, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 500, easing: tween.easeOut }); tween(gem2, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 500, easing: tween.easeOut }); // Determine combo effect based on gem types var type1 = gem1.specialType; var type2 = gem2.specialType; if ((type1 === 'striped_horizontal' || type1 === 'striped_vertical') && (type2 === 'striped_horizontal' || type2 === 'striped_vertical')) { // Striped + Striped = Clear entire row AND column for (var x = 0; x < GRID_SIZE; x++) { if (grid[x][gem1.gridY] && grid[x][gem1.gridY] !== gem1 && grid[x][gem1.gridY] !== gem2) { gemsToRemove.push(grid[x][gem1.gridY]); } } for (var y = 0; y < GRID_SIZE; y++) { if (grid[gem1.gridX][y] && grid[gem1.gridX][y] !== gem1 && grid[gem1.gridX][y] !== gem2) { gemsToRemove.push(grid[gem1.gridX][y]); } } comboScore = 500; } else if (type1 === 'bomb' && type2 === 'bomb') { // Bomb + Bomb = 5x5 explosion for (var dx = -2; dx <= 2; dx++) { for (var dy = -2; dy <= 2; dy++) { var targetX = gem1.gridX + dx; var targetY = gem1.gridY + dy; if (targetX >= 0 && targetX < GRID_SIZE && targetY >= 0 && targetY < GRID_SIZE) { if (grid[targetX][targetY] && grid[targetX][targetY] !== gem1 && grid[targetX][targetY] !== gem2) { gemsToRemove.push(grid[targetX][targetY]); } } } } comboScore = 400; } else if ((type1 === 'striped_horizontal' || type1 === 'striped_vertical') && type2 === 'bomb') { // Striped + Bomb = 3 rows or 3 columns if (type1 === 'striped_horizontal') { for (var dy = -1; dy <= 1; dy++) { for (var x = 0; x < GRID_SIZE; x++) { var targetY = gem1.gridY + dy; if (targetY >= 0 && targetY < GRID_SIZE) { if (grid[x][targetY] && grid[x][targetY] !== gem1 && grid[x][targetY] !== gem2) { gemsToRemove.push(grid[x][targetY]); } } } } } else { for (var dx = -1; dx <= 1; dx++) { for (var y = 0; y < GRID_SIZE; y++) { var targetX = gem1.gridX + dx; if (targetX >= 0 && targetX < GRID_SIZE) { if (grid[targetX][y] && grid[targetX][y] !== gem1 && grid[targetX][y] !== gem2) { gemsToRemove.push(grid[targetX][y]); } } } } } comboScore = 350; } else if (type1 === 'bomb' && (type2 === 'striped_horizontal' || type2 === 'striped_vertical')) { // Bomb + Striped = 3 rows or 3 columns if (type2 === 'striped_horizontal') { for (var dy = -1; dy <= 1; dy++) { for (var x = 0; x < GRID_SIZE; x++) { var targetY = gem2.gridY + dy; if (targetY >= 0 && targetY < GRID_SIZE) { if (grid[x][targetY] && grid[x][targetY] !== gem1 && grid[x][targetY] !== gem2) { gemsToRemove.push(grid[x][targetY]); } } } } } else { for (var dx = -1; dx <= 1; dx++) { for (var y = 0; y < GRID_SIZE; y++) { var targetX = gem2.gridX + dx; if (targetX >= 0 && targetX < GRID_SIZE) { if (grid[targetX][y] && grid[targetX][y] !== gem1 && grid[targetX][y] !== gem2) { gemsToRemove.push(grid[targetX][y]); } } } } } comboScore = 350; } else if (type1 === 'rainbow' || type2 === 'rainbow') { // Rainbow + Any special = Transform all gems of one type to that special type var otherGem = type1 === 'rainbow' ? gem2 : gem1; var targetType = gemTypes[Math.floor(Math.random() * gemTypes.length)]; for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] && grid[x][y].gemType === targetType && grid[x][y] !== gem1 && grid[x][y] !== gem2) { // Transform to special type grid[x][y].setSpecial(otherGem.specialType); } } } comboScore = 600; } else if (type1 === 'target' || type2 === 'target') { // Target + Any special = Clear all gems of 2 random colors var color1 = gemTypes[Math.floor(Math.random() * gemTypes.length)]; var color2 = gemTypes[Math.floor(Math.random() * gemTypes.length)]; while (color2 === color1) { color2 = gemTypes[Math.floor(Math.random() * gemTypes.length)]; } for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x][y] && (grid[x][y].gemType === color1 || grid[x][y].gemType === color2) && grid[x][y] !== gem1 && grid[x][y] !== gem2) { gemsToRemove.push(grid[x][y]); } } } comboScore = 450; } else if (type1 === 'line_cleaner' || type2 === 'line_cleaner') { // Line cleaner + Any special = Clear cross pattern (both row and column) var targetGem = type1 === 'line_cleaner' ? gem1 : gem2; // Clear entire row for (var x = 0; x < GRID_SIZE; x++) { if (grid[x][targetGem.gridY] && grid[x][targetGem.gridY] !== gem1 && grid[x][targetGem.gridY] !== gem2) { gemsToRemove.push(grid[x][targetGem.gridY]); } } // Clear entire column for (var y = 0; y < GRID_SIZE; y++) { if (grid[targetGem.gridX][y] && grid[targetGem.gridX][y] !== gem1 && grid[targetGem.gridX][y] !== gem2) { gemsToRemove.push(grid[targetGem.gridX][y]); } } comboScore = 400; } // Remove the special gems themselves gemsToRemove.push(gem1); gemsToRemove.push(gem2); // Remove all targeted gems with enhanced crystal crack effects for (var i = 0; i < gemsToRemove.length; i++) { var gemToRemove = gemsToRemove[i]; // Track blue gem collection if (gemToRemove.gemType === 'gem_blue') { blueGemsCollected++; blueGemsText.setText('Blue Gems: ' + blueGemsCollected + '/' + targetBlueGems); } // Track green gem collection if (gemToRemove.gemType === 'gem_green') { greenGemsCollected++; greenGemsText.setText('Green Gems: ' + greenGemsCollected + '/' + targetGreenGems); } if (grid[gemToRemove.gridX] && grid[gemToRemove.gridX][gemToRemove.gridY]) { grid[gemToRemove.gridX][gemToRemove.gridY] = null; } // Enhanced crystal crack effect for combo - dramatic shattering tween(gemToRemove, { scaleX: 1.4, scaleY: 1.4, alpha: 1.0, tint: 0xffffff }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(gemToRemove, { scaleX: 0, scaleY: 0, alpha: 0, rotation: Math.PI * 2, tint: 0x888888 }, { duration: 250, easing: tween.easeIn, onFinish: function onFinish() { if (gemToRemove.parent) { gemToRemove.destroy(); } } }); } }); } // Add bonus score for special combo currentScore += comboScore; scoreText.setText('Score: ' + currentScore); // Flash screen to indicate powerful combo LK.effects.flashScreen(0xffd700, 800); }
===================================================================
--- original.js
+++ change.js
@@ -1273,11 +1273,16 @@
var unlockedLevel = storage.unlockedLevel || 1;
if (currentLevel >= unlockedLevel && currentLevel < 10) {
storage.unlockedLevel = currentLevel + 1;
}
- showWinScreen();
+ LK.showYouWin();
return;
}
+ // Check for game over in level 3 - if moves exhausted but blocks remain
+ if (movesLeft <= 0) {
+ LK.showGameOver();
+ return;
+ }
} else {
// Check for blue gem completion for other levels
if (blueGemsCollected >= targetBlueGems && targetBlueGems > 0) {
// Level completed - blue gems collected!
@@ -1297,15 +1302,15 @@
}
showWinScreen();
return;
}
+ // Check for game over in other levels
+ if (movesLeft <= 0) {
+ LK.setTimeout(function () {
+ showMenu();
+ }, 1000);
+ }
}
- // Check for game over
- if (movesLeft <= 0) {
- LK.setTimeout(function () {
- showMenu();
- }, 1000);
- }
}
}
// Start with menu instead of initializing grid directly
showMenu();
Kristal gorunumlu rainbow bonus gem'i olmasi icin turuncu, mavi, turkuaz, yesil , pembe iceren ozel bir kristal png arka plan olmasin. In-Game asset. 2d. High contrast. No shadows
Kristal olarak bi bomba bonusu icin bir gem olustur
Bu renkte bir line clearer icin kristal bonus gem olustur
make wood for blocked gem. In-Game asset. 2d. High contrast. No shadows