User prompt
Please add in top left UI next to Health counter an Armor counter
User prompt
please add player animation, if the player starts facing north the player rotates the direction it is moving ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
please remove all player animation
User prompt
please animate the players legs when the player moves ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
increase the brightness of the shield visually on the player
User prompt
please adjust the opacity of the shield visually it is more colorful and can be seen better
User prompt
please adjust the player size to slightly larger
User prompt
please adjust when the shield is active the creeps must get closer to the player before they can hit the player
User prompt
slightly increase the health potion drop chance
User prompt
slightly increase the visual size of the shield upgrade on the player when active
User prompt
please decrease the drop chance of health potion upgrade and increase the shield upgrade drop chance
User prompt
please adjust the shield when it is active to show the visual asset on the player
User prompt
please adjust the hit points of the shield to 40 when collected, if the player has an active shield the hit points add up to 80 but cant exceed 80 hit points, please adjust the frequency of the shield upgrades dropped by the creeps increase the drop chance by 20%
User prompt
please adjust the health of all boss creeps to triple the amount and double the size of the boss creeps
User prompt
please adjust the shield upgrade the hit points of the shield upgrade is 40 and duration is 30 seconds if the player picks up another shield while a shield is active the time add up but cant exceed 180 seconds and the hit points of the shield adds up but cant exceed 80 hit points, while the shield is active the asset shieldAura is displayed on the player
User prompt
please adjust the size of the upgrades to double dropped by the creeps
User prompt
please add an shield upgrade, the shield has an 40 hit point defense and last for 30 seconds, if the players picks up another shield upgrade while an shield is already active the duration of the shields time adds up but cant exceed 180 seconds in total ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
please remove all shield upgrades in the game coding
User prompt
please adjust all creeps , every time they hit the player to continue moving towards the player they never stand still after an hit ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
please adjust all upgrades last 30 seconds before they disappear, please adjust when shield upgrade is collected first time second time any time to activate fully ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
please adjust after an creep hits the player and bumps the player the creep continues moving towards the player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
please adjust when the player gets hit by any creep the creep does not die it only bumps the player slightly and the player takes the damage ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
please adjust the elite creeps has 50% chance to drop an weapon damage upgrade after they are killed
User prompt
please adjust the shield upgrades to always activate on collecting the first shield upgrade , please adjust the creeps to not be able to stack on each other they can only stand close to each other while moving towards the player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
please adjust the frequency of the shield and weapon upgrades to happen more often than the health upgrades
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BossCreep = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('bossCreep', { anchorX: 0.5, anchorY: 0.5 }); self.health = 4000; // Base health for first boss (10x increase) self.maxHealth = 4000; self.speed = 0.8; // Slower than elite creeps self.damage = 50; // More damage than elite creeps self.targetX = 0; self.targetY = 0; self.hasReachedPlayer = false; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { return true; // Return true if boss is dead } return false; }; self.update = function () { if (self.hasReachedPlayer) return; // Continuously update target to player's current position self.targetX = player.x; self.targetY = player.y; 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; } else { self.hasReachedPlayer = true; } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.velocityX = 0; self.velocityY = 0; self.damage = 20; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; }; return self; }); var Creep = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('creep', { anchorX: 0.5, anchorY: 0.5 }); self.health = 60; // Base health requiring 3 hits (20 damage per hit) self.maxHealth = 60; self.speed = 2; self.damage = 15; self.targetX = 0; self.targetY = 0; self.hasReachedPlayer = false; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { return true; // Return true if creep is dead } return false; }; self.update = function () { if (self.hasReachedPlayer) return; // Continuously update target to player's current position self.targetX = player.x; self.targetY = player.y; 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; } else { self.hasReachedPlayer = true; } }; return self; }); var EliteCreep = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('eliteCreep', { anchorX: 0.5, anchorY: 0.5 }); self.health = 150; // Much higher base health self.maxHealth = 150; self.speed = 1.2; // Slower than regular creeps self.damage = 35; // More damage than regular creeps self.targetX = 0; self.targetY = 0; self.hasReachedPlayer = false; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { return true; // Return true if creep is dead } return false; }; self.update = function () { if (self.hasReachedPlayer) return; // Continuously update target to player's current position self.targetX = player.x; self.targetY = player.y; 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; } else { self.hasReachedPlayer = true; } }; return self; }); var Pickup = Container.expand(function (type) { var self = Container.call(this); self.type = type; var assetName; if (type === 'health') { assetName = 'healthPotion'; } else if (type === 'shield') { assetName = 'shieldUpgrade'; } else if (type === 'damage') { assetName = 'damageUpgrade'; } else if (type === 'speed') { assetName = 'shieldUpgrade'; // Reuse blue upgrade for speed } else if (type === 'attackSpeed') { assetName = 'damageUpgrade'; // Reuse red upgrade for attack speed } var graphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.lifetime = 600; // 10 seconds at 60fps (doubled from 5 seconds) self.update = function () { self.lifetime--; if (self.lifetime < 120) { // Start fading at 2 seconds remaining graphics.alpha = self.lifetime / 120; } // Magnetic pull effect when player is close if (player) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Start pulling when within 150 pixels if (distance < 150 && distance > 10) { var pullSpeed = 8; // Fast pull speed var normalizedX = dx / distance; var normalizedY = dy / distance; self.x += normalizedX * pullSpeed; self.y += normalizedY * pullSpeed; } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.shieldVisual = null; // Shield aura visual element self.maxHealth = 100; self.health = 100; self.defense = 0; self.baseDamage = 20; // Base damage that never changes self.damage = 20; // Current damage (base + upgrades) self.weaponUpgrades = 0; // Track weapon upgrades for double shot self.lastShootTime = 0; self.shootCooldown = 40; // Fixed cooldown that never changes self.baseSpeed = 4; // Base movement speed self.moveSpeed = 4; // Current movement speed (base + upgrades) self.takeDamage = function (amount) { var actualDamage = Math.max(1, amount - self.defense); self.health -= actualDamage; if (self.health < 0) self.health = 0; // Flash red when taking damage tween(graphics, { tint: 0xFF0000 }, { duration: 100, onFinish: function onFinish() { tween(graphics, { tint: 0xFFFFFF }, { duration: 100 }); } }); LK.getSound('hit').play(); }; self.heal = function (amount) { self.health = Math.min(self.maxHealth, self.health + amount); }; self.addDamage = function (amount) { self.damage += amount; self.weaponUpgrades++; // Track weapon upgrades }; self.addSpeed = function (amount) { self.moveSpeed += amount; }; self.activateShield = function () { if (shieldActive) { // If shield is already active, extend the time by 30 seconds but cap at 180 seconds shieldTimer = Math.min(10800, shieldTimer + 1800); // Add 30 seconds at 60fps, cap at 180 seconds } else { // New shield activation shieldActive = true; shieldTimer = 1800; // 30 seconds at 60fps shieldStacks = 1; shieldDefense = 10; // Start with 10 defense } // Only increase stacks and defense if we haven't hit the cap if (shieldDefense < 50) { shieldStacks++; shieldDefense = Math.min(50, shieldStacks * 10); // Cap at 50 defense } // Always ensure shield visual exists and is visible if (!self.shieldVisual) { self.shieldVisual = self.addChild(LK.getAsset('shieldAura', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 })); } else { // If shield visual exists but is hidden, make it visible self.shieldVisual.alpha = 0.7; self.shieldVisual.scaleX = 1.0; self.shieldVisual.scaleY = 1.0; } // Animate shield activation tween(self.shieldVisual, { scaleX: 1.1, scaleY: 1.1 }, { duration: 500, easing: tween.easeInOut }); // Visual feedback for shield activation tween(graphics, { tint: 0x00AAFF }, { duration: 200, onFinish: function onFinish() { tween(graphics, { tint: 0xFFFFFF }, { duration: 200 }); } }); }; self.canShoot = function () { return LK.ticks - self.lastShootTime > self.shootCooldown; }; self.shoot = function (targetX, targetY) { if (!self.canShoot()) return null; self.lastShootTime = LK.ticks; var bullets = []; var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var normalizedX = dx / distance; var normalizedY = dy / distance; var angle = Math.atan2(normalizedY, normalizedX); if (self.weaponUpgrades >= 30) { // Quad shot for 30+ upgrades var spreadAngle = 0.25; // Center bullet var bullet1 = new Bullet(); bullet1.x = self.x; bullet1.y = self.y; bullet1.velocityX = normalizedX * bullet1.speed; bullet1.velocityY = normalizedY * bullet1.speed; bullet1.damage = self.damage; bullets.push(bullet1); // Left bullet var bullet2 = new Bullet(); bullet2.x = self.x; bullet2.y = self.y; bullet2.velocityX = Math.cos(angle - spreadAngle) * bullet2.speed; bullet2.velocityY = Math.sin(angle - spreadAngle) * bullet2.speed; bullet2.damage = self.damage; bullets.push(bullet2); // Right bullet var bullet3 = new Bullet(); bullet3.x = self.x; bullet3.y = self.y; bullet3.velocityX = Math.cos(angle + spreadAngle) * bullet3.speed; bullet3.velocityY = Math.sin(angle + spreadAngle) * bullet3.speed; bullet3.damage = self.damage; bullets.push(bullet3); // Far left bullet var bullet4 = new Bullet(); bullet4.x = self.x; bullet4.y = self.y; bullet4.velocityX = Math.cos(angle - spreadAngle * 2) * bullet4.speed; bullet4.velocityY = Math.sin(angle - spreadAngle * 2) * bullet4.speed; bullet4.damage = self.damage; bullets.push(bullet4); } else if (self.weaponUpgrades >= 20) { // Triple shot V pattern at 20+ upgrades var spreadAngle = 0.3; // Wider spread for V pattern // Center bullet var bullet1 = new Bullet(); bullet1.x = self.x; bullet1.y = self.y; bullet1.velocityX = normalizedX * bullet1.speed; bullet1.velocityY = normalizedY * bullet1.speed; bullet1.damage = self.damage; bullets.push(bullet1); // Left bullet var bullet2 = new Bullet(); bullet2.x = self.x; bullet2.y = self.y; bullet2.velocityX = Math.cos(angle - spreadAngle) * bullet2.speed; bullet2.velocityY = Math.sin(angle - spreadAngle) * bullet2.speed; bullet2.damage = self.damage; bullets.push(bullet2); // Right bullet var bullet3 = new Bullet(); bullet3.x = self.x; bullet3.y = self.y; bullet3.velocityX = Math.cos(angle + spreadAngle) * bullet3.speed; bullet3.velocityY = Math.sin(angle + spreadAngle) * bullet3.speed; bullet3.damage = self.damage; bullets.push(bullet3); } else if (self.weaponUpgrades >= 10) { // Double shot side by side at 10+ upgrades var offsetDistance = 20; // Distance between bullets var perpX = -normalizedY; // Perpendicular to direction var perpY = normalizedX; // First bullet (left side) var bullet1 = new Bullet(); bullet1.x = self.x + perpX * offsetDistance; bullet1.y = self.y + perpY * offsetDistance; bullet1.velocityX = normalizedX * bullet1.speed; bullet1.velocityY = normalizedY * bullet1.speed; bullet1.damage = self.damage; bullets.push(bullet1); // Second bullet (right side) var bullet2 = new Bullet(); bullet2.x = self.x - perpX * offsetDistance; bullet2.y = self.y - perpY * offsetDistance; bullet2.velocityX = normalizedX * bullet2.speed; bullet2.velocityY = normalizedY * bullet2.speed; bullet2.damage = self.damage; bullets.push(bullet2); } else { // Single shot for upgrades < 10 var bullet1 = new Bullet(); bullet1.x = self.x; bullet1.y = self.y; bullet1.velocityX = normalizedX * bullet1.speed; bullet1.velocityY = normalizedY * bullet1.speed; bullet1.damage = self.damage; bullets.push(bullet1); } LK.getSound('shoot').play(); return bullets; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game(); /**** * Game Code ****/ // Add background image var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); var player = null; var creeps = []; var bullets = []; var pickups = []; var currentWave = 1; var creepsInWave = 5; var creepsSpawned = 0; var eliteCreepsInWave = 1; // Number of elite creeps equals wave number var eliteCreepsSpawned = 0; var waveCompleted = false; var nextWaveTimer = 0; var spawnTimer = 0; // Score tracking variables var gameScore = 0; // Shield system variables var shieldActive = false; var shieldTimer = 0; var shieldDefense = 0; var shieldStacks = 0; // Boss system variables var currentBoss = null; var bossWave = false; // UI Elements var healthText = new Text2('Health: 100', { size: 40, fill: 0xFFFFFF }); healthText.anchor.set(0, 0); LK.gui.topLeft.addChild(healthText); healthText.x = 120; // Offset from left edge var waveText = new Text2('Wave: 1', { size: 40, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0); LK.gui.top.addChild(waveText); var shieldText = new Text2('Shield: Inactive', { size: 30, fill: 0xFFFFFF }); shieldText.anchor.set(0, 0); LK.gui.topLeft.addChild(shieldText); shieldText.x = 120; shieldText.y = 50; var scoreText = new Text2('Score: 0', { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); // Boss health bar (initially hidden) var bossHealthBar = new Text2('', { size: 35, fill: 0xFF4444 }); bossHealthBar.anchor.set(0.5, 0); LK.gui.top.addChild(bossHealthBar); bossHealthBar.y = 50; bossHealthBar.alpha = 0; // Hidden initially // Initialize player player = game.addChild(new Player()); player.x = 1024; player.y = 1366; function spawnCreep() { var creep = new Creep(); // Spawn from random edge var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top creep.x = Math.random() * 2048; creep.y = -50; break; case 1: // Right creep.x = 2098; creep.y = Math.random() * 2732; break; case 2: // Bottom creep.x = Math.random() * 2048; creep.y = 2782; break; case 3: // Left creep.x = -50; creep.y = Math.random() * 2732; break; } creep.targetX = player.x; creep.targetY = player.y; creep.health += (currentWave - 1) * 20; // Scale health with wave (20 per wave) creep.maxHealth = creep.health; creeps.push(creep); game.addChild(creep); } function spawnEliteCreep() { var eliteCreep = new EliteCreep(); // Spawn from random edge var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top eliteCreep.x = Math.random() * 2048; eliteCreep.y = -50; break; case 1: // Right eliteCreep.x = 2098; eliteCreep.y = Math.random() * 2732; break; case 2: // Bottom eliteCreep.x = Math.random() * 2048; eliteCreep.y = 2782; break; case 3: // Left eliteCreep.x = -50; eliteCreep.y = Math.random() * 2732; break; } eliteCreep.targetX = player.x; eliteCreep.targetY = player.y; eliteCreep.health += (currentWave - 1) * 40; // Scale health with wave (40 per wave for elites) eliteCreep.maxHealth = eliteCreep.health; creeps.push(eliteCreep); game.addChild(eliteCreep); } function spawnBoss() { var boss = new BossCreep(); // Spawn from random edge var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top boss.x = Math.random() * 2048; boss.y = -75; break; case 1: // Right boss.x = 2123; boss.y = Math.random() * 2732; break; case 2: // Bottom boss.x = Math.random() * 2048; boss.y = 2807; break; case 3: // Left boss.x = -75; boss.y = Math.random() * 2732; break; } boss.targetX = player.x; boss.targetY = player.y; // Calculate boss health based on wave (doubles each boss wave) var bossNumber = Math.floor(currentWave / 10); boss.health = 4000 * Math.pow(2, bossNumber - 1); boss.maxHealth = boss.health; currentBoss = boss; creeps.push(boss); game.addChild(boss); // Show boss health bar bossHealthBar.alpha = 1; tween(bossHealthBar, { scaleX: 1.1, scaleY: 1.1 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(bossHealthBar, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); } function dropPickup(x, y) { if (Math.random() < 0.3) { // 30% chance to drop something var pickupType; var rand = Math.random(); if (rand < 0.15) { // Reduced health upgrade frequency from 30% to 15% pickupType = 'health'; } else if (rand < 0.5) { // Increased shield upgrade frequency from 25% to 35% pickupType = 'shield'; } else if (rand < 0.85) { // Increased damage upgrade frequency from 25% to 35% pickupType = 'damage'; } else { // Speed upgrade remains at 15% pickupType = 'speed'; } var pickup = new Pickup(pickupType); pickup.x = x; pickup.y = y; pickups.push(pickup); game.addChild(pickup); } } function startNextWave() { currentWave++; // Check if this is a boss wave (every 10th wave) if (currentWave % 10 === 0) { bossWave = true; creepsInWave = 0; // No regular creeps on boss waves eliteCreepsInWave = 0; // No elite creeps on boss waves } else { bossWave = false; creepsInWave = 8 + Math.floor(currentWave * 2.5); // More creeps per wave eliteCreepsInWave = currentWave; // Number of elite creeps equals wave number } creepsSpawned = 0; eliteCreepsSpawned = 0; waveCompleted = false; waveText.setText('Wave: ' + currentWave + (bossWave ? ' (BOSS)' : '')); } // Player movement variables var targetX = 1024; var targetY = 1366; var isMoving = false; game.down = function (x, y, obj) { targetX = x; targetY = y; isMoving = true; }; game.move = function (x, y, obj) { if (isMoving) { targetX = x; targetY = y; } }; game.up = function (x, y, obj) { isMoving = false; }; game.update = function () { // Process pickups FIRST to ensure upgrades always activate before any damage for (var i = pickups.length - 1; i >= 0; i--) { var pickup = pickups[i]; // Check pickup collection using both intersection and distance var dx = pickup.x - player.x; var dy = pickup.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); var collected = pickup.intersects(player) || distance < 50; if (collected) { // Immediately activate upgrade effect and calculate points var pickupPoints = 150; // Default points switch (pickup.type) { case 'health': // Check if player is at full health before healing var wasAtFullHealth = player.health >= player.maxHealth; player.heal(25); // Double points if player was at full health when picking up health potion if (wasAtFullHealth) { pickupPoints = 300; } break; case 'shield': player.activateShield(); break; case 'damage': player.addDamage(5); break; case 'speed': player.addSpeed(1); break; } // Give points for collecting upgrades gameScore += pickupPoints; LK.setScore(LK.getScore() + pickupPoints); LK.getSound('pickup').play(); pickup.destroy(); pickups.splice(i, 1); } else if (pickup.lifetime <= 0) { pickup.destroy(); pickups.splice(i, 1); } } // Player movement if (isMoving) { var dx = targetX - player.x; var dy = targetY - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { player.x += dx / distance * player.moveSpeed; player.y += dy / distance * player.moveSpeed; } } // Automatic shooting at closest creep if (creeps.length > 0 && player.canShoot()) { var closestCreep = null; var closestDistance = Infinity; for (var i = 0; i < creeps.length; i++) { var creep = creeps[i]; var dx = creep.x - player.x; var dy = creep.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestDistance = distance; closestCreep = creep; } } if (closestCreep) { var shotBullets = player.shoot(closestCreep.x, closestCreep.y); if (shotBullets) { for (var k = 0; k < shotBullets.length; k++) { bullets.push(shotBullets[k]); game.addChild(shotBullets[k]); } } } } // Update shield system if (shieldActive) { shieldTimer--; player.defense = shieldDefense; // Ensure shield visual is always visible when shield is active if (player.shieldVisual) { player.shieldVisual.alpha = 0.5 + 0.2 * Math.sin(LK.ticks * 0.1); player.shieldVisual.scaleX = 1.0 + 0.1 * Math.sin(LK.ticks * 0.05); player.shieldVisual.scaleY = 1.0 + 0.1 * Math.sin(LK.ticks * 0.05); } if (shieldTimer <= 0) { shieldActive = false; shieldDefense = 0; player.defense = 0; // Hide shield visual if (player.shieldVisual) { tween(player.shieldVisual, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, onFinish: function onFinish() { player.shieldVisual.alpha = 0; } }); } // Visual feedback for shield deactivation tween(player.children[0], { tint: 0xFF4444 }, { duration: 200, onFinish: function onFinish() { tween(player.children[0], { tint: 0xFFFFFF }, { duration: 200 }); } }); } } else { player.defense = 0; // Ensure shield visual is hidden when not active if (player.shieldVisual) { player.shieldVisual.alpha = 0; } } // Update player health display healthText.setText('Health: ' + player.health); if (shieldActive) { var remainingSeconds = Math.ceil(shieldTimer / 60); shieldText.setText('Shield: ' + shieldDefense + ' (' + remainingSeconds + 's)'); } else { shieldText.setText('Shield: Inactive'); } scoreText.setText('Score: ' + gameScore); // Update boss health bar if (currentBoss && bossHealthBar.alpha > 0) { var healthPercent = Math.round(currentBoss.health / currentBoss.maxHealth * 100); bossHealthBar.setText('BOSS: ' + currentBoss.health + '/' + currentBoss.maxHealth + ' (' + healthPercent + '%)'); } // Check game over if (player.health <= 0) { LK.showGameOver(); return; } // Wave management if (!waveCompleted) { if (bossWave) { // Boss wave logic if (!currentBoss && creeps.length === 0) { spawnBoss(); } // Check if boss wave is complete if (currentBoss && creeps.length === 0) { waveCompleted = true; nextWaveTimer = 180; // 3 second break currentBoss = null; // Hide boss health bar tween(bossHealthBar, { alpha: 0 }, { duration: 500 }); } } else { // Regular wave logic // Spawn creeps if (creepsSpawned < creepsInWave || eliteCreepsSpawned < eliteCreepsInWave) { spawnTimer++; if (spawnTimer >= 60) { // Spawn every second if (creepsSpawned < creepsInWave) { spawnCreep(); creepsSpawned++; } else if (eliteCreepsSpawned < eliteCreepsInWave) { spawnEliteCreep(); eliteCreepsSpawned++; } spawnTimer = 0; } } // Check if wave is complete if (creepsSpawned >= creepsInWave && eliteCreepsSpawned >= eliteCreepsInWave && creeps.length === 0) { waveCompleted = true; nextWaveTimer = 180; // 3 second break } } } else { nextWaveTimer--; if (nextWaveTimer <= 0) { startNextWave(); } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // Check if bullet is off screen if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check bullet-creep collisions var hitCreep = false; for (var j = creeps.length - 1; j >= 0; j--) { var creep = creeps[j]; if (bullet.intersects(creep)) { var isDead = creep.takeDamage(bullet.damage); if (isDead) { // Give points for killing creeps var scoreValue; if (creep instanceof BossCreep) { scoreValue = 1000; // High score for boss // Boss always drops multiple pickups for (var p = 0; p < 3; p++) { dropPickup(creep.x + (Math.random() - 0.5) * 100, creep.y + (Math.random() - 0.5) * 100); } } else if (creep instanceof EliteCreep) { scoreValue = 200; } else { scoreValue = 100; } gameScore += scoreValue; LK.setScore(LK.getScore() + scoreValue); if (!(creep instanceof BossCreep)) { dropPickup(creep.x, creep.y); } creep.destroy(); creeps.splice(j, 1); } bullet.destroy(); bullets.splice(i, 1); hitCreep = true; break; } } } // Update creeps for (var i = creeps.length - 1; i >= 0; i--) { var creep = creeps[i]; // Check if creep reached player if (creep.hasReachedPlayer || creep.intersects(player)) { if (!creep.hasReachedPlayer) { player.takeDamage(creep.damage); creep.hasReachedPlayer = true; } creep.destroy(); creeps.splice(i, 1); } } // Pickup processing moved to beginning of update loop };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BossCreep = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('bossCreep', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 4000; // Base health for first boss (10x increase)
self.maxHealth = 4000;
self.speed = 0.8; // Slower than elite creeps
self.damage = 50; // More damage than elite creeps
self.targetX = 0;
self.targetY = 0;
self.hasReachedPlayer = false;
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
return true; // Return true if boss is dead
}
return false;
};
self.update = function () {
if (self.hasReachedPlayer) return;
// Continuously update target to player's current position
self.targetX = player.x;
self.targetY = player.y;
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;
} else {
self.hasReachedPlayer = true;
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.velocityX = 0;
self.velocityY = 0;
self.damage = 20;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var Creep = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('creep', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 60; // Base health requiring 3 hits (20 damage per hit)
self.maxHealth = 60;
self.speed = 2;
self.damage = 15;
self.targetX = 0;
self.targetY = 0;
self.hasReachedPlayer = false;
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
return true; // Return true if creep is dead
}
return false;
};
self.update = function () {
if (self.hasReachedPlayer) return;
// Continuously update target to player's current position
self.targetX = player.x;
self.targetY = player.y;
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;
} else {
self.hasReachedPlayer = true;
}
};
return self;
});
var EliteCreep = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('eliteCreep', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 150; // Much higher base health
self.maxHealth = 150;
self.speed = 1.2; // Slower than regular creeps
self.damage = 35; // More damage than regular creeps
self.targetX = 0;
self.targetY = 0;
self.hasReachedPlayer = false;
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
return true; // Return true if creep is dead
}
return false;
};
self.update = function () {
if (self.hasReachedPlayer) return;
// Continuously update target to player's current position
self.targetX = player.x;
self.targetY = player.y;
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;
} else {
self.hasReachedPlayer = true;
}
};
return self;
});
var Pickup = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
var assetName;
if (type === 'health') {
assetName = 'healthPotion';
} else if (type === 'shield') {
assetName = 'shieldUpgrade';
} else if (type === 'damage') {
assetName = 'damageUpgrade';
} else if (type === 'speed') {
assetName = 'shieldUpgrade'; // Reuse blue upgrade for speed
} else if (type === 'attackSpeed') {
assetName = 'damageUpgrade'; // Reuse red upgrade for attack speed
}
var graphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 600; // 10 seconds at 60fps (doubled from 5 seconds)
self.update = function () {
self.lifetime--;
if (self.lifetime < 120) {
// Start fading at 2 seconds remaining
graphics.alpha = self.lifetime / 120;
}
// Magnetic pull effect when player is close
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Start pulling when within 150 pixels
if (distance < 150 && distance > 10) {
var pullSpeed = 8; // Fast pull speed
var normalizedX = dx / distance;
var normalizedY = dy / distance;
self.x += normalizedX * pullSpeed;
self.y += normalizedY * pullSpeed;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.shieldVisual = null; // Shield aura visual element
self.maxHealth = 100;
self.health = 100;
self.defense = 0;
self.baseDamage = 20; // Base damage that never changes
self.damage = 20; // Current damage (base + upgrades)
self.weaponUpgrades = 0; // Track weapon upgrades for double shot
self.lastShootTime = 0;
self.shootCooldown = 40; // Fixed cooldown that never changes
self.baseSpeed = 4; // Base movement speed
self.moveSpeed = 4; // Current movement speed (base + upgrades)
self.takeDamage = function (amount) {
var actualDamage = Math.max(1, amount - self.defense);
self.health -= actualDamage;
if (self.health < 0) self.health = 0;
// Flash red when taking damage
tween(graphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
LK.getSound('hit').play();
};
self.heal = function (amount) {
self.health = Math.min(self.maxHealth, self.health + amount);
};
self.addDamage = function (amount) {
self.damage += amount;
self.weaponUpgrades++; // Track weapon upgrades
};
self.addSpeed = function (amount) {
self.moveSpeed += amount;
};
self.activateShield = function () {
if (shieldActive) {
// If shield is already active, extend the time by 30 seconds but cap at 180 seconds
shieldTimer = Math.min(10800, shieldTimer + 1800); // Add 30 seconds at 60fps, cap at 180 seconds
} else {
// New shield activation
shieldActive = true;
shieldTimer = 1800; // 30 seconds at 60fps
shieldStacks = 1;
shieldDefense = 10; // Start with 10 defense
}
// Only increase stacks and defense if we haven't hit the cap
if (shieldDefense < 50) {
shieldStacks++;
shieldDefense = Math.min(50, shieldStacks * 10); // Cap at 50 defense
}
// Always ensure shield visual exists and is visible
if (!self.shieldVisual) {
self.shieldVisual = self.addChild(LK.getAsset('shieldAura', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
}));
} else {
// If shield visual exists but is hidden, make it visible
self.shieldVisual.alpha = 0.7;
self.shieldVisual.scaleX = 1.0;
self.shieldVisual.scaleY = 1.0;
}
// Animate shield activation
tween(self.shieldVisual, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.easeInOut
});
// Visual feedback for shield activation
tween(graphics, {
tint: 0x00AAFF
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
};
self.canShoot = function () {
return LK.ticks - self.lastShootTime > self.shootCooldown;
};
self.shoot = function (targetX, targetY) {
if (!self.canShoot()) return null;
self.lastShootTime = LK.ticks;
var bullets = [];
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var normalizedX = dx / distance;
var normalizedY = dy / distance;
var angle = Math.atan2(normalizedY, normalizedX);
if (self.weaponUpgrades >= 30) {
// Quad shot for 30+ upgrades
var spreadAngle = 0.25;
// Center bullet
var bullet1 = new Bullet();
bullet1.x = self.x;
bullet1.y = self.y;
bullet1.velocityX = normalizedX * bullet1.speed;
bullet1.velocityY = normalizedY * bullet1.speed;
bullet1.damage = self.damage;
bullets.push(bullet1);
// Left bullet
var bullet2 = new Bullet();
bullet2.x = self.x;
bullet2.y = self.y;
bullet2.velocityX = Math.cos(angle - spreadAngle) * bullet2.speed;
bullet2.velocityY = Math.sin(angle - spreadAngle) * bullet2.speed;
bullet2.damage = self.damage;
bullets.push(bullet2);
// Right bullet
var bullet3 = new Bullet();
bullet3.x = self.x;
bullet3.y = self.y;
bullet3.velocityX = Math.cos(angle + spreadAngle) * bullet3.speed;
bullet3.velocityY = Math.sin(angle + spreadAngle) * bullet3.speed;
bullet3.damage = self.damage;
bullets.push(bullet3);
// Far left bullet
var bullet4 = new Bullet();
bullet4.x = self.x;
bullet4.y = self.y;
bullet4.velocityX = Math.cos(angle - spreadAngle * 2) * bullet4.speed;
bullet4.velocityY = Math.sin(angle - spreadAngle * 2) * bullet4.speed;
bullet4.damage = self.damage;
bullets.push(bullet4);
} else if (self.weaponUpgrades >= 20) {
// Triple shot V pattern at 20+ upgrades
var spreadAngle = 0.3; // Wider spread for V pattern
// Center bullet
var bullet1 = new Bullet();
bullet1.x = self.x;
bullet1.y = self.y;
bullet1.velocityX = normalizedX * bullet1.speed;
bullet1.velocityY = normalizedY * bullet1.speed;
bullet1.damage = self.damage;
bullets.push(bullet1);
// Left bullet
var bullet2 = new Bullet();
bullet2.x = self.x;
bullet2.y = self.y;
bullet2.velocityX = Math.cos(angle - spreadAngle) * bullet2.speed;
bullet2.velocityY = Math.sin(angle - spreadAngle) * bullet2.speed;
bullet2.damage = self.damage;
bullets.push(bullet2);
// Right bullet
var bullet3 = new Bullet();
bullet3.x = self.x;
bullet3.y = self.y;
bullet3.velocityX = Math.cos(angle + spreadAngle) * bullet3.speed;
bullet3.velocityY = Math.sin(angle + spreadAngle) * bullet3.speed;
bullet3.damage = self.damage;
bullets.push(bullet3);
} else if (self.weaponUpgrades >= 10) {
// Double shot side by side at 10+ upgrades
var offsetDistance = 20; // Distance between bullets
var perpX = -normalizedY; // Perpendicular to direction
var perpY = normalizedX;
// First bullet (left side)
var bullet1 = new Bullet();
bullet1.x = self.x + perpX * offsetDistance;
bullet1.y = self.y + perpY * offsetDistance;
bullet1.velocityX = normalizedX * bullet1.speed;
bullet1.velocityY = normalizedY * bullet1.speed;
bullet1.damage = self.damage;
bullets.push(bullet1);
// Second bullet (right side)
var bullet2 = new Bullet();
bullet2.x = self.x - perpX * offsetDistance;
bullet2.y = self.y - perpY * offsetDistance;
bullet2.velocityX = normalizedX * bullet2.speed;
bullet2.velocityY = normalizedY * bullet2.speed;
bullet2.damage = self.damage;
bullets.push(bullet2);
} else {
// Single shot for upgrades < 10
var bullet1 = new Bullet();
bullet1.x = self.x;
bullet1.y = self.y;
bullet1.velocityX = normalizedX * bullet1.speed;
bullet1.velocityY = normalizedY * bullet1.speed;
bullet1.damage = self.damage;
bullets.push(bullet1);
}
LK.getSound('shoot').play();
return bullets;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game();
/****
* Game Code
****/
// Add background image
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
var player = null;
var creeps = [];
var bullets = [];
var pickups = [];
var currentWave = 1;
var creepsInWave = 5;
var creepsSpawned = 0;
var eliteCreepsInWave = 1; // Number of elite creeps equals wave number
var eliteCreepsSpawned = 0;
var waveCompleted = false;
var nextWaveTimer = 0;
var spawnTimer = 0;
// Score tracking variables
var gameScore = 0;
// Shield system variables
var shieldActive = false;
var shieldTimer = 0;
var shieldDefense = 0;
var shieldStacks = 0;
// Boss system variables
var currentBoss = null;
var bossWave = false;
// UI Elements
var healthText = new Text2('Health: 100', {
size: 40,
fill: 0xFFFFFF
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 120; // Offset from left edge
var waveText = new Text2('Wave: 1', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
var shieldText = new Text2('Shield: Inactive', {
size: 30,
fill: 0xFFFFFF
});
shieldText.anchor.set(0, 0);
LK.gui.topLeft.addChild(shieldText);
shieldText.x = 120;
shieldText.y = 50;
var scoreText = new Text2('Score: 0', {
size: 40,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Boss health bar (initially hidden)
var bossHealthBar = new Text2('', {
size: 35,
fill: 0xFF4444
});
bossHealthBar.anchor.set(0.5, 0);
LK.gui.top.addChild(bossHealthBar);
bossHealthBar.y = 50;
bossHealthBar.alpha = 0; // Hidden initially
// Initialize player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
function spawnCreep() {
var creep = new Creep();
// Spawn from random edge
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
creep.x = Math.random() * 2048;
creep.y = -50;
break;
case 1:
// Right
creep.x = 2098;
creep.y = Math.random() * 2732;
break;
case 2:
// Bottom
creep.x = Math.random() * 2048;
creep.y = 2782;
break;
case 3:
// Left
creep.x = -50;
creep.y = Math.random() * 2732;
break;
}
creep.targetX = player.x;
creep.targetY = player.y;
creep.health += (currentWave - 1) * 20; // Scale health with wave (20 per wave)
creep.maxHealth = creep.health;
creeps.push(creep);
game.addChild(creep);
}
function spawnEliteCreep() {
var eliteCreep = new EliteCreep();
// Spawn from random edge
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
eliteCreep.x = Math.random() * 2048;
eliteCreep.y = -50;
break;
case 1:
// Right
eliteCreep.x = 2098;
eliteCreep.y = Math.random() * 2732;
break;
case 2:
// Bottom
eliteCreep.x = Math.random() * 2048;
eliteCreep.y = 2782;
break;
case 3:
// Left
eliteCreep.x = -50;
eliteCreep.y = Math.random() * 2732;
break;
}
eliteCreep.targetX = player.x;
eliteCreep.targetY = player.y;
eliteCreep.health += (currentWave - 1) * 40; // Scale health with wave (40 per wave for elites)
eliteCreep.maxHealth = eliteCreep.health;
creeps.push(eliteCreep);
game.addChild(eliteCreep);
}
function spawnBoss() {
var boss = new BossCreep();
// Spawn from random edge
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
boss.x = Math.random() * 2048;
boss.y = -75;
break;
case 1:
// Right
boss.x = 2123;
boss.y = Math.random() * 2732;
break;
case 2:
// Bottom
boss.x = Math.random() * 2048;
boss.y = 2807;
break;
case 3:
// Left
boss.x = -75;
boss.y = Math.random() * 2732;
break;
}
boss.targetX = player.x;
boss.targetY = player.y;
// Calculate boss health based on wave (doubles each boss wave)
var bossNumber = Math.floor(currentWave / 10);
boss.health = 4000 * Math.pow(2, bossNumber - 1);
boss.maxHealth = boss.health;
currentBoss = boss;
creeps.push(boss);
game.addChild(boss);
// Show boss health bar
bossHealthBar.alpha = 1;
tween(bossHealthBar, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(bossHealthBar, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
}
function dropPickup(x, y) {
if (Math.random() < 0.3) {
// 30% chance to drop something
var pickupType;
var rand = Math.random();
if (rand < 0.15) {
// Reduced health upgrade frequency from 30% to 15%
pickupType = 'health';
} else if (rand < 0.5) {
// Increased shield upgrade frequency from 25% to 35%
pickupType = 'shield';
} else if (rand < 0.85) {
// Increased damage upgrade frequency from 25% to 35%
pickupType = 'damage';
} else {
// Speed upgrade remains at 15%
pickupType = 'speed';
}
var pickup = new Pickup(pickupType);
pickup.x = x;
pickup.y = y;
pickups.push(pickup);
game.addChild(pickup);
}
}
function startNextWave() {
currentWave++;
// Check if this is a boss wave (every 10th wave)
if (currentWave % 10 === 0) {
bossWave = true;
creepsInWave = 0; // No regular creeps on boss waves
eliteCreepsInWave = 0; // No elite creeps on boss waves
} else {
bossWave = false;
creepsInWave = 8 + Math.floor(currentWave * 2.5); // More creeps per wave
eliteCreepsInWave = currentWave; // Number of elite creeps equals wave number
}
creepsSpawned = 0;
eliteCreepsSpawned = 0;
waveCompleted = false;
waveText.setText('Wave: ' + currentWave + (bossWave ? ' (BOSS)' : ''));
}
// Player movement variables
var targetX = 1024;
var targetY = 1366;
var isMoving = false;
game.down = function (x, y, obj) {
targetX = x;
targetY = y;
isMoving = true;
};
game.move = function (x, y, obj) {
if (isMoving) {
targetX = x;
targetY = y;
}
};
game.up = function (x, y, obj) {
isMoving = false;
};
game.update = function () {
// Process pickups FIRST to ensure upgrades always activate before any damage
for (var i = pickups.length - 1; i >= 0; i--) {
var pickup = pickups[i];
// Check pickup collection using both intersection and distance
var dx = pickup.x - player.x;
var dy = pickup.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var collected = pickup.intersects(player) || distance < 50;
if (collected) {
// Immediately activate upgrade effect and calculate points
var pickupPoints = 150; // Default points
switch (pickup.type) {
case 'health':
// Check if player is at full health before healing
var wasAtFullHealth = player.health >= player.maxHealth;
player.heal(25);
// Double points if player was at full health when picking up health potion
if (wasAtFullHealth) {
pickupPoints = 300;
}
break;
case 'shield':
player.activateShield();
break;
case 'damage':
player.addDamage(5);
break;
case 'speed':
player.addSpeed(1);
break;
}
// Give points for collecting upgrades
gameScore += pickupPoints;
LK.setScore(LK.getScore() + pickupPoints);
LK.getSound('pickup').play();
pickup.destroy();
pickups.splice(i, 1);
} else if (pickup.lifetime <= 0) {
pickup.destroy();
pickups.splice(i, 1);
}
}
// Player movement
if (isMoving) {
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
player.x += dx / distance * player.moveSpeed;
player.y += dy / distance * player.moveSpeed;
}
}
// Automatic shooting at closest creep
if (creeps.length > 0 && player.canShoot()) {
var closestCreep = null;
var closestDistance = Infinity;
for (var i = 0; i < creeps.length; i++) {
var creep = creeps[i];
var dx = creep.x - player.x;
var dy = creep.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestCreep = creep;
}
}
if (closestCreep) {
var shotBullets = player.shoot(closestCreep.x, closestCreep.y);
if (shotBullets) {
for (var k = 0; k < shotBullets.length; k++) {
bullets.push(shotBullets[k]);
game.addChild(shotBullets[k]);
}
}
}
}
// Update shield system
if (shieldActive) {
shieldTimer--;
player.defense = shieldDefense;
// Ensure shield visual is always visible when shield is active
if (player.shieldVisual) {
player.shieldVisual.alpha = 0.5 + 0.2 * Math.sin(LK.ticks * 0.1);
player.shieldVisual.scaleX = 1.0 + 0.1 * Math.sin(LK.ticks * 0.05);
player.shieldVisual.scaleY = 1.0 + 0.1 * Math.sin(LK.ticks * 0.05);
}
if (shieldTimer <= 0) {
shieldActive = false;
shieldDefense = 0;
player.defense = 0;
// Hide shield visual
if (player.shieldVisual) {
tween(player.shieldVisual, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
onFinish: function onFinish() {
player.shieldVisual.alpha = 0;
}
});
}
// Visual feedback for shield deactivation
tween(player.children[0], {
tint: 0xFF4444
}, {
duration: 200,
onFinish: function onFinish() {
tween(player.children[0], {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}
} else {
player.defense = 0;
// Ensure shield visual is hidden when not active
if (player.shieldVisual) {
player.shieldVisual.alpha = 0;
}
}
// Update player health display
healthText.setText('Health: ' + player.health);
if (shieldActive) {
var remainingSeconds = Math.ceil(shieldTimer / 60);
shieldText.setText('Shield: ' + shieldDefense + ' (' + remainingSeconds + 's)');
} else {
shieldText.setText('Shield: Inactive');
}
scoreText.setText('Score: ' + gameScore);
// Update boss health bar
if (currentBoss && bossHealthBar.alpha > 0) {
var healthPercent = Math.round(currentBoss.health / currentBoss.maxHealth * 100);
bossHealthBar.setText('BOSS: ' + currentBoss.health + '/' + currentBoss.maxHealth + ' (' + healthPercent + '%)');
}
// Check game over
if (player.health <= 0) {
LK.showGameOver();
return;
}
// Wave management
if (!waveCompleted) {
if (bossWave) {
// Boss wave logic
if (!currentBoss && creeps.length === 0) {
spawnBoss();
}
// Check if boss wave is complete
if (currentBoss && creeps.length === 0) {
waveCompleted = true;
nextWaveTimer = 180; // 3 second break
currentBoss = null;
// Hide boss health bar
tween(bossHealthBar, {
alpha: 0
}, {
duration: 500
});
}
} else {
// Regular wave logic
// Spawn creeps
if (creepsSpawned < creepsInWave || eliteCreepsSpawned < eliteCreepsInWave) {
spawnTimer++;
if (spawnTimer >= 60) {
// Spawn every second
if (creepsSpawned < creepsInWave) {
spawnCreep();
creepsSpawned++;
} else if (eliteCreepsSpawned < eliteCreepsInWave) {
spawnEliteCreep();
eliteCreepsSpawned++;
}
spawnTimer = 0;
}
}
// Check if wave is complete
if (creepsSpawned >= creepsInWave && eliteCreepsSpawned >= eliteCreepsInWave && creeps.length === 0) {
waveCompleted = true;
nextWaveTimer = 180; // 3 second break
}
}
} else {
nextWaveTimer--;
if (nextWaveTimer <= 0) {
startNextWave();
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet is off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-creep collisions
var hitCreep = false;
for (var j = creeps.length - 1; j >= 0; j--) {
var creep = creeps[j];
if (bullet.intersects(creep)) {
var isDead = creep.takeDamage(bullet.damage);
if (isDead) {
// Give points for killing creeps
var scoreValue;
if (creep instanceof BossCreep) {
scoreValue = 1000; // High score for boss
// Boss always drops multiple pickups
for (var p = 0; p < 3; p++) {
dropPickup(creep.x + (Math.random() - 0.5) * 100, creep.y + (Math.random() - 0.5) * 100);
}
} else if (creep instanceof EliteCreep) {
scoreValue = 200;
} else {
scoreValue = 100;
}
gameScore += scoreValue;
LK.setScore(LK.getScore() + scoreValue);
if (!(creep instanceof BossCreep)) {
dropPickup(creep.x, creep.y);
}
creep.destroy();
creeps.splice(j, 1);
}
bullet.destroy();
bullets.splice(i, 1);
hitCreep = true;
break;
}
}
}
// Update creeps
for (var i = creeps.length - 1; i >= 0; i--) {
var creep = creeps[i];
// Check if creep reached player
if (creep.hasReachedPlayer || creep.intersects(player)) {
if (!creep.hasReachedPlayer) {
player.takeDamage(creep.damage);
creep.hasReachedPlayer = true;
}
creep.destroy();
creeps.splice(i, 1);
}
}
// Pickup processing moved to beginning of update loop
};
An space fighter jet viewed from the top. In-Game asset. 2d. High contrast. No shadows
An large circle of electric energy an circular force field shield. In-Game asset. 2d. High contrast. No shadows
An alien space mine that has spikes. In-Game asset. 2d. High contrast. No shadows
Alien mothership with spikes and glowing patterns and alien eye in middle. In-Game asset. 2d. High contrast. No shadows
an Symbol for an Shield Force shield of electric power. In-Game asset. 2d. High contrast. No shadows
An solid plasma ball of electrical force emanating power filled with reds yellows and green electric power. In-Game asset. 2d. High contrast. No shadows
Symbol for spaceship weapon upgrade with green arrow pointing up. In-Game asset. 2d. High contrast. No shadows
Alien spherical bullet with spikes emanating energy. In-Game asset. 2d. High contrast. No shadows
Symbol for a spaceship armor upgrade using an green arrow pointing up and white coloring. In-Game asset. 2d. High contrast. No shadows
symbol for spaceship speed upgrade increase. In-Game asset. 2d. High contrast. No shadows
Symbol for spaceship health increase with green arrow pointing up and red plus. In-Game asset. 2d. High contrast. No shadows
Symbol for space ship upgrade nova force field around it, with an white spaceship and orange electric circle surrounding it and an green arrow pointing up. In-Game asset. 2d. High contrast. No shadows
Symbol for an play button wide screen. In-Game asset. 2d. High contrast. No shadows
An alien space mine with spikes and red glowing center. In-Game asset. 2d. High contrast. No shadows
explosion in space. In-Game asset. 2d. High contrast. No shadows
Play again button. In-Game asset. 2d. High contrast. No shadows