User prompt
Please fix the bug: 'ReferenceError: Can't find variable: guardian' in or related to this line: 'guardian.update();' Line Number: 2120
User prompt
Please fix the bug: 'ReferenceError: Can't find variable: guardian' in or related to this line: 'guardian.update();' Line Number: 2120
User prompt
Please fix the bug: 'ReferenceError: Can't find variable: guardian' in or related to this line: 'guardian.update();' Line Number: 2120
User prompt
Add a title screen but remove all instances of initgame and replace it
User prompt
Please fix the bug: 'TypeError: self.target.takeDamage is not a function' in or related to this line: 'self.target.takeDamage(self.damage);' Line Number: 677
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'call')' in or related to this line: 'Enemy.prototype.update.call(self);' Line Number: 379
User prompt
it's still not using it, it is just a re-colored mushroom
User prompt
make the farm tower use the farm tower asset instead of the shreoom asset
User prompt
there is still no asset for both of them
User prompt
also there is no flame tower asset or farm tower asset, make them their own assets
User prompt
MORE ENEMIES
User prompt
make the healing shroom a farm tower that gives you extra cash at the end of a wave. and make the farm tower and the fire tower their own assets
User prompt
add a currency text and make the sell button work and give you back the money you spent on said tower
User prompt
make the menu BIGGER
User prompt
make the sell and upgrade button work
User prompt
make the edit menu larger and make it go to the front layer infront of everything
User prompt
make the towers editable by tapping on them when they're placed, so you can upgrade and delete them
User prompt
move the green healthbar not the text to the CENTER
User prompt
thats above, move it under
User prompt
mnove the healthbar under start wave button
User prompt
move the healthbar to the left to center the text
User prompt
move the healthbar over a bit
User prompt
add a healthbar asset and a button asset for start wave
User prompt
add more tower types and enemies
User prompt
make every wave a unique map ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, unlockedTowers: ["thorn", "shroom", "flame", "healing"] }); /**** * Classes ****/ var BuildingSpot = Container.expand(function () { var self = Container.call(this); var spotGraphics = self.attachAsset('buildingSpot', { anchorX: 0.5, anchorY: 0.5, alpha: 0.4 }); self.gridX = 0; self.gridY = 0; self.occupied = false; self.tower = null; self.down = function (x, y, obj) { if (!self.occupied && currentMode === 'building' && selectedTower !== null && essence >= towerCosts[selectedTower]) { self.buildTower(selectedTower); } }; self.buildTower = function (towerType) { var tower; if (towerType === 'thorn') { tower = new ThornTower(); } else if (towerType === 'shroom') { tower = new ShroomTower(); } else if (towerType === 'flame') { tower = new FlameTower(); } else if (towerType === 'healing') { tower = new HealingTower(); } if (tower) { tower.x = self.x; tower.y = self.y; tower.gridX = self.gridX; tower.gridY = self.gridY; game.addChild(tower); towers.push(tower); essence -= towerCosts[towerType]; updateEssenceText(); self.occupied = true; self.tower = tower; LK.getSound('towerPlaced').play(); } }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.maxHealth = 50; self.health = self.maxHealth; self.value = 10; // Essence value when defeated self.pathIndex = 0; self.alive = true; self.update = function () { if (!self.alive) { return; } // Follow path if (self.pathIndex < path.length) { var targetPoint = path[self.pathIndex]; var dx = targetPoint.x - self.x; var dy = targetPoint.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // If near target point, move to next point if (distance < 20) { self.pathIndex++; // If reached the end of path (HeartTree) if (self.pathIndex >= path.length) { heartTree.takeDamage(10); self.alive = false; return; } } else { // Move towards current target point var angle = Math.atan2(dy, dx); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; } } }; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { self.die(); } else { // Flash enemy when hit LK.effects.flashObject(self, 0xFF0000, 200); } }; self.die = function () { self.alive = false; // Drop essence var essenceObj = new Essence(); essenceObj.value = self.value; essenceObj.x = self.x; essenceObj.y = self.y; game.addChild(essenceObj); essenceItems.push(essenceObj); // Increase score LK.setScore(LK.getScore() + self.value); scoreTxt.setText(LK.getScore()); LK.getSound('enemyDeath').play(); }; return self; }); var TankEnemy = Enemy.expand(function () { var self = Enemy.call(this); // Replace with custom graphics self.removeChildAt(0); // Remove default enemy graphics var tankGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, tint: 0x666666, // Grey tint for tank enemies scaleX: 1.4, scaleY: 1.4 // Larger }); self.speed = 1; // Slower self.maxHealth = 120; // Higher health self.health = self.maxHealth; self.value = 25; // Higher value return self; }); var SpeedyEnemy = Enemy.expand(function () { var self = Enemy.call(this); // Replace with custom graphics self.removeChildAt(0); // Remove default enemy graphics var speedyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, tint: 0xFFFF00, // Yellow tint for speedy enemies scaleX: 0.8, scaleY: 1.2 // Tall and thin }); self.speed = 4; // Much faster self.maxHealth = 30; // Lower health self.health = self.maxHealth; self.value = 15; // Slightly higher value return self; }); var BossEnemy = Enemy.expand(function () { var self = Enemy.call(this); // Replace with boss graphics self.removeChildAt(0); // Remove default enemy graphics var bossGraphics = self.attachAsset('bossEnemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.2; self.maxHealth = 300; self.health = self.maxHealth; self.value = 100; return self; }); var Essence = Container.expand(function () { var self = Container.call(this); var essenceGraphics = self.attachAsset('essence', { anchorX: 0.5, anchorY: 0.5 }); self.value = 10; self.lifeTime = 10; // seconds self.creationTime = LK.ticks / 60; self.collected = false; self.update = function () { if (self.collected) { return; } // Check if guardian is close enough to collect var dx = guardian.x - self.x; var dy = guardian.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 80) { self.collect(); return; } // Check if timed out var currentTime = LK.ticks / 60; if (currentTime - self.creationTime > self.lifeTime) { self.collected = true; } // Pulse animation var pulseFactor = 1 + Math.sin(LK.ticks / 20) * 0.1; self.scale.set(pulseFactor, pulseFactor); }; self.collect = function () { essence += self.value; updateEssenceText(); self.collected = true; LK.getSound('essenceCollected').play(); // Animate collection tween(self, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 300, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var Guardian = Container.expand(function () { var self = Container.call(this); var guardianGraphics = self.attachAsset('guardian', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 7; self.targetX = null; self.targetY = null; self.moving = false; self.update = function () { if (self.moving && self.targetX !== null && self.targetY !== null) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // If near target, stop moving if (distance < 10) { self.moving = false; self.targetX = null; self.targetY = null; } else { // Move towards target var angle = Math.atan2(dy, dx); var nextX = self.x + Math.cos(angle) * self.speed; var nextY = self.y + Math.sin(angle) * self.speed; // Check if the next position is valid if (isPositionValid(nextX, nextY)) { self.x = nextX; self.y = nextY; } else { self.moving = false; } } } }; self.moveTo = function (x, y) { if (isPositionValid(x, y)) { self.targetX = x; self.targetY = y; self.moving = true; } }; return self; }); var HeartTree = Container.expand(function () { var self = Container.call(this); var treeGraphics = self.attachAsset('heartTree', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 100; self.health = self.maxHealth; self.takeDamage = function (amount) { self.health -= amount; updateHealthBar(); LK.getSound('heartTreeDamage').play(); LK.effects.flashObject(self, 0xFF0000, 300); if (self.health <= 0) { // Game over LK.showGameOver(); // Update high score if needed if (LK.getScore() > storage.highScore) { storage.highScore = LK.getScore(); } } }; return self; }); var PathTile = Container.expand(function () { var self = Container.call(this); var pathGraphics = self.attachAsset('path', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); self.gridX = 0; self.gridY = 0; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 12; self.damage = 10; self.target = null; self.alive = true; self.update = function () { if (!self.target || !self.target.alive) { self.alive = false; return; } var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 20) { // Hit target self.target.takeDamage(self.damage); self.alive = false; return; } // Move towards target var angle = Math.atan2(dy, dx); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; }; return self; }); var SpawnPoint = Container.expand(function () { var self = Container.call(this); var spawnGraphics = self.attachAsset('spawnPoint', { anchorX: 0.5, anchorY: 0.5 }); self.active = true; return self; }); var Tower = Container.expand(function () { var self = Container.call(this); var baseGraphics = self.attachAsset('towerBase', { anchorX: 0.5, anchorY: 0.5 }); self.gridX = 0; self.gridY = 0; self.range = 300; self.damage = 10; self.attackSpeed = 1; // attacks per second self.lastAttackTime = 0; self.level = 1; self.target = null; self.projectiles = []; self.findTarget = function () { var closestEnemy = null; var closestDistance = self.range; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } } return closestEnemy; }; self.attack = function () { if (!self.target || !self.target.alive) { self.target = self.findTarget(); } if (self.target) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.range) { self.target = null; return; } var currentTime = LK.ticks / 60; if (currentTime - self.lastAttackTime >= 1 / self.attackSpeed) { self.lastAttackTime = currentTime; self.fireProjectile(); } } }; self.fireProjectile = function () { var projectile = new Projectile(); projectile.damage = self.damage; projectile.target = self.target; projectile.x = self.x; projectile.y = self.y; game.addChild(projectile); self.projectiles.push(projectile); LK.getSound('projectileShot').play(); }; self.update = function () { self.attack(); // Update projectiles for (var i = self.projectiles.length - 1; i >= 0; i--) { var projectile = self.projectiles[i]; if (!projectile.alive) { projectile.destroy(); self.projectiles.splice(i, 1); } } }; return self; }); var ThornTower = Tower.expand(function () { var self = Tower.call(this); var towerGraphics = self.attachAsset('thornTower', { anchorX: 0.5, anchorY: 0.5, y: -20 // Offset to position on base }); self.range = 350; self.damage = 15; self.attackSpeed = 1.2; return self; }); var ShroomTower = Tower.expand(function () { var self = Tower.call(this); var towerGraphics = self.attachAsset('shroomTower', { anchorX: 0.5, anchorY: 0.5, y: -20 // Offset to position on base }); self.range = 250; self.damage = 25; self.attackSpeed = 0.8; return self; }); var HealingTower = Tower.expand(function () { var self = Tower.call(this); // Remove default base and add custom base with green healing tint self.removeChildAt(0); var baseGraphics = self.attachAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, tint: 0x00FF88 }); var towerGraphics = self.attachAsset('shroomTower', { anchorX: 0.5, anchorY: 0.5, y: -20, // Offset to position on base tint: 0x88FF88 }); self.range = 280; self.healAmount = 5; self.attackSpeed = 1.5; // Override the attack method to heal nearby towers instead self.attack = function () { var currentTime = LK.ticks / 60; if (currentTime - self.lastAttackTime >= 1 / self.attackSpeed) { self.lastAttackTime = currentTime; // Find all towers in range var towersHealed = 0; for (var i = 0; i < towers.length; i++) { var tower = towers[i]; // Don't heal self if (tower === self) { continue; } var dx = tower.x - self.x; var dy = tower.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range) { // Towers don't have health, so we'll boost their damage temporarily tower.damage += self.healAmount / 10; towersHealed++; // Visual effect - healing pulse var healEffect = LK.getAsset('projectile', { anchorX: 0.5, anchorY: 0.5, x: tower.x, y: tower.y, tint: 0x00FF00, alpha: 0.7 }); game.addChild(healEffect); // Animate and remove healing effect tween(healEffect, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { healEffect.destroy(); } }); } } if (towersHealed > 0) { // Play healing sound LK.getSound('projectileShot').play(); // Visual effect on self - show aura var auraEffect = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y, tint: 0x00FF00, alpha: 0.3, scaleX: self.range / 60, // Scale to match range scaleY: self.range / 60 }); game.addChild(auraEffect); // Animate and remove aura effect tween(auraEffect, { alpha: 0 }, { duration: 800, onFinish: function onFinish() { auraEffect.destroy(); } }); } } }; // Override the fireProjectile to do nothing (we use aura instead) self.fireProjectile = function () {}; return self; }); var FlameTower = Tower.expand(function () { var self = Tower.call(this); // Remove default base and add custom base with red tint self.removeChildAt(0); var baseGraphics = self.attachAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, tint: 0xFF8800 }); var towerGraphics = self.attachAsset('thornTower', { anchorX: 0.5, anchorY: 0.5, y: -20, // Offset to position on base tint: 0xFF3300 }); self.range = 200; // Short range self.damage = 8; // Lower damage per hit self.attackSpeed = 2.5; // Fast attack speed self.areaOfEffect = true; // This tower hits multiple enemies // Override the fireProjectile method for area attack self.fireProjectile = function () { // Find all enemies in range var hitEnemies = []; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range) { hitEnemies.push(enemy); // Visual effect - flame burst var flameBurst = LK.getAsset('projectile', { anchorX: 0.5, anchorY: 0.5, x: enemy.x, y: enemy.y, tint: 0xFF4500, scaleX: 1.5, scaleY: 1.5 }); game.addChild(flameBurst); // Animate and remove flame effect tween(flameBurst, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, onFinish: function onFinish() { flameBurst.destroy(); } }); // Damage the enemy enemy.takeDamage(self.damage); } } if (hitEnemies.length > 0) { LK.getSound('projectileShot').play(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2E5C2E // Forest green }); /**** * Game Code ****/ // Game variables function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) { return _arrayLikeToArray(r, a); } var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) { return; } f = !1; } else { for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0) { ; } } } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) { return; } } finally { if (o) { throw n; } } } return a; } } function _arrayWithHoles(r) { if (Array.isArray(r)) { return r; } } var gridSize = 120; var currentMode = 'guardian'; // 'guardian' or 'building' var selectedTower = 'thorn'; var essence = 100; var currentWave = 0; var waveInProgress = false; var waveTimer = null; var enemiesRemaining = 0; var towers = []; var enemies = []; var essenceItems = []; var buildingSpots = []; var path = []; var spawnPoints = []; // Tower costs var towerCosts = { 'thorn': 50, 'shroom': 100, 'flame': 150, 'healing': 200 }; // Create UI elements var scoreTxt = new Text2('0', { size: 70, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var essenceTxt = new Text2('Essence: 100', { size: 50, fill: 0x00FFFF }); essenceTxt.anchor.set(0, 0); LK.gui.topRight.addChild(essenceTxt); var waveTxt = new Text2('Wave: 0', { size: 50, fill: 0xFFFFFF }); waveTxt.anchor.set(1, 0); LK.gui.topLeft.addChild(waveTxt); // Position away from the top left corner where menu icon is waveTxt.x = 150; var healthBarBg = new Container(); var healthBarFill = new Container(); var healthBarTxt = new Text2('100/100', { size: 40, fill: 0xFFFFFF }); healthBarTxt.anchor.set(0.5, 0.5); // Setup health bar function setupHealthBar() { // Background bar var healthBg = LK.getAsset('buildingSpot', { anchorX: 0, anchorY: 0, width: 300, height: 40, tint: 0x333333 }); healthBarBg.addChild(healthBg); // Fill bar var healthFill = LK.getAsset('buildingSpot', { anchorX: 0, anchorY: 0, width: 300, height: 40, tint: 0x00FF00 }); healthBarFill.addChild(healthFill); // Add to GUI LK.gui.bottom.addChild(healthBarBg); LK.gui.bottom.addChild(healthBarFill); LK.gui.bottom.addChild(healthBarTxt); // Position health bar healthBarBg.y = -60; healthBarFill.y = -60; healthBarTxt.y = -40; } // Update health bar function updateHealthBar() { var healthPercent = heartTree.health / heartTree.maxHealth; healthBarFill.scale.x = healthPercent; healthBarTxt.setText(heartTree.health + '/' + heartTree.maxHealth); // Update color based on health percentage var fill = healthBarFill.getChildAt(0); if (healthPercent > 0.6) { fill.tint = 0x00FF00; // Green } else if (healthPercent > 0.3) { fill.tint = 0xFFFF00; // Yellow } else { fill.tint = 0xFF0000; // Red } } // Create game mode buttons var guardianBtn = new Container(); var buildBtn = new Container(); function setupModeButtons() { // Guardian mode button var guardianBtnBg = LK.getAsset('guardian', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); guardianBtn.addChild(guardianBtnBg); var guardianBtnTxt = new Text2('Move', { size: 30, fill: 0xFFFFFF }); guardianBtnTxt.anchor.set(0.5, 0.5); guardianBtnTxt.y = 50; guardianBtn.addChild(guardianBtnTxt); // Building mode button var buildBtnBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); buildBtn.addChild(buildBtnBg); var buildBtnTxt = new Text2('Build', { size: 30, fill: 0xFFFFFF }); buildBtnTxt.anchor.set(0.5, 0.5); buildBtnTxt.y = 50; buildBtn.addChild(buildBtnTxt); // Add to GUI LK.gui.bottomLeft.addChild(guardianBtn); LK.gui.bottomLeft.addChild(buildBtn); // Position buttons guardianBtn.x = 100; guardianBtn.y = -100; buildBtn.x = 220; buildBtn.y = -100; // Add event listeners guardianBtn.interactive = true; guardianBtn.down = function () { setGameMode('guardian'); }; buildBtn.interactive = true; buildBtn.down = function () { setGameMode('building'); }; // Highlight current mode updateModeButtons(); } // Create tower selection buttons var thornBtn = new Container(); var shroomBtn = new Container(); var flameBtn = new Container(); var healingBtn = new Container(); function setupTowerButtons() { // Thorn tower button var thornBtnBg = LK.getAsset('thornTower', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); thornBtn.addChild(thornBtnBg); var thornBtnTxt = new Text2('50', { size: 30, fill: 0xFFFFFF }); thornBtnTxt.anchor.set(0.5, 0.5); thornBtnTxt.y = 50; thornBtn.addChild(thornBtnTxt); // Shroom tower button var shroomBtnBg = LK.getAsset('shroomTower', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); shroomBtn.addChild(shroomBtnBg); var shroomBtnTxt = new Text2('100', { size: 30, fill: 0xFFFFFF }); shroomBtnTxt.anchor.set(0.5, 0.5); shroomBtnTxt.y = 50; shroomBtn.addChild(shroomBtnTxt); // Flame tower button var flameBtnBg = LK.getAsset('thornTower', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80, tint: 0xFF3300 }); flameBtn.addChild(flameBtnBg); var flameBtnTxt = new Text2('150', { size: 30, fill: 0xFFFFFF }); flameBtnTxt.anchor.set(0.5, 0.5); flameBtnTxt.y = 50; flameBtn.addChild(flameBtnTxt); // Healing tower button var healingBtnBg = LK.getAsset('shroomTower', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80, tint: 0x00FF88 }); healingBtn.addChild(healingBtnBg); var healingBtnTxt = new Text2('200', { size: 30, fill: 0xFFFFFF }); healingBtnTxt.anchor.set(0.5, 0.5); healingBtnTxt.y = 50; healingBtn.addChild(healingBtnTxt); // Add to GUI LK.gui.bottomRight.addChild(thornBtn); LK.gui.bottomRight.addChild(shroomBtn); LK.gui.bottomRight.addChild(flameBtn); LK.gui.bottomRight.addChild(healingBtn); // Position buttons thornBtn.x = -100; thornBtn.y = -100; shroomBtn.x = -220; shroomBtn.y = -100; flameBtn.x = -100; flameBtn.y = -200; healingBtn.x = -220; healingBtn.y = -200; // Add event listeners thornBtn.interactive = true; thornBtn.down = function () { if (currentMode === 'building') { selectTower('thorn'); } }; shroomBtn.interactive = true; shroomBtn.down = function () { if (currentMode === 'building' && storage.unlockedTowers.includes('shroom')) { selectTower('shroom'); } }; flameBtn.interactive = true; flameBtn.down = function () { if (currentMode === 'building' && storage.unlockedTowers.includes('flame')) { selectTower('flame'); } }; healingBtn.interactive = true; healingBtn.down = function () { if (currentMode === 'building' && storage.unlockedTowers.includes('healing')) { selectTower('healing'); } }; // If towers are not unlocked, gray them out if (!storage.unlockedTowers.includes('shroom')) { shroomBtn.alpha = 0.5; } if (!storage.unlockedTowers.includes('flame')) { flameBtn.alpha = 0.5; } if (!storage.unlockedTowers.includes('healing')) { healingBtn.alpha = 0.5; } // Highlight selected tower updateTowerButtons(); } // Start wave button var startWaveBtn = new Container(); function setupStartWaveButton() { var startWaveButtonBg = LK.getAsset('buildingSpot', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 80, tint: 0x4CAF50 }); startWaveBtn.addChild(startWaveButtonBg); var startWaveBtnTxt = new Text2('Start Wave', { size: 40, fill: 0xFFFFFF }); startWaveBtnTxt.anchor.set(0.5, 0.5); startWaveBtn.addChild(startWaveBtnTxt); // Add to GUI LK.gui.bottom.addChild(startWaveBtn); // Position button startWaveBtn.y = -150; // Add event listener startWaveBtn.interactive = true; startWaveBtn.down = function () { if (!waveInProgress) { startWave(); } }; } function updateModeButtons() { guardianBtn.alpha = currentMode === 'guardian' ? 1.0 : 0.6; buildBtn.alpha = currentMode === 'building' ? 1.0 : 0.6; } function updateTowerButtons() { thornBtn.alpha = currentMode === 'building' && selectedTower === 'thorn' ? 1.0 : 0.6; shroomBtn.alpha = currentMode === 'building' && selectedTower === 'shroom' && storage.unlockedTowers.includes('shroom') ? 1.0 : 0.3; flameBtn.alpha = currentMode === 'building' && selectedTower === 'flame' && storage.unlockedTowers.includes('flame') ? 1.0 : 0.3; healingBtn.alpha = currentMode === 'building' && selectedTower === 'healing' && storage.unlockedTowers.includes('healing') ? 1.0 : 0.3; } function setGameMode(mode) { currentMode = mode; updateModeButtons(); updateTowerButtons(); } function selectTower(tower) { selectedTower = tower; updateTowerButtons(); } function updateEssenceText() { essenceTxt.setText('Essence: ' + essence); } function createLevel() { // Clear any existing level elements for (var i = 0; i < buildingSpots.length; i++) { buildingSpots[i].destroy(); } buildingSpots = []; path = []; spawnPoints = []; // Level dimensions (in grid cells) var levelWidth = 15; var levelHeight = 19; // Create a grid for the level var grid = []; for (var y = 0; y < levelHeight; y++) { grid[y] = []; for (var x = 0; x < levelWidth; x++) { grid[y][x] = 0; // 0 = empty } } // Define path through the level (1 = path) var pathCoords = [[0, 9], [1, 9], [2, 9], [3, 9], [4, 9], [5, 9], [6, 9], [6, 8], [6, 7], [6, 6], [6, 5], [7, 5], [8, 5], [9, 5], [9, 6], [9, 7], [9, 8], [9, 9], [9, 10], [9, 11], [8, 11], [7, 11], [6, 11], [5, 11], [4, 11], [4, 12], [4, 13], [4, 14], [4, 15], [5, 15], [6, 15], [7, 15], [8, 15], [9, 15], [10, 15], [11, 15], [11, 14], [11, 13], [11, 12], [11, 11], [11, 10], [11, 9], [11, 8], [11, 7], [12, 7], [13, 7], [14, 7]]; for (var i = 0; i < pathCoords.length; i++) { var _pathCoords$i = _slicedToArray(pathCoords[i], 2), x = _pathCoords$i[0], y = _pathCoords$i[1]; grid[y][x] = 1; } // Set spawn point (2 = spawn) grid[9][0] = 2; // Set heart tree location (3 = heart tree) grid[7][14] = 3; // Create level elements based on grid for (var y = 0; y < levelHeight; y++) { for (var x = 0; x < levelWidth; x++) { var gridValue = grid[y][x]; var worldX = x * gridSize + gridSize / 2 + 174; // Center in grid cell with some offset var worldY = y * gridSize + gridSize / 2 + 150; if (gridValue === 1) { // Path tile var pathTile = new PathTile(); pathTile.x = worldX; pathTile.y = worldY; pathTile.gridX = x; pathTile.gridY = y; game.addChild(pathTile); // Add to path array for enemy movement path.push(pathTile); } else if (gridValue === 2) { // Spawn point var spawnPoint = new SpawnPoint(); spawnPoint.x = worldX; spawnPoint.y = worldY; game.addChild(spawnPoint); spawnPoints.push(spawnPoint); // Also add as first path point path.unshift(spawnPoint); } else if (gridValue === 3) { // Heart Tree heartTree = new HeartTree(); heartTree.x = worldX; heartTree.y = worldY; game.addChild(heartTree); } else if (gridValue === 0) { // Check if adjacent to path (can build here) var adjacentToPath = false; // Check all adjacent cells var directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; for (var _i = 0, _directions = directions; _i < _directions.length; _i++) { var dir = _directions[_i]; var adjX = x + dir[0]; var adjY = y + dir[1]; if (adjX >= 0 && adjX < levelWidth && adjY >= 0 && adjY < levelHeight && grid[adjY][adjX] === 1) { adjacentToPath = true; break; } } if (adjacentToPath) { // Create building spot var spot = new BuildingSpot(); spot.x = worldX; spot.y = worldY; spot.gridX = x; spot.gridY = y; game.addChild(spot); buildingSpots.push(spot); } } } } // Sort path from start to end path.sort(function (a, b) { return pathCoords.findIndex(function (coords) { return coords[0] === a.gridX && coords[1] === a.gridY; }) - pathCoords.findIndex(function (coords) { return coords[0] === b.gridX && coords[1] === b.gridY; }); }); // Create guardian guardian = new Guardian(); guardian.x = path[Math.floor(path.length / 2)].x; guardian.y = path[Math.floor(path.length / 2)].y; game.addChild(guardian); } function startWave() { if (waveInProgress) { return; } currentWave++; waveTxt.setText('Wave: ' + currentWave); waveInProgress = true; startWaveBtn.alpha = 0.5; // Calculate enemies for this wave var numEnemies = 5 + Math.floor(currentWave * 1.5); var hasBoss = currentWave % 5 === 0; enemiesRemaining = numEnemies + (hasBoss ? 1 : 0); LK.getSound('waveStart').play(); // Spawn enemies periodically var enemiesSpawned = 0; waveTimer = LK.setInterval(function () { if (enemiesSpawned < numEnemies) { spawnEnemy(false); enemiesSpawned++; } else if (hasBoss && enemiesSpawned === numEnemies) { spawnEnemy(true); // Spawn boss enemiesSpawned++; } else { LK.clearInterval(waveTimer); } }, 1500); } function spawnEnemy(isBoss) { var enemy; if (isBoss) { enemy = new BossEnemy(); } else { // Randomly choose enemy type based on wave progression var randomType = Math.random(); if (currentWave >= 2 && randomType < 0.3) { // 30% chance of spawning speedy enemy after wave 2 enemy = new SpeedyEnemy(); // Scale difficulty with wave number enemy.maxHealth = 30 + currentWave * 6; enemy.health = enemy.maxHealth; enemy.speed = 4 + currentWave * 0.15; enemy.value = 15 + currentWave; } else if (currentWave >= 4 && randomType < 0.5) { // 20% chance of spawning tank enemy after wave 4 enemy = new TankEnemy(); // Scale difficulty with wave number enemy.maxHealth = 120 + currentWave * 15; enemy.health = enemy.maxHealth; enemy.speed = 1 + currentWave * 0.05; enemy.value = 25 + currentWave; } else { // Regular enemy enemy = new Enemy(); // Scale difficulty with wave number enemy.maxHealth = 50 + currentWave * 10; enemy.health = enemy.maxHealth; enemy.speed = 2 + currentWave * 0.1; enemy.value = 10 + currentWave; } } // Set initial position at spawn point var spawnPoint = spawnPoints[0]; enemy.x = spawnPoint.x; enemy.y = spawnPoint.y; game.addChild(enemy); enemies.push(enemy); // Apply animation for spawning enemy.alpha = 0; enemy.scale.set(0.5, 0.5); tween(enemy, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500 }); } function checkWaveComplete() { if (waveInProgress && enemies.length === 0 && enemiesRemaining === 0) { waveInProgress = false; startWaveBtn.alpha = 1.0; // Reward between waves var waveBonus = 50 + currentWave * 10; essence += waveBonus; updateEssenceText(); // Show wave complete message var waveBonusTxt = new Text2('Wave Complete! +' + waveBonus + ' Essence', { size: 80, fill: 0xFFFFFF }); waveBonusTxt.anchor.set(0.5, 0.5); waveBonusTxt.x = 2048 / 2; waveBonusTxt.y = 2732 / 2; game.addChild(waveBonusTxt); // Animate and remove message tween(waveBonusTxt, { alpha: 0, y: waveBonusTxt.y - 100 }, { duration: 2000, onFinish: function onFinish() { waveBonusTxt.destroy(); } }); // Unlock new tower types based on wave progress if (currentWave === 3 && !storage.unlockedTowers.includes('shroom')) { storage.unlockedTowers.push('shroom'); shroomBtn.alpha = 0.6; // Show unlock message var unlockTxt = new Text2('New Tower Unlocked: Shroom Puff!', { size: 60, fill: 0xFFFF00 }); unlockTxt.anchor.set(0.5, 0.5); unlockTxt.x = 2048 / 2; unlockTxt.y = 2732 / 2 + 100; game.addChild(unlockTxt); // Animate and remove message tween(unlockTxt, { alpha: 0, y: unlockTxt.y - 100 }, { duration: 3000, onFinish: function onFinish() { unlockTxt.destroy(); } }); } else if (currentWave === 5 && !storage.unlockedTowers.includes('flame')) { storage.unlockedTowers.push('flame'); flameBtn.alpha = 0.6; // Show unlock message var unlockTxt = new Text2('New Tower Unlocked: Flame Fern!', { size: 60, fill: 0xFF5500 }); unlockTxt.anchor.set(0.5, 0.5); unlockTxt.x = 2048 / 2; unlockTxt.y = 2732 / 2 + 100; game.addChild(unlockTxt); // Animate and remove message tween(unlockTxt, { alpha: 0, y: unlockTxt.y - 100 }, { duration: 3000, onFinish: function onFinish() { unlockTxt.destroy(); } }); } else if (currentWave === 8 && !storage.unlockedTowers.includes('healing')) { storage.unlockedTowers.push('healing'); healingBtn.alpha = 0.6; // Show unlock message var unlockTxt = new Text2('New Tower Unlocked: Healing Bloom!', { size: 60, fill: 0x00FF88 }); unlockTxt.anchor.set(0.5, 0.5); unlockTxt.x = 2048 / 2; unlockTxt.y = 2732 / 2 + 100; game.addChild(unlockTxt); // Animate and remove message tween(unlockTxt, { alpha: 0, y: unlockTxt.y - 100 }, { duration: 3000, onFinish: function onFinish() { unlockTxt.destroy(); } }); } } } function isPositionValid(x, y) { // Check if position is within game bounds if (x < 0 || x > 2048 || y < 0 || y > 2732) { return false; } return true; } // Initialize game function initGame() { // Setup UI elements setupHealthBar(); setupModeButtons(); setupTowerButtons(); setupStartWaveButton(); // Create game level createLevel(); // Set initial game state LK.setScore(0); scoreTxt.setText('0'); updateEssenceText(); updateHealthBar(); // Start background music LK.playMusic('forestAmbience', { loop: true }); } // Game event handlers game.down = function (x, y, obj) { if (currentMode === 'guardian') { guardian.moveTo(x, y); } }; // Game update loop game.update = function () { // Update all game objects for (var i = 0; i < towers.length; i++) { towers[i].update(); } // Update enemies (backwards to safely remove) for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].update(); if (!enemies[i].alive) { enemies[i].destroy(); enemies.splice(i, 1); enemiesRemaining--; } } // Update essence items (backwards to safely remove) for (var i = essenceItems.length - 1; i >= 0; i--) { essenceItems[i].update(); if (essenceItems[i].collected) { essenceItems[i].destroy(); essenceItems.splice(i, 1); } } // Update guardian guardian.update(); // Check if wave is complete checkWaveComplete(); }; // Initialize the game initGame();
===================================================================
--- original.js
+++ change.js
@@ -3,9 +3,9 @@
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
- unlockedTowers: ["thorn"]
+ unlockedTowers: ["thorn", "shroom", "flame", "healing"]
});
/****
* Classes
@@ -31,8 +31,12 @@
if (towerType === 'thorn') {
tower = new ThornTower();
} else if (towerType === 'shroom') {
tower = new ShroomTower();
+ } else if (towerType === 'flame') {
+ tower = new FlameTower();
+ } else if (towerType === 'healing') {
+ tower = new HealingTower();
}
if (tower) {
tower.x = self.x;
tower.y = self.y;
@@ -112,8 +116,44 @@
LK.getSound('enemyDeath').play();
};
return self;
});
+var TankEnemy = Enemy.expand(function () {
+ var self = Enemy.call(this);
+ // Replace with custom graphics
+ self.removeChildAt(0); // Remove default enemy graphics
+ var tankGraphics = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x666666,
+ // Grey tint for tank enemies
+ scaleX: 1.4,
+ scaleY: 1.4 // Larger
+ });
+ self.speed = 1; // Slower
+ self.maxHealth = 120; // Higher health
+ self.health = self.maxHealth;
+ self.value = 25; // Higher value
+ return self;
+});
+var SpeedyEnemy = Enemy.expand(function () {
+ var self = Enemy.call(this);
+ // Replace with custom graphics
+ self.removeChildAt(0); // Remove default enemy graphics
+ var speedyGraphics = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0xFFFF00,
+ // Yellow tint for speedy enemies
+ scaleX: 0.8,
+ scaleY: 1.2 // Tall and thin
+ });
+ self.speed = 4; // Much faster
+ self.maxHealth = 30; // Lower health
+ self.health = self.maxHealth;
+ self.value = 15; // Slightly higher value
+ return self;
+});
var BossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace with boss graphics
self.removeChildAt(0); // Remove default enemy graphics
@@ -391,8 +431,165 @@
self.damage = 25;
self.attackSpeed = 0.8;
return self;
});
+var HealingTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Remove default base and add custom base with green healing tint
+ self.removeChildAt(0);
+ var baseGraphics = self.attachAsset('towerBase', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x00FF88
+ });
+ var towerGraphics = self.attachAsset('shroomTower', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -20,
+ // Offset to position on base
+ tint: 0x88FF88
+ });
+ self.range = 280;
+ self.healAmount = 5;
+ self.attackSpeed = 1.5;
+ // Override the attack method to heal nearby towers instead
+ self.attack = function () {
+ var currentTime = LK.ticks / 60;
+ if (currentTime - self.lastAttackTime >= 1 / self.attackSpeed) {
+ self.lastAttackTime = currentTime;
+ // Find all towers in range
+ var towersHealed = 0;
+ for (var i = 0; i < towers.length; i++) {
+ var tower = towers[i];
+ // Don't heal self
+ if (tower === self) {
+ continue;
+ }
+ var dx = tower.x - self.x;
+ var dy = tower.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range) {
+ // Towers don't have health, so we'll boost their damage temporarily
+ tower.damage += self.healAmount / 10;
+ towersHealed++;
+ // Visual effect - healing pulse
+ var healEffect = LK.getAsset('projectile', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: tower.x,
+ y: tower.y,
+ tint: 0x00FF00,
+ alpha: 0.7
+ });
+ game.addChild(healEffect);
+ // Animate and remove healing effect
+ tween(healEffect, {
+ alpha: 0,
+ scaleX: 2,
+ scaleY: 2
+ }, {
+ duration: 400,
+ onFinish: function onFinish() {
+ healEffect.destroy();
+ }
+ });
+ }
+ }
+ if (towersHealed > 0) {
+ // Play healing sound
+ LK.getSound('projectileShot').play();
+ // Visual effect on self - show aura
+ var auraEffect = LK.getAsset('towerBase', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: self.x,
+ y: self.y,
+ tint: 0x00FF00,
+ alpha: 0.3,
+ scaleX: self.range / 60,
+ // Scale to match range
+ scaleY: self.range / 60
+ });
+ game.addChild(auraEffect);
+ // Animate and remove aura effect
+ tween(auraEffect, {
+ alpha: 0
+ }, {
+ duration: 800,
+ onFinish: function onFinish() {
+ auraEffect.destroy();
+ }
+ });
+ }
+ }
+ };
+ // Override the fireProjectile to do nothing (we use aura instead)
+ self.fireProjectile = function () {};
+ return self;
+});
+var FlameTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Remove default base and add custom base with red tint
+ self.removeChildAt(0);
+ var baseGraphics = self.attachAsset('towerBase', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0xFF8800
+ });
+ var towerGraphics = self.attachAsset('thornTower', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -20,
+ // Offset to position on base
+ tint: 0xFF3300
+ });
+ self.range = 200; // Short range
+ self.damage = 8; // Lower damage per hit
+ self.attackSpeed = 2.5; // Fast attack speed
+ self.areaOfEffect = true; // This tower hits multiple enemies
+ // Override the fireProjectile method for area attack
+ self.fireProjectile = function () {
+ // Find all enemies in range
+ var hitEnemies = [];
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ var dx = enemy.x - self.x;
+ var dy = enemy.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range) {
+ hitEnemies.push(enemy);
+ // Visual effect - flame burst
+ var flameBurst = LK.getAsset('projectile', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: enemy.x,
+ y: enemy.y,
+ tint: 0xFF4500,
+ scaleX: 1.5,
+ scaleY: 1.5
+ });
+ game.addChild(flameBurst);
+ // Animate and remove flame effect
+ tween(flameBurst, {
+ alpha: 0,
+ scaleX: 0.5,
+ scaleY: 0.5
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ flameBurst.destroy();
+ }
+ });
+ // Damage the enemy
+ enemy.takeDamage(self.damage);
+ }
+ }
+ if (hitEnemies.length > 0) {
+ LK.getSound('projectileShot').play();
+ }
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -402,200 +599,8 @@
/****
* Game Code
****/
-// Wave environment effects
-var environmentEffects = [];
-// Apply themed environment based on wave type
-function applyWaveEnvironment(waveNumber) {
- // Clear any existing environment effects
- for (var i = 0; i < environmentEffects.length; i++) {
- environmentEffects[i].destroy();
- }
- environmentEffects = [];
- var waveTheme = waveNumber % 5;
- var gameBackgroundColor;
- if (waveTheme === 0) {
- // Boss wave - dark and ominous
- gameBackgroundColor = 0x1A1A2E;
- // Add ambient particles for boss wave (dark energy)
- for (var i = 0; i < 20; i++) {
- var particle = new Container();
- var graphics = particle.attachAsset('essence', {
- anchorX: 0.5,
- anchorY: 0.5,
- tint: 0xFF00FF,
- alpha: 0.3 + Math.random() * 0.3
- });
- particle.x = Math.random() * 2048;
- particle.y = Math.random() * 2732;
- particle.scale.set(0.5 + Math.random() * 1);
- particle.speedX = (Math.random() - 0.5) * 2;
- particle.speedY = (Math.random() - 0.5) * 2;
- particle.update = function () {
- this.x += this.speedX;
- this.y += this.speedY;
- // Wrap around screen
- if (this.x < 0) {
- this.x = 2048;
- }
- if (this.x > 2048) {
- this.x = 0;
- }
- if (this.y < 0) {
- this.y = 2732;
- }
- if (this.y > 2732) {
- this.y = 0;
- }
- // Pulsate
- var scale = 0.5 + Math.sin(LK.ticks / 20 + this.x) * 0.2;
- this.scale.set(scale, scale);
- };
- game.addChild(particle);
- environmentEffects.push(particle);
- }
- } else if (waveTheme === 1) {
- // Forest - lush green
- gameBackgroundColor = 0x2E5C2E;
- // Add ambient particles for forest (leaves/pollen)
- for (var i = 0; i < 15; i++) {
- var particle = new Container();
- var graphics = particle.attachAsset('essence', {
- anchorX: 0.5,
- anchorY: 0.5,
- tint: 0xAAFF88,
- alpha: 0.4 + Math.random() * 0.3
- });
- particle.x = Math.random() * 2048;
- particle.y = Math.random() * 2732;
- particle.scale.set(0.3 + Math.random() * 0.3);
- particle.speedX = (Math.random() - 0.3) * 1;
- particle.speedY = -0.5 - Math.random() * 1;
- particle.update = function () {
- this.x += this.speedX;
- this.y += this.speedY;
- // Reset when off screen
- if (this.y < -20) {
- this.y = 2732 + 20;
- this.x = Math.random() * 2048;
- }
- };
- game.addChild(particle);
- environmentEffects.push(particle);
- }
- } else if (waveTheme === 2) {
- // Swamp - murky
- gameBackgroundColor = 0x3A5311;
- // Add ambient particles for swamp (mist)
- for (var i = 0; i < 10; i++) {
- var particle = new Container();
- var graphics = particle.attachAsset('buildingSpot', {
- anchorX: 0.5,
- anchorY: 0.5,
- tint: 0xCCDDAA,
- alpha: 0.15 + Math.random() * 0.1
- });
- particle.x = Math.random() * 2048;
- particle.y = Math.random() * 2732;
- particle.scale.set(3 + Math.random() * 5);
- particle.speedX = (Math.random() - 0.5) * 0.3;
- particle.update = function () {
- this.x += this.speedX;
- // Wrap around screen
- if (this.x < -200) {
- this.x = 2248;
- }
- if (this.x > 2248) {
- this.x = -200;
- }
- // Slight pulsating
- var scale = this.scale.x + Math.sin(LK.ticks / 100) * 0.05;
- this.scale.set(scale, scale);
- };
- game.addChild(particle);
- environmentEffects.push(particle);
- }
- } else if (waveTheme === 3) {
- // Crystal river - blue/clear
- gameBackgroundColor = 0x3A6A9F;
- // Add ambient particles for crystal (sparkles)
- for (var i = 0; i < 25; i++) {
- var particle = new Container();
- var graphics = particle.attachAsset('projectile', {
- anchorX: 0.5,
- anchorY: 0.5,
- tint: 0xFFFFFF,
- alpha: 0.4 + Math.random() * 0.6
- });
- particle.x = Math.random() * 2048;
- particle.y = Math.random() * 2732;
- particle.scale.set(0.2 + Math.random() * 0.3);
- particle.lifeTime = 30 + Math.random() * 60;
- particle.age = Math.random() * particle.lifeTime;
- particle.update = function () {
- this.age++;
- if (this.age >= this.lifeTime) {
- this.age = 0;
- this.x = Math.random() * 2048;
- this.y = Math.random() * 2732;
- this.alpha = 0;
- }
- // Fade in and out
- if (this.age < this.lifeTime * 0.2) {
- this.alpha = this.age / (this.lifeTime * 0.2) * 0.8;
- } else if (this.age > this.lifeTime * 0.8) {
- this.alpha = (this.lifeTime - this.age) / (this.lifeTime * 0.2) * 0.8;
- }
- };
- game.addChild(particle);
- environmentEffects.push(particle);
- }
- } else if (waveTheme === 4) {
- // Mechanical - industrial
- gameBackgroundColor = 0x4A4A4A;
- // Add ambient particles for mechanical (smoke)
- for (var i = 0; i < 8; i++) {
- var particle = new Container();
- var graphics = particle.attachAsset('buildingSpot', {
- anchorX: 0.5,
- anchorY: 0.5,
- tint: 0x888888,
- alpha: 0.2 + Math.random() * 0.1
- });
- particle.x = 200 + Math.random() * 1648;
- particle.y = 2732 + Math.random() * 100;
- particle.scale.set(1 + Math.random() * 3);
- particle.speedY = -0.8 - Math.random() * 0.5;
- particle.update = function () {
- this.y += this.speedY;
- this.x += Math.sin(this.y / 200) * 0.5;
- // Grow slightly as it rises
- this.scale.x += 0.003;
- this.scale.y += 0.003;
- // Fade out as it rises
- if (this.y < 1000) {
- this.alpha -= 0.001;
- }
- // Reset when off screen or fully transparent
- if (this.y < -300 || this.alpha <= 0) {
- this.y = 2732 + Math.random() * 100;
- this.x = 200 + Math.random() * 1648;
- this.scale.set(1 + Math.random() * 3);
- this.alpha = 0.2 + Math.random() * 0.1;
- }
- };
- game.addChild(particle);
- environmentEffects.push(particle);
- }
- }
- // Apply background color transition
- tween(game, {
- backgroundColor: gameBackgroundColor
- }, {
- duration: 1000
- });
-}
// Game variables
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
@@ -676,9 +681,11 @@
var spawnPoints = [];
// Tower costs
var towerCosts = {
'thorn': 50,
- 'shroom': 100
+ 'shroom': 100,
+ 'flame': 150,
+ 'healing': 200
};
// Create UI elements
var scoreTxt = new Text2('0', {
size: 70,
@@ -807,8 +814,10 @@
}
// Create tower selection buttons
var thornBtn = new Container();
var shroomBtn = new Container();
+var flameBtn = new Container();
+var healingBtn = new Container();
function setupTowerButtons() {
// Thorn tower button
var thornBtnBg = LK.getAsset('thornTower', {
anchorX: 0.5,
@@ -838,16 +847,54 @@
});
shroomBtnTxt.anchor.set(0.5, 0.5);
shroomBtnTxt.y = 50;
shroomBtn.addChild(shroomBtnTxt);
+ // Flame tower button
+ var flameBtnBg = LK.getAsset('thornTower', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 80,
+ height: 80,
+ tint: 0xFF3300
+ });
+ flameBtn.addChild(flameBtnBg);
+ var flameBtnTxt = new Text2('150', {
+ size: 30,
+ fill: 0xFFFFFF
+ });
+ flameBtnTxt.anchor.set(0.5, 0.5);
+ flameBtnTxt.y = 50;
+ flameBtn.addChild(flameBtnTxt);
+ // Healing tower button
+ var healingBtnBg = LK.getAsset('shroomTower', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 80,
+ height: 80,
+ tint: 0x00FF88
+ });
+ healingBtn.addChild(healingBtnBg);
+ var healingBtnTxt = new Text2('200', {
+ size: 30,
+ fill: 0xFFFFFF
+ });
+ healingBtnTxt.anchor.set(0.5, 0.5);
+ healingBtnTxt.y = 50;
+ healingBtn.addChild(healingBtnTxt);
// Add to GUI
LK.gui.bottomRight.addChild(thornBtn);
LK.gui.bottomRight.addChild(shroomBtn);
+ LK.gui.bottomRight.addChild(flameBtn);
+ LK.gui.bottomRight.addChild(healingBtn);
// Position buttons
thornBtn.x = -100;
thornBtn.y = -100;
shroomBtn.x = -220;
shroomBtn.y = -100;
+ flameBtn.x = -100;
+ flameBtn.y = -200;
+ healingBtn.x = -220;
+ healingBtn.y = -200;
// Add event listeners
thornBtn.interactive = true;
thornBtn.down = function () {
if (currentMode === 'building') {
@@ -859,12 +906,30 @@
if (currentMode === 'building' && storage.unlockedTowers.includes('shroom')) {
selectTower('shroom');
}
};
- // If shroom tower is not unlocked, gray it out
+ flameBtn.interactive = true;
+ flameBtn.down = function () {
+ if (currentMode === 'building' && storage.unlockedTowers.includes('flame')) {
+ selectTower('flame');
+ }
+ };
+ healingBtn.interactive = true;
+ healingBtn.down = function () {
+ if (currentMode === 'building' && storage.unlockedTowers.includes('healing')) {
+ selectTower('healing');
+ }
+ };
+ // If towers are not unlocked, gray them out
if (!storage.unlockedTowers.includes('shroom')) {
shroomBtn.alpha = 0.5;
}
+ if (!storage.unlockedTowers.includes('flame')) {
+ flameBtn.alpha = 0.5;
+ }
+ if (!storage.unlockedTowers.includes('healing')) {
+ healingBtn.alpha = 0.5;
+ }
// Highlight selected tower
updateTowerButtons();
}
// Start wave button
@@ -902,8 +967,10 @@
}
function updateTowerButtons() {
thornBtn.alpha = currentMode === 'building' && selectedTower === 'thorn' ? 1.0 : 0.6;
shroomBtn.alpha = currentMode === 'building' && selectedTower === 'shroom' && storage.unlockedTowers.includes('shroom') ? 1.0 : 0.3;
+ flameBtn.alpha = currentMode === 'building' && selectedTower === 'flame' && storage.unlockedTowers.includes('flame') ? 1.0 : 0.3;
+ healingBtn.alpha = currentMode === 'building' && selectedTower === 'healing' && storage.unlockedTowers.includes('healing') ? 1.0 : 0.3;
}
function setGameMode(mode) {
currentMode = mode;
updateModeButtons();
@@ -915,128 +982,39 @@
}
function updateEssenceText() {
essenceTxt.setText('Essence: ' + essence);
}
-function generateLevelForWave(waveNumber) {
+function createLevel() {
+ // Clear any existing level elements
+ for (var i = 0; i < buildingSpots.length; i++) {
+ buildingSpots[i].destroy();
+ }
+ buildingSpots = [];
+ path = [];
+ spawnPoints = [];
// Level dimensions (in grid cells)
var levelWidth = 15;
var levelHeight = 19;
- // Create an empty grid
+ // Create a grid for the level
var grid = [];
for (var y = 0; y < levelHeight; y++) {
grid[y] = [];
for (var x = 0; x < levelWidth; x++) {
grid[y][x] = 0; // 0 = empty
}
}
- // Different path patterns based on wave number
- var pathCoords = [];
- var heartTreeX = 0;
- var heartTreeY = 0;
- var spawnX = 0;
- var spawnY = 0;
- // Create different map layouts for different waves
- if (waveNumber % 5 === 1) {
- // First map type (waves 1, 6, 11, etc)
- // Zigzag path from left to right
- pathCoords = [[0, 9], [1, 9], [2, 9], [3, 9], [4, 9], [5, 9], [6, 9], [6, 8], [6, 7], [6, 6], [6, 5], [7, 5], [8, 5], [9, 5], [9, 6], [9, 7], [9, 8], [9, 9], [9, 10], [9, 11], [8, 11], [7, 11], [6, 11], [5, 11], [4, 11], [4, 12], [4, 13], [4, 14], [4, 15], [5, 15], [6, 15], [7, 15], [8, 15], [9, 15], [10, 15], [11, 15], [11, 14], [11, 13], [11, 12], [11, 11], [11, 10], [11, 9], [11, 8], [11, 7], [12, 7], [13, 7], [14, 7]];
- spawnX = 9;
- spawnY = 0;
- heartTreeX = 7;
- heartTreeY = 14;
- } else if (waveNumber % 5 === 2) {
- // Second map type (waves 2, 7, 12, etc)
- // Spiral path around center
- pathCoords = [[7, 0], [7, 1], [7, 2], [7, 3], [7, 4], [7, 5], [7, 6], [7, 7], [6, 7], [5, 7], [4, 7], [3, 7], [3, 8], [3, 9], [3, 10], [3, 11], [4, 11], [5, 11], [6, 11], [7, 11], [8, 11], [9, 11], [10, 11], [11, 11], [11, 10], [11, 9], [11, 8], [11, 7], [10, 7], [9, 7], [8, 7]];
- spawnX = 7;
- spawnY = 0;
- heartTreeX = 8;
- heartTreeY = 7;
- } else if (waveNumber % 5 === 3) {
- // Third map type (waves 3, 8, 13, etc)
- // U-shaped path
- pathCoords = [[0, 3], [1, 3], [2, 3], [3, 3], [4, 3], [5, 3], [6, 3], [7, 3], [8, 3], [9, 3], [10, 3], [11, 3], [12, 3], [13, 3], [14, 3], [14, 4], [14, 5], [14, 6], [14, 7], [14, 8], [14, 9], [14, 10], [14, 11], [14, 12], [14, 13], [14, 14], [14, 15], [13, 15], [12, 15], [11, 15], [10, 15], [9, 15], [8, 15], [7, 15], [6, 15], [5, 15], [4, 15], [3, 15], [2, 15], [1, 15], [0, 15], [0, 14], [0, 13], [0, 12], [0, 11], [0, 10], [0, 9], [0, 8], [0, 7], [0, 6], [0, 5], [0, 4]];
- spawnX = 0;
- spawnY = 3;
- heartTreeX = 7;
- heartTreeY = 9;
- } else if (waveNumber % 5 === 4) {
- // Fourth map type (waves 4, 9, 14, etc)
- // X-shaped crossing paths
- pathCoords = [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9], [10, 10], [11, 11], [12, 12], [13, 13], [14, 14], [0, 14], [1, 13], [2, 12], [3, 11], [4, 10], [5, 9], [6, 8], [8, 6], [9, 5], [10, 4], [11, 3], [12, 2], [13, 1], [14, 0]];
- spawnX = 0;
- spawnY = 0;
- heartTreeX = 7;
- heartTreeY = 7;
- } else {
- // Fifth map type (waves 5, 10, 15, etc) - boss waves
- // Circular path around center with multiple entrances
- var centerX = 7;
- var centerY = 9;
- var radius = 5;
- // Create a circular path
- for (var angle = 0; angle < 360; angle += 15) {
- var rad = angle * (Math.PI / 180);
- var x = Math.round(centerX + radius * Math.cos(rad));
- var y = Math.round(centerY + radius * Math.sin(rad));
- // Ensure coordinates are within bounds
- x = Math.max(0, Math.min(x, levelWidth - 1));
- y = Math.max(0, Math.min(y, levelHeight - 1));
- pathCoords.push([x, y]);
- }
- // Add entrance paths from each side
- pathCoords = pathCoords.concat([[0, 9], [1, 9], [2, 9], [3, 9], [14, 9], [13, 9], [12, 9], [11, 9], [7, 0], [7, 1], [7, 2], [7, 3], [7, 4], [7, 18], [7, 17], [7, 16], [7, 15], [7, 14]]);
- spawnX = 0;
- spawnY = 9;
- heartTreeX = 7;
- heartTreeY = 9;
- }
- // Set path on grid (1 = path)
+ // Define path through the level (1 = path)
+ var pathCoords = [[0, 9], [1, 9], [2, 9], [3, 9], [4, 9], [5, 9], [6, 9], [6, 8], [6, 7], [6, 6], [6, 5], [7, 5], [8, 5], [9, 5], [9, 6], [9, 7], [9, 8], [9, 9], [9, 10], [9, 11], [8, 11], [7, 11], [6, 11], [5, 11], [4, 11], [4, 12], [4, 13], [4, 14], [4, 15], [5, 15], [6, 15], [7, 15], [8, 15], [9, 15], [10, 15], [11, 15], [11, 14], [11, 13], [11, 12], [11, 11], [11, 10], [11, 9], [11, 8], [11, 7], [12, 7], [13, 7], [14, 7]];
for (var i = 0; i < pathCoords.length; i++) {
- var coords = pathCoords[i];
- var x = coords[0];
- var y = coords[1];
- // Ensure coordinates are within bounds
- if (x >= 0 && x < levelWidth && y >= 0 && y < levelHeight) {
- grid[y][x] = 1;
- }
+ var _pathCoords$i = _slicedToArray(pathCoords[i], 2),
+ x = _pathCoords$i[0],
+ y = _pathCoords$i[1];
+ grid[y][x] = 1;
}
// Set spawn point (2 = spawn)
- grid[spawnY][spawnX] = 2;
+ grid[9][0] = 2;
// Set heart tree location (3 = heart tree)
- grid[heartTreeY][heartTreeX] = 3;
- return {
- grid: grid,
- pathCoords: pathCoords
- };
-}
-function createLevel() {
- // Clear any existing level elements
- for (var i = 0; i < buildingSpots.length; i++) {
- buildingSpots[i].destroy();
- }
- // Clear existing game elements
- for (var i = 0; i < towers.length; i++) {
- towers[i].destroy();
- }
- for (var i = 0; i < enemies.length; i++) {
- enemies[i].destroy();
- }
- for (var i = 0; i < essenceItems.length; i++) {
- essenceItems[i].destroy();
- }
- buildingSpots = [];
- path = [];
- spawnPoints = [];
- towers = [];
- enemies = [];
- essenceItems = [];
- // Generate level data based on current wave
- var levelData = generateLevelForWave(currentWave);
- var grid = levelData.grid;
- var pathCoords = levelData.pathCoords;
- var levelWidth = grid[0].length;
- var levelHeight = grid.length;
+ grid[7][14] = 3;
// Create level elements based on grid
for (var y = 0; y < levelHeight; y++) {
for (var x = 0; x < levelWidth; x++) {
var gridValue = grid[y][x];
@@ -1113,209 +1091,78 @@
return;
}
currentWave++;
waveTxt.setText('Wave: ' + currentWave);
- // Get wave theme name
- var waveTheme = "";
- var textColor = 0xFFFF00;
- switch (currentWave % 5) {
- case 1:
- waveTheme = "Forest";
- textColor = 0x00FF00;
- break;
- case 2:
- waveTheme = "Swamp";
- textColor = 0x99CC33;
- break;
- case 3:
- waveTheme = "Crystal River";
- textColor = 0x33CCFF;
- break;
- case 4:
- waveTheme = "Mechanical";
- textColor = 0xCCCCCC;
- break;
- case 0:
- waveTheme = "BOSS";
- textColor = 0xFF00FF;
- break;
- }
- // Show wave transition message with theme
- var transitionText = new Text2('Wave ' + currentWave + ' - ' + waveTheme + ' Incoming!', {
- size: 90,
- fill: textColor
- });
- transitionText.anchor.set(0.5, 0.5);
- transitionText.x = 2048 / 2;
- transitionText.y = 2732 / 2;
- game.addChild(transitionText);
- // Flash screen to signal wave transition (color based on theme)
- var flashColor;
- switch (currentWave % 5) {
- case 1:
- flashColor = 0x004400;
- break;
- // Forest - dark green
- case 2:
- flashColor = 0x445500;
- break;
- // Swamp - swampy green
- case 3:
- flashColor = 0x000088;
- break;
- // Crystal - blue
- case 4:
- flashColor = 0x444444;
- break;
- // Mechanical - grey
- case 0:
- flashColor = 0x440044;
- break;
- // Boss - purple
- }
- LK.effects.flashScreen(flashColor, 800);
- // Apply the environment effects for this wave
- applyWaveEnvironment(currentWave);
- // Animate the transition text
- tween(transitionText, {
- scaleX: 1.5,
- scaleY: 1.5,
- alpha: 0
- }, {
- duration: 1500,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- transitionText.destroy();
- // Generate new level layout for this wave
- createLevel();
- // Set game state for the new wave
- waveInProgress = true;
- startWaveBtn.alpha = 0.5;
- // Calculate enemies for this wave
- var numEnemies = 5 + Math.floor(currentWave * 1.5);
- var hasBoss = currentWave % 5 === 0;
- enemiesRemaining = numEnemies + (hasBoss ? 1 : 0);
- LK.getSound('waveStart').play();
- // Spawn enemies periodically
- var enemiesSpawned = 0;
- waveTimer = LK.setInterval(function () {
- if (enemiesSpawned < numEnemies) {
- spawnEnemy(false);
- enemiesSpawned++;
- } else if (hasBoss && enemiesSpawned === numEnemies) {
- spawnEnemy(true); // Spawn boss
- enemiesSpawned++;
- } else {
- LK.clearInterval(waveTimer);
- }
- }, 1500);
+ waveInProgress = true;
+ startWaveBtn.alpha = 0.5;
+ // Calculate enemies for this wave
+ var numEnemies = 5 + Math.floor(currentWave * 1.5);
+ var hasBoss = currentWave % 5 === 0;
+ enemiesRemaining = numEnemies + (hasBoss ? 1 : 0);
+ LK.getSound('waveStart').play();
+ // Spawn enemies periodically
+ var enemiesSpawned = 0;
+ waveTimer = LK.setInterval(function () {
+ if (enemiesSpawned < numEnemies) {
+ spawnEnemy(false);
+ enemiesSpawned++;
+ } else if (hasBoss && enemiesSpawned === numEnemies) {
+ spawnEnemy(true); // Spawn boss
+ enemiesSpawned++;
+ } else {
+ LK.clearInterval(waveTimer);
}
- });
+ }, 1500);
}
function spawnEnemy(isBoss) {
var enemy;
if (isBoss) {
enemy = new BossEnemy();
- // Make boss appearance based on wave type
- if (currentWave % 15 === 5) {
- // Forest boss (tint green)
- enemy.getChildAt(0).tint = 0x00AA00;
- } else if (currentWave % 15 === 10) {
- // Mechanical boss (tint silver)
- enemy.getChildAt(0).tint = 0xCCCCCC;
- } else {
- // Corrupted boss (tint purple)
- enemy.getChildAt(0).tint = 0x9900FF;
- }
} else {
- enemy = new Enemy();
- // Scale difficulty with wave number
- enemy.maxHealth = 50 + currentWave * 10;
- enemy.health = enemy.maxHealth;
- enemy.speed = 2 + currentWave * 0.1;
- enemy.value = 10 + currentWave;
- // Customize enemy appearance based on wave type
- var waveTheme = currentWave % 5;
- if (waveTheme === 1) {
- // Forest enemies (green)
- enemy.getChildAt(0).tint = 0x33CC33;
- } else if (waveTheme === 2) {
- // Swamp enemies (muddy brown)
- enemy.getChildAt(0).tint = 0x996633;
- enemy.speed *= 0.8; // Slower in swamp
- } else if (waveTheme === 3) {
- // Crystal enemies (blue)
- enemy.getChildAt(0).tint = 0x3399FF;
- enemy.maxHealth *= 0.8; // Less health but...
+ // Randomly choose enemy type based on wave progression
+ var randomType = Math.random();
+ if (currentWave >= 2 && randomType < 0.3) {
+ // 30% chance of spawning speedy enemy after wave 2
+ enemy = new SpeedyEnemy();
+ // Scale difficulty with wave number
+ enemy.maxHealth = 30 + currentWave * 6;
enemy.health = enemy.maxHealth;
- enemy.speed *= 1.2; // ...faster
- } else if (waveTheme === 4) {
- // Mechanical enemies (gray)
- enemy.getChildAt(0).tint = 0x999999;
- enemy.maxHealth *= 1.5; // More health but...
+ enemy.speed = 4 + currentWave * 0.15;
+ enemy.value = 15 + currentWave;
+ } else if (currentWave >= 4 && randomType < 0.5) {
+ // 20% chance of spawning tank enemy after wave 4
+ enemy = new TankEnemy();
+ // Scale difficulty with wave number
+ enemy.maxHealth = 120 + currentWave * 15;
enemy.health = enemy.maxHealth;
- enemy.speed *= 0.9; // ...slower
+ enemy.speed = 1 + currentWave * 0.05;
+ enemy.value = 25 + currentWave;
} else {
- // Corrupted enemies (purple)
- enemy.getChildAt(0).tint = 0x9933CC;
+ // Regular enemy
+ enemy = new Enemy();
+ // Scale difficulty with wave number
+ enemy.maxHealth = 50 + currentWave * 10;
+ enemy.health = enemy.maxHealth;
+ enemy.speed = 2 + currentWave * 0.1;
+ enemy.value = 10 + currentWave;
}
}
// Set initial position at spawn point
var spawnPoint = spawnPoints[0];
enemy.x = spawnPoint.x;
enemy.y = spawnPoint.y;
game.addChild(enemy);
enemies.push(enemy);
- // Apply animation for spawning with themed effects
+ // Apply animation for spawning
enemy.alpha = 0;
enemy.scale.set(0.5, 0.5);
- // Different spawn animations based on wave type
- var waveTheme = currentWave % 5;
- if (waveTheme === 0 && isBoss) {
- // Boss wave - dramatic entrance
- tween(enemy, {
- alpha: 1,
- scaleX: 1.3,
- scaleY: 1.3
- }, {
- duration: 800,
- easing: tween.elasticOut,
- onFinish: function onFinish() {
- // Return to normal size
- tween(enemy, {
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 300
- });
- }
- });
- } else {
- // Regular spawn animation with different tweens based on theme
- var tweenConfig = {
- alpha: 1,
- scaleX: 1,
- scaleY: 1
- };
- var tweenOptions = {
- duration: 500
- };
- if (waveTheme === 2) {
- // Swamp - sluggish
- tweenOptions.duration = 800;
- tweenOptions.easing = tween.easeOut;
- } else if (waveTheme === 3) {
- // Crystal - bouncy
- tweenOptions.duration = 400;
- tweenOptions.easing = tween.bounceOut;
- } else if (waveTheme === 4) {
- // Mechanical - robotic
- tweenOptions.easing = function (t) {
- return t < 0.5 ? 2 * t : 2 * (1 - t);
- };
- }
- tween(enemy, tweenConfig, tweenOptions); //{5K}{5L}
- }
+ tween(enemy, {
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 500
+ });
}
function checkWaveComplete() {
if (waveInProgress && enemies.length === 0 && enemiesRemaining === 0) {
waveInProgress = false;
@@ -1342,9 +1189,9 @@
onFinish: function onFinish() {
waveBonusTxt.destroy();
}
});
- // Unlock new tower types based on progress
+ // Unlock new tower types based on wave progress
if (currentWave === 3 && !storage.unlockedTowers.includes('shroom')) {
storage.unlockedTowers.push('shroom');
shroomBtn.alpha = 0.6;
// Show unlock message
@@ -1365,8 +1212,52 @@
onFinish: function onFinish() {
unlockTxt.destroy();
}
});
+ } else if (currentWave === 5 && !storage.unlockedTowers.includes('flame')) {
+ storage.unlockedTowers.push('flame');
+ flameBtn.alpha = 0.6;
+ // Show unlock message
+ var unlockTxt = new Text2('New Tower Unlocked: Flame Fern!', {
+ size: 60,
+ fill: 0xFF5500
+ });
+ unlockTxt.anchor.set(0.5, 0.5);
+ unlockTxt.x = 2048 / 2;
+ unlockTxt.y = 2732 / 2 + 100;
+ game.addChild(unlockTxt);
+ // Animate and remove message
+ tween(unlockTxt, {
+ alpha: 0,
+ y: unlockTxt.y - 100
+ }, {
+ duration: 3000,
+ onFinish: function onFinish() {
+ unlockTxt.destroy();
+ }
+ });
+ } else if (currentWave === 8 && !storage.unlockedTowers.includes('healing')) {
+ storage.unlockedTowers.push('healing');
+ healingBtn.alpha = 0.6;
+ // Show unlock message
+ var unlockTxt = new Text2('New Tower Unlocked: Healing Bloom!', {
+ size: 60,
+ fill: 0x00FF88
+ });
+ unlockTxt.anchor.set(0.5, 0.5);
+ unlockTxt.x = 2048 / 2;
+ unlockTxt.y = 2732 / 2 + 100;
+ game.addChild(unlockTxt);
+ // Animate and remove message
+ tween(unlockTxt, {
+ alpha: 0,
+ y: unlockTxt.y - 100
+ }, {
+ duration: 3000,
+ onFinish: function onFinish() {
+ unlockTxt.destroy();
+ }
+ });
}
}
}
function isPositionValid(x, y) {
@@ -1382,36 +1273,15 @@
setupHealthBar();
setupModeButtons();
setupTowerButtons();
setupStartWaveButton();
+ // Create game level
+ createLevel();
// Set initial game state
- currentWave = 0; // Start with intro map
LK.setScore(0);
scoreTxt.setText('0');
updateEssenceText();
- // Create initial game level
- createLevel();
updateHealthBar();
- // Show welcome message
- var welcomeTxt = new Text2('Warden of the Woods\nDefend the Heart Tree!', {
- size: 80,
- fill: 0x00FF00
- });
- welcomeTxt.anchor.set(0.5, 0.5);
- welcomeTxt.x = 2048 / 2;
- welcomeTxt.y = 2732 / 2 - 200;
- game.addChild(welcomeTxt);
- // Animate welcome message
- tween(welcomeTxt, {
- alpha: 0,
- y: welcomeTxt.y - 100
- }, {
- duration: 4000,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- welcomeTxt.destroy();
- }
- });
// Start background music
LK.playMusic('forestAmbience', {
loop: true
});
@@ -1444,14 +1314,8 @@
essenceItems[i].destroy();
essenceItems.splice(i, 1);
}
}
- // Update environment effects
- for (var i = 0; i < environmentEffects.length; i++) {
- if (environmentEffects[i].update) {
- environmentEffects[i].update();
- }
- }
// Update guardian
guardian.update();
// Check if wave is complete
checkWaveComplete();
top-down angle of a tree. In-Game asset. 2d. High contrast. No shadows
thorn flower. In-Game asset. 2d. High contrast. No shadows
purple mushroom. In-Game asset. 2d. High contrast. No shadows
guardian of the forest. In-Game asset. 2d. High contrast. No shadows
mini cave invader that is covered in crystals and is made of stone. In-Game asset. 2d. High contrast. No shadows
GIANT cave boss invader that is covered in crystal diamonds and is made of stone.. In-Game asset. 2d. High contrast. No shadows
mini farm tile. In-Game asset. 2d. High contrast. No shadows
flaming flower. In-Game asset. 2d. High contrast. No shadows
cave enterance. In-Game asset. 2d. High contrast. No shadows
car parked at an angle. In-Game asset. 2d. High contrast. No shadows
top-down angle of a tire. In-Game asset. 2d. High contrast. No shadows
finish line. In-Game asset. 2d. High contrast. No shadows
spilt acid barrel fallen over. In-Game asset. 2d. High contrast. No shadows
mutant tree. In-Game asset. 2d. High contrast. No shadows
soul. In-Game asset. 2d. High contrast. No shadows
planty spike ball with no stem. In-Game asset. 2d. High contrast. No shadows
Abandoned building that’s boarded up. In-Game asset. 2d. High contrast. No shadows
Rectangle button. In-Game asset. 2d. High contrast. No shadows
https://api.upit.com/img/IwopnnYt58_k_iLtUBxBq3JSiO4=/fit-in/256x256/filters:format(png):quality(85)/https://cdn.frvr.ai/680fe4cf833660e79135a83b.png%3F3 But empty. In-Game asset. 2d. High contrast. No shadows
Empty healthbar with no heart. In-Game asset. 2d. High contrast. No shadows
Hammer icon. In-Game asset. 2d. High contrast. No shadows
Garbage can icon. In-Game asset. 2d. High contrast. No shadows
Running feet icon. In-Game asset. 2d. High contrast. No shadows