User prompt
Please fix the bug: 'ReferenceError: increasePressure is not defined' in or related to this line: 'increasePressure(steamGained);' Line Number: 431
User prompt
убери pressure_bar и pressure_bg
User prompt
исправь 124 строку
User prompt
Please fix the bug: 'self.shuffleBoard is not a function' in or related to this line: 'self.shuffleBoard();' Line Number: 124
User prompt
Please fix the bug: 'self is undefined' in or related to this line: 'self.shuffleBoard = function () {' Line Number: 753
User prompt
Please fix the bug: 'self.shuffleBoard is not a function' in or related to this line: 'self.shuffleBoard();' Line Number: 125
User prompt
пусть шестерни будут раскиданы более рандомно а также пусть прогресс бар пара на бойлере увелчивается за каждую комбинацию
User prompt
сделай так чтобы так часто 3 в ряд не выпадало
User prompt
Please fix the bug: 'right-hand side of 'in' should be an object, got undefined' in or related to this line: 'tween(self.hammerButtonBg, {' Line Number: 76
User prompt
убери steam hummer и turbo charger
User prompt
убери кнопки selected_cell
Code edit (1 edits merged)
Please save this source code
User prompt
Steam Gear Fusion
Initial prompt
Концепт игры «3 в ряд» в стиле Стимпанк-Механик Название: «Паровая Комбинация» 🎮 Основная механика: Классический матч-3 (три в ряд), но с стимпанк-твистами: Шестерни вместо фишек – игрок собирает линии из медных, стальных и латунных деталей. Давление пара – каждая комбинация наполняет паровой котёл, который дает бонусы. Механические помехи – иногда на поле появляются заклинившие шестерни, которые нужно убирать спец-ходом. ⚙️ Уникальные особенности: ✔ Режим «Перегрузка» – при заполнении шкалы пара можно активировать супер-способности: Паровой Молот – уничтожает все детали в одном ряду. Турбо-Нагнетатель – перемешивает поле, создавая новые комбинации. ✔ Босс-уровни – сражение с гигантской паровой машиной, которая усложняет игру: Добавляет ржавые болты, блокирующие ходы. Запускает конвейер, смещающий ряды. ✔ Квестовый сюжет – герой-механик чинит огромный завод-мегаполис, уровень за уровнем. 🎨 Визуальный стиль: Тёмные металлические тона с огненными вспышками пара. Анимация – детали скрепляются, взрываются и превращаются в пар. Саундтрек – заводские шумы, лязг металла, гудки.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, currentLevel: 1 }); /**** * Classes ****/ var Boiler = Container.expand(function () { var self = Container.call(this); // Boiler background self.boilerBg = self.attachAsset('boiler', { anchorX: 0.5, anchorY: 0.5 }); // Pressure bar background self.pressureBg = self.attachAsset('pressure_bg', { anchorX: 0.5, anchorY: 0.5, y: 25 }); // Pressure bar self.pressureBar = self.attachAsset('pressure_bar', { anchorX: 0, anchorY: 0.5, x: -275, y: 25, scaleX: 0 // Start with empty bar }); // Current pressure and max pressure self.currentPressure = 0; self.maxPressure = 100; // Labels for abilities self.hammerLabel = new Text2('Steam Hammer', { size: 40, fill: 0xFFFFFF }); self.hammerLabel.anchor.set(0.5, 0.5); self.hammerLabel.x = -150; self.hammerLabel.y = -40; self.addChild(self.hammerLabel); self.turboLabel = new Text2('Turbo-Charger', { size: 40, fill: 0xFFFFFF }); self.turboLabel.anchor.set(0.5, 0.5); self.turboLabel.x = 150; self.turboLabel.y = -40; self.addChild(self.turboLabel); // Button backgrounds self.hammerButtonBg = self.attachAsset('cell_bg', { anchorX: 0.5, anchorY: 0.5, x: -150, y: 0, scaleX: 0.8, scaleY: 0.6 }); self.turboButtonBg = self.attachAsset('cell_bg', { anchorX: 0.5, anchorY: 0.5, x: 150, y: 0, scaleX: 0.8, scaleY: 0.6 }); // Ability costs self.hammerCost = 25; self.turboCost = 50; // Ability availability self.canUseHammer = false; self.canUseTurbo = false; // Update pressure bar self.updatePressure = function (newPressure) { self.currentPressure = Math.min(newPressure, self.maxPressure); // Update pressure bar scale tween(self.pressureBar, { scaleX: self.currentPressure / self.maxPressure }, { duration: 300, easing: tween.easeOut }); // Update ability availability var previousHammer = self.canUseHammer; var previousTurbo = self.canUseTurbo; self.canUseHammer = self.currentPressure >= self.hammerCost; self.canUseTurbo = self.currentPressure >= self.turboCost; // Visual feedback for available abilities if (self.canUseHammer !== previousHammer) { tween(self.hammerButtonBg, { tint: self.canUseHammer ? 0x44FF44 : 0x444444 }, { duration: 300, easing: tween.easeOut }); } if (self.canUseTurbo !== previousTurbo) { tween(self.turboButtonBg, { tint: self.canUseTurbo ? 0x44FF44 : 0x444444 }, { duration: 300, easing: tween.easeOut }); } }; // Initialize buttons as disabled self.hammerButtonBg.tint = 0x444444; self.turboButtonBg.tint = 0x444444; // Add click handlers for ability buttons self.hammerButtonBg.interactive = true; self.turboButtonBg.interactive = true; self.hammerButtonBg.down = function () { if (self.canUseHammer) { if (gameBoard.useHammerAbility()) { // Ability used successfully self.currentPressure -= self.hammerCost; self.updatePressure(self.currentPressure); // Play steam release sound LK.getSound('steam_release').play(); } } }; self.turboButtonBg.down = function () { if (self.canUseTurbo) { if (gameBoard.useTurboChargerAbility()) { // Ability used successfully self.currentPressure -= self.turboCost; self.updatePressure(self.currentPressure); // Play steam release sound LK.getSound('steam_release').play(); } } }; return self; }); var GameBoard = Container.expand(function () { var self = Container.call(this); self.gridSize = 8; self.cellSize = 160; self.padding = 10; self.boardSize = (self.cellSize + self.padding) * self.gridSize; // Metrics for positioning self.boardStartX = (2048 - self.boardSize) / 2; self.boardStartY = (2732 - self.boardSize) / 2; // Game state self.selectedGear = null; self.grid = []; self.gearTypes = ['copper', 'steel', 'brass']; // Board background var boardBg = self.attachAsset('board_bg', { anchorX: 0.5, anchorY: 0.5, x: self.boardSize / 2, y: self.boardSize / 2 }); // Selection indicator self.selectionIndicator = self.attachAsset('selected_cell', { anchorX: 0.5, anchorY: 0.5 }); self.selectionIndicator.alpha = 0; // Initialize grid cells for (var row = 0; row < self.gridSize; row++) { self.grid[row] = []; for (var col = 0; col < self.gridSize; col++) { // Create cell background var cellBg = self.attachAsset('cell_bg', { anchorX: 0.5, anchorY: 0.5, x: col * (self.cellSize + self.padding) + self.cellSize / 2, y: row * (self.cellSize + self.padding) + self.cellSize / 2 }); // Initialize with null (empty cell) self.grid[row][col] = null; } } // Fill the board with gears self.fillBoard = function () { for (var row = 0; row < self.gridSize; row++) { for (var col = 0; col < self.gridSize; col++) { self.createRandomGear(row, col); } } // Add some rusty bolts as obstacles var numBolts = Math.min(Math.floor(currentLevel / 2) + 2, 10); for (var i = 0; i < numBolts; i++) { var randomRow = Math.floor(Math.random() * self.gridSize); var randomCol = Math.floor(Math.random() * self.gridSize); if (self.grid[randomRow][randomCol]) { self.removeGearAt(randomRow, randomCol); } self.createRustyBolt(randomRow, randomCol); } // Check for initial matches and resolve them self.checkAndResolveMatches(); }; self.createRandomGear = function (row, col) { if (self.grid[row][col]) { self.removeGearAt(row, col); } var randomType = self.gearTypes[Math.floor(Math.random() * self.gearTypes.length)]; var gear = new Gear(randomType); gear.row = row; gear.col = col; gear.x = col * (self.cellSize + self.padding) + self.cellSize / 2; gear.y = row * (self.cellSize + self.padding) + self.cellSize / 2; self.grid[row][col] = gear; self.addChild(gear); return gear; }; self.createRustyBolt = function (row, col) { if (self.grid[row][col]) { self.removeGearAt(row, col); } var bolt = new RustyBolt(); bolt.row = row; bolt.col = col; bolt.x = col * (self.cellSize + self.padding) + self.cellSize / 2; bolt.y = row * (self.cellSize + self.padding) + self.cellSize / 2; self.grid[row][col] = bolt; self.addChild(bolt); return bolt; }; self.removeGearAt = function (row, col) { if (self.grid[row][col]) { self.removeChild(self.grid[row][col]); self.grid[row][col] = null; } }; self.handleGearClick = function (gear) { if (!gear || gear instanceof RustyBolt) { return; } if (self.selectedGear === null) { // Select the gear self.selectedGear = gear; gear.select(); // Show selection indicator self.selectionIndicator.x = gear.x; self.selectionIndicator.y = gear.y; self.selectionIndicator.alpha = 1; } else if (self.selectedGear === gear) { // Deselect the gear self.selectedGear.deselect(); self.selectedGear = null; self.selectionIndicator.alpha = 0; } else { // Check if the gears are adjacent var row1 = self.selectedGear.row; var col1 = self.selectedGear.col; var row2 = gear.row; var col2 = gear.col; if (self.areGearsAdjacent(row1, col1, row2, col2)) { // Swap gears self.swapGears(row1, col1, row2, col2); // Deselect after swapping self.selectedGear.deselect(); self.selectedGear = null; self.selectionIndicator.alpha = 0; } else { // Not adjacent, select the new gear instead self.selectedGear.deselect(); self.selectedGear = gear; gear.select(); // Move selection indicator self.selectionIndicator.x = gear.x; self.selectionIndicator.y = gear.y; } } }; self.areGearsAdjacent = function (row1, col1, row2, col2) { return Math.abs(row1 - row2) === 1 && col1 === col2 || Math.abs(col1 - col2) === 1 && row1 === row2; }; self.swapGears = function (row1, col1, row2, col2) { var gear1 = self.grid[row1][col1]; var gear2 = self.grid[row2][col2]; if (!gear1 || !gear2 || gear1 instanceof RustyBolt || gear2 instanceof RustyBolt) { return false; } // Update grid references self.grid[row1][col1] = gear2; self.grid[row2][col2] = gear1; // Update gear positions var tempRow = gear1.row; var tempCol = gear1.col; gear1.row = gear2.row; gear1.col = gear2.col; gear2.row = tempRow; gear2.col = tempCol; // Animate the swapping tween(gear1, { x: col2 * (self.cellSize + self.padding) + self.cellSize / 2, y: row2 * (self.cellSize + self.padding) + self.cellSize / 2 }, { duration: 300, easing: tween.easeOut }); tween(gear2, { x: col1 * (self.cellSize + self.padding) + self.cellSize / 2, y: row1 * (self.cellSize + self.padding) + self.cellSize / 2 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // After swapping, check for matches var foundMatches = self.checkAndResolveMatches(); // If no matches, swap back if (!foundMatches) { // Update grid references back self.grid[row1][col1] = gear1; self.grid[row2][col2] = gear2; // Update gear data gear1.row = row1; gear1.col = col1; gear2.row = row2; gear2.col = col2; // Animate swapping back tween(gear1, { x: col1 * (self.cellSize + self.padding) + self.cellSize / 2, y: row1 * (self.cellSize + self.padding) + self.cellSize / 2 }, { duration: 300, easing: tween.easeOut }); tween(gear2, { x: col2 * (self.cellSize + self.padding) + self.cellSize / 2, y: row2 * (self.cellSize + self.padding) + self.cellSize / 2 }, { duration: 300, easing: tween.easeOut }); } } }); return true; }; self.checkAndResolveMatches = function () { var matches = self.findMatches(); if (matches.length > 0) { self.resolveMatches(matches); return true; } return false; }; self.findMatches = function () { var matches = []; // Check horizontal matches for (var row = 0; row < self.gridSize; row++) { var currentType = null; var count = 0; var startCol = 0; for (var col = 0; col < self.gridSize; col++) { var gear = self.grid[row][col]; if (gear && gear instanceof Gear) { if (currentType === null) { currentType = gear.type; count = 1; startCol = col; } else if (gear.type === currentType) { count++; } else { if (count >= 3) { matches.push({ row: row, startCol: startCol, endCol: col - 1, direction: 'horizontal', type: currentType, count: count }); } currentType = gear.type; count = 1; startCol = col; } } else { if (count >= 3) { matches.push({ row: row, startCol: startCol, endCol: col - 1, direction: 'horizontal', type: currentType, count: count }); } currentType = null; count = 0; } } // Check at the end of row if (count >= 3) { matches.push({ row: row, startCol: startCol, endCol: self.gridSize - 1, direction: 'horizontal', type: currentType, count: count }); } } // Check vertical matches for (var col = 0; col < self.gridSize; col++) { var currentType = null; var count = 0; var startRow = 0; for (var row = 0; row < self.gridSize; row++) { var gear = self.grid[row][col]; if (gear && gear instanceof Gear) { if (currentType === null) { currentType = gear.type; count = 1; startRow = row; } else if (gear.type === currentType) { count++; } else { if (count >= 3) { matches.push({ col: col, startRow: startRow, endRow: row - 1, direction: 'vertical', type: currentType, count: count }); } currentType = gear.type; count = 1; startRow = row; } } else { if (count >= 3) { matches.push({ col: col, startRow: startRow, endRow: row - 1, direction: 'vertical', type: currentType, count: count }); } currentType = null; count = 0; } } // Check at the end of column if (count >= 3) { matches.push({ col: col, startRow: startRow, endRow: self.gridSize - 1, direction: 'vertical', type: currentType, count: count }); } } return matches; }; self.resolveMatches = function (matches) { var gearsToRemove = []; var pointsGained = 0; var steamGained = 0; // Mark all gears to be removed for (var i = 0; i < matches.length; i++) { var match = matches[i]; var matchCount = 0; if (match.direction === 'horizontal') { for (var col = match.startCol; col <= match.endCol; col++) { if (self.grid[match.row][col] && self.grid[match.row][col] instanceof Gear) { gearsToRemove.push({ row: match.row, col: col }); matchCount++; } } } else { // vertical for (var row = match.startRow; row <= match.endRow; row++) { if (self.grid[row][match.col] && self.grid[row][match.col] instanceof Gear) { gearsToRemove.push({ row: row, col: match.col }); matchCount++; } } } // Calculate points and steam for this match var matchPoints = matchCount * 10; // Basic points var matchSteam = 0; // Special bonuses based on match length if (matchCount >= 5) { matchPoints *= 2; // Double points for 5+ matches matchSteam = 25; // Big steam boost } else if (matchCount >= 4) { matchPoints += 20; // Bonus for 4 matches matchSteam = 15; // Good steam boost } else { matchSteam = 10; // Basic steam boost } // Type bonuses if (match.type === 'brass') { matchPoints += 5; // Bonus for brass gears matchSteam += 5; // Extra steam for brass } else if (match.type === 'steel') { matchPoints += 3; // Small bonus for steel } pointsGained += matchPoints; steamGained += matchSteam; } // Remove duplicate entries var uniqueRemoves = []; for (var i = 0; i < gearsToRemove.length; i++) { var alreadyIncluded = false; for (var j = 0; j < uniqueRemoves.length; j++) { if (gearsToRemove[i].row === uniqueRemoves[j].row && gearsToRemove[i].col === uniqueRemoves[j].col) { alreadyIncluded = true; break; } } if (!alreadyIncluded) { uniqueRemoves.push(gearsToRemove[i]); } } // Play match sound LK.getSound('gear_match').play(); // Add to score score += pointsGained; scoreTxt.setText(score); // Add to steam pressure increasePressure(steamGained); // Animate and remove matched gears for (var i = 0; i < uniqueRemoves.length; i++) { var pos = uniqueRemoves[i]; var gear = self.grid[pos.row][pos.col]; if (gear && gear instanceof Gear) { gear.matched(); self.grid[pos.row][pos.col] = null; } } // Wait for animations to complete before dropping gears LK.setTimeout(function () { self.dropGears(); LK.setTimeout(function () { self.fillEmptyCells(); LK.setTimeout(function () { // Check for more matches after filling self.checkAndResolveMatches(); }, 500); }, 500); }, 300); return uniqueRemoves.length; }; self.dropGears = function () { // For each column, check from bottom to top for (var col = 0; col < self.gridSize; col++) { var emptySpaces = 0; // Start from bottom and count empty spaces for (var row = self.gridSize - 1; row >= 0; row--) { var cell = self.grid[row][col]; if (!cell) { // Empty cell emptySpaces++; } else if (cell instanceof RustyBolt) { // Rusty bolts don't drop emptySpaces = 0; } else if (emptySpaces > 0) { // Move gear down var newRow = row + emptySpaces; self.grid[newRow][col] = cell; self.grid[row][col] = null; // Update gear data cell.row = newRow; // Animate the drop tween(cell, { y: newRow * (self.cellSize + self.padding) + self.cellSize / 2 }, { duration: 300, easing: tween.bounceOut }); } } } }; self.fillEmptyCells = function () { for (var col = 0; col < self.gridSize; col++) { for (var row = 0; row < self.gridSize; row++) { if (!self.grid[row][col]) { // Create new gear from top (with animation) var gear = self.createRandomGear(row, col); // Start position above the board gear.y = -150; // Animate dropping in tween(gear, { y: row * (self.cellSize + self.padding) + self.cellSize / 2 }, { duration: 300, easing: tween.easeIn }); } } } }; self.useHammerAbility = function () { if (self.selectedGear) { // Deselect the current gear self.selectedGear.deselect(); self.selectedGear = null; self.selectionIndicator.alpha = 0; } // Find a rusty bolt to destroy var boltPositions = []; for (var row = 0; row < self.gridSize; row++) { for (var col = 0; col < self.gridSize; col++) { if (self.grid[row][col] instanceof RustyBolt) { boltPositions.push({ row: row, col: col }); } } } if (boltPositions.length > 0) { var randomBolt = boltPositions[Math.floor(Math.random() * boltPositions.length)]; var bolt = self.grid[randomBolt.row][randomBolt.col]; if (bolt) { // Flash effect LK.effects.flashObject(bolt, 0xFFFFFF, 500); // Play sound LK.getSound('ability_use').play(); // Break the bolt bolt.breakBolt(); self.grid[randomBolt.row][randomBolt.col] = null; // Fill in after delay LK.setTimeout(function () { self.dropGears(); LK.setTimeout(function () { self.fillEmptyCells(); LK.setTimeout(function () { self.checkAndResolveMatches(); }, 500); }, 500); }, 500); return true; } } return false; }; self.useTurboChargerAbility = function () { if (self.selectedGear) { // Deselect the current gear self.selectedGear.deselect(); self.selectedGear = null; self.selectionIndicator.alpha = 0; } // Find random positions to make a pattern that will match var row = Math.floor(Math.random() * (self.gridSize - 2)); var col = Math.floor(Math.random() * self.gridSize); var type = self.gearTypes[Math.floor(Math.random() * self.gearTypes.length)]; // Make sure positions don't contain rusty bolts if (self.grid[row][col] instanceof RustyBolt || self.grid[row + 1][col] instanceof RustyBolt || self.grid[row + 2][col] instanceof RustyBolt) { // Try horizontally instead row = Math.floor(Math.random() * self.gridSize); col = Math.floor(Math.random() * (self.gridSize - 2)); // Check again if (self.grid[row][col] instanceof RustyBolt || self.grid[row][col + 1] instanceof RustyBolt || self.grid[row][col + 2] instanceof RustyBolt) { // Find any viable position var foundViablePosition = false; for (var r = 0; r < self.gridSize; r++) { for (var c = 0; c < self.gridSize - 2; c++) { if (!(self.grid[r][c] instanceof RustyBolt) && !(self.grid[r][c + 1] instanceof RustyBolt) && !(self.grid[r][c + 2] instanceof RustyBolt)) { row = r; col = c; foundViablePosition = true; break; } } if (foundViablePosition) { break; } } if (!foundViablePosition) { // No viable position found return false; } } // Create horizontal match if (self.grid[row][col]) { self.removeGearAt(row, col); } if (self.grid[row][col + 1]) { self.removeGearAt(row, col + 1); } if (self.grid[row][col + 2]) { self.removeGearAt(row, col + 2); } var gear1 = self.createRandomGear(row, col); var gear2 = self.createRandomGear(row, col + 1); var gear3 = self.createRandomGear(row, col + 2); gear1.type = gear2.type = gear3.type = type; // Flash effect on the new gears LK.effects.flashObject(gear1, 0xFFD700, 500); LK.effects.flashObject(gear2, 0xFFD700, 500); LK.effects.flashObject(gear3, 0xFFD700, 500); // Play sound LK.getSound('ability_use').play(); } else { // Create vertical match if (self.grid[row][col]) { self.removeGearAt(row, col); } if (self.grid[row + 1][col]) { self.removeGearAt(row + 1, col); } if (self.grid[row + 2][col]) { self.removeGearAt(row + 2, col); } var gear1 = self.createRandomGear(row, col); var gear2 = self.createRandomGear(row + 1, col); var gear3 = self.createRandomGear(row + 2, col); gear1.type = gear2.type = gear3.type = type; // Flash effect on the new gears LK.effects.flashObject(gear1, 0xFFD700, 500); LK.effects.flashObject(gear2, 0xFFD700, 500); LK.effects.flashObject(gear3, 0xFFD700, 500); // Play sound LK.getSound('ability_use').play(); } // Check for matches after a delay LK.setTimeout(function () { self.checkAndResolveMatches(); }, 700); return true; }; return self; }); var Gear = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'copper'; // Default to copper if no type specified var color; switch (self.type) { case 'copper': color = 'gear_copper'; break; case 'steel': color = 'gear_steel'; break; case 'brass': color = 'gear_brass'; break; default: color = 'gear_copper'; } self.gearGraphic = self.attachAsset(color, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.9, scaleY: 0.9 }); // Add teeth to make it look more like a gear self.teethCount = 8; self.radius = self.gearGraphic.width / 2; // Apply a small rotation animation to make gears feel mechanical self.rotationSpeed = Math.random() * 0.01 + 0.005; if (Math.random() > 0.5) { self.rotationSpeed *= -1; } // Random direction self.update = function () { self.gearGraphic.rotation += self.rotationSpeed; }; self.select = function () { tween(self.gearGraphic, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200, easing: tween.easeOut }); LK.getSound('gear_select').play(); }; self.deselect = function () { tween(self.gearGraphic, { scaleX: 0.9, scaleY: 0.9 }, { duration: 200, easing: tween.easeOut }); }; self.matched = function () { tween(self, { alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { if (self.parent) { self.parent.removeChild(self); } } }); }; self.down = function (x, y, obj) { gameBoard.handleGearClick(self); }; return self; }); var RustyBolt = Container.expand(function () { var self = Container.call(this); self.boltGraphic = self.attachAsset('rusty_bolt', { anchorX: 0.5, anchorY: 0.5 }); self.breakBolt = function () { tween(self, { alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { if (self.parent) { self.parent.removeChild(self); } } }); }; self.down = function (x, y, obj) { // Rusty bolts cannot be selected }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C3E50 // Dark blue-gray background }); /**** * Game Code ****/ // Game variables var score = 0; var currentLevel = storage.currentLevel || 1; var targetScore = currentLevel * 1000; // Score needed to complete the level var gameBoard; var boiler; // UI elements var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.y = 50; var levelTxt = new Text2('Level: ' + currentLevel, { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(levelTxt); levelTxt.x = 120; // Leave space for menu icon levelTxt.y = 50; var targetTxt = new Text2('Target: ' + targetScore, { size: 60, fill: 0xFFFFFF }); targetTxt.anchor.set(1, 0); LK.gui.topRight.addChild(targetTxt); targetTxt.y = 50; // Initialize game board gameBoard = new GameBoard(); game.addChild(gameBoard); gameBoard.x = (2048 - gameBoard.boardSize) / 2; gameBoard.y = (2732 - gameBoard.boardSize) / 2; // Initialize boiler (steam pressure meter) boiler = new Boiler(); game.addChild(boiler); boiler.x = 2048 / 2; boiler.y = 2732 - 200; // Fill the board with initial gears gameBoard.fillBoard(); // Function to increase steam pressure function increasePressure(amount) { boiler.updatePressure(boiler.currentPressure + amount); } // Play background music LK.playMusic('steampunk_bgm'); // Main game update loop game.update = function () { // Check if level is complete if (score >= targetScore) { // Level complete logic currentLevel++; storage.currentLevel = currentLevel; // Update high score if (score > storage.highScore) { storage.highScore = score; } // Show win screen LK.showYouWin(); } }; // Global input handling game.down = function (x, y, obj) { // Handle any global click events if needed }; game.move = function (x, y, obj) { // Handle any global move events if needed }; game.up = function (x, y, obj) { // Handle any global release events if needed };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,921 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ currentLevel: 1
+});
+
+/****
+* Classes
+****/
+var Boiler = Container.expand(function () {
+ var self = Container.call(this);
+ // Boiler background
+ self.boilerBg = self.attachAsset('boiler', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Pressure bar background
+ self.pressureBg = self.attachAsset('pressure_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: 25
+ });
+ // Pressure bar
+ self.pressureBar = self.attachAsset('pressure_bar', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: -275,
+ y: 25,
+ scaleX: 0 // Start with empty bar
+ });
+ // Current pressure and max pressure
+ self.currentPressure = 0;
+ self.maxPressure = 100;
+ // Labels for abilities
+ self.hammerLabel = new Text2('Steam Hammer', {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ self.hammerLabel.anchor.set(0.5, 0.5);
+ self.hammerLabel.x = -150;
+ self.hammerLabel.y = -40;
+ self.addChild(self.hammerLabel);
+ self.turboLabel = new Text2('Turbo-Charger', {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ self.turboLabel.anchor.set(0.5, 0.5);
+ self.turboLabel.x = 150;
+ self.turboLabel.y = -40;
+ self.addChild(self.turboLabel);
+ // Button backgrounds
+ self.hammerButtonBg = self.attachAsset('cell_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: -150,
+ y: 0,
+ scaleX: 0.8,
+ scaleY: 0.6
+ });
+ self.turboButtonBg = self.attachAsset('cell_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 150,
+ y: 0,
+ scaleX: 0.8,
+ scaleY: 0.6
+ });
+ // Ability costs
+ self.hammerCost = 25;
+ self.turboCost = 50;
+ // Ability availability
+ self.canUseHammer = false;
+ self.canUseTurbo = false;
+ // Update pressure bar
+ self.updatePressure = function (newPressure) {
+ self.currentPressure = Math.min(newPressure, self.maxPressure);
+ // Update pressure bar scale
+ tween(self.pressureBar, {
+ scaleX: self.currentPressure / self.maxPressure
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ // Update ability availability
+ var previousHammer = self.canUseHammer;
+ var previousTurbo = self.canUseTurbo;
+ self.canUseHammer = self.currentPressure >= self.hammerCost;
+ self.canUseTurbo = self.currentPressure >= self.turboCost;
+ // Visual feedback for available abilities
+ if (self.canUseHammer !== previousHammer) {
+ tween(self.hammerButtonBg, {
+ tint: self.canUseHammer ? 0x44FF44 : 0x444444
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ }
+ if (self.canUseTurbo !== previousTurbo) {
+ tween(self.turboButtonBg, {
+ tint: self.canUseTurbo ? 0x44FF44 : 0x444444
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ }
+ };
+ // Initialize buttons as disabled
+ self.hammerButtonBg.tint = 0x444444;
+ self.turboButtonBg.tint = 0x444444;
+ // Add click handlers for ability buttons
+ self.hammerButtonBg.interactive = true;
+ self.turboButtonBg.interactive = true;
+ self.hammerButtonBg.down = function () {
+ if (self.canUseHammer) {
+ if (gameBoard.useHammerAbility()) {
+ // Ability used successfully
+ self.currentPressure -= self.hammerCost;
+ self.updatePressure(self.currentPressure);
+ // Play steam release sound
+ LK.getSound('steam_release').play();
+ }
+ }
+ };
+ self.turboButtonBg.down = function () {
+ if (self.canUseTurbo) {
+ if (gameBoard.useTurboChargerAbility()) {
+ // Ability used successfully
+ self.currentPressure -= self.turboCost;
+ self.updatePressure(self.currentPressure);
+ // Play steam release sound
+ LK.getSound('steam_release').play();
+ }
+ }
+ };
+ return self;
+});
+var GameBoard = Container.expand(function () {
+ var self = Container.call(this);
+ self.gridSize = 8;
+ self.cellSize = 160;
+ self.padding = 10;
+ self.boardSize = (self.cellSize + self.padding) * self.gridSize;
+ // Metrics for positioning
+ self.boardStartX = (2048 - self.boardSize) / 2;
+ self.boardStartY = (2732 - self.boardSize) / 2;
+ // Game state
+ self.selectedGear = null;
+ self.grid = [];
+ self.gearTypes = ['copper', 'steel', 'brass'];
+ // Board background
+ var boardBg = self.attachAsset('board_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: self.boardSize / 2,
+ y: self.boardSize / 2
+ });
+ // Selection indicator
+ self.selectionIndicator = self.attachAsset('selected_cell', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.selectionIndicator.alpha = 0;
+ // Initialize grid cells
+ for (var row = 0; row < self.gridSize; row++) {
+ self.grid[row] = [];
+ for (var col = 0; col < self.gridSize; col++) {
+ // Create cell background
+ var cellBg = self.attachAsset('cell_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: col * (self.cellSize + self.padding) + self.cellSize / 2,
+ y: row * (self.cellSize + self.padding) + self.cellSize / 2
+ });
+ // Initialize with null (empty cell)
+ self.grid[row][col] = null;
+ }
+ }
+ // Fill the board with gears
+ self.fillBoard = function () {
+ for (var row = 0; row < self.gridSize; row++) {
+ for (var col = 0; col < self.gridSize; col++) {
+ self.createRandomGear(row, col);
+ }
+ }
+ // Add some rusty bolts as obstacles
+ var numBolts = Math.min(Math.floor(currentLevel / 2) + 2, 10);
+ for (var i = 0; i < numBolts; i++) {
+ var randomRow = Math.floor(Math.random() * self.gridSize);
+ var randomCol = Math.floor(Math.random() * self.gridSize);
+ if (self.grid[randomRow][randomCol]) {
+ self.removeGearAt(randomRow, randomCol);
+ }
+ self.createRustyBolt(randomRow, randomCol);
+ }
+ // Check for initial matches and resolve them
+ self.checkAndResolveMatches();
+ };
+ self.createRandomGear = function (row, col) {
+ if (self.grid[row][col]) {
+ self.removeGearAt(row, col);
+ }
+ var randomType = self.gearTypes[Math.floor(Math.random() * self.gearTypes.length)];
+ var gear = new Gear(randomType);
+ gear.row = row;
+ gear.col = col;
+ gear.x = col * (self.cellSize + self.padding) + self.cellSize / 2;
+ gear.y = row * (self.cellSize + self.padding) + self.cellSize / 2;
+ self.grid[row][col] = gear;
+ self.addChild(gear);
+ return gear;
+ };
+ self.createRustyBolt = function (row, col) {
+ if (self.grid[row][col]) {
+ self.removeGearAt(row, col);
+ }
+ var bolt = new RustyBolt();
+ bolt.row = row;
+ bolt.col = col;
+ bolt.x = col * (self.cellSize + self.padding) + self.cellSize / 2;
+ bolt.y = row * (self.cellSize + self.padding) + self.cellSize / 2;
+ self.grid[row][col] = bolt;
+ self.addChild(bolt);
+ return bolt;
+ };
+ self.removeGearAt = function (row, col) {
+ if (self.grid[row][col]) {
+ self.removeChild(self.grid[row][col]);
+ self.grid[row][col] = null;
+ }
+ };
+ self.handleGearClick = function (gear) {
+ if (!gear || gear instanceof RustyBolt) {
+ return;
+ }
+ if (self.selectedGear === null) {
+ // Select the gear
+ self.selectedGear = gear;
+ gear.select();
+ // Show selection indicator
+ self.selectionIndicator.x = gear.x;
+ self.selectionIndicator.y = gear.y;
+ self.selectionIndicator.alpha = 1;
+ } else if (self.selectedGear === gear) {
+ // Deselect the gear
+ self.selectedGear.deselect();
+ self.selectedGear = null;
+ self.selectionIndicator.alpha = 0;
+ } else {
+ // Check if the gears are adjacent
+ var row1 = self.selectedGear.row;
+ var col1 = self.selectedGear.col;
+ var row2 = gear.row;
+ var col2 = gear.col;
+ if (self.areGearsAdjacent(row1, col1, row2, col2)) {
+ // Swap gears
+ self.swapGears(row1, col1, row2, col2);
+ // Deselect after swapping
+ self.selectedGear.deselect();
+ self.selectedGear = null;
+ self.selectionIndicator.alpha = 0;
+ } else {
+ // Not adjacent, select the new gear instead
+ self.selectedGear.deselect();
+ self.selectedGear = gear;
+ gear.select();
+ // Move selection indicator
+ self.selectionIndicator.x = gear.x;
+ self.selectionIndicator.y = gear.y;
+ }
+ }
+ };
+ self.areGearsAdjacent = function (row1, col1, row2, col2) {
+ return Math.abs(row1 - row2) === 1 && col1 === col2 || Math.abs(col1 - col2) === 1 && row1 === row2;
+ };
+ self.swapGears = function (row1, col1, row2, col2) {
+ var gear1 = self.grid[row1][col1];
+ var gear2 = self.grid[row2][col2];
+ if (!gear1 || !gear2 || gear1 instanceof RustyBolt || gear2 instanceof RustyBolt) {
+ return false;
+ }
+ // Update grid references
+ self.grid[row1][col1] = gear2;
+ self.grid[row2][col2] = gear1;
+ // Update gear positions
+ var tempRow = gear1.row;
+ var tempCol = gear1.col;
+ gear1.row = gear2.row;
+ gear1.col = gear2.col;
+ gear2.row = tempRow;
+ gear2.col = tempCol;
+ // Animate the swapping
+ tween(gear1, {
+ x: col2 * (self.cellSize + self.padding) + self.cellSize / 2,
+ y: row2 * (self.cellSize + self.padding) + self.cellSize / 2
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ tween(gear2, {
+ x: col1 * (self.cellSize + self.padding) + self.cellSize / 2,
+ y: row1 * (self.cellSize + self.padding) + self.cellSize / 2
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ // After swapping, check for matches
+ var foundMatches = self.checkAndResolveMatches();
+ // If no matches, swap back
+ if (!foundMatches) {
+ // Update grid references back
+ self.grid[row1][col1] = gear1;
+ self.grid[row2][col2] = gear2;
+ // Update gear data
+ gear1.row = row1;
+ gear1.col = col1;
+ gear2.row = row2;
+ gear2.col = col2;
+ // Animate swapping back
+ tween(gear1, {
+ x: col1 * (self.cellSize + self.padding) + self.cellSize / 2,
+ y: row1 * (self.cellSize + self.padding) + self.cellSize / 2
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ tween(gear2, {
+ x: col2 * (self.cellSize + self.padding) + self.cellSize / 2,
+ y: row2 * (self.cellSize + self.padding) + self.cellSize / 2
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ }
+ }
+ });
+ return true;
+ };
+ self.checkAndResolveMatches = function () {
+ var matches = self.findMatches();
+ if (matches.length > 0) {
+ self.resolveMatches(matches);
+ return true;
+ }
+ return false;
+ };
+ self.findMatches = function () {
+ var matches = [];
+ // Check horizontal matches
+ for (var row = 0; row < self.gridSize; row++) {
+ var currentType = null;
+ var count = 0;
+ var startCol = 0;
+ for (var col = 0; col < self.gridSize; col++) {
+ var gear = self.grid[row][col];
+ if (gear && gear instanceof Gear) {
+ if (currentType === null) {
+ currentType = gear.type;
+ count = 1;
+ startCol = col;
+ } else if (gear.type === currentType) {
+ count++;
+ } else {
+ if (count >= 3) {
+ matches.push({
+ row: row,
+ startCol: startCol,
+ endCol: col - 1,
+ direction: 'horizontal',
+ type: currentType,
+ count: count
+ });
+ }
+ currentType = gear.type;
+ count = 1;
+ startCol = col;
+ }
+ } else {
+ if (count >= 3) {
+ matches.push({
+ row: row,
+ startCol: startCol,
+ endCol: col - 1,
+ direction: 'horizontal',
+ type: currentType,
+ count: count
+ });
+ }
+ currentType = null;
+ count = 0;
+ }
+ }
+ // Check at the end of row
+ if (count >= 3) {
+ matches.push({
+ row: row,
+ startCol: startCol,
+ endCol: self.gridSize - 1,
+ direction: 'horizontal',
+ type: currentType,
+ count: count
+ });
+ }
+ }
+ // Check vertical matches
+ for (var col = 0; col < self.gridSize; col++) {
+ var currentType = null;
+ var count = 0;
+ var startRow = 0;
+ for (var row = 0; row < self.gridSize; row++) {
+ var gear = self.grid[row][col];
+ if (gear && gear instanceof Gear) {
+ if (currentType === null) {
+ currentType = gear.type;
+ count = 1;
+ startRow = row;
+ } else if (gear.type === currentType) {
+ count++;
+ } else {
+ if (count >= 3) {
+ matches.push({
+ col: col,
+ startRow: startRow,
+ endRow: row - 1,
+ direction: 'vertical',
+ type: currentType,
+ count: count
+ });
+ }
+ currentType = gear.type;
+ count = 1;
+ startRow = row;
+ }
+ } else {
+ if (count >= 3) {
+ matches.push({
+ col: col,
+ startRow: startRow,
+ endRow: row - 1,
+ direction: 'vertical',
+ type: currentType,
+ count: count
+ });
+ }
+ currentType = null;
+ count = 0;
+ }
+ }
+ // Check at the end of column
+ if (count >= 3) {
+ matches.push({
+ col: col,
+ startRow: startRow,
+ endRow: self.gridSize - 1,
+ direction: 'vertical',
+ type: currentType,
+ count: count
+ });
+ }
+ }
+ return matches;
+ };
+ self.resolveMatches = function (matches) {
+ var gearsToRemove = [];
+ var pointsGained = 0;
+ var steamGained = 0;
+ // Mark all gears to be removed
+ for (var i = 0; i < matches.length; i++) {
+ var match = matches[i];
+ var matchCount = 0;
+ if (match.direction === 'horizontal') {
+ for (var col = match.startCol; col <= match.endCol; col++) {
+ if (self.grid[match.row][col] && self.grid[match.row][col] instanceof Gear) {
+ gearsToRemove.push({
+ row: match.row,
+ col: col
+ });
+ matchCount++;
+ }
+ }
+ } else {
+ // vertical
+ for (var row = match.startRow; row <= match.endRow; row++) {
+ if (self.grid[row][match.col] && self.grid[row][match.col] instanceof Gear) {
+ gearsToRemove.push({
+ row: row,
+ col: match.col
+ });
+ matchCount++;
+ }
+ }
+ }
+ // Calculate points and steam for this match
+ var matchPoints = matchCount * 10; // Basic points
+ var matchSteam = 0;
+ // Special bonuses based on match length
+ if (matchCount >= 5) {
+ matchPoints *= 2; // Double points for 5+ matches
+ matchSteam = 25; // Big steam boost
+ } else if (matchCount >= 4) {
+ matchPoints += 20; // Bonus for 4 matches
+ matchSteam = 15; // Good steam boost
+ } else {
+ matchSteam = 10; // Basic steam boost
+ }
+ // Type bonuses
+ if (match.type === 'brass') {
+ matchPoints += 5; // Bonus for brass gears
+ matchSteam += 5; // Extra steam for brass
+ } else if (match.type === 'steel') {
+ matchPoints += 3; // Small bonus for steel
+ }
+ pointsGained += matchPoints;
+ steamGained += matchSteam;
+ }
+ // Remove duplicate entries
+ var uniqueRemoves = [];
+ for (var i = 0; i < gearsToRemove.length; i++) {
+ var alreadyIncluded = false;
+ for (var j = 0; j < uniqueRemoves.length; j++) {
+ if (gearsToRemove[i].row === uniqueRemoves[j].row && gearsToRemove[i].col === uniqueRemoves[j].col) {
+ alreadyIncluded = true;
+ break;
+ }
+ }
+ if (!alreadyIncluded) {
+ uniqueRemoves.push(gearsToRemove[i]);
+ }
+ }
+ // Play match sound
+ LK.getSound('gear_match').play();
+ // Add to score
+ score += pointsGained;
+ scoreTxt.setText(score);
+ // Add to steam pressure
+ increasePressure(steamGained);
+ // Animate and remove matched gears
+ for (var i = 0; i < uniqueRemoves.length; i++) {
+ var pos = uniqueRemoves[i];
+ var gear = self.grid[pos.row][pos.col];
+ if (gear && gear instanceof Gear) {
+ gear.matched();
+ self.grid[pos.row][pos.col] = null;
+ }
+ }
+ // Wait for animations to complete before dropping gears
+ LK.setTimeout(function () {
+ self.dropGears();
+ LK.setTimeout(function () {
+ self.fillEmptyCells();
+ LK.setTimeout(function () {
+ // Check for more matches after filling
+ self.checkAndResolveMatches();
+ }, 500);
+ }, 500);
+ }, 300);
+ return uniqueRemoves.length;
+ };
+ self.dropGears = function () {
+ // For each column, check from bottom to top
+ for (var col = 0; col < self.gridSize; col++) {
+ var emptySpaces = 0;
+ // Start from bottom and count empty spaces
+ for (var row = self.gridSize - 1; row >= 0; row--) {
+ var cell = self.grid[row][col];
+ if (!cell) {
+ // Empty cell
+ emptySpaces++;
+ } else if (cell instanceof RustyBolt) {
+ // Rusty bolts don't drop
+ emptySpaces = 0;
+ } else if (emptySpaces > 0) {
+ // Move gear down
+ var newRow = row + emptySpaces;
+ self.grid[newRow][col] = cell;
+ self.grid[row][col] = null;
+ // Update gear data
+ cell.row = newRow;
+ // Animate the drop
+ tween(cell, {
+ y: newRow * (self.cellSize + self.padding) + self.cellSize / 2
+ }, {
+ duration: 300,
+ easing: tween.bounceOut
+ });
+ }
+ }
+ }
+ };
+ self.fillEmptyCells = function () {
+ for (var col = 0; col < self.gridSize; col++) {
+ for (var row = 0; row < self.gridSize; row++) {
+ if (!self.grid[row][col]) {
+ // Create new gear from top (with animation)
+ var gear = self.createRandomGear(row, col);
+ // Start position above the board
+ gear.y = -150;
+ // Animate dropping in
+ tween(gear, {
+ y: row * (self.cellSize + self.padding) + self.cellSize / 2
+ }, {
+ duration: 300,
+ easing: tween.easeIn
+ });
+ }
+ }
+ }
+ };
+ self.useHammerAbility = function () {
+ if (self.selectedGear) {
+ // Deselect the current gear
+ self.selectedGear.deselect();
+ self.selectedGear = null;
+ self.selectionIndicator.alpha = 0;
+ }
+ // Find a rusty bolt to destroy
+ var boltPositions = [];
+ for (var row = 0; row < self.gridSize; row++) {
+ for (var col = 0; col < self.gridSize; col++) {
+ if (self.grid[row][col] instanceof RustyBolt) {
+ boltPositions.push({
+ row: row,
+ col: col
+ });
+ }
+ }
+ }
+ if (boltPositions.length > 0) {
+ var randomBolt = boltPositions[Math.floor(Math.random() * boltPositions.length)];
+ var bolt = self.grid[randomBolt.row][randomBolt.col];
+ if (bolt) {
+ // Flash effect
+ LK.effects.flashObject(bolt, 0xFFFFFF, 500);
+ // Play sound
+ LK.getSound('ability_use').play();
+ // Break the bolt
+ bolt.breakBolt();
+ self.grid[randomBolt.row][randomBolt.col] = null;
+ // Fill in after delay
+ LK.setTimeout(function () {
+ self.dropGears();
+ LK.setTimeout(function () {
+ self.fillEmptyCells();
+ LK.setTimeout(function () {
+ self.checkAndResolveMatches();
+ }, 500);
+ }, 500);
+ }, 500);
+ return true;
+ }
+ }
+ return false;
+ };
+ self.useTurboChargerAbility = function () {
+ if (self.selectedGear) {
+ // Deselect the current gear
+ self.selectedGear.deselect();
+ self.selectedGear = null;
+ self.selectionIndicator.alpha = 0;
+ }
+ // Find random positions to make a pattern that will match
+ var row = Math.floor(Math.random() * (self.gridSize - 2));
+ var col = Math.floor(Math.random() * self.gridSize);
+ var type = self.gearTypes[Math.floor(Math.random() * self.gearTypes.length)];
+ // Make sure positions don't contain rusty bolts
+ if (self.grid[row][col] instanceof RustyBolt || self.grid[row + 1][col] instanceof RustyBolt || self.grid[row + 2][col] instanceof RustyBolt) {
+ // Try horizontally instead
+ row = Math.floor(Math.random() * self.gridSize);
+ col = Math.floor(Math.random() * (self.gridSize - 2));
+ // Check again
+ if (self.grid[row][col] instanceof RustyBolt || self.grid[row][col + 1] instanceof RustyBolt || self.grid[row][col + 2] instanceof RustyBolt) {
+ // Find any viable position
+ var foundViablePosition = false;
+ for (var r = 0; r < self.gridSize; r++) {
+ for (var c = 0; c < self.gridSize - 2; c++) {
+ if (!(self.grid[r][c] instanceof RustyBolt) && !(self.grid[r][c + 1] instanceof RustyBolt) && !(self.grid[r][c + 2] instanceof RustyBolt)) {
+ row = r;
+ col = c;
+ foundViablePosition = true;
+ break;
+ }
+ }
+ if (foundViablePosition) {
+ break;
+ }
+ }
+ if (!foundViablePosition) {
+ // No viable position found
+ return false;
+ }
+ }
+ // Create horizontal match
+ if (self.grid[row][col]) {
+ self.removeGearAt(row, col);
+ }
+ if (self.grid[row][col + 1]) {
+ self.removeGearAt(row, col + 1);
+ }
+ if (self.grid[row][col + 2]) {
+ self.removeGearAt(row, col + 2);
+ }
+ var gear1 = self.createRandomGear(row, col);
+ var gear2 = self.createRandomGear(row, col + 1);
+ var gear3 = self.createRandomGear(row, col + 2);
+ gear1.type = gear2.type = gear3.type = type;
+ // Flash effect on the new gears
+ LK.effects.flashObject(gear1, 0xFFD700, 500);
+ LK.effects.flashObject(gear2, 0xFFD700, 500);
+ LK.effects.flashObject(gear3, 0xFFD700, 500);
+ // Play sound
+ LK.getSound('ability_use').play();
+ } else {
+ // Create vertical match
+ if (self.grid[row][col]) {
+ self.removeGearAt(row, col);
+ }
+ if (self.grid[row + 1][col]) {
+ self.removeGearAt(row + 1, col);
+ }
+ if (self.grid[row + 2][col]) {
+ self.removeGearAt(row + 2, col);
+ }
+ var gear1 = self.createRandomGear(row, col);
+ var gear2 = self.createRandomGear(row + 1, col);
+ var gear3 = self.createRandomGear(row + 2, col);
+ gear1.type = gear2.type = gear3.type = type;
+ // Flash effect on the new gears
+ LK.effects.flashObject(gear1, 0xFFD700, 500);
+ LK.effects.flashObject(gear2, 0xFFD700, 500);
+ LK.effects.flashObject(gear3, 0xFFD700, 500);
+ // Play sound
+ LK.getSound('ability_use').play();
+ }
+ // Check for matches after a delay
+ LK.setTimeout(function () {
+ self.checkAndResolveMatches();
+ }, 700);
+ return true;
+ };
+ return self;
+});
+var Gear = Container.expand(function (type) {
+ var self = Container.call(this);
+ self.type = type || 'copper'; // Default to copper if no type specified
+ var color;
+ switch (self.type) {
+ case 'copper':
+ color = 'gear_copper';
+ break;
+ case 'steel':
+ color = 'gear_steel';
+ break;
+ case 'brass':
+ color = 'gear_brass';
+ break;
+ default:
+ color = 'gear_copper';
+ }
+ self.gearGraphic = self.attachAsset(color, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.9,
+ scaleY: 0.9
+ });
+ // Add teeth to make it look more like a gear
+ self.teethCount = 8;
+ self.radius = self.gearGraphic.width / 2;
+ // Apply a small rotation animation to make gears feel mechanical
+ self.rotationSpeed = Math.random() * 0.01 + 0.005;
+ if (Math.random() > 0.5) {
+ self.rotationSpeed *= -1;
+ } // Random direction
+ self.update = function () {
+ self.gearGraphic.rotation += self.rotationSpeed;
+ };
+ self.select = function () {
+ tween(self.gearGraphic, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ LK.getSound('gear_select').play();
+ };
+ self.deselect = function () {
+ tween(self.gearGraphic, {
+ scaleX: 0.9,
+ scaleY: 0.9
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ };
+ self.matched = function () {
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (self.parent) {
+ self.parent.removeChild(self);
+ }
+ }
+ });
+ };
+ self.down = function (x, y, obj) {
+ gameBoard.handleGearClick(self);
+ };
+ return self;
+});
+var RustyBolt = Container.expand(function () {
+ var self = Container.call(this);
+ self.boltGraphic = self.attachAsset('rusty_bolt', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.breakBolt = function () {
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (self.parent) {
+ self.parent.removeChild(self);
+ }
+ }
+ });
+ };
+ self.down = function (x, y, obj) {
+ // Rusty bolts cannot be selected
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2C3E50 // Dark blue-gray background
+});
+
+/****
+* Game Code
+****/
+// Game variables
+var score = 0;
+var currentLevel = storage.currentLevel || 1;
+var targetScore = currentLevel * 1000; // Score needed to complete the level
+var gameBoard;
+var boiler;
+// UI elements
+var scoreTxt = new Text2('0', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+scoreTxt.y = 50;
+var levelTxt = new Text2('Level: ' + currentLevel, {
+ size: 60,
+ fill: 0xFFFFFF
+});
+levelTxt.anchor.set(0, 0);
+LK.gui.topLeft.addChild(levelTxt);
+levelTxt.x = 120; // Leave space for menu icon
+levelTxt.y = 50;
+var targetTxt = new Text2('Target: ' + targetScore, {
+ size: 60,
+ fill: 0xFFFFFF
+});
+targetTxt.anchor.set(1, 0);
+LK.gui.topRight.addChild(targetTxt);
+targetTxt.y = 50;
+// Initialize game board
+gameBoard = new GameBoard();
+game.addChild(gameBoard);
+gameBoard.x = (2048 - gameBoard.boardSize) / 2;
+gameBoard.y = (2732 - gameBoard.boardSize) / 2;
+// Initialize boiler (steam pressure meter)
+boiler = new Boiler();
+game.addChild(boiler);
+boiler.x = 2048 / 2;
+boiler.y = 2732 - 200;
+// Fill the board with initial gears
+gameBoard.fillBoard();
+// Function to increase steam pressure
+function increasePressure(amount) {
+ boiler.updatePressure(boiler.currentPressure + amount);
+}
+// Play background music
+LK.playMusic('steampunk_bgm');
+// Main game update loop
+game.update = function () {
+ // Check if level is complete
+ if (score >= targetScore) {
+ // Level complete logic
+ currentLevel++;
+ storage.currentLevel = currentLevel;
+ // Update high score
+ if (score > storage.highScore) {
+ storage.highScore = score;
+ }
+ // Show win screen
+ LK.showYouWin();
+ }
+};
+// Global input handling
+game.down = function (x, y, obj) {
+ // Handle any global click events if needed
+};
+game.move = function (x, y, obj) {
+ // Handle any global move events if needed
+};
+game.up = function (x, y, obj) {
+ // Handle any global release events if needed
+};
\ No newline at end of file
латунная шестерня в стиле hand-paint. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
медная шестерня в стиле hand-paint. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
стальная шестерня в стиле hand-paint. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
ржавый болт в стиле hand-paint. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
котел в стиле hand-paint. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A hand-painted, steampunk-style illustration of billowing steam and smoke, rich with warm copper tones and industrial textures. The vapor swirls dynamically around intricate brass gears and pipes, glowing with subtle orange highlights as if lit by flickering gaslight. The painting style should mimic traditional concept art with visible brush strokes, soft edges, and a slightly weathered, vintage feel. The background features hints of a dimly lit factory, with atmospheric perspective fading into deep browns and blues. The steam itself appears thick, almost liquid, with a mix of transparency and volumetric density, evoking a sense of pressurized heat. Artstation trending, fantasy illustration, painterly style, warm lighting. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
фон для прогресс бара. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows