Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'initialSpawn is not defined' in or related to this line: 'initialSpawn();' Line Number: 778
User prompt
Please fix the bug: 'ReferenceError: quantumSelectionActive is not defined' in or related to this line: 'if (quantumSelectionActive) {' Line Number: 746
User prompt
Please fix the bug: 'ReferenceError: upgradeMenu is not defined' in or related to this line: 'if (upgradeMenu.parent) {' Line Number: 733
User prompt
Please fix the bug: 'ReferenceError: droneObjects is not defined' in or related to this line: 'for (var i = 0; i < droneObjects.length; i++) {' Line Number: 715
User prompt
Please fix the bug: 'ReferenceError: clusters is not defined' in or related to this line: 'clusters.forEach(function (c) {' Line Number: 167
User prompt
Please fix the bug: 'updateUI is not defined' in or related to this line: 'updateUI();' Line Number: 783
User prompt
Please fix the bug: 'initialSpawn is not defined' in or related to this line: 'initialSpawn();' Line Number: 778
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'elapsed')' in or related to this line: 'self.y += Math.sin(LK.time.elapsed / 250) * 0.5;' Line Number: 262
User prompt
var Drone = Container.expand(function () { var self = Container.call(this); // Attach the drone sprite self.droneSprite = LK.getAsset('drone_asset', { anchorX: 0.5, anchorY: 0.5 }); self.addChild(self.droneSprite); // Movement self.vx = (Math.random() - 0.5) * 6; // random velocity x self.vy = (Math.random() - 0.5) * 6; // random velocity y self.speed = 3; self.changeDirCounter = 0; // how many frames until we pick new direction // AoE stats self.AOE_RANGE = 100; self.droneDamage = 2; // how much damage each zap deals (tweak as needed) self.cooldown = 0; // frames self.COOLDOWN_MAX = 60; // 1 second if your game is ~60fps self.updateDrone = function () { // 1) Movement if (self.changeDirCounter <= 0) { // pick new random direction occasionally self.vx = (Math.random() - 0.5) * self.speed; self.vy = (Math.random() - 0.5) * self.speed; self.changeDirCounter = 120; // every 2s } else { self.changeDirCounter--; } // update position self.x += self.vx; self.y += self.vy; // bounce off edges (assuming 2048x2732 stage) if (self.x < 50 || self.x > 2000) self.vx *= -1; if (self.y < 50 || self.y > 2682) self.vy *= -1; // 2) AoE Zap if cooldown is ready if (self.cooldown > 0) { self.cooldown--; } else { self.tryZap(); } }; self.tryZap = function () { // Find any ore within AOE_RANGE // We'll gather a list of clusters or single ores within range var anyHit = false; clusters.forEach(function (cluster) { cluster.oreList.forEach(function (ore) { if (ore.health > 0) { var oreGlobalX = cluster.x + ore.x; var oreGlobalY = cluster.y + ore.y; var dx = self.x - oreGlobalX; var dy = self.y - oreGlobalY; var dist = Math.sqrt(dx*dx + dy*dy); if (dist < self.AOE_RANGE) { // deal damage ore.health -= self.droneDamage; anyHit = true; if (ore.health <= 0) { var baseValue = ore.getValue(); gameState.money += baseValue; updateUI(); ore.cluster.notifyOreDestroyed(ore); spawnMiningParticles(ore, 5); } } } }); }); // If we zapped anything, apply cooldown if (anyHit) { self.cooldown = self.COOLDOWN_MAX; } }; return self; }); game.update = function () { // existing miner update if (miner) miner.update(); // your other logic (clusters, etc.) // update each drone for (var i = 0; i < droneObjects.length; i++) { droneObjects[i].updateDrone(); } }; { id: 'drone_level_1', name: 'Buy Drones (Lv +1)', cost: 5000, effect: 'Each level adds another drone that roams & AoE zaps', purchased: false, multi: true, level: 0, action: function () { if (!gameState.droneLevel) gameState.droneLevel = 0; gameState.droneLevel++; this.level++; this.cost = Math.floor(this.cost * 1.5); updateDroneObjects(); } } var droneObjects = []; // A function to create new drones up to gameState.droneLevel function updateDroneObjects() { // If we want exactly gameState.droneLevel drones: while (droneObjects.length < gameState.droneLevel) { var d = new Drone(); // position them randomly d.x = 200 + Math.random() * (2048 - 400); d.y = 200 + Math.random() * (2732 - 400); droneObjects.push(d); game.addChild(d); } }
User prompt
// Make sure to call updateDroneSprites() after you buy or increase drone level: { // inside the 'drone_level_1' upgrade or anywhere you increment droneLevel: action: function () { gameState.droneLevel++; this.level++; this.cost = Math.floor(this.cost * 1.5); updateDroneSprites(); } }
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'elapsed')' in or related to this line: 'if (LK.time.elapsed % 60 === 0) {' Line Number: 1332
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'p.x = ore.parent.x + ore.x;' Line Number: 336
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'p.x = ore.parent.x + ore.x;' Line Number: 294
Code edit (1 edits merged)
Please save this source code
User prompt
Fix it
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'ref.textObj.style.fill = 0x666666;' Line Number: 638
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'ref.textObj.style.fill = 0x666666;' Line Number: 637
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 75
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'p.lastX = ore.parent.x + ore.x;' Line Number: 317
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'p.x = ore.parent.x + ore.x;' Line Number: 317
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ /**** * CLASSES ****/ /** * Cluster spawns multiple Ore objects of a given type. */ var Cluster = Container.expand(function (type) { var self = Container.call(this); self.type = type; self.oreList = []; // Random center var centerX = 100 + Math.random() * (2048 - 200); var centerY = 100 + Math.random() * (2732 - 200); self.x = centerX; self.y = centerY; // Decide how many ore in this cluster var cc = gameState.clusterConfig; var count = randomInt(cc.min, cc.max); // Create ore for (var i = 0; i < count; i++) { var ore = new Ore(type, self); ore.x = (Math.random() - 0.5) * 120; ore.y = (Math.random() - 0.5) * 120; self.oreList.push(ore); self.addChild(ore); } self.notifyOreDestroyed = function (ore) { var idx = self.oreList.indexOf(ore); if (idx >= 0) { self.oreList.splice(idx, 1); } ore.destroy(); // If all gone => remove cluster if (self.oreList.length === 0) { if (self.parent) { self.parent.removeChild(self); } var cidx = clusters.indexOf(self); if (cidx >= 0) { clusters.splice(cidx, 1); } gameState.clusterCount[type]--; // Wait respawnTime, then spawn new cluster var finalDelay = gameState.respawnTime; if (type === 'coal') { finalDelay *= 2; // slow for coal } LK.setTimeout(function () { maybeSpawnCluster(type); }, finalDelay); } }; return self; }); /** * Miner moves to the closest valid ore and mines it. */ var Miner = Container.expand(function () { var self = Container.call(this); self.attachAsset('miner', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.currentTarget = null; self.miningRange = 25; self.miningCooldown = 0; self.miningRate = 30; // frames per "hit" self.miningDamage = 1; self.findNewTarget = function () { var validOre = []; clusters.forEach(function (c) { c.oreList.forEach(function (ore) { if (ore.health > 0 && ore.tier <= gameState.currentTier) { validOre.push(ore); } }); }); if (validOre.length === 0) { self.currentTarget = null; return; } // Sort by distance self.currentTarget = validOre.sort(function (a, b) { var aX = a.parent.x + a.x; var aY = a.parent.y + a.y; var bX = b.parent.x + b.x; var bY = b.parent.y + b.y; var distA = Math.hypot(aX - self.x, aY - self.y); var distB = Math.hypot(bX - self.x, bY - self.y); return distA - distB; })[0]; }; self.update = function () { self.findNewTarget(); if (self.currentTarget) { var tx = self.currentTarget.parent.x + self.currentTarget.x; var ty = self.currentTarget.parent.y + self.currentTarget.y; var dx = tx - self.x; var dy = ty - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > self.miningRange) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } else { self.mineOre(self.currentTarget); } } else { // idle float self.y += Math.sin(LK.time.elapsed / 250) * 0.5; } }; self.mineOre = function (ore) { if (self.miningCooldown > 0) { self.miningCooldown--; return; } ore.health -= self.miningDamage * gameState.pickaxeLevel; self.miningCooldown = self.miningRate; if (ore.health <= 0) { // Add money gameState.money += ore.getValue(); updateUI(); ore.cluster.notifyOreDestroyed(ore); spawnMiningParticles(ore, 5); } else { spawnMiningParticles(ore, 2); } }; return self; }); /** * A single ore object (7 possible types). */ var Ore = Container.expand(function (type, cluster) { var self = Container.call(this); self.type = type; self.cluster = cluster; // Determine tier based on order in this array: // [coal, iron, gold, diamond, sapphire, emerald, ruby] var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; self.tier = typeList.indexOf(type) + 1; self.baseValue = oreData[type].baseValue; self.maxHealth = oreData[type].baseHealth; self.health = self.maxHealth; // Attach sprite self.attachAsset(type + '_ore', { anchorX: 0.5, anchorY: 0.5 }); // Health bar self.healthBar = LK.getAsset('rectangle', { width: 120, height: 20, fill: 0x00FF00, anchorX: 0.5, anchorY: 0.5 }); self.healthBar.x = 0; self.healthBar.y = -70; self.addChild(self.healthBar); self.getValue = function () { return self.baseValue * gameState.oreMultipliers[self.type]; }; return self; }); /**** * Initialize Game ****/ /**** * HELPER FUNCTIONS ****/ /**** * THE GAME ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ // We'll keep references to each cluster container /**** * GLOBAL ARRAYS & STATE ****/ /**** * PLUGINS ****/ // NEW asset for shop icon // NEW assets for additional ores: /**** * ASSETS ****/ // Create Miner var clusters = []; /**** * ORE DATA ****/ var oreData = { coal: { baseValue: 5, baseHealth: 10 }, iron: { baseValue: 500, baseHealth: 100 }, gold: { baseValue: 10000, baseHealth: 500 }, diamond: { baseValue: 25000, baseHealth: 1000 }, sapphire: { baseValue: 100000, baseHealth: 2000 }, emerald: { baseValue: 500000, baseHealth: 5000 }, ruby: { baseValue: 1000000, baseHealth: 10000 } }; /**** * GAME STATE ****/ var gameState = { money: 0, pickaxeLevel: 1, currentTier: 1, oreMultipliers: { coal: 1, iron: 1, gold: 1, diamond: 1, sapphire: 1, emerald: 1, ruby: 1 }, // For controlling cluster spawns & respawns respawnTime: 3000, // base maxClustersPerType: 3, clusterCount: { coal: 0, iron: 0, gold: 0, diamond: 0, sapphire: 0, emerald: 0, ruby: 0 }, clusterConfigLevels: [{ min: 2, max: 3 }, // default { min: 2, max: 4 }, { min: 3, max: 5 }, { min: 5, max: 10 }], clusterUpgradeTier: 0, get clusterConfig() { return this.clusterConfigLevels[this.clusterUpgradeTier] || { min: 2, max: 3 }; } }; /**** * HELPER FUNCTIONS ****/ function maybeSpawnCluster(type) { var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; var tIndex = typeList.indexOf(type) + 1; if (tIndex > gameState.currentTier) { return; } if (gameState.clusterCount[type] >= gameState.maxClustersPerType) { return; } var cluster = new Cluster(type); game.addChild(cluster); clusters.push(cluster); gameState.clusterCount[type]++; } function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function spawnMiningParticles(ore, num) { for (var i = 0; i < num; i++) { var p = LK.getAsset('mining_particle', { anchorX: 0.5, anchorY: 0.5 }); p.x = ore.parent.x + ore.x; p.y = ore.parent.y + ore.y; p.vx = (Math.random() - 0.5) * 10; p.vy = (Math.random() - 0.5) * 10; p.alpha = 1; tween(p, { alpha: 0, y: p.y - 50 }, { duration: 1000, onFinish: function onFinish() { p.destroy(); } }); game.addChild(p); } } function interpolateColor(c1, c2, f) { var r1 = c1 >> 16 & 0xFF, g1 = c1 >> 8 & 0xFF, b1 = c1 & 0xFF; var r2 = c2 >> 16 & 0xFF, g2 = c2 >> 8 & 0xFF, b2 = c2 & 0xFF; var r = Math.round(r1 + f * (r2 - r1)); var g = Math.round(g1 + f * (g2 - g1)); var b = Math.round(b1 + f * (b2 - b1)); return r << 16 | g << 8 | b; } var miner = game.addChild(new Miner()); miner.x = 2048 / 2; miner.y = 2732 / 2; // Background var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5 }); background.x = 2048 / 2; background.y = 2732 / 2; game.addChildAt(background, 0); /**** * UI ****/ var upgradeMenu = new Container(); var tooltip = new Text2('', { size: 40, fill: 0xFFFFFF }); game.addChild(tooltip); var moneyDisplay = new Text2('$0', { size: 80, fill: 0xFFFFFF, fontWeight: 'bold', stroke: 0x000000, strokeThickness: 5 }); moneyDisplay.x = 2048 / 2 - moneyDisplay.width / 2; moneyDisplay.y = 50; game.addChild(moneyDisplay); // Shop icon (replacing the old buy_button for opening menu) var shopOpenButton = LK.getAsset('shop_icon', { anchorX: 0.5, anchorY: 0.5 }); shopOpenButton.x = 2048 - 150; shopOpenButton.y = 2732 - 150; shopOpenButton.down = function () { createMainUpgradeMenu(); game.addChild(upgradeMenu); }; game.addChild(shopOpenButton); // Debug: Add money button var addMoneyButton = LK.getAsset('buy_button', { anchorX: 0.5, anchorY: 0.5 }); addMoneyButton.x = 200; addMoneyButton.y = 2732 - 150; addMoneyButton.down = function () { gameState.money += 50000; updateUI(); }; game.addChild(addMoneyButton); /**** * UPGRADE DEFINITIONS ****/ // Each ore has (1) an unlock (except coal) and (2) a double-value multi upgrade. var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; // “Unlock” costs + “Double Value” costs are arbitrary examples. Tweak if desired. var oreUpgrades = { coal: [{ id: 'double_coal', name: 'Double Coal Value', cost: 100, multi: true, level: 0, effect: 'Doubles Coal Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.coal *= 2; this.cost *= 2; } }], iron: [{ id: 'unlock_iron', name: 'Unlock Iron Mining', cost: 500, effect: 'Allows iron ore clusters to spawn', purchased: false, action: function action() { // Increase currentTier if needed if (gameState.currentTier < 2) { gameState.currentTier = 2; } // Immediately spawn some iron for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('iron'); } } }, { id: 'double_iron', name: 'Double Iron Value', cost: 1000, multi: true, level: 0, effect: 'Doubles Iron Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.iron *= 2; this.cost *= 2; } }], gold: [{ id: 'unlock_gold', name: 'Unlock Gold Mining', cost: 5000, effect: 'Allows gold ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 3) { gameState.currentTier = 3; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('gold'); } } }, { id: 'double_gold', name: 'Double Gold Value', cost: 20000, multi: true, level: 0, effect: 'Doubles Gold Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.gold *= 2; this.cost *= 2; } }], diamond: [{ id: 'unlock_diamond', name: 'Unlock Diamond Mining', cost: 20000, effect: 'Allows diamond ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 4) { gameState.currentTier = 4; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('diamond'); } } }, { id: 'double_diamond', name: 'Double Diamond Value', cost: 50000, multi: true, level: 0, effect: 'Doubles Diamond Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.diamond *= 2; this.cost *= 2; } }], sapphire: [{ id: 'unlock_sapphire', name: 'Unlock Sapphire Mining', cost: 100000, effect: 'Allows sapphire ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 5) { gameState.currentTier = 5; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('sapphire'); } } }, { id: 'double_sapphire', name: 'Double Sapphire Value', cost: 200000, multi: true, level: 0, effect: 'Doubles Sapphire Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.sapphire *= 2; this.cost *= 2; } }], emerald: [{ id: 'unlock_emerald', name: 'Unlock Emerald Mining', cost: 500000, effect: 'Allows emerald ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 6) { gameState.currentTier = 6; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('emerald'); } } }, { id: 'double_emerald', name: 'Double Emerald Value', cost: 1000000, multi: true, level: 0, effect: 'Doubles Emerald Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.emerald *= 2; this.cost *= 2; } }], ruby: [{ id: 'unlock_ruby', name: 'Unlock Ruby Mining', cost: 1000000, effect: 'Allows ruby ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 7) { gameState.currentTier = 7; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('ruby'); } } }, { id: 'double_ruby', name: 'Double Ruby Value', cost: 2000000, multi: true, level: 0, effect: 'Doubles Ruby Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.ruby *= 2; this.cost *= 2; } }] }; // General Upgrades var generalUpgrades = [{ id: 'faster_respawn', name: 'Quicker Respawn', cost: 8000, effect: 'Halves respawn time (min 500 ms)', purchased: false, action: function action() { gameState.respawnTime = Math.max(500, gameState.respawnTime / 2); } }, { id: 'cluster_up', name: 'Cluster Growth', cost: 1000, effect: 'Increases cluster size range', purchased: false, action: function action() { if (gameState.clusterUpgradeTier < gameState.clusterConfigLevels.length - 1) { gameState.clusterUpgradeTier++; } this.cost += 2000; } }]; /**** * MAIN MENU ****/ function createMainUpgradeMenu() { upgradeMenu.removeChildren(); subUpgradeItemRefs = []; // reset // Big background var menuBg = LK.getAsset('rectangle', { width: 1800, height: 2000, color: 0x2a2a2a, anchorX: 0.5, anchorY: 0.5 }); menuBg.x = 2048 / 2; menuBg.y = 2732 / 2 + 50; upgradeMenu.addChild(menuBg); // We'll define 8 “categories”: 7 Ores + 1 “General” var categories = [{ name: 'Coal Upgrades', yOff: -700, type: 'coal' }, { name: 'Iron Upgrades', yOff: -500, type: 'iron' }, { name: 'Gold Upgrades', yOff: -300, type: 'gold' }, { name: 'Diamond Upgrades', yOff: -100, type: 'diamond' }, { name: 'Sapphire Upgrades', yOff: 100, type: 'sapphire' }, { name: 'Emerald Upgrades', yOff: 300, type: 'emerald' }, { name: 'Ruby Upgrades', yOff: 500, type: 'ruby' }, { name: 'General Upgrades', yOff: 700, type: 'general' }]; categories.forEach(function (cat) { var btn = LK.getAsset('buy_button', { anchorX: 0.5, anchorY: 0.5 }); btn.x = menuBg.x; btn.y = menuBg.y + cat.yOff; upgradeMenu.addChild(btn); // Then text on top var txt = new Text2(cat.name, { size: 50, fill: 0x000000, // black text for contrast align: 'center' }); txt.anchor.set(0.5); txt.x = btn.x; txt.y = btn.y; upgradeMenu.addChild(txt); btn.down = function () { if (cat.type === 'general') { createSubUpgradeMenu('General Upgrades', generalUpgrades); } else { // show sub-menu for that specific ore createSubUpgradeMenu(cat.name, oreUpgrades[cat.type]); } }; }); // Close button var closeBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); closeBtn.x = menuBg.x + 700; closeBtn.y = menuBg.y - 800; closeBtn.down = function () { game.removeChild(upgradeMenu); }; upgradeMenu.addChild(closeBtn); } /**** * SUB-MENU ****/ var subUpgradeItemRefs = []; function createSubUpgradeMenu(title, upgList) { upgradeMenu.removeChildren(); subUpgradeItemRefs = []; var menuBg = LK.getAsset('rectangle', { width: 1800, height: 2000, color: 0x2a2a2a, anchorX: 0.5, anchorY: 0.5 }); menuBg.x = 2048 / 2; menuBg.y = 2732 / 2 + 50; upgradeMenu.addChild(menuBg); // Title var titleText = new Text2(title, { size: 60, fill: 0xFFFFFF, align: 'center' }); titleText.anchor.set(0.5); titleText.x = menuBg.x; titleText.y = menuBg.y - 850; upgradeMenu.addChild(titleText); // Spacing out each upgrade by ~250 px var startY = menuBg.y - 600; upgList.forEach(function (upg, i) { var itemContainer = new Container(); upgradeMenu.addChild(itemContainer); var btn = LK.getAsset('buy_button', { anchorX: 0.5, anchorY: 0.5 }); btn.x = menuBg.x; btn.y = startY + i * 250; itemContainer.addChild(btn); // If multi with a "level" property var displayName = upg.name; if (typeof upg.level === 'number' && upg.level > 0) { displayName += " (Lv " + upg.level + ")"; } var txtStr = displayName + "\n" + upg.effect + "\n$" + upg.cost; var txt = new Text2(txtStr, { size: 40, fill: 0x666666, align: 'center' }); txt.anchor.set(0.5); txt.x = btn.x; txt.y = btn.y; itemContainer.addChild(txt); btn.down = function () { if (canPurchaseUpgrade(upgList, upg)) { gameState.money -= upg.cost; upg.purchased = true; upg.action(); updateUI(); createSubUpgradeMenu(title, upgList); } }; subUpgradeItemRefs.push({ upgList: upgList, upgrade: upg, textObj: txt }); }); // Back button var backBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); backBtn.x = menuBg.x + 700; backBtn.y = menuBg.y - 800; backBtn.down = function () { createMainUpgradeMenu(); }; upgradeMenu.addChild(backBtn); } function canPurchaseUpgrade(upgList, upg) { // If there's a 'requires' property, check that upgrade is purchased first if (upg.requires) { var needed = upgList.find(function (u) { return u.id === upg.requires; }); if (!needed || !needed.purchased) { return false; } } // If not multi and already purchased => can't buy again if (!upg.multi && upg.purchased) { return false; } // Check money if (gameState.money < upg.cost) { return false; } return true; } /**** * GAME LOOP ****/ game.update = function () { // 1) Miner miner.update(); // 2) Update ore visuals clusters.forEach(function (cluster) { cluster.oreList.forEach(function (ore) { if (ore.health > 0) { var fraction = ore.health / ore.maxHealth; ore.healthBar.width = 120 * fraction; ore.healthBar.fill = interpolateColor(0xFF0000, 0x00FF00, fraction); ore.alpha = fraction; } }); }); // 3) Sub-menu color updates if (upgradeMenu.parent) { subUpgradeItemRefs.forEach(function (ref) { var upg = ref.upgrade; var canBuy = canPurchaseUpgrade(ref.upgList, upg); if (ref.textObj && ref.textObj.style) { ref.textObj.style.fill = canBuy ? 0xFFFFFF : 0x666666; } }); } }; /**** * UI REFRESH ****/ function updateUI() { moneyDisplay.setText("$" + gameState.money.toLocaleString() + "\n" + "Multipliers: " + "C" + gameState.oreMultipliers.coal + "x " + "I" + gameState.oreMultipliers.iron + "x " + "G" + gameState.oreMultipliers.gold + "x " + "D" + gameState.oreMultipliers.diamond + "x " + "S" + gameState.oreMultipliers.sapphire + "x " + "E" + gameState.oreMultipliers.emerald + "x " + "R" + gameState.oreMultipliers.ruby + "x"); moneyDisplay.x = 2048 / 2 - moneyDisplay.width / 2; } /**** * SAVE & LOAD ****/ LK.saveGame = function () { return gameState; }; LK.loadGame = function (data) { gameState = data; updateUI(); }; /**** * INITIAL SPAWN ****/ function initialSpawn() { // We'll spawn clusters for any ore type up to currentTier // Tiers: 1=Coal,2=Iron,3=Gold,4=Diamond,5=Sapphire,6=Emerald,7=Ruby var allTypes = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; allTypes.forEach(function (type, idx) { var t = idx + 1; if (t <= gameState.currentTier) { for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster(type); } } }); } initialSpawn(); updateUI();
===================================================================
--- original.js
+++ change.js
@@ -9,11 +9,9 @@
/****
* CLASSES
****/
/**
-* A cluster container that spawns several Ore objects of the same type.
-* We track how many remain. Once all are destroyed, we remove the cluster
-* and eventually spawn a new one (after a delay).
+* Cluster spawns multiple Ore objects of a given type.
*/
var Cluster = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
@@ -22,49 +20,49 @@
var centerX = 100 + Math.random() * (2048 - 200);
var centerY = 100 + Math.random() * (2732 - 200);
self.x = centerX;
self.y = centerY;
- // Decide how many ore are in this cluster
- var clusterConfig = gameState.clusterConfig;
- var count = randomInt(clusterConfig.min, clusterConfig.max);
- // Create each ore with random offsets
+ // Decide how many ore in this cluster
+ var cc = gameState.clusterConfig;
+ var count = randomInt(cc.min, cc.max);
+ // Create ore
for (var i = 0; i < count; i++) {
var ore = new Ore(type, self);
ore.x = (Math.random() - 0.5) * 120;
ore.y = (Math.random() - 0.5) * 120;
self.oreList.push(ore);
self.addChild(ore);
}
self.notifyOreDestroyed = function (ore) {
- if (self.oreList.indexOf(ore) >= 0) {
- self.oreList.splice(self.oreList.indexOf(ore), 1);
+ var idx = self.oreList.indexOf(ore);
+ if (idx >= 0) {
+ self.oreList.splice(idx, 1);
}
ore.destroy();
- // If all gone => cluster done
+ // If all gone => remove cluster
if (self.oreList.length === 0) {
if (self.parent) {
self.parent.removeChild(self);
}
- var idx = clusters.indexOf(self);
- if (idx >= 0) {
- clusters.splice(idx, 1);
+ var cidx = clusters.indexOf(self);
+ if (cidx >= 0) {
+ clusters.splice(cidx, 1);
}
- // Decrement cluster count
- gameState.clusterCount[self.type]--;
- // Wait, then spawn new cluster if not max
+ gameState.clusterCount[type]--;
+ // Wait respawnTime, then spawn new cluster
var finalDelay = gameState.respawnTime;
- if (self.type === 'coal') {
- finalDelay *= 2; // slower for coal
+ if (type === 'coal') {
+ finalDelay *= 2; // slow for coal
}
LK.setTimeout(function () {
- maybeSpawnCluster(self.type);
+ maybeSpawnCluster(type);
}, finalDelay);
}
};
return self;
});
/**
-* Miner class: moves to the closest available ore (within currentTier) and mines it.
+* Miner moves to the closest valid ore and mines it.
*/
var Miner = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('miner', {
@@ -74,16 +72,14 @@
self.speed = 5;
self.currentTarget = null;
self.miningRange = 25;
self.miningCooldown = 0;
- self.miningRate = 30;
+ self.miningRate = 30; // frames per "hit"
self.miningDamage = 1;
- // findNewTarget picks from ALL clusters' ore, sorted by distance
self.findNewTarget = function () {
var validOre = [];
clusters.forEach(function (c) {
c.oreList.forEach(function (ore) {
- // only if alive and within tier
if (ore.health > 0 && ore.tier <= gameState.currentTier) {
validOre.push(ore);
}
});
@@ -91,9 +87,9 @@
if (validOre.length === 0) {
self.currentTarget = null;
return;
}
- // global coords
+ // Sort by distance
self.currentTarget = validOre.sort(function (a, b) {
var aX = a.parent.x + a.x;
var aY = a.parent.y + a.y;
var bX = b.parent.x + b.x;
@@ -109,12 +105,12 @@
var tx = self.currentTarget.parent.x + self.currentTarget.x;
var ty = self.currentTarget.parent.y + self.currentTarget.y;
var dx = tx - self.x;
var dy = ty - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- if (distance > self.miningRange) {
- self.x += dx / distance * self.speed;
- self.y += dy / distance * self.speed;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > self.miningRange) {
+ self.x += dx / dist * self.speed;
+ self.y += dy / dist * self.speed;
} else {
self.mineOre(self.currentTarget);
}
} else {
@@ -129,8 +125,9 @@
}
ore.health -= self.miningDamage * gameState.pickaxeLevel;
self.miningCooldown = self.miningRate;
if (ore.health <= 0) {
+ // Add money
gameState.money += ore.getValue();
updateUI();
ore.cluster.notifyOreDestroyed(ore);
spawnMiningParticles(ore, 5);
@@ -140,24 +137,27 @@
};
return self;
});
/**
-* A single ore object.
+* A single ore object (7 possible types).
*/
var Ore = Container.expand(function (type, cluster) {
var self = Container.call(this);
self.type = type;
self.cluster = cluster;
- // Tier
- self.tier = ['coal', 'iron', 'gold', 'diamond'].indexOf(type) + 1;
- self.maxHealth = 10;
+ // Determine tier based on order in this array:
+ // [coal, iron, gold, diamond, sapphire, emerald, ruby]
+ var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby'];
+ self.tier = typeList.indexOf(type) + 1;
+ self.baseValue = oreData[type].baseValue;
+ self.maxHealth = oreData[type].baseHealth;
self.health = self.maxHealth;
- self.baseValue = 5 * self.tier; // base money
+ // Attach sprite
self.attachAsset(type + '_ore', {
anchorX: 0.5,
anchorY: 0.5
});
- // health bar: 120×20
+ // Health bar
self.healthBar = LK.getAsset('rectangle', {
width: 120,
height: 20,
fill: 0x00FF00,
@@ -176,9 +176,9 @@
/****
* Initialize Game
****/
/****
-* HELPER / UTILITY FUNCTIONS
+* HELPER FUNCTIONS
****/
/****
* THE GAME
****/
@@ -188,43 +188,84 @@
/****
* Game Code
****/
+// We'll keep references to each cluster container
/****
* GLOBAL ARRAYS & STATE
****/
/****
* PLUGINS
****/
-// NEW asset for opening the shop:
-// Existing assets
+// NEW asset for shop icon
+// NEW assets for additional ores:
/****
* ASSETS
****/
-// The Miner
-var clusters = []; // containers for each "cluster" of ore
+// Create Miner
+var clusters = [];
+/****
+* ORE DATA
+****/
+var oreData = {
+ coal: {
+ baseValue: 5,
+ baseHealth: 10
+ },
+ iron: {
+ baseValue: 500,
+ baseHealth: 100
+ },
+ gold: {
+ baseValue: 10000,
+ baseHealth: 500
+ },
+ diamond: {
+ baseValue: 25000,
+ baseHealth: 1000
+ },
+ sapphire: {
+ baseValue: 100000,
+ baseHealth: 2000
+ },
+ emerald: {
+ baseValue: 500000,
+ baseHealth: 5000
+ },
+ ruby: {
+ baseValue: 1000000,
+ baseHealth: 10000
+ }
+};
+/****
+* GAME STATE
+****/
var gameState = {
money: 0,
pickaxeLevel: 1,
currentTier: 1,
oreMultipliers: {
coal: 1,
iron: 1,
gold: 1,
- diamond: 1
+ diamond: 1,
+ sapphire: 1,
+ emerald: 1,
+ ruby: 1
},
- // Respawn timing (in ms)
+ // For controlling cluster spawns & respawns
respawnTime: 3000,
- // Max # of clusters per type
+ // base
maxClustersPerType: 3,
- // Currently existing cluster count by type
clusterCount: {
coal: 0,
iron: 0,
gold: 0,
- diamond: 0
+ diamond: 0,
+ sapphire: 0,
+ emerald: 0,
+ ruby: 0
},
- // Config for cluster sizes
clusterConfigLevels: [{
min: 2,
max: 3
},
@@ -240,20 +281,20 @@
max: 10
}],
clusterUpgradeTier: 0,
get clusterConfig() {
- // e.g. clusterConfigLevels[0] => 2-3
return this.clusterConfigLevels[this.clusterUpgradeTier] || {
min: 2,
max: 3
};
}
};
/****
-* HELPER / UTILITY FUNCTIONS
+* HELPER FUNCTIONS
****/
function maybeSpawnCluster(type) {
- var tIndex = ['coal', 'iron', 'gold', 'diamond'].indexOf(type) + 1;
+ var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby'];
+ var tIndex = typeList.indexOf(type) + 1;
if (tIndex > gameState.currentTier) {
return;
}
if (gameState.clusterCount[type] >= gameState.maxClustersPerType) {
@@ -263,23 +304,19 @@
game.addChild(cluster);
clusters.push(cluster);
gameState.clusterCount[type]++;
}
-// random int in [min, max]
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
-// spawn mining particles
function spawnMiningParticles(ore, num) {
for (var i = 0; i < num; i++) {
var p = LK.getAsset('mining_particle', {
anchorX: 0.5,
anchorY: 0.5
});
- if (ore.parent) {
- p.x = ore.parent.x + ore.x;
- p.y = ore.parent.y + ore.y;
- }
+ p.x = ore.parent.x + ore.x;
+ p.y = ore.parent.y + ore.y;
p.vx = (Math.random() - 0.5) * 10;
p.vy = (Math.random() - 0.5) * 10;
p.alpha = 1;
tween(p, {
@@ -293,19 +330,18 @@
});
game.addChild(p);
}
}
-// color interpolation
-function interpolateColor(color1, color2, factor) {
- var r1 = color1 >> 16 & 0xff;
- var g1 = color1 >> 8 & 0xff;
- var b1 = color1 & 0xff;
- var r2 = color2 >> 16 & 0xff;
- var g2 = color2 >> 8 & 0xff;
- var b2 = color2 & 0xff;
- var r = Math.round(r1 + factor * (r2 - r1));
- var g = Math.round(g1 + factor * (g2 - g1));
- var b = Math.round(b1 + factor * (b2 - b1));
+function interpolateColor(c1, c2, f) {
+ var r1 = c1 >> 16 & 0xFF,
+ g1 = c1 >> 8 & 0xFF,
+ b1 = c1 & 0xFF;
+ var r2 = c2 >> 16 & 0xFF,
+ g2 = c2 >> 8 & 0xFF,
+ b2 = c2 & 0xFF;
+ var r = Math.round(r1 + f * (r2 - r1));
+ var g = Math.round(g1 + f * (g2 - g1));
+ var b = Math.round(b1 + f * (b2 - b1));
return r << 16 | g << 8 | b;
}
var miner = game.addChild(new Miner());
miner.x = 2048 / 2;
@@ -325,8 +361,9 @@
var tooltip = new Text2('', {
size: 40,
fill: 0xFFFFFF
});
+game.addChild(tooltip);
var moneyDisplay = new Text2('$0', {
size: 80,
fill: 0xFFFFFF,
fontWeight: 'bold',
@@ -335,10 +372,10 @@
});
moneyDisplay.x = 2048 / 2 - moneyDisplay.width / 2;
moneyDisplay.y = 50;
game.addChild(moneyDisplay);
+// Shop icon (replacing the old buy_button for opening menu)
var shopOpenButton = LK.getAsset('shop_icon', {
- // new asset
anchorX: 0.5,
anchorY: 0.5
});
shopOpenButton.x = 2048 - 150;
@@ -347,9 +384,9 @@
createMainUpgradeMenu();
game.addChild(upgradeMenu);
};
game.addChild(shopOpenButton);
-// Debug: Add money button (bottom left)
+// Debug: Add money button
var addMoneyButton = LK.getAsset('buy_button', {
anchorX: 0.5,
anchorY: 0.5
});
@@ -359,122 +396,222 @@
gameState.money += 50000;
updateUI();
};
game.addChild(addMoneyButton);
-game.addChild(tooltip);
/****
-* UPGRADE SYSTEM
+* UPGRADE DEFINITIONS
****/
-// We split upgrades by category for our new sub-menu system
-var coalUpgrades = [{
- id: 'coal_expert',
- name: "Coal Expertise",
- cost: 100,
- multi: true,
- level: 0,
- effect: "Doubles coal value each purchase",
- action: function action() {
- this.level++;
- gameState.oreMultipliers.coal *= 2;
- this.cost *= 2;
- }
-}];
-var ironUpgrades = [{
- id: 'unlock_iron',
- name: "Unlock Iron Mining",
- cost: 500,
- effect: "Allows iron ore clusters to spawn",
- purchased: false,
- action: function action() {
- gameState.currentTier = Math.max(gameState.currentTier, 2);
- // Immediately spawn iron clusters
- for (var i = 0; i < gameState.maxClustersPerType; i++) {
- maybeSpawnCluster('iron');
+// Each ore has (1) an unlock (except coal) and (2) a double-value multi upgrade.
+var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby'];
+// “Unlock” costs + “Double Value” costs are arbitrary examples. Tweak if desired.
+var oreUpgrades = {
+ coal: [{
+ id: 'double_coal',
+ name: 'Double Coal Value',
+ cost: 100,
+ multi: true,
+ level: 0,
+ effect: 'Doubles Coal Value each purchase',
+ action: function action() {
+ this.level++;
+ gameState.oreMultipliers.coal *= 2;
+ this.cost *= 2;
}
- }
-}, {
- id: 'iron_expert',
- name: "Iron Expertise",
- cost: 2000,
- effect: "Triple iron value",
- requires: 'unlock_iron',
- purchased: false,
- action: function action() {
- gameState.oreMultipliers.iron *= 3;
- }
-}];
-var goldUpgrades = [{
- id: 'unlock_gold',
- name: "Unlock Gold Mining",
- cost: 5000,
- effect: "Allows gold ore clusters to spawn",
- action: function action() {
- gameState.currentTier = Math.max(gameState.currentTier, 3);
- // Immediately spawn gold
- for (var i = 0; i < gameState.maxClustersPerType; i++) {
- maybeSpawnCluster('gold');
+ }],
+ iron: [{
+ id: 'unlock_iron',
+ name: 'Unlock Iron Mining',
+ cost: 500,
+ effect: 'Allows iron ore clusters to spawn',
+ purchased: false,
+ action: function action() {
+ // Increase currentTier if needed
+ if (gameState.currentTier < 2) {
+ gameState.currentTier = 2;
+ }
+ // Immediately spawn some iron
+ for (var i = 0; i < gameState.maxClustersPerType; i++) {
+ maybeSpawnCluster('iron');
+ }
}
- }
-}, {
- id: 'gold_expert',
- name: "Gold Expertise",
- cost: 10000,
- effect: "Quadruple gold value",
- requires: 'unlock_gold',
- action: function action() {
- gameState.oreMultipliers.gold *= 4;
- }
-}];
-var diamondUpgrades = [{
- id: 'unlock_diamond',
- name: "Unlock Diamond Mining",
- cost: 20000,
- effect: "Allows diamond ore clusters to spawn",
- action: function action() {
- gameState.currentTier = Math.max(gameState.currentTier, 4);
- // Immediately spawn diamond
- for (var i = 0; i < gameState.maxClustersPerType; i++) {
- maybeSpawnCluster('diamond');
+ }, {
+ id: 'double_iron',
+ name: 'Double Iron Value',
+ cost: 1000,
+ multi: true,
+ level: 0,
+ effect: 'Doubles Iron Value each purchase',
+ action: function action() {
+ this.level++;
+ gameState.oreMultipliers.iron *= 2;
+ this.cost *= 2;
}
- }
-}];
+ }],
+ gold: [{
+ id: 'unlock_gold',
+ name: 'Unlock Gold Mining',
+ cost: 5000,
+ effect: 'Allows gold ore clusters to spawn',
+ purchased: false,
+ action: function action() {
+ if (gameState.currentTier < 3) {
+ gameState.currentTier = 3;
+ }
+ for (var i = 0; i < gameState.maxClustersPerType; i++) {
+ maybeSpawnCluster('gold');
+ }
+ }
+ }, {
+ id: 'double_gold',
+ name: 'Double Gold Value',
+ cost: 20000,
+ multi: true,
+ level: 0,
+ effect: 'Doubles Gold Value each purchase',
+ action: function action() {
+ this.level++;
+ gameState.oreMultipliers.gold *= 2;
+ this.cost *= 2;
+ }
+ }],
+ diamond: [{
+ id: 'unlock_diamond',
+ name: 'Unlock Diamond Mining',
+ cost: 20000,
+ effect: 'Allows diamond ore clusters to spawn',
+ purchased: false,
+ action: function action() {
+ if (gameState.currentTier < 4) {
+ gameState.currentTier = 4;
+ }
+ for (var i = 0; i < gameState.maxClustersPerType; i++) {
+ maybeSpawnCluster('diamond');
+ }
+ }
+ }, {
+ id: 'double_diamond',
+ name: 'Double Diamond Value',
+ cost: 50000,
+ multi: true,
+ level: 0,
+ effect: 'Doubles Diamond Value each purchase',
+ action: function action() {
+ this.level++;
+ gameState.oreMultipliers.diamond *= 2;
+ this.cost *= 2;
+ }
+ }],
+ sapphire: [{
+ id: 'unlock_sapphire',
+ name: 'Unlock Sapphire Mining',
+ cost: 100000,
+ effect: 'Allows sapphire ore clusters to spawn',
+ purchased: false,
+ action: function action() {
+ if (gameState.currentTier < 5) {
+ gameState.currentTier = 5;
+ }
+ for (var i = 0; i < gameState.maxClustersPerType; i++) {
+ maybeSpawnCluster('sapphire');
+ }
+ }
+ }, {
+ id: 'double_sapphire',
+ name: 'Double Sapphire Value',
+ cost: 200000,
+ multi: true,
+ level: 0,
+ effect: 'Doubles Sapphire Value each purchase',
+ action: function action() {
+ this.level++;
+ gameState.oreMultipliers.sapphire *= 2;
+ this.cost *= 2;
+ }
+ }],
+ emerald: [{
+ id: 'unlock_emerald',
+ name: 'Unlock Emerald Mining',
+ cost: 500000,
+ effect: 'Allows emerald ore clusters to spawn',
+ purchased: false,
+ action: function action() {
+ if (gameState.currentTier < 6) {
+ gameState.currentTier = 6;
+ }
+ for (var i = 0; i < gameState.maxClustersPerType; i++) {
+ maybeSpawnCluster('emerald');
+ }
+ }
+ }, {
+ id: 'double_emerald',
+ name: 'Double Emerald Value',
+ cost: 1000000,
+ multi: true,
+ level: 0,
+ effect: 'Doubles Emerald Value each purchase',
+ action: function action() {
+ this.level++;
+ gameState.oreMultipliers.emerald *= 2;
+ this.cost *= 2;
+ }
+ }],
+ ruby: [{
+ id: 'unlock_ruby',
+ name: 'Unlock Ruby Mining',
+ cost: 1000000,
+ effect: 'Allows ruby ore clusters to spawn',
+ purchased: false,
+ action: function action() {
+ if (gameState.currentTier < 7) {
+ gameState.currentTier = 7;
+ }
+ for (var i = 0; i < gameState.maxClustersPerType; i++) {
+ maybeSpawnCluster('ruby');
+ }
+ }
+ }, {
+ id: 'double_ruby',
+ name: 'Double Ruby Value',
+ cost: 2000000,
+ multi: true,
+ level: 0,
+ effect: 'Doubles Ruby Value each purchase',
+ action: function action() {
+ this.level++;
+ gameState.oreMultipliers.ruby *= 2;
+ this.cost *= 2;
+ }
+ }]
+};
+// General Upgrades
var generalUpgrades = [{
id: 'faster_respawn',
- name: "Quicker Respawn",
+ name: 'Quicker Respawn',
cost: 8000,
- effect: "Halves respawn time (min 500 ms)",
+ effect: 'Halves respawn time (min 500 ms)',
+ purchased: false,
action: function action() {
gameState.respawnTime = Math.max(500, gameState.respawnTime / 2);
}
}, {
id: 'cluster_up',
- name: "Cluster Growth",
+ name: 'Cluster Growth',
cost: 1000,
- effect: "Increase cluster size range",
+ effect: 'Increases cluster size range',
purchased: false,
action: function action() {
if (gameState.clusterUpgradeTier < gameState.clusterConfigLevels.length - 1) {
gameState.clusterUpgradeTier++;
}
this.cost += 2000;
}
}];
-// We can define a quick "requires" check function
-function meetsRequirement(upgList, upg) {
- if (!upg.requires) {
- return true;
- }
- // if upg requires 'xxx', find that upgrade in the same category
- var needed = upgList.find(function (u) {
- return u.id === upg.requires;
- });
- return needed && needed.purchased;
-}
/****
-* MAIN MENU: 5 categories
+* MAIN MENU
****/
function createMainUpgradeMenu() {
upgradeMenu.removeChildren();
+ subUpgradeItemRefs = []; // reset
// Big background
var menuBg = LK.getAsset('rectangle', {
width: 1800,
height: 2000,
@@ -482,63 +619,71 @@
anchorX: 0.5,
anchorY: 0.5
});
menuBg.x = 2048 / 2;
- // shift down slightly
menuBg.y = 2732 / 2 + 50;
upgradeMenu.addChild(menuBg);
- // We'll create 5 buttons for categories: Coal, Iron, Gold, Diamond, General
+ // We'll define 8 “categories”: 7 Ores + 1 “General”
var categories = [{
- name: "Coal Upgrades",
- yOff: -600,
- onClick: function onClick() {
- createSubUpgradeMenu("Coal Upgrades", coalUpgrades);
- }
+ name: 'Coal Upgrades',
+ yOff: -700,
+ type: 'coal'
}, {
- name: "Iron Upgrades",
+ name: 'Iron Upgrades',
+ yOff: -500,
+ type: 'iron'
+ }, {
+ name: 'Gold Upgrades',
yOff: -300,
- onClick: function onClick() {
- createSubUpgradeMenu("Iron Upgrades", ironUpgrades);
- }
+ type: 'gold'
}, {
- name: "Gold Upgrades",
- yOff: 0,
- onClick: function onClick() {
- createSubUpgradeMenu("Gold Upgrades", goldUpgrades);
- }
+ name: 'Diamond Upgrades',
+ yOff: -100,
+ type: 'diamond'
}, {
- name: "Diamond Upgrades",
+ name: 'Sapphire Upgrades',
+ yOff: 100,
+ type: 'sapphire'
+ }, {
+ name: 'Emerald Upgrades',
yOff: 300,
- onClick: function onClick() {
- createSubUpgradeMenu("Diamond Upgrades", diamondUpgrades);
- }
+ type: 'emerald'
}, {
- name: "General Upgrades",
- yOff: 600,
- onClick: function onClick() {
- createSubUpgradeMenu("General Upgrades", generalUpgrades);
- }
+ name: 'Ruby Upgrades',
+ yOff: 500,
+ type: 'ruby'
+ }, {
+ name: 'General Upgrades',
+ yOff: 700,
+ type: 'general'
}];
- var centerX = menuBg.x;
- var centerY = menuBg.y;
categories.forEach(function (cat) {
var btn = LK.getAsset('buy_button', {
anchorX: 0.5,
anchorY: 0.5
});
- btn.x = centerX;
- btn.y = centerY + cat.yOff;
- btn.down = cat.onClick;
+ btn.x = menuBg.x;
+ btn.y = menuBg.y + cat.yOff;
upgradeMenu.addChild(btn);
+ // Then text on top
var txt = new Text2(cat.name, {
size: 50,
- fill: 0xFFFFFF,
+ fill: 0x000000,
+ // black text for contrast
align: 'center'
});
txt.anchor.set(0.5);
txt.x = btn.x;
txt.y = btn.y;
upgradeMenu.addChild(txt);
+ btn.down = function () {
+ if (cat.type === 'general') {
+ createSubUpgradeMenu('General Upgrades', generalUpgrades);
+ } else {
+ // show sub-menu for that specific ore
+ createSubUpgradeMenu(cat.name, oreUpgrades[cat.type]);
+ }
+ };
});
// Close button
var closeBtn = LK.getAsset('cancelButton', {
anchorX: 0.5,
@@ -551,15 +696,14 @@
};
upgradeMenu.addChild(closeBtn);
}
/****
-* SUB MENU for a given category of upgrades
+* SUB-MENU
****/
-var subUpgradeItemRefs = []; // track references to update color in real-time
+var subUpgradeItemRefs = [];
function createSubUpgradeMenu(title, upgList) {
upgradeMenu.removeChildren();
subUpgradeItemRefs = [];
- // Big background
var menuBg = LK.getAsset('rectangle', {
width: 1800,
height: 2000,
color: 0x2a2a2a,
@@ -578,25 +722,23 @@
titleText.anchor.set(0.5);
titleText.x = menuBg.x;
titleText.y = menuBg.y - 850;
upgradeMenu.addChild(titleText);
- // Layout the upgrades in a single column
- // We'll do ~150px vertical spacing between items
- var startY = menuBg.y - 650;
+ // Spacing out each upgrade by ~250 px
+ var startY = menuBg.y - 600;
upgList.forEach(function (upg, i) {
- // Container for button + text
- var c = new Container();
- upgradeMenu.addChild(c);
+ var itemContainer = new Container();
+ upgradeMenu.addChild(itemContainer);
var btn = LK.getAsset('buy_button', {
anchorX: 0.5,
anchorY: 0.5
});
btn.x = menuBg.x;
- btn.y = startY + i * 150;
- c.addChild(btn);
- // Display name
+ btn.y = startY + i * 250;
+ itemContainer.addChild(btn);
+ // If multi with a "level" property
var displayName = upg.name;
- if (upg.level && upg.level > 0) {
+ if (typeof upg.level === 'number' && upg.level > 0) {
displayName += " (Lv " + upg.level + ")";
}
var txtStr = displayName + "\n" + upg.effect + "\n$" + upg.cost;
var txt = new Text2(txtStr, {
@@ -606,23 +748,21 @@
});
txt.anchor.set(0.5);
txt.x = btn.x;
txt.y = btn.y;
- c.addChild(txt);
+ itemContainer.addChild(txt);
btn.down = function () {
- var canBuy = checkSubUpgradeBuyable(upgList, upg);
- if (canBuy) {
+ if (canPurchaseUpgrade(upgList, upg)) {
gameState.money -= upg.cost;
- upg.purchased = true; // Mark purchased
+ upg.purchased = true;
upg.action();
updateUI();
- // Refresh sub-menu so cost, text, etc. updates
createSubUpgradeMenu(title, upgList);
}
};
subUpgradeItemRefs.push({
+ upgList: upgList,
upgrade: upg,
- upgradesList: upgList,
textObj: txt
});
});
// Back button
@@ -636,30 +776,33 @@
createMainUpgradeMenu();
};
upgradeMenu.addChild(backBtn);
}
-// Helper to see if we can buy an upgrade in a sub-menu
-function checkSubUpgradeBuyable(upgList, upg) {
- // If we have a "requires" that isn't purchased, can't buy
- if (!meetsRequirement(upgList, upg)) {
- return false;
+function canPurchaseUpgrade(upgList, upg) {
+ // If there's a 'requires' property, check that upgrade is purchased first
+ if (upg.requires) {
+ var needed = upgList.find(function (u) {
+ return u.id === upg.requires;
+ });
+ if (!needed || !needed.purchased) {
+ return false;
+ }
}
- // If it's multi: we do not block further purchases.
- // If not multi & purchased => no
+ // If not multi and already purchased => can't buy again
if (!upg.multi && upg.purchased) {
return false;
}
+ // Check money
if (gameState.money < upg.cost) {
return false;
}
return true;
}
-// Also re-check color each frame
/****
-* MAIN GAME LOOP: updating the buy menu text colors
+* GAME LOOP
****/
game.update = function () {
- // 1) Miner logic
+ // 1) Miner
miner.update();
// 2) Update ore visuals
clusters.forEach(function (cluster) {
cluster.oreList.forEach(function (ore) {
@@ -670,24 +813,24 @@
ore.alpha = fraction;
}
});
});
- // 3) If a sub-menu is open, re-check color
+ // 3) Sub-menu color updates
if (upgradeMenu.parent) {
subUpgradeItemRefs.forEach(function (ref) {
var upg = ref.upgrade;
- var canBuy = checkSubUpgradeBuyable(ref.upgradesList, upg);
+ var canBuy = canPurchaseUpgrade(ref.upgList, upg);
if (ref.textObj && ref.textObj.style) {
ref.textObj.style.fill = canBuy ? 0xFFFFFF : 0x666666;
}
});
}
};
/****
-* UI UPDATE
+* UI REFRESH
****/
function updateUI() {
- moneyDisplay.setText("$" + gameState.money.toLocaleString() + "\n" + "Multipliers: " + "C" + gameState.oreMultipliers.coal + "x " + "I" + gameState.oreMultipliers.iron + "x " + "G" + gameState.oreMultipliers.gold + "x " + "D" + gameState.oreMultipliers.diamond + "x");
+ moneyDisplay.setText("$" + gameState.money.toLocaleString() + "\n" + "Multipliers: " + "C" + gameState.oreMultipliers.coal + "x " + "I" + gameState.oreMultipliers.iron + "x " + "G" + gameState.oreMultipliers.gold + "x " + "D" + gameState.oreMultipliers.diamond + "x " + "S" + gameState.oreMultipliers.sapphire + "x " + "E" + gameState.oreMultipliers.emerald + "x " + "R" + gameState.oreMultipliers.ruby + "x");
moneyDisplay.x = 2048 / 2 - moneyDisplay.width / 2;
}
/****
* SAVE & LOAD
@@ -700,15 +843,16 @@
updateUI();
};
/****
* INITIAL SPAWN
-* Spawn up to maxClusters for each ore up to currentTier
****/
function initialSpawn() {
- var oreTypes = ['coal', 'iron', 'gold', 'diamond'];
- oreTypes.forEach(function (type, idx) {
- var tier = idx + 1;
- if (tier <= gameState.currentTier) {
+ // We'll spawn clusters for any ore type up to currentTier
+ // Tiers: 1=Coal,2=Iron,3=Gold,4=Diamond,5=Sapphire,6=Emerald,7=Ruby
+ var allTypes = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby'];
+ allTypes.forEach(function (type, idx) {
+ var t = idx + 1;
+ if (t <= gameState.currentTier) {
for (var i = 0; i < gameState.maxClustersPerType; i++) {
maybeSpawnCluster(type);
}
}
drone_shot
Sound effect
mine_coal
Sound effect
mine_iron
Sound effect
mine_gold
Sound effect
mine_diamond
Sound effect
mine_sapphire
Sound effect
mine_emerald
Sound effect
mine_ruby
Sound effect
mine_chronostone
Sound effect
mine_quantumshard
Sound effect
ore_destroy_coal
Sound effect
ore_destroy_iron
Sound effect
ore_destroy_gold
Sound effect
ore_destroy_diamond
Sound effect
ore_destroy_sapphire
Sound effect
ore_destroy_emerald
Sound effect
ore_destroy_ruby
Sound effect
mine_coal_1
Sound effect
mine_coal_2
Sound effect
mine_coal_3
Sound effect
mine_diamond1
Sound effect
mine_diamond2
Sound effect
mine_diamond3
Sound effect
mine_emerald1
Sound effect
mine_emerald2
Sound effect
mine_emerald3
Sound effect
mine_gold1
Sound effect
mine_gold2
Sound effect
mine_gold3
Sound effect
mine_iron1
Sound effect
mine_iron2
Sound effect
mine_iron3
Sound effect
mine_ruby1
Sound effect
mine_ruby2
Sound effect
mine_ruby3
Sound effect
mine_sapphire1
Sound effect
mine_sapphire2
Sound effect
mine_sapphire3
Sound effect
song1
Music
song2
Music
song3
Music
song4
Music
song5
Music
song6
Music
song7
Music
song8
Music
song9
Music
song10
Music
song11
Music
song12
Music
song1a
Music
song1b
Music
song2a
Music
song2b
Music
song3a
Music
song3b
Music
song4a
Music
song4b
Music
song5a
Music
song5b
Music
song6a
Music
song6b
Music
song7a
Music
song7b
Music
song8a
Music
song8b
Music
song9a
Music
song9b
Music
song10a
Music
song10b
Music
song11a
Music
song11b
Music
song12a
Music
song12b
Music