User prompt
Hero cannot die now
User prompt
When hero dead when all attack on base
User prompt
Add assets on revie button
User prompt
Add background colour into image of graveyard
User prompt
Add revie button that we can see . Add on screen when we died. And when we revie th Button cannot see. The assets this author
User prompt
The player cannot revie
User prompt
There were leaderboard that tell our position in scored ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Base helath 3000
User prompt
Bot also move to attack player base
User prompt
Bot also move to attack
User prompt
Start button have assets
User prompt
When there were not boss level hero special abilities deactive.
User prompt
When boss level their hero have special abilities
User prompt
Add assets of boss
User prompt
Boss health 4000
User prompt
Boss health reduce 4000
User prompt
Zombie attack on defence tower and hero
User prompt
After 9 wave complete. Come boss wave. Boss health 10000
User prompt
Hero revive on his base
User prompt
Add health of hero. And hero can revive
User prompt
I cannot see total money of my . Change place to see me
User prompt
Add screen to check my total money
User prompt
Big icon of coin i cannot see my coins
User prompt
Add start button when one wave complete then we click the start to next wave
User prompt
Add background music
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BigDefenseTower = Container.expand(function () { var self = Container.call(this); var towerGraphics = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: 0xFF4444 }); self.health = 500; self.maxHealth = 500; self.damage = 80; self.range = 450; self.shootCooldown = 0; self.update = function () { var target = self.findNearestEnemy(); if (target && self.shootCooldown <= 0) { self.shootAt(target); self.shootCooldown = 35; // Slightly faster than regular tower } if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.findNearestEnemy = function () { var nearest = null; var minDistance = Infinity; // Check zombies for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2)); if (distance < minDistance && distance < self.range) { minDistance = distance; nearest = zombie; } } // Check enemy bots for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2)); if (distance < minDistance && distance < self.range) { minDistance = distance; nearest = bot; } } return nearest; }; self.shootAt = function (target) { var bullet = new BigTowerBullet(); bullet.x = self.x; bullet.y = self.y; bullet.targetX = target.x; bullet.targetY = target.y; bullet.damage = self.damage; bigTowerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { self.destroy(); var index = bigDefenseTowers.indexOf(self); if (index > -1) { bigDefenseTowers.splice(index, 1); } }; return self; }); var BigTowerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: 0xFF4444 }); self.speed = 10; self.damage = 80; self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.explode(); } // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); var index = bigTowerBullets.indexOf(self); if (index > -1) { bigTowerBullets.splice(index, 1); } } }; self.explode = function () { // Check for zombie hits for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; if (self.intersects(zombie)) { zombie.takeDamage(self.damage); break; } } // Check for enemy bot hits for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; if (self.intersects(bot)) { bot.takeDamage(self.damage); break; } } self.destroy(); var index = bigTowerBullets.indexOf(self); if (index > -1) { bigTowerBullets.splice(index, 1); } }; return self; }); var BuyBigTowerButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('buyButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, tint: 0xFF4444 }); var towerIcon = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6, tint: 0xFF4444, y: -15 }); var buttonText = new Text2('Big Tower', { size: 28, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.y = 15; self.addChild(buttonText); var costText = new Text2('R:100 $100', { size: 22, fill: 0xFFFFFF }); costText.anchor.set(0.5, 0.5); costText.y = 35; self.addChild(costText); self.down = function (x, y, obj) { var towerCost = 100; if (resources >= 100 && money >= towerCost) { // Enable big tower placement mode placingBigTower = true; LK.effects.flashObject(self, 0x00FF00, 300); } else { // Flash red if can't afford LK.effects.flashObject(self, 0xFF0000, 300); } }; self.update = function () { var towerCost = 100 + Math.floor(wave / 2) * 15; var resourceCost = 100 + Math.floor(wave / 3) * 20; if (resources >= resourceCost && money >= towerCost) { buttonGraphics.tint = 0xFF2222; // Red when affordable buttonText.setText('Big Tower'); costText.setText('R:' + resourceCost + ' $' + towerCost); } else { buttonGraphics.tint = 0x808080; // Gray when not affordable buttonText.setText('Big Tower'); costText.setText('R:' + resourceCost + ' $' + towerCost); } }; return self; }); var BuyRapidFireTowerButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('buyButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, tint: 0x00FF00 }); var towerIcon = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, tint: 0x00FF00, y: -15 }); var buttonText = new Text2('Rapid', { size: 28, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.y = 15; self.addChild(buttonText); var costText = new Text2('R:75 $40', { size: 22, fill: 0xFFFFFF }); costText.anchor.set(0.5, 0.5); costText.y = 35; self.addChild(costText); self.down = function (x, y, obj) { var towerCost = 40; if (resources >= 75 && money >= towerCost) { // Enable rapid fire tower placement mode placingRapidFireTower = true; LK.effects.flashObject(self, 0x00FF00, 300); } else { // Flash red if can't afford LK.effects.flashObject(self, 0xFF0000, 300); } }; self.update = function () { var towerCost = 40; if (resources >= 75 && money >= towerCost) { buttonGraphics.tint = 0x00AA00; // Green when affordable buttonText.setText('Rapid'); costText.setText('R:75 $40'); } else { buttonGraphics.tint = 0x808080; // Gray when not affordable buttonText.setText('Rapid'); costText.setText('R:75 $40'); } }; return self; }); var BuySniperTowerButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('buyButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, tint: 0x0088FF }); var towerIcon = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, tint: 0x0088FF, y: -15 }); var buttonText = new Text2('Sniper', { size: 26, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.y = 15; self.addChild(buttonText); var costText = new Text2('R:125 $75', { size: 20, fill: 0xFFFFFF }); costText.anchor.set(0.5, 0.5); costText.y = 35; self.addChild(costText); self.down = function (x, y, obj) { var towerCost = 75; if (resources >= 125 && money >= towerCost) { // Enable sniper tower placement mode placingSniperTower = true; LK.effects.flashObject(self, 0x00FF00, 300); } else { // Flash red if can't afford LK.effects.flashObject(self, 0xFF0000, 300); } }; self.update = function () { var towerCost = 75; if (resources >= 125 && money >= towerCost) { buttonGraphics.tint = 0x0066CC; // Blue when affordable buttonText.setText('Sniper'); costText.setText('R:125 $75'); } else { buttonGraphics.tint = 0x808080; // Gray when not affordable buttonText.setText('Sniper'); costText.setText('R:125 $75'); } }; return self; }); var BuyTowerButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('buyButton', { anchorX: 0.5, anchorY: 0.5 }); var towerIcon = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4, y: -15 }); var buttonText = new Text2('Tower', { size: 32, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.y = 15; self.addChild(buttonText); var costText = new Text2('R:50 $25', { size: 24, fill: 0xFFFFFF }); costText.anchor.set(0.5, 0.5); costText.y = 35; self.addChild(costText); self.down = function (x, y, obj) { var towerCost = 25; if (resources >= 50 && money >= towerCost) { // Enable tower placement mode placingTower = true; LK.effects.flashObject(self, 0x00FF00, 300); } else { // Flash red if can't afford LK.effects.flashObject(self, 0xFF0000, 300); } }; self.update = function () { var towerCost = 25 + Math.floor(wave / 2) * 5; var resourceCost = 50 + Math.floor(wave / 3) * 10; if (resources >= resourceCost && money >= towerCost) { buttonGraphics.tint = 0x4CAF50; // Green when affordable buttonText.setText('Tower'); costText.setText('R:' + resourceCost + ' $' + towerCost); } else { buttonGraphics.tint = 0x808080; // Gray when not affordable buttonText.setText('Tower'); costText.setText('R:' + resourceCost + ' $' + towerCost); } }; return self; }); var DefenseTower = Container.expand(function () { var self = Container.call(this); var towerGraphics = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5 }); self.health = 200; self.maxHealth = 200; self.damage = 30; self.range = 300; self.shootCooldown = 0; self.update = function () { var target = self.findNearestEnemy(); if (target && self.shootCooldown <= 0) { self.shootAt(target); self.shootCooldown = 45; // 0.75 second cooldown } if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.findNearestEnemy = function () { var nearest = null; var minDistance = Infinity; for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2)); if (distance < minDistance && distance < self.range) { minDistance = distance; nearest = zombie; } } return nearest; }; self.shootAt = function (target) { var bullet = new TowerBullet(); bullet.x = self.x; bullet.y = self.y; bullet.targetX = target.x; bullet.targetY = target.y; bullet.damage = self.damage; towerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { self.destroy(); var index = defenseTowers.indexOf(self); if (index > -1) { defenseTowers.splice(index, 1); } }; return self; }); var EnemyBot = Container.expand(function (botType) { var self = Container.call(this); var botGraphics = self.attachAsset(botType, { anchorX: 0.5, anchorY: 0.5 }); self.botType = botType; // Scale bot stats based on current wave var healthMultiplier = 1 + (wave - 1) * 0.25; // 25% more health per wave var damageMultiplier = 1 + (wave - 1) * 0.15; // 15% more damage per wave self.health = Math.floor(150 * healthMultiplier); self.maxHealth = Math.floor(150 * healthMultiplier); self.damage = Math.floor(25 * damageMultiplier); self.range = 350; self.shootCooldown = 0; // Set specific properties based on bot type if (botType === 'artilleryBot') { self.damage = 60; self.range = 400; self.shootCooldown = 90; // Slower but more powerful } else if (botType === 'assaultBot') { self.damage = 20; self.range = 250; self.shootCooldown = 20; // Faster firing } else if (botType === 'disruptionBot') { self.damage = 15; self.range = 300; self.shootCooldown = 120; // Special ability cooldown } else if (botType === 'repairBot') { self.damage = 0; self.range = 200; self.shootCooldown = 180; // Repair cooldown } self.update = function () { var target = self.findTarget(); if (target && self.shootCooldown <= 0) { if (self.botType === 'repairBot') { self.repairAllies(); } else { self.shootAt(target); } self.shootCooldown = self.getBaseCooldown(); } if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.findTarget = function () { var targets = []; // Add player base as target var distanceToBase = Math.sqrt(Math.pow(playerBase.x - self.x, 2) + Math.pow(playerBase.y - self.y, 2)); if (distanceToBase < self.range) { targets.push({ target: playerBase, distance: distanceToBase }); } // Add hero as target var distanceToHero = Math.sqrt(Math.pow(hero.x - self.x, 2) + Math.pow(hero.y - self.y, 2)); if (distanceToHero < self.range) { targets.push({ target: hero, distance: distanceToHero }); } // Add defense towers as targets for (var i = 0; i < defenseTowers.length; i++) { var tower = defenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < self.range) { targets.push({ target: tower, distance: distance }); } } // Add big defense towers as targets for (var i = 0; i < bigDefenseTowers.length; i++) { var tower = bigDefenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < self.range) { targets.push({ target: tower, distance: distance }); } } // Add rapid fire towers as targets for (var i = 0; i < rapidFireTowers.length; i++) { var tower = rapidFireTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < self.range) { targets.push({ target: tower, distance: distance }); } } // Add sniper towers as targets for (var i = 0; i < sniperTowers.length; i++) { var tower = sniperTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < self.range) { targets.push({ target: tower, distance: distance }); } } // Return nearest target if (targets.length > 0) { targets.sort(function (a, b) { return a.distance - b.distance; }); return targets[0].target; } return null; }; self.shootAt = function (target) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; bullet.targetX = target.x; bullet.targetY = target.y; bullet.damage = self.damage; bullet.isAOE = self.botType === 'artilleryBot'; enemyBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); }; self.repairAllies = function () { for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; if (bot !== self) { var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2)); if (distance < self.range) { bot.health = Math.min(bot.health + 30, bot.maxHealth); LK.effects.flashObject(bot, 0x00ff00, 300); } } } }; self.getBaseCooldown = function () { if (self.botType === 'artilleryBot') return 90; if (self.botType === 'assaultBot') return 20; if (self.botType === 'disruptionBot') return 120; if (self.botType === 'repairBot') return 180; return 60; }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { LK.getSound('explosion').play(); LK.setScore(LK.getScore() + 25); scoreText.setText('Score: ' + LK.getScore()); // Add money and spawn money icon var moneyEarned = 15; money += moneyEarned; moneyText.setText('Money: $' + money); var moneyIcon = new MoneyIcon(moneyEarned); moneyIcon.x = self.x; moneyIcon.y = self.y; moneyIcons.push(moneyIcon); game.addChild(moneyIcon); self.destroy(); var index = enemyBots.indexOf(self); if (index > -1) { enemyBots.splice(index, 1); } }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.damage = 25; self.targetX = 0; self.targetY = 0; self.isAOE = false; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.explode(); } // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); var index = enemyBullets.indexOf(self); if (index > -1) { enemyBullets.splice(index, 1); } } }; self.explode = function () { if (self.isAOE) { // AOE damage var explosion = LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y, alpha: 0.7 }); game.addChild(explosion); tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { explosion.destroy(); } }); // Damage everything in range var explosionRange = 150; if (self.intersects(playerBase)) { playerBase.takeDamage(self.damage); } if (self.intersects(hero)) { hero.takeDamage(self.damage); } for (var i = 0; i < defenseTowers.length; i++) { var tower = defenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < explosionRange) { tower.takeDamage(self.damage); } } for (var i = 0; i < bigDefenseTowers.length; i++) { var tower = bigDefenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < explosionRange) { tower.takeDamage(self.damage); } } for (var i = 0; i < rapidFireTowers.length; i++) { var tower = rapidFireTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < explosionRange) { tower.takeDamage(self.damage); } } for (var i = 0; i < sniperTowers.length; i++) { var tower = sniperTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2)); if (distance < explosionRange) { tower.takeDamage(self.damage); } } LK.getSound('explosion').play(); } else { // Single target damage if (self.intersects(playerBase)) { playerBase.takeDamage(self.damage); } else if (self.intersects(hero)) { hero.takeDamage(self.damage); } else { for (var i = 0; i < defenseTowers.length; i++) { var tower = defenseTowers[i]; if (self.intersects(tower)) { tower.takeDamage(self.damage); break; } } for (var i = 0; i < bigDefenseTowers.length; i++) { var tower = bigDefenseTowers[i]; if (self.intersects(tower)) { tower.takeDamage(self.damage); break; } } for (var i = 0; i < rapidFireTowers.length; i++) { var tower = rapidFireTowers[i]; if (self.intersects(tower)) { tower.takeDamage(self.damage); break; } } for (var i = 0; i < sniperTowers.length; i++) { var tower = sniperTowers[i]; if (self.intersects(tower)) { tower.takeDamage(self.damage); break; } } } } self.destroy(); var index = enemyBullets.indexOf(self); if (index > -1) { enemyBullets.splice(index, 1); } }; return self; }); var Hero = Container.expand(function () { var self = Container.call(this); var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.health = 300; self.maxHealth = 300; self.speed = 3; self.damage = 40; self.shootCooldown = 0; self.targetX = self.x; self.targetY = self.y; self.update = function () { // Move towards target position var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Auto-attack nearest enemy var nearestEnemy = self.findNearestEnemy(); if (nearestEnemy && self.shootCooldown <= 0) { self.shootAt(nearestEnemy); self.shootCooldown = 30; // 0.5 second cooldown } if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.findNearestEnemy = function () { var nearest = null; var minDistance = Infinity; // Check zombies for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2)); if (distance < minDistance && distance < 400) { minDistance = distance; nearest = zombie; } } // Check enemy bots for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2)); if (distance < minDistance && distance < 400) { minDistance = distance; nearest = bot; } } return nearest; }; self.shootAt = function (target) { var bullet = new HeroBullet(); bullet.x = self.x; bullet.y = self.y; bullet.targetX = target.x; bullet.targetY = target.y; bullet.damage = self.damage; heroBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); }; self.moveTo = function (x, y) { self.targetX = x; self.targetY = y; }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 300); if (self.health <= 0) { self.die(); } }; self.die = function () { gameOver = true; LK.showGameOver(); }; return self; }); var HeroBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('heroBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.damage = 40; self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.explode(); } // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); var index = heroBullets.indexOf(self); if (index > -1) { heroBullets.splice(index, 1); } } }; self.explode = function () { // Check for zombie hits for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; if (self.intersects(zombie)) { zombie.takeDamage(self.damage); self.destroy(); var index = heroBullets.indexOf(self); if (index > -1) { heroBullets.splice(index, 1); } return; } } // Check for enemy bot hits for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; if (self.intersects(bot)) { bot.takeDamage(self.damage); self.destroy(); var index = heroBullets.indexOf(self); if (index > -1) { heroBullets.splice(index, 1); } return; } } self.destroy(); var index = heroBullets.indexOf(self); if (index > -1) { heroBullets.splice(index, 1); } }; return self; }); var MoneyIcon = Container.expand(function (amount) { var self = Container.call(this); var moneyGraphics = self.attachAsset('money', { anchorX: 0.5, anchorY: 0.5 }); var moneyText = new Text2('+$' + amount, { size: 30, fill: 0xFFD700 }); moneyText.anchor.set(0.5, 0.5); moneyText.x = 30; self.addChild(moneyText); self.lifeTime = 120; // 2 seconds at 60fps self.floatSpeed = -2; self.update = function () { self.y += self.floatSpeed; self.alpha -= 0.02; self.lifeTime--; if (self.lifeTime <= 0 || self.alpha <= 0) { self.destroy(); var index = moneyIcons.indexOf(self); if (index > -1) { moneyIcons.splice(index, 1); } } }; return self; }); var PlayerBase = Container.expand(function () { var self = Container.call(this); var baseGraphics = self.attachAsset('playerBase', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1000; self.maxHealth = 1000; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 300); healthText.setText('Base Health: ' + self.health + '/' + self.maxHealth); if (self.health <= 0) { gameOver = true; LK.showGameOver(); } }; return self; }); var RapidFireBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6, tint: 0x00FF00 }); self.speed = 12; self.damage = 15; self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.explode(); } // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); var index = rapidFireBullets.indexOf(self); if (index > -1) { rapidFireBullets.splice(index, 1); } } }; self.explode = function () { // Check for zombie hits for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; if (self.intersects(zombie)) { zombie.takeDamage(self.damage); break; } } // Check for enemy bot hits for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; if (self.intersects(bot)) { bot.takeDamage(self.damage); break; } } self.destroy(); var index = rapidFireBullets.indexOf(self); if (index > -1) { rapidFireBullets.splice(index, 1); } }; return self; }); var RapidFireTower = Container.expand(function () { var self = Container.call(this); var towerGraphics = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, tint: 0x00FF00 }); self.health = 150; self.maxHealth = 150; self.damage = 15; self.range = 250; self.shootCooldown = 0; self.update = function () { var target = self.findNearestEnemy(); if (target && self.shootCooldown <= 0) { self.shootAt(target); self.shootCooldown = 15; // Very fast firing } if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.findNearestEnemy = function () { var nearest = null; var minDistance = Infinity; // Check zombies for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2)); if (distance < minDistance && distance < self.range) { minDistance = distance; nearest = zombie; } } // Check enemy bots for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2)); if (distance < minDistance && distance < self.range) { minDistance = distance; nearest = bot; } } return nearest; }; self.shootAt = function (target) { var bullet = new RapidFireBullet(); bullet.x = self.x; bullet.y = self.y; bullet.targetX = target.x; bullet.targetY = target.y; bullet.damage = self.damage; rapidFireBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { self.destroy(); var index = rapidFireTowers.indexOf(self); if (index > -1) { rapidFireTowers.splice(index, 1); } }; return self; }); var SniperBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.8, scaleY: 1.8, tint: 0x0088FF }); self.speed = 15; self.damage = 120; self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.explode(); } // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); var index = sniperBullets.indexOf(self); if (index > -1) { sniperBullets.splice(index, 1); } } }; self.explode = function () { // Check for zombie hits for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; if (self.intersects(zombie)) { zombie.takeDamage(self.damage); break; } } // Check for enemy bot hits for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; if (self.intersects(bot)) { bot.takeDamage(self.damage); break; } } self.destroy(); var index = sniperBullets.indexOf(self); if (index > -1) { sniperBullets.splice(index, 1); } }; return self; }); var SniperTower = Container.expand(function () { var self = Container.call(this); var towerGraphics = self.attachAsset('defenseTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, tint: 0x0088FF }); self.health = 250; self.maxHealth = 250; self.damage = 120; self.range = 600; self.shootCooldown = 0; self.update = function () { var target = self.findNearestEnemy(); if (target && self.shootCooldown <= 0) { self.shootAt(target); self.shootCooldown = 80; // Slow but powerful } if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.findNearestEnemy = function () { var nearest = null; var minDistance = Infinity; // Check zombies for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2)); if (distance < minDistance && distance < self.range) { minDistance = distance; nearest = zombie; } } // Check enemy bots for (var i = 0; i < enemyBots.length; i++) { var bot = enemyBots[i]; var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2)); if (distance < minDistance && distance < self.range) { minDistance = distance; nearest = bot; } } return nearest; }; self.shootAt = function (target) { var bullet = new SniperBullet(); bullet.x = self.x; bullet.y = self.y; bullet.targetX = target.x; bullet.targetY = target.y; bullet.damage = self.damage; sniperBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { self.destroy(); var index = sniperTowers.indexOf(self); if (index > -1) { sniperTowers.splice(index, 1); } }; return self; }); var TowerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 30; self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.explode(); } // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.destroy(); var index = towerBullets.indexOf(self); if (index > -1) { towerBullets.splice(index, 1); } } }; self.explode = function () { // Check for zombie hits for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; if (self.intersects(zombie)) { zombie.takeDamage(self.damage); break; } } self.destroy(); var index = towerBullets.indexOf(self); if (index > -1) { towerBullets.splice(index, 1); } }; return self; }); var Zombie = Container.expand(function () { var self = Container.call(this); var zombieGraphics = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); // Scale health and damage based on current wave var healthMultiplier = 1 + (wave - 1) * 0.3; // 30% more health per wave var damageMultiplier = 1 + (wave - 1) * 0.2; // 20% more damage per wave var speedMultiplier = 1 + (wave - 1) * 0.1; // 10% faster per wave self.health = Math.floor(100 * healthMultiplier); self.maxHealth = Math.floor(100 * healthMultiplier); self.speed = Math.min(3, 1 * speedMultiplier); // Cap speed at 3 self.damage = Math.floor(20 * damageMultiplier); self.target = null; self.attackCooldown = 0; self.update = function () { if (!self.target) { self.target = playerBase; } // Move towards 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 > 50) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { // Attack target if (self.attackCooldown <= 0) { if (self.target === playerBase) { playerBase.takeDamage(self.damage); } self.attackCooldown = 60; // 1 second cooldown } } if (self.attackCooldown > 0) { self.attackCooldown--; } }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { LK.getSound('zombieHit').play(); LK.setScore(LK.getScore() + 10); scoreText.setText('Score: ' + LK.getScore()); // Add money and spawn money icon var moneyEarned = 5; money += moneyEarned; moneyText.setText('Money: $' + money); var moneyIcon = new MoneyIcon(moneyEarned); moneyIcon.x = self.x; moneyIcon.y = self.y; moneyIcons.push(moneyIcon); game.addChild(moneyIcon); self.destroy(); var index = zombies.indexOf(self); if (index > -1) { zombies.splice(index, 1); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2a2a2a }); /**** * Game Code ****/ // Game state variables var gameOver = false; var wave = 1; var zombiesSpawned = 0; var zombiesPerWave = 5; var spawnTimer = 0; var botSpawnTimer = 0; var resources = 100; var money = 0; var placingTower = false; var placingBigTower = false; var placingRapidFireTower = false; var placingSniperTower = false; // Game objects arrays var zombies = []; var enemyBots = []; var defenseTowers = []; var bigDefenseTowers = []; var rapidFireTowers = []; var sniperTowers = []; var towerBullets = []; var bigTowerBullets = []; var rapidFireBullets = []; var sniperBullets = []; var heroBullets = []; var enemyBullets = []; var moneyIcons = []; // Create player base var playerBase = new PlayerBase(); playerBase.x = 1024; playerBase.y = 2400; game.addChild(playerBase); // Create hero var hero = new Hero(); hero.x = 1024; hero.y = 2200; game.addChild(hero); // Create UI elements var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topRight.addChild(scoreText); var healthText = new Text2('Base Health: 1000/1000', { size: 50, fill: 0xFFFFFF }); healthText.anchor.set(0, 0); healthText.x = -400; LK.gui.topRight.addChild(healthText); var waveText = new Text2('Wave: 1', { size: 55, fill: 0xFFFF00 }); waveText.anchor.set(0.5, 0); LK.gui.top.addChild(waveText); var resourceText = new Text2('Resources: 100', { size: 45, fill: 0x00FF00 }); resourceText.anchor.set(0, 0); LK.gui.bottomLeft.addChild(resourceText); var moneyText = new Text2('Money: $0', { size: 45, fill: 0xFFD700 }); moneyText.anchor.set(0.5, 0); moneyText.y = 60; LK.gui.bottom.addChild(moneyText); // Create buy tower button var buyTowerButton = new BuyTowerButton(); buyTowerButton.x = 120; buyTowerButton.y = -120; LK.gui.bottomLeft.addChild(buyTowerButton); // Create buy big tower button var buyBigTowerButton = new BuyBigTowerButton(); buyBigTowerButton.x = 280; buyBigTowerButton.y = -120; LK.gui.bottomLeft.addChild(buyBigTowerButton); // Create buy rapid fire tower button var buyRapidFireTowerButton = new BuyRapidFireTowerButton(); buyRapidFireTowerButton.x = 440; buyRapidFireTowerButton.y = -120; LK.gui.bottomLeft.addChild(buyRapidFireTowerButton); // Create buy sniper tower button var buySniperTowerButton = new BuySniperTowerButton(); buySniperTowerButton.x = 600; buySniperTowerButton.y = -120; LK.gui.bottomLeft.addChild(buySniperTowerButton); // Game control functions function spawnZombie() { var zombie = new Zombie(); // Spawn from random edge var edge = Math.floor(Math.random() * 4); if (edge === 0) { // Top zombie.x = Math.random() * 2048; zombie.y = 0; } else if (edge === 1) { // Right zombie.x = 2048; zombie.y = Math.random() * 2732; } else if (edge === 2) { // Bottom zombie.x = Math.random() * 2048; zombie.y = 2732; } else { // Left zombie.x = 0; zombie.y = Math.random() * 2732; } zombies.push(zombie); game.addChild(zombie); zombiesSpawned++; } function spawnEnemyBot() { var botTypes = ['artilleryBot', 'assaultBot', 'disruptionBot', 'repairBot']; var randomType = botTypes[Math.floor(Math.random() * botTypes.length)]; var bot = new EnemyBot(randomType); bot.x = Math.random() * 1800 + 124; bot.y = Math.random() * 1000 + 200; enemyBots.push(bot); game.addChild(bot); } function buildDefenseTower(x, y) { var towerCost = 25 + Math.floor(wave / 2) * 5; // Increase cost every 2 waves var resourceCost = 50 + Math.floor(wave / 3) * 10; // Increase resource cost every 3 waves if (resources >= resourceCost && money >= towerCost) { var tower = new DefenseTower(); tower.x = x; tower.y = y; defenseTowers.push(tower); game.addChild(tower); resources -= resourceCost; money -= towerCost; resourceText.setText('Resources: ' + resources); moneyText.setText('Money: $' + money); } } function buildBigDefenseTower(x, y) { var towerCost = 100 + Math.floor(wave / 2) * 15; // Increase cost every 2 waves var resourceCost = 100 + Math.floor(wave / 3) * 20; // Increase resource cost every 3 waves if (resources >= resourceCost && money >= towerCost) { var tower = new BigDefenseTower(); tower.x = x; tower.y = y; bigDefenseTowers.push(tower); game.addChild(tower); resources -= resourceCost; money -= towerCost; resourceText.setText('Resources: ' + resources); moneyText.setText('Money: $' + money); } } function buildRapidFireTower(x, y) { var towerCost = 40; // Money cost for rapid fire tower if (resources >= 75 && money >= towerCost) { var tower = new RapidFireTower(); tower.x = x; tower.y = y; rapidFireTowers.push(tower); game.addChild(tower); resources -= 75; money -= towerCost; resourceText.setText('Resources: ' + resources); moneyText.setText('Money: $' + money); } } function buildSniperTower(x, y) { var towerCost = 75; // Money cost for sniper tower if (resources >= 125 && money >= towerCost) { var tower = new SniperTower(); tower.x = x; tower.y = y; sniperTowers.push(tower); game.addChild(tower); resources -= 125; money -= towerCost; resourceText.setText('Resources: ' + resources); moneyText.setText('Money: $' + money); } } // Event handlers game.down = function (x, y, obj) { if (placingTower) { // Tower placement mode var canBuild = true; var minDistance = 120; // Check distance from other towers for (var i = 0; i < defenseTowers.length; i++) { var tower = defenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } // Check distance from big towers for (var i = 0; i < bigDefenseTowers.length; i++) { var tower = bigDefenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } // Check distance from base var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2)); if (distanceToBase < 150) { canBuild = false; } // Check distance from hero var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2)); if (distanceToHero < 100) { canBuild = false; } if (canBuild && y < 2300) { // Don't build too close to base area buildDefenseTower(x, y); placingTower = false; // Exit placement mode after building } } else if (placingBigTower) { // Big tower placement mode var canBuild = true; var minDistance = 150; // Check distance from regular towers for (var i = 0; i < defenseTowers.length; i++) { var tower = defenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } // Check distance from other big towers for (var i = 0; i < bigDefenseTowers.length; i++) { var tower = bigDefenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } // Check distance from base var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2)); if (distanceToBase < 200) { canBuild = false; } // Check distance from hero var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2)); if (distanceToHero < 120) { canBuild = false; } if (canBuild && y < 2300) { // Don't build too close to base area buildBigDefenseTower(x, y); placingBigTower = false; // Exit placement mode after building } } else if (placingRapidFireTower) { // Rapid fire tower placement mode var canBuild = true; var minDistance = 100; // Check distance from all towers for (var i = 0; i < defenseTowers.length; i++) { var tower = defenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } for (var i = 0; i < bigDefenseTowers.length; i++) { var tower = bigDefenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } for (var i = 0; i < rapidFireTowers.length; i++) { var tower = rapidFireTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } for (var i = 0; i < sniperTowers.length; i++) { var tower = sniperTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2)); if (distanceToBase < 120) { canBuild = false; } var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2)); if (distanceToHero < 80) { canBuild = false; } if (canBuild && y < 2300) { buildRapidFireTower(x, y); placingRapidFireTower = false; } } else if (placingSniperTower) { // Sniper tower placement mode var canBuild = true; var minDistance = 140; // Check distance from all towers for (var i = 0; i < defenseTowers.length; i++) { var tower = defenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } for (var i = 0; i < bigDefenseTowers.length; i++) { var tower = bigDefenseTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } for (var i = 0; i < rapidFireTowers.length; i++) { var tower = rapidFireTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } for (var i = 0; i < sniperTowers.length; i++) { var tower = sniperTowers[i]; var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2)); if (distance < minDistance) { canBuild = false; break; } } var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2)); if (distanceToBase < 180) { canBuild = false; } var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2)); if (distanceToHero < 100) { canBuild = false; } if (canBuild && y < 2300) { buildSniperTower(x, y); placingSniperTower = false; } } else { // Normal mode - move hero hero.moveTo(x, y); } }; // Start background music LK.playMusic('Zombiewarmuic'); // Main game loop game.update = function () { if (gameOver) return; // Resource generation if (LK.ticks % 180 === 0) { // Every 3 seconds resources += 10; resourceText.setText('Resources: ' + resources); } // Zombie spawning - faster spawn rate at higher waves if (zombiesSpawned < zombiesPerWave) { spawnTimer++; var zombieSpawnInterval = Math.max(60, 120 - (wave - 1) * 8); // Faster spawning each wave, minimum 1 second if (spawnTimer >= zombieSpawnInterval) { spawnZombie(); spawnTimer = 0; } } // Enemy bot spawning - faster spawn rate at higher waves botSpawnTimer++; var botSpawnInterval = Math.max(300, 600 - (wave - 1) * 30); // Faster spawning each wave, minimum 5 seconds if (botSpawnTimer >= botSpawnInterval) { spawnEnemyBot(); // Spawn additional bots at higher waves if (wave >= 5 && Math.random() < 0.3) { spawnEnemyBot(); // 30% chance for second bot } if (wave >= 8 && Math.random() < 0.2) { spawnEnemyBot(); // 20% chance for third bot } botSpawnTimer = 0; } // Check for wave completion if (zombiesSpawned >= zombiesPerWave && zombies.length === 0) { wave++; zombiesSpawned = 0; zombiesPerWave += 3 + Math.floor(wave / 3); // More zombies per wave as game progresses waveText.setText('Wave: ' + wave); // Bonus resources for completing wave - but less bonus at higher waves resources += Math.max(15, 35 - wave); resourceText.setText('Resources: ' + resources); } // Win condition if (wave >= 10 && zombies.length === 0 && enemyBots.length === 0) { LK.showYouWin(); } // Update all bullets for (var i = towerBullets.length - 1; i >= 0; i--) { var bullet = towerBullets[i]; if (bullet.destroyed) { towerBullets.splice(i, 1); } } for (var i = bigTowerBullets.length - 1; i >= 0; i--) { var bullet = bigTowerBullets[i]; if (bullet.destroyed) { bigTowerBullets.splice(i, 1); } } for (var i = rapidFireBullets.length - 1; i >= 0; i--) { var bullet = rapidFireBullets[i]; if (bullet.destroyed) { rapidFireBullets.splice(i, 1); } } for (var i = sniperBullets.length - 1; i >= 0; i--) { var bullet = sniperBullets[i]; if (bullet.destroyed) { sniperBullets.splice(i, 1); } } for (var i = heroBullets.length - 1; i >= 0; i--) { var bullet = heroBullets[i]; if (bullet.destroyed) { heroBullets.splice(i, 1); } } for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; if (bullet.destroyed) { enemyBullets.splice(i, 1); } } // Update money icons for (var i = moneyIcons.length - 1; i >= 0; i--) { var icon = moneyIcons[i]; if (icon.destroyed) { moneyIcons.splice(i, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigDefenseTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4444
});
self.health = 500;
self.maxHealth = 500;
self.damage = 80;
self.range = 450;
self.shootCooldown = 0;
self.update = function () {
var target = self.findNearestEnemy();
if (target && self.shootCooldown <= 0) {
self.shootAt(target);
self.shootCooldown = 35; // Slightly faster than regular tower
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.findNearestEnemy = function () {
var nearest = null;
var minDistance = Infinity;
// Check zombies
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < minDistance && distance < self.range) {
minDistance = distance;
nearest = zombie;
}
}
// Check enemy bots
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2));
if (distance < minDistance && distance < self.range) {
minDistance = distance;
nearest = bot;
}
}
return nearest;
};
self.shootAt = function (target) {
var bullet = new BigTowerBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
bigTowerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
self.destroy();
var index = bigDefenseTowers.indexOf(self);
if (index > -1) {
bigDefenseTowers.splice(index, 1);
}
};
return self;
});
var BigTowerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4444
});
self.speed = 10;
self.damage = 80;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.explode();
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
var index = bigTowerBullets.indexOf(self);
if (index > -1) {
bigTowerBullets.splice(index, 1);
}
}
};
self.explode = function () {
// Check for zombie hits
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(self.damage);
break;
}
}
// Check for enemy bot hits
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
if (self.intersects(bot)) {
bot.takeDamage(self.damage);
break;
}
}
self.destroy();
var index = bigTowerBullets.indexOf(self);
if (index > -1) {
bigTowerBullets.splice(index, 1);
}
};
return self;
});
var BuyBigTowerButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFF4444
});
var towerIcon = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
tint: 0xFF4444,
y: -15
});
var buttonText = new Text2('Big Tower', {
size: 28,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 15;
self.addChild(buttonText);
var costText = new Text2('R:100 $100', {
size: 22,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0.5);
costText.y = 35;
self.addChild(costText);
self.down = function (x, y, obj) {
var towerCost = 100;
if (resources >= 100 && money >= towerCost) {
// Enable big tower placement mode
placingBigTower = true;
LK.effects.flashObject(self, 0x00FF00, 300);
} else {
// Flash red if can't afford
LK.effects.flashObject(self, 0xFF0000, 300);
}
};
self.update = function () {
var towerCost = 100 + Math.floor(wave / 2) * 15;
var resourceCost = 100 + Math.floor(wave / 3) * 20;
if (resources >= resourceCost && money >= towerCost) {
buttonGraphics.tint = 0xFF2222; // Red when affordable
buttonText.setText('Big Tower');
costText.setText('R:' + resourceCost + ' $' + towerCost);
} else {
buttonGraphics.tint = 0x808080; // Gray when not affordable
buttonText.setText('Big Tower');
costText.setText('R:' + resourceCost + ' $' + towerCost);
}
};
return self;
});
var BuyRapidFireTowerButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
tint: 0x00FF00
});
var towerIcon = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: 0x00FF00,
y: -15
});
var buttonText = new Text2('Rapid', {
size: 28,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 15;
self.addChild(buttonText);
var costText = new Text2('R:75 $40', {
size: 22,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0.5);
costText.y = 35;
self.addChild(costText);
self.down = function (x, y, obj) {
var towerCost = 40;
if (resources >= 75 && money >= towerCost) {
// Enable rapid fire tower placement mode
placingRapidFireTower = true;
LK.effects.flashObject(self, 0x00FF00, 300);
} else {
// Flash red if can't afford
LK.effects.flashObject(self, 0xFF0000, 300);
}
};
self.update = function () {
var towerCost = 40;
if (resources >= 75 && money >= towerCost) {
buttonGraphics.tint = 0x00AA00; // Green when affordable
buttonText.setText('Rapid');
costText.setText('R:75 $40');
} else {
buttonGraphics.tint = 0x808080; // Gray when not affordable
buttonText.setText('Rapid');
costText.setText('R:75 $40');
}
};
return self;
});
var BuySniperTowerButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
tint: 0x0088FF
});
var towerIcon = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: 0x0088FF,
y: -15
});
var buttonText = new Text2('Sniper', {
size: 26,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 15;
self.addChild(buttonText);
var costText = new Text2('R:125 $75', {
size: 20,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0.5);
costText.y = 35;
self.addChild(costText);
self.down = function (x, y, obj) {
var towerCost = 75;
if (resources >= 125 && money >= towerCost) {
// Enable sniper tower placement mode
placingSniperTower = true;
LK.effects.flashObject(self, 0x00FF00, 300);
} else {
// Flash red if can't afford
LK.effects.flashObject(self, 0xFF0000, 300);
}
};
self.update = function () {
var towerCost = 75;
if (resources >= 125 && money >= towerCost) {
buttonGraphics.tint = 0x0066CC; // Blue when affordable
buttonText.setText('Sniper');
costText.setText('R:125 $75');
} else {
buttonGraphics.tint = 0x808080; // Gray when not affordable
buttonText.setText('Sniper');
costText.setText('R:125 $75');
}
};
return self;
});
var BuyTowerButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5
});
var towerIcon = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
y: -15
});
var buttonText = new Text2('Tower', {
size: 32,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 15;
self.addChild(buttonText);
var costText = new Text2('R:50 $25', {
size: 24,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0.5);
costText.y = 35;
self.addChild(costText);
self.down = function (x, y, obj) {
var towerCost = 25;
if (resources >= 50 && money >= towerCost) {
// Enable tower placement mode
placingTower = true;
LK.effects.flashObject(self, 0x00FF00, 300);
} else {
// Flash red if can't afford
LK.effects.flashObject(self, 0xFF0000, 300);
}
};
self.update = function () {
var towerCost = 25 + Math.floor(wave / 2) * 5;
var resourceCost = 50 + Math.floor(wave / 3) * 10;
if (resources >= resourceCost && money >= towerCost) {
buttonGraphics.tint = 0x4CAF50; // Green when affordable
buttonText.setText('Tower');
costText.setText('R:' + resourceCost + ' $' + towerCost);
} else {
buttonGraphics.tint = 0x808080; // Gray when not affordable
buttonText.setText('Tower');
costText.setText('R:' + resourceCost + ' $' + towerCost);
}
};
return self;
});
var DefenseTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 200;
self.maxHealth = 200;
self.damage = 30;
self.range = 300;
self.shootCooldown = 0;
self.update = function () {
var target = self.findNearestEnemy();
if (target && self.shootCooldown <= 0) {
self.shootAt(target);
self.shootCooldown = 45; // 0.75 second cooldown
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.findNearestEnemy = function () {
var nearest = null;
var minDistance = Infinity;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < minDistance && distance < self.range) {
minDistance = distance;
nearest = zombie;
}
}
return nearest;
};
self.shootAt = function (target) {
var bullet = new TowerBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
towerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
self.destroy();
var index = defenseTowers.indexOf(self);
if (index > -1) {
defenseTowers.splice(index, 1);
}
};
return self;
});
var EnemyBot = Container.expand(function (botType) {
var self = Container.call(this);
var botGraphics = self.attachAsset(botType, {
anchorX: 0.5,
anchorY: 0.5
});
self.botType = botType;
// Scale bot stats based on current wave
var healthMultiplier = 1 + (wave - 1) * 0.25; // 25% more health per wave
var damageMultiplier = 1 + (wave - 1) * 0.15; // 15% more damage per wave
self.health = Math.floor(150 * healthMultiplier);
self.maxHealth = Math.floor(150 * healthMultiplier);
self.damage = Math.floor(25 * damageMultiplier);
self.range = 350;
self.shootCooldown = 0;
// Set specific properties based on bot type
if (botType === 'artilleryBot') {
self.damage = 60;
self.range = 400;
self.shootCooldown = 90; // Slower but more powerful
} else if (botType === 'assaultBot') {
self.damage = 20;
self.range = 250;
self.shootCooldown = 20; // Faster firing
} else if (botType === 'disruptionBot') {
self.damage = 15;
self.range = 300;
self.shootCooldown = 120; // Special ability cooldown
} else if (botType === 'repairBot') {
self.damage = 0;
self.range = 200;
self.shootCooldown = 180; // Repair cooldown
}
self.update = function () {
var target = self.findTarget();
if (target && self.shootCooldown <= 0) {
if (self.botType === 'repairBot') {
self.repairAllies();
} else {
self.shootAt(target);
}
self.shootCooldown = self.getBaseCooldown();
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.findTarget = function () {
var targets = [];
// Add player base as target
var distanceToBase = Math.sqrt(Math.pow(playerBase.x - self.x, 2) + Math.pow(playerBase.y - self.y, 2));
if (distanceToBase < self.range) {
targets.push({
target: playerBase,
distance: distanceToBase
});
}
// Add hero as target
var distanceToHero = Math.sqrt(Math.pow(hero.x - self.x, 2) + Math.pow(hero.y - self.y, 2));
if (distanceToHero < self.range) {
targets.push({
target: hero,
distance: distanceToHero
});
}
// Add defense towers as targets
for (var i = 0; i < defenseTowers.length; i++) {
var tower = defenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < self.range) {
targets.push({
target: tower,
distance: distance
});
}
}
// Add big defense towers as targets
for (var i = 0; i < bigDefenseTowers.length; i++) {
var tower = bigDefenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < self.range) {
targets.push({
target: tower,
distance: distance
});
}
}
// Add rapid fire towers as targets
for (var i = 0; i < rapidFireTowers.length; i++) {
var tower = rapidFireTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < self.range) {
targets.push({
target: tower,
distance: distance
});
}
}
// Add sniper towers as targets
for (var i = 0; i < sniperTowers.length; i++) {
var tower = sniperTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < self.range) {
targets.push({
target: tower,
distance: distance
});
}
}
// Return nearest target
if (targets.length > 0) {
targets.sort(function (a, b) {
return a.distance - b.distance;
});
return targets[0].target;
}
return null;
};
self.shootAt = function (target) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
bullet.isAOE = self.botType === 'artilleryBot';
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.repairAllies = function () {
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
if (bot !== self) {
var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2));
if (distance < self.range) {
bot.health = Math.min(bot.health + 30, bot.maxHealth);
LK.effects.flashObject(bot, 0x00ff00, 300);
}
}
}
};
self.getBaseCooldown = function () {
if (self.botType === 'artilleryBot') return 90;
if (self.botType === 'assaultBot') return 20;
if (self.botType === 'disruptionBot') return 120;
if (self.botType === 'repairBot') return 180;
return 60;
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
LK.getSound('explosion').play();
LK.setScore(LK.getScore() + 25);
scoreText.setText('Score: ' + LK.getScore());
// Add money and spawn money icon
var moneyEarned = 15;
money += moneyEarned;
moneyText.setText('Money: $' + money);
var moneyIcon = new MoneyIcon(moneyEarned);
moneyIcon.x = self.x;
moneyIcon.y = self.y;
moneyIcons.push(moneyIcon);
game.addChild(moneyIcon);
self.destroy();
var index = enemyBots.indexOf(self);
if (index > -1) {
enemyBots.splice(index, 1);
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.damage = 25;
self.targetX = 0;
self.targetY = 0;
self.isAOE = false;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.explode();
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
var index = enemyBullets.indexOf(self);
if (index > -1) {
enemyBullets.splice(index, 1);
}
}
};
self.explode = function () {
if (self.isAOE) {
// AOE damage
var explosion = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.7
});
game.addChild(explosion);
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage everything in range
var explosionRange = 150;
if (self.intersects(playerBase)) {
playerBase.takeDamage(self.damage);
}
if (self.intersects(hero)) {
hero.takeDamage(self.damage);
}
for (var i = 0; i < defenseTowers.length; i++) {
var tower = defenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < explosionRange) {
tower.takeDamage(self.damage);
}
}
for (var i = 0; i < bigDefenseTowers.length; i++) {
var tower = bigDefenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < explosionRange) {
tower.takeDamage(self.damage);
}
}
for (var i = 0; i < rapidFireTowers.length; i++) {
var tower = rapidFireTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < explosionRange) {
tower.takeDamage(self.damage);
}
}
for (var i = 0; i < sniperTowers.length; i++) {
var tower = sniperTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < explosionRange) {
tower.takeDamage(self.damage);
}
}
LK.getSound('explosion').play();
} else {
// Single target damage
if (self.intersects(playerBase)) {
playerBase.takeDamage(self.damage);
} else if (self.intersects(hero)) {
hero.takeDamage(self.damage);
} else {
for (var i = 0; i < defenseTowers.length; i++) {
var tower = defenseTowers[i];
if (self.intersects(tower)) {
tower.takeDamage(self.damage);
break;
}
}
for (var i = 0; i < bigDefenseTowers.length; i++) {
var tower = bigDefenseTowers[i];
if (self.intersects(tower)) {
tower.takeDamage(self.damage);
break;
}
}
for (var i = 0; i < rapidFireTowers.length; i++) {
var tower = rapidFireTowers[i];
if (self.intersects(tower)) {
tower.takeDamage(self.damage);
break;
}
}
for (var i = 0; i < sniperTowers.length; i++) {
var tower = sniperTowers[i];
if (self.intersects(tower)) {
tower.takeDamage(self.damage);
break;
}
}
}
}
self.destroy();
var index = enemyBullets.indexOf(self);
if (index > -1) {
enemyBullets.splice(index, 1);
}
};
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 300;
self.maxHealth = 300;
self.speed = 3;
self.damage = 40;
self.shootCooldown = 0;
self.targetX = self.x;
self.targetY = self.y;
self.update = function () {
// Move towards target position
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Auto-attack nearest enemy
var nearestEnemy = self.findNearestEnemy();
if (nearestEnemy && self.shootCooldown <= 0) {
self.shootAt(nearestEnemy);
self.shootCooldown = 30; // 0.5 second cooldown
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.findNearestEnemy = function () {
var nearest = null;
var minDistance = Infinity;
// Check zombies
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < minDistance && distance < 400) {
minDistance = distance;
nearest = zombie;
}
}
// Check enemy bots
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2));
if (distance < minDistance && distance < 400) {
minDistance = distance;
nearest = bot;
}
}
return nearest;
};
self.shootAt = function (target) {
var bullet = new HeroBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
heroBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.moveTo = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
gameOver = true;
LK.showGameOver();
};
return self;
});
var HeroBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('heroBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.damage = 40;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.explode();
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
var index = heroBullets.indexOf(self);
if (index > -1) {
heroBullets.splice(index, 1);
}
}
};
self.explode = function () {
// Check for zombie hits
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(self.damage);
self.destroy();
var index = heroBullets.indexOf(self);
if (index > -1) {
heroBullets.splice(index, 1);
}
return;
}
}
// Check for enemy bot hits
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
if (self.intersects(bot)) {
bot.takeDamage(self.damage);
self.destroy();
var index = heroBullets.indexOf(self);
if (index > -1) {
heroBullets.splice(index, 1);
}
return;
}
}
self.destroy();
var index = heroBullets.indexOf(self);
if (index > -1) {
heroBullets.splice(index, 1);
}
};
return self;
});
var MoneyIcon = Container.expand(function (amount) {
var self = Container.call(this);
var moneyGraphics = self.attachAsset('money', {
anchorX: 0.5,
anchorY: 0.5
});
var moneyText = new Text2('+$' + amount, {
size: 30,
fill: 0xFFD700
});
moneyText.anchor.set(0.5, 0.5);
moneyText.x = 30;
self.addChild(moneyText);
self.lifeTime = 120; // 2 seconds at 60fps
self.floatSpeed = -2;
self.update = function () {
self.y += self.floatSpeed;
self.alpha -= 0.02;
self.lifeTime--;
if (self.lifeTime <= 0 || self.alpha <= 0) {
self.destroy();
var index = moneyIcons.indexOf(self);
if (index > -1) {
moneyIcons.splice(index, 1);
}
}
};
return self;
});
var PlayerBase = Container.expand(function () {
var self = Container.call(this);
var baseGraphics = self.attachAsset('playerBase', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1000;
self.maxHealth = 1000;
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
healthText.setText('Base Health: ' + self.health + '/' + self.maxHealth);
if (self.health <= 0) {
gameOver = true;
LK.showGameOver();
}
};
return self;
});
var RapidFireBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
tint: 0x00FF00
});
self.speed = 12;
self.damage = 15;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.explode();
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
var index = rapidFireBullets.indexOf(self);
if (index > -1) {
rapidFireBullets.splice(index, 1);
}
}
};
self.explode = function () {
// Check for zombie hits
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(self.damage);
break;
}
}
// Check for enemy bot hits
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
if (self.intersects(bot)) {
bot.takeDamage(self.damage);
break;
}
}
self.destroy();
var index = rapidFireBullets.indexOf(self);
if (index > -1) {
rapidFireBullets.splice(index, 1);
}
};
return self;
});
var RapidFireTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
tint: 0x00FF00
});
self.health = 150;
self.maxHealth = 150;
self.damage = 15;
self.range = 250;
self.shootCooldown = 0;
self.update = function () {
var target = self.findNearestEnemy();
if (target && self.shootCooldown <= 0) {
self.shootAt(target);
self.shootCooldown = 15; // Very fast firing
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.findNearestEnemy = function () {
var nearest = null;
var minDistance = Infinity;
// Check zombies
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < minDistance && distance < self.range) {
minDistance = distance;
nearest = zombie;
}
}
// Check enemy bots
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2));
if (distance < minDistance && distance < self.range) {
minDistance = distance;
nearest = bot;
}
}
return nearest;
};
self.shootAt = function (target) {
var bullet = new RapidFireBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
rapidFireBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
self.destroy();
var index = rapidFireTowers.indexOf(self);
if (index > -1) {
rapidFireTowers.splice(index, 1);
}
};
return self;
});
var SniperBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8,
tint: 0x0088FF
});
self.speed = 15;
self.damage = 120;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.explode();
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
var index = sniperBullets.indexOf(self);
if (index > -1) {
sniperBullets.splice(index, 1);
}
}
};
self.explode = function () {
// Check for zombie hits
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(self.damage);
break;
}
}
// Check for enemy bot hits
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
if (self.intersects(bot)) {
bot.takeDamage(self.damage);
break;
}
}
self.destroy();
var index = sniperBullets.indexOf(self);
if (index > -1) {
sniperBullets.splice(index, 1);
}
};
return self;
});
var SniperTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('defenseTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0x0088FF
});
self.health = 250;
self.maxHealth = 250;
self.damage = 120;
self.range = 600;
self.shootCooldown = 0;
self.update = function () {
var target = self.findNearestEnemy();
if (target && self.shootCooldown <= 0) {
self.shootAt(target);
self.shootCooldown = 80; // Slow but powerful
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.findNearestEnemy = function () {
var nearest = null;
var minDistance = Infinity;
// Check zombies
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < minDistance && distance < self.range) {
minDistance = distance;
nearest = zombie;
}
}
// Check enemy bots
for (var i = 0; i < enemyBots.length; i++) {
var bot = enemyBots[i];
var distance = Math.sqrt(Math.pow(bot.x - self.x, 2) + Math.pow(bot.y - self.y, 2));
if (distance < minDistance && distance < self.range) {
minDistance = distance;
nearest = bot;
}
}
return nearest;
};
self.shootAt = function (target) {
var bullet = new SniperBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
sniperBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
self.destroy();
var index = sniperTowers.indexOf(self);
if (index > -1) {
sniperTowers.splice(index, 1);
}
};
return self;
});
var TowerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 30;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.explode();
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
var index = towerBullets.indexOf(self);
if (index > -1) {
towerBullets.splice(index, 1);
}
}
};
self.explode = function () {
// Check for zombie hits
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(self.damage);
break;
}
}
self.destroy();
var index = towerBullets.indexOf(self);
if (index > -1) {
towerBullets.splice(index, 1);
}
};
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
// Scale health and damage based on current wave
var healthMultiplier = 1 + (wave - 1) * 0.3; // 30% more health per wave
var damageMultiplier = 1 + (wave - 1) * 0.2; // 20% more damage per wave
var speedMultiplier = 1 + (wave - 1) * 0.1; // 10% faster per wave
self.health = Math.floor(100 * healthMultiplier);
self.maxHealth = Math.floor(100 * healthMultiplier);
self.speed = Math.min(3, 1 * speedMultiplier); // Cap speed at 3
self.damage = Math.floor(20 * damageMultiplier);
self.target = null;
self.attackCooldown = 0;
self.update = function () {
if (!self.target) {
self.target = playerBase;
}
// Move towards 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 > 50) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// Attack target
if (self.attackCooldown <= 0) {
if (self.target === playerBase) {
playerBase.takeDamage(self.damage);
}
self.attackCooldown = 60; // 1 second cooldown
}
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
LK.getSound('zombieHit').play();
LK.setScore(LK.getScore() + 10);
scoreText.setText('Score: ' + LK.getScore());
// Add money and spawn money icon
var moneyEarned = 5;
money += moneyEarned;
moneyText.setText('Money: $' + money);
var moneyIcon = new MoneyIcon(moneyEarned);
moneyIcon.x = self.x;
moneyIcon.y = self.y;
moneyIcons.push(moneyIcon);
game.addChild(moneyIcon);
self.destroy();
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2a2a2a
});
/****
* Game Code
****/
// Game state variables
var gameOver = false;
var wave = 1;
var zombiesSpawned = 0;
var zombiesPerWave = 5;
var spawnTimer = 0;
var botSpawnTimer = 0;
var resources = 100;
var money = 0;
var placingTower = false;
var placingBigTower = false;
var placingRapidFireTower = false;
var placingSniperTower = false;
// Game objects arrays
var zombies = [];
var enemyBots = [];
var defenseTowers = [];
var bigDefenseTowers = [];
var rapidFireTowers = [];
var sniperTowers = [];
var towerBullets = [];
var bigTowerBullets = [];
var rapidFireBullets = [];
var sniperBullets = [];
var heroBullets = [];
var enemyBullets = [];
var moneyIcons = [];
// Create player base
var playerBase = new PlayerBase();
playerBase.x = 1024;
playerBase.y = 2400;
game.addChild(playerBase);
// Create hero
var hero = new Hero();
hero.x = 1024;
hero.y = 2200;
game.addChild(hero);
// Create UI elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
var healthText = new Text2('Base Health: 1000/1000', {
size: 50,
fill: 0xFFFFFF
});
healthText.anchor.set(0, 0);
healthText.x = -400;
LK.gui.topRight.addChild(healthText);
var waveText = new Text2('Wave: 1', {
size: 55,
fill: 0xFFFF00
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
var resourceText = new Text2('Resources: 100', {
size: 45,
fill: 0x00FF00
});
resourceText.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(resourceText);
var moneyText = new Text2('Money: $0', {
size: 45,
fill: 0xFFD700
});
moneyText.anchor.set(0.5, 0);
moneyText.y = 60;
LK.gui.bottom.addChild(moneyText);
// Create buy tower button
var buyTowerButton = new BuyTowerButton();
buyTowerButton.x = 120;
buyTowerButton.y = -120;
LK.gui.bottomLeft.addChild(buyTowerButton);
// Create buy big tower button
var buyBigTowerButton = new BuyBigTowerButton();
buyBigTowerButton.x = 280;
buyBigTowerButton.y = -120;
LK.gui.bottomLeft.addChild(buyBigTowerButton);
// Create buy rapid fire tower button
var buyRapidFireTowerButton = new BuyRapidFireTowerButton();
buyRapidFireTowerButton.x = 440;
buyRapidFireTowerButton.y = -120;
LK.gui.bottomLeft.addChild(buyRapidFireTowerButton);
// Create buy sniper tower button
var buySniperTowerButton = new BuySniperTowerButton();
buySniperTowerButton.x = 600;
buySniperTowerButton.y = -120;
LK.gui.bottomLeft.addChild(buySniperTowerButton);
// Game control functions
function spawnZombie() {
var zombie = new Zombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
// Top
zombie.x = Math.random() * 2048;
zombie.y = 0;
} else if (edge === 1) {
// Right
zombie.x = 2048;
zombie.y = Math.random() * 2732;
} else if (edge === 2) {
// Bottom
zombie.x = Math.random() * 2048;
zombie.y = 2732;
} else {
// Left
zombie.x = 0;
zombie.y = Math.random() * 2732;
}
zombies.push(zombie);
game.addChild(zombie);
zombiesSpawned++;
}
function spawnEnemyBot() {
var botTypes = ['artilleryBot', 'assaultBot', 'disruptionBot', 'repairBot'];
var randomType = botTypes[Math.floor(Math.random() * botTypes.length)];
var bot = new EnemyBot(randomType);
bot.x = Math.random() * 1800 + 124;
bot.y = Math.random() * 1000 + 200;
enemyBots.push(bot);
game.addChild(bot);
}
function buildDefenseTower(x, y) {
var towerCost = 25 + Math.floor(wave / 2) * 5; // Increase cost every 2 waves
var resourceCost = 50 + Math.floor(wave / 3) * 10; // Increase resource cost every 3 waves
if (resources >= resourceCost && money >= towerCost) {
var tower = new DefenseTower();
tower.x = x;
tower.y = y;
defenseTowers.push(tower);
game.addChild(tower);
resources -= resourceCost;
money -= towerCost;
resourceText.setText('Resources: ' + resources);
moneyText.setText('Money: $' + money);
}
}
function buildBigDefenseTower(x, y) {
var towerCost = 100 + Math.floor(wave / 2) * 15; // Increase cost every 2 waves
var resourceCost = 100 + Math.floor(wave / 3) * 20; // Increase resource cost every 3 waves
if (resources >= resourceCost && money >= towerCost) {
var tower = new BigDefenseTower();
tower.x = x;
tower.y = y;
bigDefenseTowers.push(tower);
game.addChild(tower);
resources -= resourceCost;
money -= towerCost;
resourceText.setText('Resources: ' + resources);
moneyText.setText('Money: $' + money);
}
}
function buildRapidFireTower(x, y) {
var towerCost = 40; // Money cost for rapid fire tower
if (resources >= 75 && money >= towerCost) {
var tower = new RapidFireTower();
tower.x = x;
tower.y = y;
rapidFireTowers.push(tower);
game.addChild(tower);
resources -= 75;
money -= towerCost;
resourceText.setText('Resources: ' + resources);
moneyText.setText('Money: $' + money);
}
}
function buildSniperTower(x, y) {
var towerCost = 75; // Money cost for sniper tower
if (resources >= 125 && money >= towerCost) {
var tower = new SniperTower();
tower.x = x;
tower.y = y;
sniperTowers.push(tower);
game.addChild(tower);
resources -= 125;
money -= towerCost;
resourceText.setText('Resources: ' + resources);
moneyText.setText('Money: $' + money);
}
}
// Event handlers
game.down = function (x, y, obj) {
if (placingTower) {
// Tower placement mode
var canBuild = true;
var minDistance = 120;
// Check distance from other towers
for (var i = 0; i < defenseTowers.length; i++) {
var tower = defenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
// Check distance from big towers
for (var i = 0; i < bigDefenseTowers.length; i++) {
var tower = bigDefenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
// Check distance from base
var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2));
if (distanceToBase < 150) {
canBuild = false;
}
// Check distance from hero
var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2));
if (distanceToHero < 100) {
canBuild = false;
}
if (canBuild && y < 2300) {
// Don't build too close to base area
buildDefenseTower(x, y);
placingTower = false; // Exit placement mode after building
}
} else if (placingBigTower) {
// Big tower placement mode
var canBuild = true;
var minDistance = 150;
// Check distance from regular towers
for (var i = 0; i < defenseTowers.length; i++) {
var tower = defenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
// Check distance from other big towers
for (var i = 0; i < bigDefenseTowers.length; i++) {
var tower = bigDefenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
// Check distance from base
var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2));
if (distanceToBase < 200) {
canBuild = false;
}
// Check distance from hero
var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2));
if (distanceToHero < 120) {
canBuild = false;
}
if (canBuild && y < 2300) {
// Don't build too close to base area
buildBigDefenseTower(x, y);
placingBigTower = false; // Exit placement mode after building
}
} else if (placingRapidFireTower) {
// Rapid fire tower placement mode
var canBuild = true;
var minDistance = 100;
// Check distance from all towers
for (var i = 0; i < defenseTowers.length; i++) {
var tower = defenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
for (var i = 0; i < bigDefenseTowers.length; i++) {
var tower = bigDefenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
for (var i = 0; i < rapidFireTowers.length; i++) {
var tower = rapidFireTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
for (var i = 0; i < sniperTowers.length; i++) {
var tower = sniperTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2));
if (distanceToBase < 120) {
canBuild = false;
}
var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2));
if (distanceToHero < 80) {
canBuild = false;
}
if (canBuild && y < 2300) {
buildRapidFireTower(x, y);
placingRapidFireTower = false;
}
} else if (placingSniperTower) {
// Sniper tower placement mode
var canBuild = true;
var minDistance = 140;
// Check distance from all towers
for (var i = 0; i < defenseTowers.length; i++) {
var tower = defenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
for (var i = 0; i < bigDefenseTowers.length; i++) {
var tower = bigDefenseTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
for (var i = 0; i < rapidFireTowers.length; i++) {
var tower = rapidFireTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
for (var i = 0; i < sniperTowers.length; i++) {
var tower = sniperTowers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance < minDistance) {
canBuild = false;
break;
}
}
var distanceToBase = Math.sqrt(Math.pow(playerBase.x - x, 2) + Math.pow(playerBase.y - y, 2));
if (distanceToBase < 180) {
canBuild = false;
}
var distanceToHero = Math.sqrt(Math.pow(hero.x - x, 2) + Math.pow(hero.y - y, 2));
if (distanceToHero < 100) {
canBuild = false;
}
if (canBuild && y < 2300) {
buildSniperTower(x, y);
placingSniperTower = false;
}
} else {
// Normal mode - move hero
hero.moveTo(x, y);
}
};
// Start background music
LK.playMusic('Zombiewarmuic');
// Main game loop
game.update = function () {
if (gameOver) return;
// Resource generation
if (LK.ticks % 180 === 0) {
// Every 3 seconds
resources += 10;
resourceText.setText('Resources: ' + resources);
}
// Zombie spawning - faster spawn rate at higher waves
if (zombiesSpawned < zombiesPerWave) {
spawnTimer++;
var zombieSpawnInterval = Math.max(60, 120 - (wave - 1) * 8); // Faster spawning each wave, minimum 1 second
if (spawnTimer >= zombieSpawnInterval) {
spawnZombie();
spawnTimer = 0;
}
}
// Enemy bot spawning - faster spawn rate at higher waves
botSpawnTimer++;
var botSpawnInterval = Math.max(300, 600 - (wave - 1) * 30); // Faster spawning each wave, minimum 5 seconds
if (botSpawnTimer >= botSpawnInterval) {
spawnEnemyBot();
// Spawn additional bots at higher waves
if (wave >= 5 && Math.random() < 0.3) {
spawnEnemyBot(); // 30% chance for second bot
}
if (wave >= 8 && Math.random() < 0.2) {
spawnEnemyBot(); // 20% chance for third bot
}
botSpawnTimer = 0;
}
// Check for wave completion
if (zombiesSpawned >= zombiesPerWave && zombies.length === 0) {
wave++;
zombiesSpawned = 0;
zombiesPerWave += 3 + Math.floor(wave / 3); // More zombies per wave as game progresses
waveText.setText('Wave: ' + wave);
// Bonus resources for completing wave - but less bonus at higher waves
resources += Math.max(15, 35 - wave);
resourceText.setText('Resources: ' + resources);
}
// Win condition
if (wave >= 10 && zombies.length === 0 && enemyBots.length === 0) {
LK.showYouWin();
}
// Update all bullets
for (var i = towerBullets.length - 1; i >= 0; i--) {
var bullet = towerBullets[i];
if (bullet.destroyed) {
towerBullets.splice(i, 1);
}
}
for (var i = bigTowerBullets.length - 1; i >= 0; i--) {
var bullet = bigTowerBullets[i];
if (bullet.destroyed) {
bigTowerBullets.splice(i, 1);
}
}
for (var i = rapidFireBullets.length - 1; i >= 0; i--) {
var bullet = rapidFireBullets[i];
if (bullet.destroyed) {
rapidFireBullets.splice(i, 1);
}
}
for (var i = sniperBullets.length - 1; i >= 0; i--) {
var bullet = sniperBullets[i];
if (bullet.destroyed) {
sniperBullets.splice(i, 1);
}
}
for (var i = heroBullets.length - 1; i >= 0; i--) {
var bullet = heroBullets[i];
if (bullet.destroyed) {
heroBullets.splice(i, 1);
}
}
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.destroyed) {
enemyBullets.splice(i, 1);
}
}
// Update money icons
for (var i = moneyIcons.length - 1; i >= 0; i--) {
var icon = moneyIcons[i];
if (icon.destroyed) {
moneyIcons.splice(i, 1);
}
}
};
bullet. 2d. High contrast. No shadows
zombie. 2d. High contrast. No shadows
playerBase. In-Game asset. 2d. High contrast. No shadows
hero. In-Game asset. 2d. High contrast. No shadows
artilleryBot. In-Game asset. 2d. High contrast. No shadows
defenseTower. In-Game asset. 2d. High contrast. No shadows
enemyBullet. In-Game asset. 2d. High contrast. No shadows
assaultBot. In-Game asset. 2d. High contrast. No shadows
repairBot. In-Game asset. 2d. High contrast. No shadows
explosion. In-Game asset. 2d. High contrast. No shadows
disruptionBot. In-Game asset. 2d. High contrast. No shadows
heroBullet. In-Game asset. 2d. High contrast. No shadows
Coin. In-Game asset. 2d. High contrast. No shadows
buyButton. In-Game asset. 2d. High contrast. No shadows
Zombie boss. In-Game asset. 2d. High contrast. No shadows
Start button. In-Game asset. 2d. High contrast. No shadows