User prompt
add boss healty bar
User prompt
boss öldüğünde 2 fire rate ve 3 healty item düşürsün, shooter enemy uzaktan ateş etsin
User prompt
boss 1 healty 2800
User prompt
level atladığımda maximum canım %10 artsın, Reduce boss1 health by from 3800 to 3200
User prompt
Reduce boss health by 40% from 8000 to 3800
User prompt
fire rate item %20 daha fazla görünsün, boss 2 yi yeni asset olarak ekle, tank enemy uzak mesafeden ateş etsin
User prompt
add boss 2 for level 15
User prompt
fire range 1000
User prompt
boss health decrease %40
User prompt
boss %20 daha kolay olsun ve düşmanlar ölürken efekt yap ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
boss ile savaşırken çok az düşman gelsin, fire range 1200 olsun ve her fire range item %10 arttırsın
User prompt
increase fire range 900
User prompt
fire range %50 artsın
User prompt
boss %30 daha az agrasif olsun ve %50 daha az hasar versin
User prompt
change background again jungle
User prompt
change background desert
User prompt
boss %30 daha az saldırgan olsun
User prompt
boss level 8 de gelsin ve boss geldiğinde diğer düşmanalr kaybolsun
User prompt
magnet item etkisi 10 saniye daha fazla sürsün, tank enemy level 5 ten sonra gelmeye başlasın
User prompt
fire range item %30 daha sık spawn olsun
User prompt
karakterim hasar yediğinde kızarsın ya da efekt olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
düşmanlar %10 daha az olsun level atlamak %20 daha kolay olsun
User prompt
xp 15 saniye sonra kaybolsun can ve fire rate hariç diğer itemlar biraz daha sık çıksın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
tank enemy comes level 5
User prompt
change backgraund castle,jungle and city every click on game over button
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.damage = 25; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) { self.removeSelf(); } for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (self.intersects(enemy)) { enemy.takeDamage(self.damage); self.removeSelf(); break; } } }; self.removeSelf = function () { var index = bullets.indexOf(self); if (index !== -1) { bullets.splice(index, 1); } self.destroy(); }; return self; }); var EnemyBase = Container.expand(function (assetType, health, speed, damage, xpValue) { var self = Container.call(this); var enemyGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); self.health = health || 20; self.maxHealth = self.health; self.speed = speed || 1; self.damage = damage || 10; self.xpValue = xpValue || 3; self.lastDamageTime = 0; self.baseSpeed = self.speed; self.assetType = assetType; self.healthBar = null; self.needsHealthBar = health > 50; // Big enemies (TankEnemy, ShooterEnemy) get health bars self.update = function () { self.updateMovement(); self.checkPlayerCollision(); if (self.healthBar) { self.healthBar.update(); } }; self.updateMovement = function () { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; self.checkPlayerCollision = function () { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 50 && LK.ticks - self.lastDamageTime > 30) { player.takeDamage(self.damage); self.lastDamageTime = LK.ticks; } }; self.takeDamage = function (damage) { self.health -= damage; // Create health bar if this enemy needs one and doesn't have one yet if (self.needsHealthBar && !self.healthBar) { var barSize = enemyHealthBarSizes[self.assetType] || { width: 40, height: 6 }; self.healthBar = new EnemyHealthBar(self, barSize.width, barSize.height); game.addChild(self.healthBar); } if (self.health <= 0) { self.die(); } }; self.die = function () { // Clean up health bar if it exists if (self.healthBar) { self.healthBar.removeSelf(); self.healthBar = null; } for (var i = 0; i < self.xpValue; i++) { var xpOrb = new XPOrb(); xpOrb.x = self.x + (Math.random() - 0.5) * 50; xpOrb.y = self.y + (Math.random() - 0.5) * 50; xpOrbs.push(xpOrb); game.addChild(xpOrb); } var index = enemies.indexOf(self); if (index !== -1) { enemies.splice(index, 1); } self.destroy(); }; return self; }); var TankEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'tankEnemy', 150, 0.6, 20, 8); // Increased health to 150 (6 hits to kill) return self; }); var SummonerEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'summonerEnemy', 60, 0.5, 10, 4); self.summonTimer = 0; self.summonRate = 180; // 3 seconds self.maxSummons = 3; self.currentSummons = 0; self.shootTimer = 0; self.updateMovement = function () { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Keep far distance from player and shoot if (distance > 400) { if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } else if (distance < 300) { // Move away if too close if (distance > 0) { self.x -= dx / distance * self.speed; self.y -= dy / distance * self.speed; } } else { // In optimal range - shoot at player self.shootTimer++; if (self.shootTimer >= 90) { // Shoot every 1.5 seconds self.shootAtPlayer(); self.shootTimer = 0; } } // Summon minions self.summonTimer++; if (self.summonTimer >= self.summonRate && self.currentSummons < self.maxSummons) { self.summonMinion(); self.summonTimer = 0; } }; self.summonMinion = function () { var minion = new BasicEnemy(); minion.x = self.x + (Math.random() - 0.5) * 100; minion.y = self.y + (Math.random() - 0.5) * 100; minion.summoner = self; // Reference to summoner enemies.push(minion); game.addChild(minion); self.currentSummons++; // Visual summoning effect tween(minion, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 0 }); tween(minion, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 500, easing: tween.bounceOut }); }; self.shootAtPlayer = function () { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { bullet.velocityX = dx / distance * 5; bullet.velocityY = dy / distance * 5; enemyBullets.push(bullet); game.addChild(bullet); } // Visual shooting effect tween(self, { tint: 0xff6600 }, { duration: 200, onFinish: function onFinish() { tween(self, { tint: 0xffffff }, { duration: 200 }); } }); }; self.die = function () { // Clean up health bar if it exists if (self.healthBar) { self.healthBar.removeSelf(); self.healthBar = null; } // Kill all summoned minions for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].summoner === self) { enemies[i].die(); } } for (var i = 0; i < self.xpValue; i++) { var xpOrb = new XPOrb(); xpOrb.x = self.x + (Math.random() - 0.5) * 50; xpOrb.y = self.y + (Math.random() - 0.5) * 50; xpOrbs.push(xpOrb); game.addChild(xpOrb); } var index = enemies.indexOf(self); if (index !== -1) { enemies.splice(index, 1); } self.destroy(); }; return self; }); var StealthEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'enemy', 25, 2, 15, 3); self.stealthTimer = 0; self.stealthDuration = 120; // 2 seconds invisible self.visibleDuration = 180; // 3 seconds visible self.isStealthed = false; self.update = function () { self.updateMovement(); self.checkPlayerCollision(); self.updateStealth(); if (self.healthBar) { self.healthBar.update(); } }; self.updateStealth = function () { self.stealthTimer++; if (self.isStealthed) { if (self.stealthTimer >= self.stealthDuration) { self.becomeVisible(); self.stealthTimer = 0; } } else { if (self.stealthTimer >= self.visibleDuration) { self.becomeStealth(); self.stealthTimer = 0; } } }; self.becomeStealth = function () { self.isStealthed = true; tween(self, { alpha: 0.2 }, { duration: 300 }); // Increase speed while stealthed self.speed = self.baseSpeed * 1.5; }; self.becomeVisible = function () { self.isStealthed = false; tween(self, { alpha: 1 }, { duration: 300 }); // Reset speed self.speed = self.baseSpeed; }; self.takeDamage = function (damage) { // Take less damage while stealthed var actualDamage = self.isStealthed ? damage * 0.5 : damage; self.health -= actualDamage; // Become visible when hit if (self.isStealthed) { self.becomeVisible(); self.stealthTimer = 0; } if (self.needsHealthBar && !self.healthBar) { var barSize = enemyHealthBarSizes[self.assetType] || { width: 40, height: 6 }; self.healthBar = new EnemyHealthBar(self, barSize.width, barSize.height); game.addChild(self.healthBar); } if (self.health <= 0) { self.die(); } }; return self; }); var ShooterEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'shooterEnemy', 75, 0.8, 12, 5); // Increased health to 75 (3 hits to kill) self.shootTimer = 0; self.shootRate = 120; self.updateMovement = function () { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Stop moving when close to player and start shooting if (distance > 200) { if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } else { // Shoot at player self.shootTimer++; if (self.shootTimer >= self.shootRate) { self.shootAtPlayer(); self.shootTimer = 0; } } }; self.shootAtPlayer = function () { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { bullet.velocityX = dx / distance * 6; bullet.velocityY = dy / distance * 6; enemyBullets.push(bullet); game.addChild(bullet); } }; return self; }); var FastEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'fastEnemy', 10, 2.5, 8, 1); return self; }); var ExplodingEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'fastEnemy', 30, 1.5, 25, 2); self.explosionRange = 120; self.hasExploded = false; self.checkPlayerCollision = function () { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.explosionRange && !self.hasExploded) { self.explode(); } else if (distance < 50 && LK.ticks - self.lastDamageTime > 30) { player.takeDamage(self.damage); self.lastDamageTime = LK.ticks; } }; self.explode = function () { self.hasExploded = true; // Visual explosion effect tween(self, { scaleX: 3, scaleY: 3, alpha: 0, tint: 0xff4400 }, { duration: 400, easing: tween.easeOut }); // Damage player if in range var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.explosionRange) { player.takeDamage(self.damage * 2); } // Remove after explosion LK.setTimeout(function () { self.die(); }, 400); }; self.takeDamage = function (damage) { self.health -= damage; if (self.needsHealthBar && !self.healthBar) { var barSize = enemyHealthBarSizes[self.assetType] || { width: 40, height: 6 }; self.healthBar = new EnemyHealthBar(self, barSize.width, barSize.height); game.addChild(self.healthBar); } if (self.health <= 0) { self.explode(); // Explode when killed } }; return self; }); var Boss = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'boss', 10000, 0.8, 50, 50); self.maxHealth = 10000 + Math.floor((player.level - 1) / 10) * 4000; // 20x harder with more scaling self.health = self.maxHealth; self.needsHealthBar = true; self.attackTimer = 0; self.attackPhase = 0; self.isCharging = false; self.chargeTarget = { x: 0, y: 0 }; // Boss entrance animation self.alpha = 0; tween(self, { alpha: 1 }, { duration: 2000, easing: tween.easeOut }); tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.bounceOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 500 }); } }); self.updateMovement = function () { if (self.isCharging) return; // Don't move normally when charging var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Keep distance from player but still move towards them slowly if (distance > 300) { if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } else if (distance < 200) { // Move away if too close if (distance > 0) { self.x -= dx / distance * self.speed * 0.5; self.y -= dy / distance * self.speed * 0.5; } } }; self.update = function () { self.updateMovement(); self.checkPlayerCollision(); self.updateAttacks(); if (self.healthBar) { self.healthBar.update(); } }; self.updateAttacks = function () { self.attackTimer++; // Much more frequent attacks - every 0.75 seconds instead of 3 seconds if (self.attackTimer >= 45) { // 0.75 seconds self.attackPhase = (self.attackPhase + 1) % 3; self.performAttack(); self.attackTimer = 0; } }; self.performAttack = function () { switch (self.attackPhase) { case 0: self.spiralAttack(); break; case 1: self.chargeAttack(); break; case 2: self.burstAttack(); break; } }; self.spiralAttack = function () { // Fire many more bullets in a spiral pattern for (var i = 0; i < 16; i++) { var angle = i / 16 * Math.PI * 2 + LK.ticks * 0.15; var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; bullet.velocityX = Math.cos(angle) * 7; bullet.velocityY = Math.sin(angle) * 7; enemyBullets.push(bullet); game.addChild(bullet); } // Visual effect tween(self, { tint: 0xff4444 }, { duration: 200, onFinish: function onFinish() { tween(self, { tint: 0xffffff }, { duration: 200 }); } }); }; self.chargeAttack = function () { // Charge towards player self.isCharging = true; self.chargeTarget.x = player.x; self.chargeTarget.y = player.y; // Shorter warning time, faster charge tween(self, { tint: 0xff0000, scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { // Perform the charge much faster tween(self, { x: self.chargeTarget.x, y: self.chargeTarget.y }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.isCharging = false; tween(self, { tint: 0xffffff, scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } }); }; self.burstAttack = function () { // Fire many more bullets towards player in multiple bursts for (var i = 0; i < 24; i++) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; bullet.damage = 25; // Increased damage var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var spread = (i - 12) * 0.15; // Tighter spread, more bullets if (distance > 0) { var angle = Math.atan2(dy, dx) + spread; bullet.velocityX = Math.cos(angle) * 8; bullet.velocityY = Math.sin(angle) * 8; enemyBullets.push(bullet); game.addChild(bullet); } } }; self.die = function () { // Boss death animation tween(self, { alpha: 0, scaleX: 2, scaleY: 2, rotation: Math.PI }, { duration: 2000, easing: tween.easeOut, onFinish: function onFinish() { // Clean up health bar if it exists if (self.healthBar) { self.healthBar.removeSelf(); self.healthBar = null; } // Drop lots of XP for (var i = 0; i < self.xpValue; i++) { var xpOrb = new XPOrb(); xpOrb.x = self.x + (Math.random() - 0.5) * 100; xpOrb.y = self.y + (Math.random() - 0.5) * 100; xpOrbs.push(xpOrb); game.addChild(xpOrb); } var index = enemies.indexOf(self); if (index !== -1) { enemies.splice(index, 1); } // End boss fight isBossFight = false; self.destroy(); } }); }; return self; }); var BasicEnemy = EnemyBase.expand(function () { var self = EnemyBase.call(this, 'enemy', 20, 1, 10, 1); return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, tint: 0xff0000 }); self.velocityX = 0; self.velocityY = 0; self.damage = 15; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) { self.removeSelf(); } var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 30) { player.takeDamage(self.damage); self.removeSelf(); } }; self.removeSelf = function () { var index = enemyBullets.indexOf(self); if (index !== -1) { enemyBullets.splice(index, 1); } self.destroy(); }; return self; }); var EnemyHealthBar = Container.expand(function (enemy, barWidth, barHeight) { var self = Container.call(this); self.enemy = enemy; self.barWidth = barWidth || 40; self.barHeight = barHeight || 6; self.background = LK.getAsset('enemy', { width: self.barWidth, height: self.barHeight, anchorX: 0.5, anchorY: 0.5, tint: 0x666666 }); self.foreground = LK.getAsset('healthItem', { width: self.barWidth, height: self.barHeight, anchorX: 0.5, anchorY: 0.5, tint: 0x4CAF50 }); self.addChild(self.background); self.addChild(self.foreground); self.update = function () { // Position above enemy self.x = self.enemy.x; self.y = self.enemy.y - 30; // Update health display var healthPercent = self.enemy.health / self.enemy.maxHealth; self.foreground.width = self.barWidth * healthPercent; // Hide if enemy is at full health self.visible = healthPercent < 1.0; }; self.removeSelf = function () { self.destroy(); }; return self; }); var ExperienceBar = Container.expand(function () { var self = Container.call(this); self.background = LK.getAsset('enemy', { width: 300, height: 15, anchorX: 0, anchorY: 0, tint: 0x333333 }); self.foreground = LK.getAsset('xp', { width: 300, height: 15, anchorX: 0, anchorY: 0, tint: 0x9C27B0 }); self.addChild(self.background); self.addChild(self.foreground); self.updateDisplay = function () { var xpPercent = player.experience / player.experienceToNext; self.foreground.width = 300 * xpPercent; }; return self; }); var FireRangeItem = Container.expand(function () { var self = Container.call(this); var itemGraphics = self.attachAsset('fireRangeItem', { anchorX: 0.5, anchorY: 0.5, tint: 0x00AAFF }); self.lifeTime = 0; self.maxLifeTime = 600; // 10 seconds at 60fps self.update = function () { self.lifeTime++; // Fade out and remove after lifetime expires if (self.lifeTime >= self.maxLifeTime) { tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, onFinish: function onFinish() { self.removeSelf(); } }); return; } // Check for player collection var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 120) { self.applyEffect(); self.removeSelf(); } }; self.applyEffect = function () { // Increase fire range (bullets can target enemies farther away) player.fireRange = Math.min(800, player.fireRange + 100); // Visual effect tween(self, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, easing: tween.easeOut }); LK.getSound('pickup').play(); }; self.removeSelf = function () { var index = fireRangeItems.indexOf(self); if (index !== -1) { fireRangeItems.splice(index, 1); } self.destroy(); }; return self; }); var FireRateItem = Container.expand(function () { var self = Container.call(this); var itemGraphics = self.attachAsset('fireRateItem', { anchorX: 0.5, anchorY: 0.5, tint: 0xFFAA00 }); self.lifeTime = 0; self.maxLifeTime = 600; // 10 seconds at 60fps self.update = function () { self.lifeTime++; // Fade out and remove after lifetime expires if (self.lifeTime >= self.maxLifeTime) { tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, onFinish: function onFinish() { self.removeSelf(); } }); return; } // Check for player collection var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 120) { self.applyEffect(); self.removeSelf(); } }; self.applyEffect = function () { // Increase fire rate (lower fireRate value means faster shooting) player.fireRate = Math.max(5, player.fireRate - 8); // Visual effect tween(self, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, easing: tween.easeOut }); LK.getSound('pickup').play(); }; self.removeSelf = function () { var index = fireRateItems.indexOf(self); if (index !== -1) { fireRateItems.splice(index, 1); } self.destroy(); }; return self; }); var HealthBar = Container.expand(function () { var self = Container.call(this); self.background = LK.getAsset('enemy', { width: 200, height: 20, anchorX: 0, anchorY: 0, tint: 0x333333 }); self.foreground = LK.getAsset('player', { width: 200, height: 20, anchorX: 0, anchorY: 0, tint: 0x4CAF50 }); self.addChild(self.background); self.addChild(self.foreground); self.updateDisplay = function () { var healthPercent = player.health / player.maxHealth; self.foreground.width = 200 * healthPercent; }; return self; }); var HealthItem = Container.expand(function () { var self = Container.call(this); var itemGraphics = self.attachAsset('healthItem', { anchorX: 0.5, anchorY: 0.5 }); self.lifeTime = 0; self.update = function () { self.lifeTime++; if (self.lifeTime > 1800) { self.removeSelf(); } var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 120) { self.applyEffect(); self.removeSelf(); } }; self.applyEffect = function () { player.health = Math.min(player.maxHealth, player.health + 25); healthBar.updateDisplay(); LK.getSound('pickup').play(); }; self.removeSelf = function () { var index = healthItems.indexOf(self); if (index !== -1) { healthItems.splice(index, 1); } self.destroy(); }; return self; }); var MagnetItem = Container.expand(function () { var self = Container.call(this); var itemGraphics = self.attachAsset('magnetItem', { anchorX: 0.5, anchorY: 0.5, tint: 0x9C27B0 }); self.lifeTime = 0; self.maxLifeTime = 600; self.update = function () { self.lifeTime++; if (self.lifeTime >= self.maxLifeTime) { tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, onFinish: function onFinish() { self.removeSelf(); } }); return; } var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 120) { self.applyEffect(); self.removeSelf(); } }; self.applyEffect = function () { player.magnetRange = 200; player.magnetDuration = 600; // 10 seconds tween(self, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, easing: tween.easeOut }); LK.getSound('pickup').play(); }; self.removeSelf = function () { var index = magnetItems.indexOf(self); if (index !== -1) { magnetItems.splice(index, 1); } self.destroy(); }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 60; self.maxHealth = 60; self.speed = 2; self.fireRate = 75; self.fireTimer = 0; self.experience = 0; self.level = 1; self.experienceToNext = 5; self.magnetRange = 0; self.magnetDuration = 0; self.fireRange = 400; // Default fire range self.update = function () { self.fireTimer++; if (self.fireTimer >= self.fireRate) { self.fireAtNearestEnemy(); self.fireTimer = 0; } // Update magnet duration if (self.magnetDuration > 0) { self.magnetDuration--; if (self.magnetDuration <= 0) { self.magnetRange = 0; } } }; self.fireAtNearestEnemy = function () { var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance && distance < self.fireRange) { nearestDistance = distance; nearestEnemy = enemy; } } if (nearestEnemy) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; var dx = nearestEnemy.x - self.x; var dy = nearestEnemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); bullet.velocityX = dx / distance * 8; bullet.velocityY = dy / distance * 8; bullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); } }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.health = 0; LK.showGameOver(); } healthBar.updateDisplay(); }; self.gainExperience = function (amount) { self.experience += amount; experienceBar.updateDisplay(); if (self.experience >= self.experienceToNext) { self.levelUp(); } }; self.levelUp = function () { if (self.level >= 50) { // At max level, just reset experience but don't level up self.experience = 0; experienceBar.updateDisplay(); return; } self.level++; self.experience = 0; self.experienceToNext = Math.floor(self.experienceToNext * 1.5); experienceBar.updateDisplay(); levelText.setText('Level: ' + self.level); // Check for boss fight every 10 levels if (self.level % 10 === 0 && !isBossFight) { spawnBoss(); } else { // Increase enemy speed based on player level (only if not boss fight) for (var i = 0; i < enemies.length; i++) { var levelFactor = 1 + (self.level - 1) * 0.1; enemies[i].speed = enemies[i].baseSpeed * levelFactor; } } LK.getSound('levelUp').play(); showUpgradeOptions(); }; return self; }); var XPOrb = Container.expand(function () { var self = Container.call(this); var xpGraphics = self.attachAsset('xp', { anchorX: 0.5, anchorY: 0.5 }); self.value = 1; self.lifeTime = 0; self.maxLifeTime = 600; // 10 seconds at 60fps self.update = function () { // Increment lifetime self.lifeTime++; // Check if XP orb has expired if (self.lifeTime >= self.maxLifeTime) { // Create fade out effect before removing tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, onFinish: function onFinish() { self.removeSelf(); } }); return; // Don't process movement if fading out } var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // If magnet is active, attract ALL XP orbs regardless of distance // Otherwise use normal collection range var attractionRange = player.magnetRange > 0 ? Infinity : 100; if (distance < attractionRange) { var speed = player.magnetRange > 0 ? 8 : 4; self.x += dx / distance * speed; self.y += dy / distance * speed; } if (distance < 25) { // Create collection effect tween(self, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 200, easing: tween.easeOut }); player.gainExperience(self.value); LK.getSound('pickup').play(); self.removeSelf(); } }; self.removeSelf = function () { var index = xpOrbs.indexOf(self); if (index !== -1) { xpOrbs.splice(index, 1); } self.destroy(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2D5016 }); /**** * Game Code ****/ // Create jungle background with grass and trees for (var i = 0; i < 15; i++) { var tree = LK.getAsset('tankEnemy', { width: 80 + Math.random() * 40, height: 120 + Math.random() * 60, anchorX: 0.5, anchorY: 1, tint: 0x228B22 }); tree.x = Math.random() * 2048; tree.y = Math.random() * 2732; game.addChild(tree); } // Add grass patches for (var i = 0; i < 25; i++) { var grass = LK.getAsset('xp', { width: 60 + Math.random() * 40, height: 20 + Math.random() * 15, anchorX: 0.5, anchorY: 0.5, tint: 0x32CD32 }); grass.x = Math.random() * 2048; grass.y = Math.random() * 2732; game.addChild(grass); } // Add some bushes for (var i = 0; i < 10; i++) { var bush = LK.getAsset('enemy', { width: 40 + Math.random() * 30, height: 30 + Math.random() * 20, anchorX: 0.5, anchorY: 0.5, tint: 0x006400 }); bush.x = Math.random() * 2048; bush.y = Math.random() * 2732; game.addChild(bush); } var player; var enemies = []; var enemyHealthBarSizes = { 'enemy': { width: 40, height: 6 }, // BasicEnemy 'fastEnemy': { width: 30, height: 5 }, // FastEnemy 'shooterEnemy': { width: 35, height: 6 }, // ShooterEnemy 'summonerEnemy': { width: 40, height: 7 }, // SummonerEnemy 'tankEnemy': { width: 60, height: 8 } // TankEnemy (big) }; var bullets = []; var enemyBullets = []; var xpOrbs = []; var healthItems = []; var magnetItems = []; var fireRateItems = []; var fireRangeItems = []; var enemySpawnTimer = 0; var itemSpawnTimer = 0; var waveLevel = 1; var upgradePanel = null; var healthBar; var experienceBar; var levelText; var hordeSpawnTimer = 0; var isBossFight = false; var currentBoss = null; var backgroundThemes = { jungle: { backgroundColor: 0x2D5016, name: 'Jungle' }, castle: { backgroundColor: 0x696969, name: 'Castle' }, city: { backgroundColor: 0x1E1E1E, name: 'City' } }; var themeOrder = ['jungle', 'castle', 'city']; var currentThemeIndex = 0; // Initialize player player = game.addChild(new Player()); player.x = 1024; player.y = 1366; // Initialize UI healthBar = new HealthBar(); healthBar.x = 50; healthBar.y = 50; LK.gui.topLeft.addChild(healthBar); experienceBar = new ExperienceBar(); experienceBar.x = 50; experienceBar.y = 80; LK.gui.topLeft.addChild(experienceBar); levelText = new Text2('Level: 1', { size: 40, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); levelText.x = 50; levelText.y = 110; LK.gui.topLeft.addChild(levelText); // Movement variables var dragNode = null; function showUpgradeOptions() { if (upgradePanel) return; upgradePanel = LK.getAsset('enemy', { width: 800, height: 600, anchorX: 0.5, anchorY: 0.5, tint: 0x333333 }); upgradePanel.x = 1024; upgradePanel.y = 1366; LK.gui.center.addChild(upgradePanel); var upgrades = [{ name: 'Extra Health', effect: function effect() { player.maxHealth += 25; player.health += 25; healthBar.updateDisplay(); } }, { name: 'Faster Fire', effect: function effect() { player.fireRate = Math.max(10, player.fireRate - 5); } }, { name: 'XP Magnet', effect: function effect() { player.magnetRange = 200; player.magnetDuration = 600; } }, { name: 'Bigger Bullets', effect: function effect() {/* Visual upgrade */} }, { name: 'More Damage', effect: function effect() {/* Would need bullet damage tracking */} }]; var selectedUpgrades = []; for (var i = 0; i < 3; i++) { var randomIndex = Math.floor(Math.random() * upgrades.length); selectedUpgrades.push(upgrades[randomIndex]); } for (var i = 0; i < 3; i++) { var button = LK.getAsset('player', { width: 200, height: 80, anchorX: 0.5, anchorY: 0.5, tint: 0x4CAF50 }); button.x = -250 + i * 250; button.y = 0; button.upgradeIndex = i; button.upgrade = selectedUpgrades[i]; button.down = function (x, y, obj) { obj.upgrade.effect(); hideUpgradeOptions(); }; upgradePanel.addChild(button); var buttonText = new Text2(selectedUpgrades[i].name, { size: 24, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.x = button.x; buttonText.y = button.y; upgradePanel.addChild(buttonText); } } function hideUpgradeOptions() { if (upgradePanel) { upgradePanel.destroy(); upgradePanel = null; } } function spawnEnemy() { var enemy; var levelFactor = 1 + (player.level - 1) * 0.1; // Choose enemy type based on player level - different enemies every 5 levels var rand = Math.random(); if (player.level < 3) { enemy = new BasicEnemy(); } else if (player.level < 5) { if (rand < 0.8) enemy = new BasicEnemy();else enemy = new SummonerEnemy(); } else if (player.level < 10) { if (rand < 0.5) enemy = new BasicEnemy();else if (rand < 0.75) enemy = new FastEnemy();else if (rand < 0.9) enemy = new ExplodingEnemy();else enemy = new SummonerEnemy(); } else if (player.level < 15) { if (rand < 0.25) enemy = new BasicEnemy();else if (rand < 0.4) enemy = new FastEnemy();else if (rand < 0.6) enemy = new ExplodingEnemy();else if (rand < 0.75) enemy = new ShooterEnemy();else if (rand < 0.9) enemy = new StealthEnemy();else enemy = new SummonerEnemy(); } else { if (rand < 0.1) enemy = new BasicEnemy();else if (rand < 0.25) enemy = new FastEnemy();else if (rand < 0.4) enemy = new ExplodingEnemy();else if (rand < 0.55) enemy = new TankEnemy();else if (rand < 0.7) enemy = new ShooterEnemy();else if (rand < 0.85) enemy = new StealthEnemy();else enemy = new SummonerEnemy(); } // Scale enemy stats with player level - reduced speed scaling enemy.speed = enemy.baseSpeed * (levelFactor * 1.2); enemy.health = Math.floor(enemy.maxHealth * levelFactor); enemy.maxHealth = enemy.health; var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top enemy.x = Math.random() * 2048; enemy.y = -50; break; case 1: // Right enemy.x = 2098; enemy.y = Math.random() * 2732; break; case 2: // Bottom enemy.x = Math.random() * 2048; enemy.y = 2782; break; case 3: // Left enemy.x = -50; enemy.y = Math.random() * 2732; break; } enemies.push(enemy); game.addChild(enemy); } function spawnHorde() { var hordeSize = Math.min(25, 5 + Math.floor(player.level / 2)); // Hordes grow much faster and larger var rand = Math.random(); var enemyType; if (player.level < 10) { enemyType = rand < 0.7 ? BasicEnemy : FastEnemy; } else if (player.level < 20) { if (rand < 0.4) enemyType = BasicEnemy;else if (rand < 0.7) enemyType = FastEnemy;else enemyType = ExplodingEnemy; } else { if (rand < 0.3) enemyType = BasicEnemy;else if (rand < 0.5) enemyType = FastEnemy;else if (rand < 0.7) enemyType = ExplodingEnemy;else enemyType = StealthEnemy; } for (var i = 0; i < hordeSize; i++) { var enemy = new enemyType(); var levelFactor = 1 + (player.level - 1) * 0.1; enemy.speed = enemy.baseSpeed * (levelFactor * 1.2); enemy.health = Math.floor(enemy.maxHealth * levelFactor); enemy.maxHealth = enemy.health; // Spawn all enemies from the same side var side = Math.floor(Math.random() * 4); var offset = i * 80; switch (side) { case 0: enemy.x = (Math.random() * 1000 + 500 + offset) % 2048; enemy.y = -50; break; case 1: enemy.x = 2098; enemy.y = (Math.random() * 1000 + 500 + offset) % 2732; break; case 2: enemy.x = (Math.random() * 1000 + 500 + offset) % 2048; enemy.y = 2782; break; case 3: enemy.x = -50; enemy.y = (Math.random() * 1000 + 500 + offset) % 2732; break; } enemies.push(enemy); game.addChild(enemy); } } function spawnBoss() { // Clear all existing enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); enemies.splice(i, 1); } // Clear all enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { enemyBullets[i].destroy(); enemyBullets.splice(i, 1); } isBossFight = true; currentBoss = new Boss(); currentBoss.x = 1024; // Center X currentBoss.y = 400; // Top area enemies.push(currentBoss); game.addChild(currentBoss); } function spawnHealthItem() { var item = new HealthItem(); item.x = Math.random() * 1800 + 100; item.y = Math.random() * 2400 + 100; healthItems.push(item); game.addChild(item); } function spawnMagnetItem() { var item = new MagnetItem(); item.x = Math.random() * 1800 + 100; item.y = Math.random() * 2400 + 100; magnetItems.push(item); game.addChild(item); } function spawnFireRateItem() { var item = new FireRateItem(); item.x = Math.random() * 1800 + 100; item.y = Math.random() * 2400 + 100; fireRateItems.push(item); game.addChild(item); } function spawnFireRangeItem() { var item = new FireRangeItem(); item.x = Math.random() * 1800 + 100; item.y = Math.random() * 2400 + 100; fireRangeItems.push(item); game.addChild(item); } game.move = function (x, y, obj) { if (dragNode) { // Calculate target position with bounds checking var targetX = Math.max(30, Math.min(2018, x)); var targetY = Math.max(30, Math.min(2702, y)); // Move character slower towards target position using interpolation var moveSpeed = 0.1; // Lower value = slower movement (0.1 = 10% of distance per frame) var dx = targetX - dragNode.x; var dy = targetY - dragNode.y; dragNode.x += dx * moveSpeed; dragNode.y += dy * moveSpeed; } }; game.down = function (x, y, obj) { dragNode = player; }; game.up = function (x, y, obj) { dragNode = null; }; // Override the game restart functionality to change background var originalShowGameOver = LK.showGameOver; LK.showGameOver = function () { // Change to next theme when game over is shown currentThemeIndex = (currentThemeIndex + 1) % themeOrder.length; var newTheme = backgroundThemes[themeOrder[currentThemeIndex]]; game.setBackgroundColor(newTheme.backgroundColor); // Call original game over function originalShowGameOver(); }; game.update = function () { // Spawn enemies continuously (even during boss fights but at reduced rate) enemySpawnTimer++; var baseSpawnRate = Math.max(30, 180 - waveLevel * 10); var levelSpawnBonus = Math.floor(player.level / 4); var spawnRate = Math.max(15, baseSpawnRate - levelSpawnBonus * 5); // Reduce spawn rate during boss fights but don't stop completely if (isBossFight) { spawnRate = spawnRate * 2; // Spawn enemies at half rate during boss fights } if (enemySpawnTimer >= spawnRate) { // Enemies multiply significantly as player levels up var spawnCount = 1; // Base spawn count increases with level var baseMultiplier = Math.floor(player.level / 5) + 1; // +1 enemy every 5 levels spawnCount = baseMultiplier; // Additional spawns with high probability at higher levels if (!isBossFight && player.level > 5) spawnCount += Math.random() < 0.8 ? 1 : 0; if (!isBossFight && player.level > 10) spawnCount += Math.random() < 0.7 ? 2 : 0; if (!isBossFight && player.level > 15) spawnCount += Math.random() < 0.6 ? 3 : 0; if (!isBossFight && player.level > 20) spawnCount += Math.random() < 0.5 ? 4 : 0; if (!isBossFight && player.level > 25) spawnCount += Math.random() < 0.4 ? 5 : 0; // Cap maximum spawn count to prevent performance issues spawnCount = Math.min(spawnCount, 15); for (var s = 0; s < spawnCount; s++) { spawnEnemy(); } enemySpawnTimer = 0; } // Spawn hordes periodically when player gets stronger (not during boss fights) if (!isBossFight) { hordeSpawnTimer++; var hordeRate = Math.max(800, 2400 - player.level * 20); if (hordeSpawnTimer >= hordeRate && player.level >= 3) { spawnHorde(); hordeSpawnTimer = 0; } } // Spawn health items (less frequently) itemSpawnTimer++; if (itemSpawnTimer >= 900) { spawnHealthItem(); itemSpawnTimer = 0; } // Spawn magnet items (more frequently) if (LK.ticks % 800 === 0 && Math.random() < 0.7) { spawnMagnetItem(); } // Spawn fire rate items (much less frequently) if (LK.ticks % 1500 === 0 && Math.random() < 0.3) { // Every 25 seconds with 30% chance spawnFireRateItem(); } // Spawn fire range items (much less frequently) if (LK.ticks % 1800 === 0 && Math.random() < 0.25) { // Every 30 seconds with 25% chance spawnFireRangeItem(); } // Increase difficulty over time if (LK.ticks % 1800 === 0) { waveLevel++; } // Update all game objects for (var i = enemies.length - 1; i >= 0; i--) { // Continuously increase enemy speed based on current player level var currentLevelFactor = 1 + (player.level - 1) * 0.08; // Reduced scaling enemies[i].speed = enemies[i].baseSpeed * currentLevelFactor; enemies[i].update(); } for (var i = bullets.length - 1; i >= 0; i--) { bullets[i].update(); } for (var i = enemyBullets.length - 1; i >= 0; i--) { enemyBullets[i].update(); } for (var i = xpOrbs.length - 1; i >= 0; i--) { xpOrbs[i].update(); } for (var i = healthItems.length - 1; i >= 0; i--) { healthItems[i].update(); } for (var i = magnetItems.length - 1; i >= 0; i--) { magnetItems[i].update(); } for (var i = fireRateItems.length - 1; i >= 0; i--) { fireRateItems[i].update(); } for (var i = fireRangeItems.length - 1; i >= 0; i--) { fireRangeItems[i].update(); } player.update(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.damage = 25;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
self.removeSelf();
}
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (self.intersects(enemy)) {
enemy.takeDamage(self.damage);
self.removeSelf();
break;
}
}
};
self.removeSelf = function () {
var index = bullets.indexOf(self);
if (index !== -1) {
bullets.splice(index, 1);
}
self.destroy();
};
return self;
});
var EnemyBase = Container.expand(function (assetType, health, speed, damage, xpValue) {
var self = Container.call(this);
var enemyGraphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
self.health = health || 20;
self.maxHealth = self.health;
self.speed = speed || 1;
self.damage = damage || 10;
self.xpValue = xpValue || 3;
self.lastDamageTime = 0;
self.baseSpeed = self.speed;
self.assetType = assetType;
self.healthBar = null;
self.needsHealthBar = health > 50; // Big enemies (TankEnemy, ShooterEnemy) get health bars
self.update = function () {
self.updateMovement();
self.checkPlayerCollision();
if (self.healthBar) {
self.healthBar.update();
}
};
self.updateMovement = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.checkPlayerCollision = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 50 && LK.ticks - self.lastDamageTime > 30) {
player.takeDamage(self.damage);
self.lastDamageTime = LK.ticks;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
// Create health bar if this enemy needs one and doesn't have one yet
if (self.needsHealthBar && !self.healthBar) {
var barSize = enemyHealthBarSizes[self.assetType] || {
width: 40,
height: 6
};
self.healthBar = new EnemyHealthBar(self, barSize.width, barSize.height);
game.addChild(self.healthBar);
}
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Clean up health bar if it exists
if (self.healthBar) {
self.healthBar.removeSelf();
self.healthBar = null;
}
for (var i = 0; i < self.xpValue; i++) {
var xpOrb = new XPOrb();
xpOrb.x = self.x + (Math.random() - 0.5) * 50;
xpOrb.y = self.y + (Math.random() - 0.5) * 50;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
}
var index = enemies.indexOf(self);
if (index !== -1) {
enemies.splice(index, 1);
}
self.destroy();
};
return self;
});
var TankEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'tankEnemy', 150, 0.6, 20, 8);
// Increased health to 150 (6 hits to kill)
return self;
});
var SummonerEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'summonerEnemy', 60, 0.5, 10, 4);
self.summonTimer = 0;
self.summonRate = 180; // 3 seconds
self.maxSummons = 3;
self.currentSummons = 0;
self.shootTimer = 0;
self.updateMovement = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Keep far distance from player and shoot
if (distance > 400) {
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
} else if (distance < 300) {
// Move away if too close
if (distance > 0) {
self.x -= dx / distance * self.speed;
self.y -= dy / distance * self.speed;
}
} else {
// In optimal range - shoot at player
self.shootTimer++;
if (self.shootTimer >= 90) {
// Shoot every 1.5 seconds
self.shootAtPlayer();
self.shootTimer = 0;
}
}
// Summon minions
self.summonTimer++;
if (self.summonTimer >= self.summonRate && self.currentSummons < self.maxSummons) {
self.summonMinion();
self.summonTimer = 0;
}
};
self.summonMinion = function () {
var minion = new BasicEnemy();
minion.x = self.x + (Math.random() - 0.5) * 100;
minion.y = self.y + (Math.random() - 0.5) * 100;
minion.summoner = self; // Reference to summoner
enemies.push(minion);
game.addChild(minion);
self.currentSummons++;
// Visual summoning effect
tween(minion, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 0
});
tween(minion, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 500,
easing: tween.bounceOut
});
};
self.shootAtPlayer = function () {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 5;
bullet.velocityY = dy / distance * 5;
enemyBullets.push(bullet);
game.addChild(bullet);
}
// Visual shooting effect
tween(self, {
tint: 0xff6600
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 200
});
}
});
};
self.die = function () {
// Clean up health bar if it exists
if (self.healthBar) {
self.healthBar.removeSelf();
self.healthBar = null;
}
// Kill all summoned minions
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].summoner === self) {
enemies[i].die();
}
}
for (var i = 0; i < self.xpValue; i++) {
var xpOrb = new XPOrb();
xpOrb.x = self.x + (Math.random() - 0.5) * 50;
xpOrb.y = self.y + (Math.random() - 0.5) * 50;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
}
var index = enemies.indexOf(self);
if (index !== -1) {
enemies.splice(index, 1);
}
self.destroy();
};
return self;
});
var StealthEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'enemy', 25, 2, 15, 3);
self.stealthTimer = 0;
self.stealthDuration = 120; // 2 seconds invisible
self.visibleDuration = 180; // 3 seconds visible
self.isStealthed = false;
self.update = function () {
self.updateMovement();
self.checkPlayerCollision();
self.updateStealth();
if (self.healthBar) {
self.healthBar.update();
}
};
self.updateStealth = function () {
self.stealthTimer++;
if (self.isStealthed) {
if (self.stealthTimer >= self.stealthDuration) {
self.becomeVisible();
self.stealthTimer = 0;
}
} else {
if (self.stealthTimer >= self.visibleDuration) {
self.becomeStealth();
self.stealthTimer = 0;
}
}
};
self.becomeStealth = function () {
self.isStealthed = true;
tween(self, {
alpha: 0.2
}, {
duration: 300
});
// Increase speed while stealthed
self.speed = self.baseSpeed * 1.5;
};
self.becomeVisible = function () {
self.isStealthed = false;
tween(self, {
alpha: 1
}, {
duration: 300
});
// Reset speed
self.speed = self.baseSpeed;
};
self.takeDamage = function (damage) {
// Take less damage while stealthed
var actualDamage = self.isStealthed ? damage * 0.5 : damage;
self.health -= actualDamage;
// Become visible when hit
if (self.isStealthed) {
self.becomeVisible();
self.stealthTimer = 0;
}
if (self.needsHealthBar && !self.healthBar) {
var barSize = enemyHealthBarSizes[self.assetType] || {
width: 40,
height: 6
};
self.healthBar = new EnemyHealthBar(self, barSize.width, barSize.height);
game.addChild(self.healthBar);
}
if (self.health <= 0) {
self.die();
}
};
return self;
});
var ShooterEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'shooterEnemy', 75, 0.8, 12, 5);
// Increased health to 75 (3 hits to kill)
self.shootTimer = 0;
self.shootRate = 120;
self.updateMovement = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Stop moving when close to player and start shooting
if (distance > 200) {
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
} else {
// Shoot at player
self.shootTimer++;
if (self.shootTimer >= self.shootRate) {
self.shootAtPlayer();
self.shootTimer = 0;
}
}
};
self.shootAtPlayer = function () {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 6;
bullet.velocityY = dy / distance * 6;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
var FastEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'fastEnemy', 10, 2.5, 8, 1);
return self;
});
var ExplodingEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'fastEnemy', 30, 1.5, 25, 2);
self.explosionRange = 120;
self.hasExploded = false;
self.checkPlayerCollision = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.explosionRange && !self.hasExploded) {
self.explode();
} else if (distance < 50 && LK.ticks - self.lastDamageTime > 30) {
player.takeDamage(self.damage);
self.lastDamageTime = LK.ticks;
}
};
self.explode = function () {
self.hasExploded = true;
// Visual explosion effect
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0,
tint: 0xff4400
}, {
duration: 400,
easing: tween.easeOut
});
// Damage player if in range
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.explosionRange) {
player.takeDamage(self.damage * 2);
}
// Remove after explosion
LK.setTimeout(function () {
self.die();
}, 400);
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.needsHealthBar && !self.healthBar) {
var barSize = enemyHealthBarSizes[self.assetType] || {
width: 40,
height: 6
};
self.healthBar = new EnemyHealthBar(self, barSize.width, barSize.height);
game.addChild(self.healthBar);
}
if (self.health <= 0) {
self.explode(); // Explode when killed
}
};
return self;
});
var Boss = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'boss', 10000, 0.8, 50, 50);
self.maxHealth = 10000 + Math.floor((player.level - 1) / 10) * 4000; // 20x harder with more scaling
self.health = self.maxHealth;
self.needsHealthBar = true;
self.attackTimer = 0;
self.attackPhase = 0;
self.isCharging = false;
self.chargeTarget = {
x: 0,
y: 0
};
// Boss entrance animation
self.alpha = 0;
tween(self, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeOut
});
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500
});
}
});
self.updateMovement = function () {
if (self.isCharging) return; // Don't move normally when charging
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Keep distance from player but still move towards them slowly
if (distance > 300) {
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
} else if (distance < 200) {
// Move away if too close
if (distance > 0) {
self.x -= dx / distance * self.speed * 0.5;
self.y -= dy / distance * self.speed * 0.5;
}
}
};
self.update = function () {
self.updateMovement();
self.checkPlayerCollision();
self.updateAttacks();
if (self.healthBar) {
self.healthBar.update();
}
};
self.updateAttacks = function () {
self.attackTimer++;
// Much more frequent attacks - every 0.75 seconds instead of 3 seconds
if (self.attackTimer >= 45) {
// 0.75 seconds
self.attackPhase = (self.attackPhase + 1) % 3;
self.performAttack();
self.attackTimer = 0;
}
};
self.performAttack = function () {
switch (self.attackPhase) {
case 0:
self.spiralAttack();
break;
case 1:
self.chargeAttack();
break;
case 2:
self.burstAttack();
break;
}
};
self.spiralAttack = function () {
// Fire many more bullets in a spiral pattern
for (var i = 0; i < 16; i++) {
var angle = i / 16 * Math.PI * 2 + LK.ticks * 0.15;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.velocityX = Math.cos(angle) * 7;
bullet.velocityY = Math.sin(angle) * 7;
enemyBullets.push(bullet);
game.addChild(bullet);
}
// Visual effect
tween(self, {
tint: 0xff4444
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 200
});
}
});
};
self.chargeAttack = function () {
// Charge towards player
self.isCharging = true;
self.chargeTarget.x = player.x;
self.chargeTarget.y = player.y;
// Shorter warning time, faster charge
tween(self, {
tint: 0xff0000,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
// Perform the charge much faster
tween(self, {
x: self.chargeTarget.x,
y: self.chargeTarget.y
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isCharging = false;
tween(self, {
tint: 0xffffff,
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
});
};
self.burstAttack = function () {
// Fire many more bullets towards player in multiple bursts
for (var i = 0; i < 24; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.damage = 25; // Increased damage
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var spread = (i - 12) * 0.15; // Tighter spread, more bullets
if (distance > 0) {
var angle = Math.atan2(dy, dx) + spread;
bullet.velocityX = Math.cos(angle) * 8;
bullet.velocityY = Math.sin(angle) * 8;
enemyBullets.push(bullet);
game.addChild(bullet);
}
}
};
self.die = function () {
// Boss death animation
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2,
rotation: Math.PI
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Clean up health bar if it exists
if (self.healthBar) {
self.healthBar.removeSelf();
self.healthBar = null;
}
// Drop lots of XP
for (var i = 0; i < self.xpValue; i++) {
var xpOrb = new XPOrb();
xpOrb.x = self.x + (Math.random() - 0.5) * 100;
xpOrb.y = self.y + (Math.random() - 0.5) * 100;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
}
var index = enemies.indexOf(self);
if (index !== -1) {
enemies.splice(index, 1);
}
// End boss fight
isBossFight = false;
self.destroy();
}
});
};
return self;
});
var BasicEnemy = EnemyBase.expand(function () {
var self = EnemyBase.call(this, 'enemy', 20, 1, 10, 1);
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xff0000
});
self.velocityX = 0;
self.velocityY = 0;
self.damage = 15;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
self.removeSelf();
}
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
player.takeDamage(self.damage);
self.removeSelf();
}
};
self.removeSelf = function () {
var index = enemyBullets.indexOf(self);
if (index !== -1) {
enemyBullets.splice(index, 1);
}
self.destroy();
};
return self;
});
var EnemyHealthBar = Container.expand(function (enemy, barWidth, barHeight) {
var self = Container.call(this);
self.enemy = enemy;
self.barWidth = barWidth || 40;
self.barHeight = barHeight || 6;
self.background = LK.getAsset('enemy', {
width: self.barWidth,
height: self.barHeight,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x666666
});
self.foreground = LK.getAsset('healthItem', {
width: self.barWidth,
height: self.barHeight,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4CAF50
});
self.addChild(self.background);
self.addChild(self.foreground);
self.update = function () {
// Position above enemy
self.x = self.enemy.x;
self.y = self.enemy.y - 30;
// Update health display
var healthPercent = self.enemy.health / self.enemy.maxHealth;
self.foreground.width = self.barWidth * healthPercent;
// Hide if enemy is at full health
self.visible = healthPercent < 1.0;
};
self.removeSelf = function () {
self.destroy();
};
return self;
});
var ExperienceBar = Container.expand(function () {
var self = Container.call(this);
self.background = LK.getAsset('enemy', {
width: 300,
height: 15,
anchorX: 0,
anchorY: 0,
tint: 0x333333
});
self.foreground = LK.getAsset('xp', {
width: 300,
height: 15,
anchorX: 0,
anchorY: 0,
tint: 0x9C27B0
});
self.addChild(self.background);
self.addChild(self.foreground);
self.updateDisplay = function () {
var xpPercent = player.experience / player.experienceToNext;
self.foreground.width = 300 * xpPercent;
};
return self;
});
var FireRangeItem = Container.expand(function () {
var self = Container.call(this);
var itemGraphics = self.attachAsset('fireRangeItem', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x00AAFF
});
self.lifeTime = 0;
self.maxLifeTime = 600; // 10 seconds at 60fps
self.update = function () {
self.lifeTime++;
// Fade out and remove after lifetime expires
if (self.lifeTime >= self.maxLifeTime) {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
onFinish: function onFinish() {
self.removeSelf();
}
});
return;
}
// Check for player collection
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 120) {
self.applyEffect();
self.removeSelf();
}
};
self.applyEffect = function () {
// Increase fire range (bullets can target enemies farther away)
player.fireRange = Math.min(800, player.fireRange + 100);
// Visual effect
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
LK.getSound('pickup').play();
};
self.removeSelf = function () {
var index = fireRangeItems.indexOf(self);
if (index !== -1) {
fireRangeItems.splice(index, 1);
}
self.destroy();
};
return self;
});
var FireRateItem = Container.expand(function () {
var self = Container.call(this);
var itemGraphics = self.attachAsset('fireRateItem', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFAA00
});
self.lifeTime = 0;
self.maxLifeTime = 600; // 10 seconds at 60fps
self.update = function () {
self.lifeTime++;
// Fade out and remove after lifetime expires
if (self.lifeTime >= self.maxLifeTime) {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
onFinish: function onFinish() {
self.removeSelf();
}
});
return;
}
// Check for player collection
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 120) {
self.applyEffect();
self.removeSelf();
}
};
self.applyEffect = function () {
// Increase fire rate (lower fireRate value means faster shooting)
player.fireRate = Math.max(5, player.fireRate - 8);
// Visual effect
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
LK.getSound('pickup').play();
};
self.removeSelf = function () {
var index = fireRateItems.indexOf(self);
if (index !== -1) {
fireRateItems.splice(index, 1);
}
self.destroy();
};
return self;
});
var HealthBar = Container.expand(function () {
var self = Container.call(this);
self.background = LK.getAsset('enemy', {
width: 200,
height: 20,
anchorX: 0,
anchorY: 0,
tint: 0x333333
});
self.foreground = LK.getAsset('player', {
width: 200,
height: 20,
anchorX: 0,
anchorY: 0,
tint: 0x4CAF50
});
self.addChild(self.background);
self.addChild(self.foreground);
self.updateDisplay = function () {
var healthPercent = player.health / player.maxHealth;
self.foreground.width = 200 * healthPercent;
};
return self;
});
var HealthItem = Container.expand(function () {
var self = Container.call(this);
var itemGraphics = self.attachAsset('healthItem', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifeTime = 0;
self.update = function () {
self.lifeTime++;
if (self.lifeTime > 1800) {
self.removeSelf();
}
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 120) {
self.applyEffect();
self.removeSelf();
}
};
self.applyEffect = function () {
player.health = Math.min(player.maxHealth, player.health + 25);
healthBar.updateDisplay();
LK.getSound('pickup').play();
};
self.removeSelf = function () {
var index = healthItems.indexOf(self);
if (index !== -1) {
healthItems.splice(index, 1);
}
self.destroy();
};
return self;
});
var MagnetItem = Container.expand(function () {
var self = Container.call(this);
var itemGraphics = self.attachAsset('magnetItem', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x9C27B0
});
self.lifeTime = 0;
self.maxLifeTime = 600;
self.update = function () {
self.lifeTime++;
if (self.lifeTime >= self.maxLifeTime) {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
onFinish: function onFinish() {
self.removeSelf();
}
});
return;
}
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 120) {
self.applyEffect();
self.removeSelf();
}
};
self.applyEffect = function () {
player.magnetRange = 200;
player.magnetDuration = 600; // 10 seconds
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
LK.getSound('pickup').play();
};
self.removeSelf = function () {
var index = magnetItems.indexOf(self);
if (index !== -1) {
magnetItems.splice(index, 1);
}
self.destroy();
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 60;
self.maxHealth = 60;
self.speed = 2;
self.fireRate = 75;
self.fireTimer = 0;
self.experience = 0;
self.level = 1;
self.experienceToNext = 5;
self.magnetRange = 0;
self.magnetDuration = 0;
self.fireRange = 400; // Default fire range
self.update = function () {
self.fireTimer++;
if (self.fireTimer >= self.fireRate) {
self.fireAtNearestEnemy();
self.fireTimer = 0;
}
// Update magnet duration
if (self.magnetDuration > 0) {
self.magnetDuration--;
if (self.magnetDuration <= 0) {
self.magnetRange = 0;
}
}
};
self.fireAtNearestEnemy = function () {
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance && distance < self.fireRange) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
if (nearestEnemy) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = nearestEnemy.x - self.x;
var dy = nearestEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.velocityX = dx / distance * 8;
bullet.velocityY = dy / distance * 8;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
healthBar.updateDisplay();
};
self.gainExperience = function (amount) {
self.experience += amount;
experienceBar.updateDisplay();
if (self.experience >= self.experienceToNext) {
self.levelUp();
}
};
self.levelUp = function () {
if (self.level >= 50) {
// At max level, just reset experience but don't level up
self.experience = 0;
experienceBar.updateDisplay();
return;
}
self.level++;
self.experience = 0;
self.experienceToNext = Math.floor(self.experienceToNext * 1.5);
experienceBar.updateDisplay();
levelText.setText('Level: ' + self.level);
// Check for boss fight every 10 levels
if (self.level % 10 === 0 && !isBossFight) {
spawnBoss();
} else {
// Increase enemy speed based on player level (only if not boss fight)
for (var i = 0; i < enemies.length; i++) {
var levelFactor = 1 + (self.level - 1) * 0.1;
enemies[i].speed = enemies[i].baseSpeed * levelFactor;
}
}
LK.getSound('levelUp').play();
showUpgradeOptions();
};
return self;
});
var XPOrb = Container.expand(function () {
var self = Container.call(this);
var xpGraphics = self.attachAsset('xp', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 1;
self.lifeTime = 0;
self.maxLifeTime = 600; // 10 seconds at 60fps
self.update = function () {
// Increment lifetime
self.lifeTime++;
// Check if XP orb has expired
if (self.lifeTime >= self.maxLifeTime) {
// Create fade out effect before removing
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
onFinish: function onFinish() {
self.removeSelf();
}
});
return; // Don't process movement if fading out
}
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If magnet is active, attract ALL XP orbs regardless of distance
// Otherwise use normal collection range
var attractionRange = player.magnetRange > 0 ? Infinity : 100;
if (distance < attractionRange) {
var speed = player.magnetRange > 0 ? 8 : 4;
self.x += dx / distance * speed;
self.y += dy / distance * speed;
}
if (distance < 25) {
// Create collection effect
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200,
easing: tween.easeOut
});
player.gainExperience(self.value);
LK.getSound('pickup').play();
self.removeSelf();
}
};
self.removeSelf = function () {
var index = xpOrbs.indexOf(self);
if (index !== -1) {
xpOrbs.splice(index, 1);
}
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2D5016
});
/****
* Game Code
****/
// Create jungle background with grass and trees
for (var i = 0; i < 15; i++) {
var tree = LK.getAsset('tankEnemy', {
width: 80 + Math.random() * 40,
height: 120 + Math.random() * 60,
anchorX: 0.5,
anchorY: 1,
tint: 0x228B22
});
tree.x = Math.random() * 2048;
tree.y = Math.random() * 2732;
game.addChild(tree);
}
// Add grass patches
for (var i = 0; i < 25; i++) {
var grass = LK.getAsset('xp', {
width: 60 + Math.random() * 40,
height: 20 + Math.random() * 15,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x32CD32
});
grass.x = Math.random() * 2048;
grass.y = Math.random() * 2732;
game.addChild(grass);
}
// Add some bushes
for (var i = 0; i < 10; i++) {
var bush = LK.getAsset('enemy', {
width: 40 + Math.random() * 30,
height: 30 + Math.random() * 20,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x006400
});
bush.x = Math.random() * 2048;
bush.y = Math.random() * 2732;
game.addChild(bush);
}
var player;
var enemies = [];
var enemyHealthBarSizes = {
'enemy': {
width: 40,
height: 6
},
// BasicEnemy
'fastEnemy': {
width: 30,
height: 5
},
// FastEnemy
'shooterEnemy': {
width: 35,
height: 6
},
// ShooterEnemy
'summonerEnemy': {
width: 40,
height: 7
},
// SummonerEnemy
'tankEnemy': {
width: 60,
height: 8
} // TankEnemy (big)
};
var bullets = [];
var enemyBullets = [];
var xpOrbs = [];
var healthItems = [];
var magnetItems = [];
var fireRateItems = [];
var fireRangeItems = [];
var enemySpawnTimer = 0;
var itemSpawnTimer = 0;
var waveLevel = 1;
var upgradePanel = null;
var healthBar;
var experienceBar;
var levelText;
var hordeSpawnTimer = 0;
var isBossFight = false;
var currentBoss = null;
var backgroundThemes = {
jungle: {
backgroundColor: 0x2D5016,
name: 'Jungle'
},
castle: {
backgroundColor: 0x696969,
name: 'Castle'
},
city: {
backgroundColor: 0x1E1E1E,
name: 'City'
}
};
var themeOrder = ['jungle', 'castle', 'city'];
var currentThemeIndex = 0;
// Initialize player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Initialize UI
healthBar = new HealthBar();
healthBar.x = 50;
healthBar.y = 50;
LK.gui.topLeft.addChild(healthBar);
experienceBar = new ExperienceBar();
experienceBar.x = 50;
experienceBar.y = 80;
LK.gui.topLeft.addChild(experienceBar);
levelText = new Text2('Level: 1', {
size: 40,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 50;
levelText.y = 110;
LK.gui.topLeft.addChild(levelText);
// Movement variables
var dragNode = null;
function showUpgradeOptions() {
if (upgradePanel) return;
upgradePanel = LK.getAsset('enemy', {
width: 800,
height: 600,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
upgradePanel.x = 1024;
upgradePanel.y = 1366;
LK.gui.center.addChild(upgradePanel);
var upgrades = [{
name: 'Extra Health',
effect: function effect() {
player.maxHealth += 25;
player.health += 25;
healthBar.updateDisplay();
}
}, {
name: 'Faster Fire',
effect: function effect() {
player.fireRate = Math.max(10, player.fireRate - 5);
}
}, {
name: 'XP Magnet',
effect: function effect() {
player.magnetRange = 200;
player.magnetDuration = 600;
}
}, {
name: 'Bigger Bullets',
effect: function effect() {/* Visual upgrade */}
}, {
name: 'More Damage',
effect: function effect() {/* Would need bullet damage tracking */}
}];
var selectedUpgrades = [];
for (var i = 0; i < 3; i++) {
var randomIndex = Math.floor(Math.random() * upgrades.length);
selectedUpgrades.push(upgrades[randomIndex]);
}
for (var i = 0; i < 3; i++) {
var button = LK.getAsset('player', {
width: 200,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4CAF50
});
button.x = -250 + i * 250;
button.y = 0;
button.upgradeIndex = i;
button.upgrade = selectedUpgrades[i];
button.down = function (x, y, obj) {
obj.upgrade.effect();
hideUpgradeOptions();
};
upgradePanel.addChild(button);
var buttonText = new Text2(selectedUpgrades[i].name, {
size: 24,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = button.x;
buttonText.y = button.y;
upgradePanel.addChild(buttonText);
}
}
function hideUpgradeOptions() {
if (upgradePanel) {
upgradePanel.destroy();
upgradePanel = null;
}
}
function spawnEnemy() {
var enemy;
var levelFactor = 1 + (player.level - 1) * 0.1;
// Choose enemy type based on player level - different enemies every 5 levels
var rand = Math.random();
if (player.level < 3) {
enemy = new BasicEnemy();
} else if (player.level < 5) {
if (rand < 0.8) enemy = new BasicEnemy();else enemy = new SummonerEnemy();
} else if (player.level < 10) {
if (rand < 0.5) enemy = new BasicEnemy();else if (rand < 0.75) enemy = new FastEnemy();else if (rand < 0.9) enemy = new ExplodingEnemy();else enemy = new SummonerEnemy();
} else if (player.level < 15) {
if (rand < 0.25) enemy = new BasicEnemy();else if (rand < 0.4) enemy = new FastEnemy();else if (rand < 0.6) enemy = new ExplodingEnemy();else if (rand < 0.75) enemy = new ShooterEnemy();else if (rand < 0.9) enemy = new StealthEnemy();else enemy = new SummonerEnemy();
} else {
if (rand < 0.1) enemy = new BasicEnemy();else if (rand < 0.25) enemy = new FastEnemy();else if (rand < 0.4) enemy = new ExplodingEnemy();else if (rand < 0.55) enemy = new TankEnemy();else if (rand < 0.7) enemy = new ShooterEnemy();else if (rand < 0.85) enemy = new StealthEnemy();else enemy = new SummonerEnemy();
}
// Scale enemy stats with player level - reduced speed scaling
enemy.speed = enemy.baseSpeed * (levelFactor * 1.2);
enemy.health = Math.floor(enemy.maxHealth * levelFactor);
enemy.maxHealth = enemy.health;
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 2098;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2782;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 2732;
break;
}
enemies.push(enemy);
game.addChild(enemy);
}
function spawnHorde() {
var hordeSize = Math.min(25, 5 + Math.floor(player.level / 2)); // Hordes grow much faster and larger
var rand = Math.random();
var enemyType;
if (player.level < 10) {
enemyType = rand < 0.7 ? BasicEnemy : FastEnemy;
} else if (player.level < 20) {
if (rand < 0.4) enemyType = BasicEnemy;else if (rand < 0.7) enemyType = FastEnemy;else enemyType = ExplodingEnemy;
} else {
if (rand < 0.3) enemyType = BasicEnemy;else if (rand < 0.5) enemyType = FastEnemy;else if (rand < 0.7) enemyType = ExplodingEnemy;else enemyType = StealthEnemy;
}
for (var i = 0; i < hordeSize; i++) {
var enemy = new enemyType();
var levelFactor = 1 + (player.level - 1) * 0.1;
enemy.speed = enemy.baseSpeed * (levelFactor * 1.2);
enemy.health = Math.floor(enemy.maxHealth * levelFactor);
enemy.maxHealth = enemy.health;
// Spawn all enemies from the same side
var side = Math.floor(Math.random() * 4);
var offset = i * 80;
switch (side) {
case 0:
enemy.x = (Math.random() * 1000 + 500 + offset) % 2048;
enemy.y = -50;
break;
case 1:
enemy.x = 2098;
enemy.y = (Math.random() * 1000 + 500 + offset) % 2732;
break;
case 2:
enemy.x = (Math.random() * 1000 + 500 + offset) % 2048;
enemy.y = 2782;
break;
case 3:
enemy.x = -50;
enemy.y = (Math.random() * 1000 + 500 + offset) % 2732;
break;
}
enemies.push(enemy);
game.addChild(enemy);
}
}
function spawnBoss() {
// Clear all existing enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
enemies.splice(i, 1);
}
// Clear all enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].destroy();
enemyBullets.splice(i, 1);
}
isBossFight = true;
currentBoss = new Boss();
currentBoss.x = 1024; // Center X
currentBoss.y = 400; // Top area
enemies.push(currentBoss);
game.addChild(currentBoss);
}
function spawnHealthItem() {
var item = new HealthItem();
item.x = Math.random() * 1800 + 100;
item.y = Math.random() * 2400 + 100;
healthItems.push(item);
game.addChild(item);
}
function spawnMagnetItem() {
var item = new MagnetItem();
item.x = Math.random() * 1800 + 100;
item.y = Math.random() * 2400 + 100;
magnetItems.push(item);
game.addChild(item);
}
function spawnFireRateItem() {
var item = new FireRateItem();
item.x = Math.random() * 1800 + 100;
item.y = Math.random() * 2400 + 100;
fireRateItems.push(item);
game.addChild(item);
}
function spawnFireRangeItem() {
var item = new FireRangeItem();
item.x = Math.random() * 1800 + 100;
item.y = Math.random() * 2400 + 100;
fireRangeItems.push(item);
game.addChild(item);
}
game.move = function (x, y, obj) {
if (dragNode) {
// Calculate target position with bounds checking
var targetX = Math.max(30, Math.min(2018, x));
var targetY = Math.max(30, Math.min(2702, y));
// Move character slower towards target position using interpolation
var moveSpeed = 0.1; // Lower value = slower movement (0.1 = 10% of distance per frame)
var dx = targetX - dragNode.x;
var dy = targetY - dragNode.y;
dragNode.x += dx * moveSpeed;
dragNode.y += dy * moveSpeed;
}
};
game.down = function (x, y, obj) {
dragNode = player;
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Override the game restart functionality to change background
var originalShowGameOver = LK.showGameOver;
LK.showGameOver = function () {
// Change to next theme when game over is shown
currentThemeIndex = (currentThemeIndex + 1) % themeOrder.length;
var newTheme = backgroundThemes[themeOrder[currentThemeIndex]];
game.setBackgroundColor(newTheme.backgroundColor);
// Call original game over function
originalShowGameOver();
};
game.update = function () {
// Spawn enemies continuously (even during boss fights but at reduced rate)
enemySpawnTimer++;
var baseSpawnRate = Math.max(30, 180 - waveLevel * 10);
var levelSpawnBonus = Math.floor(player.level / 4);
var spawnRate = Math.max(15, baseSpawnRate - levelSpawnBonus * 5);
// Reduce spawn rate during boss fights but don't stop completely
if (isBossFight) {
spawnRate = spawnRate * 2; // Spawn enemies at half rate during boss fights
}
if (enemySpawnTimer >= spawnRate) {
// Enemies multiply significantly as player levels up
var spawnCount = 1;
// Base spawn count increases with level
var baseMultiplier = Math.floor(player.level / 5) + 1; // +1 enemy every 5 levels
spawnCount = baseMultiplier;
// Additional spawns with high probability at higher levels
if (!isBossFight && player.level > 5) spawnCount += Math.random() < 0.8 ? 1 : 0;
if (!isBossFight && player.level > 10) spawnCount += Math.random() < 0.7 ? 2 : 0;
if (!isBossFight && player.level > 15) spawnCount += Math.random() < 0.6 ? 3 : 0;
if (!isBossFight && player.level > 20) spawnCount += Math.random() < 0.5 ? 4 : 0;
if (!isBossFight && player.level > 25) spawnCount += Math.random() < 0.4 ? 5 : 0;
// Cap maximum spawn count to prevent performance issues
spawnCount = Math.min(spawnCount, 15);
for (var s = 0; s < spawnCount; s++) {
spawnEnemy();
}
enemySpawnTimer = 0;
}
// Spawn hordes periodically when player gets stronger (not during boss fights)
if (!isBossFight) {
hordeSpawnTimer++;
var hordeRate = Math.max(800, 2400 - player.level * 20);
if (hordeSpawnTimer >= hordeRate && player.level >= 3) {
spawnHorde();
hordeSpawnTimer = 0;
}
}
// Spawn health items (less frequently)
itemSpawnTimer++;
if (itemSpawnTimer >= 900) {
spawnHealthItem();
itemSpawnTimer = 0;
}
// Spawn magnet items (more frequently)
if (LK.ticks % 800 === 0 && Math.random() < 0.7) {
spawnMagnetItem();
}
// Spawn fire rate items (much less frequently)
if (LK.ticks % 1500 === 0 && Math.random() < 0.3) {
// Every 25 seconds with 30% chance
spawnFireRateItem();
}
// Spawn fire range items (much less frequently)
if (LK.ticks % 1800 === 0 && Math.random() < 0.25) {
// Every 30 seconds with 25% chance
spawnFireRangeItem();
}
// Increase difficulty over time
if (LK.ticks % 1800 === 0) {
waveLevel++;
}
// Update all game objects
for (var i = enemies.length - 1; i >= 0; i--) {
// Continuously increase enemy speed based on current player level
var currentLevelFactor = 1 + (player.level - 1) * 0.08; // Reduced scaling
enemies[i].speed = enemies[i].baseSpeed * currentLevelFactor;
enemies[i].update();
}
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].update();
}
for (var i = enemyBullets.length - 1; i >= 0; i--) {
enemyBullets[i].update();
}
for (var i = xpOrbs.length - 1; i >= 0; i--) {
xpOrbs[i].update();
}
for (var i = healthItems.length - 1; i >= 0; i--) {
healthItems[i].update();
}
for (var i = magnetItems.length - 1; i >= 0; i--) {
magnetItems[i].update();
}
for (var i = fireRateItems.length - 1; i >= 0; i--) {
fireRateItems[i].update();
}
for (var i = fireRangeItems.length - 1; i >= 0; i--) {
fireRangeItems[i].update();
}
player.update();
};
yuvarlak mermi. In-Game asset. 2d. High contrast. No shadows
boss creature. In-Game asset. 2d. High contrast. No shadows
Tank enemy big creature. In-Game asset. 2d. High contrast. No shadows
XP point only round, no writing on and around it
creature enemy. In-Game asset. 2d. High contrast. No shadows
shooter enemy. In-Game asset. 2d. High contrast. No shadows
healty. In-Game asset. 2d. High contrast. No shadows
fire rate. In-Game asset. 2d. High contrast. No shadows
magnet. In-Game asset. 2d. High contrast. No shadows
hedef tahtası. In-Game asset. 2d. High contrast. No shadows
Give pistol
submachine gun. In-Game asset. 2d. High contrast. No shadows
Stronge. In-Game asset. 2d. High contrast. No shadows