User prompt
special item drop little more fast
User prompt
sometime runner drop bomb it chance is 0.0019 and solider drop shield it chance is 0.00025 and tank drop missile it chance is 0.000045
User prompt
towers are picked up and after when you relies it their tower placed and when i picked towers they show their range to fire
User prompt
game starts with 350 money
User prompt
solider range is more little short
User prompt
cannon range is little big and solider range is little short
User prompt
cannon range is little big
User prompt
after two boss killed some solider have shield
User prompt
wings are behind the runner
User prompt
wings are more visible ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
runners wings color is white ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
runners wings are small big ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
runner look like round with two wings and two eye
User prompt
runner look like round
User prompt
solider and boss look like smile face
User prompt
dont show arrow
User prompt
show where towers are fire with small arrow on place towers ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when i selected towers it shows their fire range ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
boss Reward is 200
User prompt
boss Reward is 200
User prompt
runner Reward is 5 and Tank Reward is 15 and solider Reward is 10 and boss Reward is 180
User prompt
sniper can regenerate his hp in 3.75 second and cannon regenerate his hp in 2.75 and ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
laser can regenerate his hp in 2 second and cannon can regenerate his hp in 3 second and sniper can regenerate his hp in 5 second ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
laser can regenerate his hp in 0.75 second and cannon can regenerate his hp in 1.25 second and sniper can regenerate his hp in 1.90 second ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
boss can fire missile and damage towers and when it kill it blast and damage towers ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function (startX, startY, target, damage) {
var self = Container.call(this);
self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = startX;
self.y = startY;
self.target = target;
self.damage = damage;
self.speed = 8;
self.update = function () {
if (!self.target || self.target.destroyed) {
self.removeBullet();
return;
}
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.target.takeDamage(self.damage);
self.removeBullet();
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.removeBullet = function () {
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] === self) {
bullets.splice(i, 1);
break;
}
}
self.destroy();
};
return self;
});
var Enemy = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.pathIndex = 0;
self.x = path[0].x;
self.y = path[0].y;
self.lastPathIndex = 0;
if (type === 'soldier') {
self.attachAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5
});
var soldierEyeLeft = self.attachAsset('soldierEyeLeft', {
anchorX: 0.5,
anchorY: 0.5,
x: -12,
y: -8
});
var soldierEyeRight = self.attachAsset('soldierEyeRight', {
anchorX: 0.5,
anchorY: 0.5,
x: 12,
y: -8
});
var soldierMouth = self.attachAsset('soldierMouth', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 8
});
self.health = 100;
self.maxHealth = 100;
self.speed = 2.5;
self.reward = 10;
// Add shield for soldiers after 2 bosses killed
self.hasShield = false;
self.shieldGraphics = null;
if (bossKillCount >= 2 && Math.random() < 0.6) {
// 60% chance for shield after 2 bosses
self.hasShield = true;
self.shieldGraphics = self.attachAsset('soldierShield', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
alpha: 0.8
});
self.health = 150; // Increased health with shield
self.maxHealth = 150;
}
} else if (type === 'tank') {
self.attachAsset('tank', {
anchorX: 0.5,
anchorY: 0.5
});
var tankNozzle = self.attachAsset('tankNozzle', {
anchorX: 0,
anchorY: 0.5,
x: 40,
y: 0
});
self.health = 250;
self.maxHealth = 250;
self.speed = 2;
self.reward = 15;
} else if (type === 'runner') {
var runnerWingLeft = self.attachAsset('runnerWingLeft', {
anchorX: 0.5,
anchorY: 0.5,
x: -28,
y: 0,
rotation: 0
});
var runnerWingRight = self.attachAsset('runnerWingRight', {
anchorX: 0.5,
anchorY: 0.5,
x: 28,
y: 0,
rotation: 0
});
self.attachAsset('runner', {
anchorX: 0.5,
anchorY: 0.5
});
// Add wing flapping animation to make wings more visible
self.wingFlapTimer = 0;
tween(runnerWingLeft, {
rotation: -0.3
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(runnerWingLeft, {
rotation: 0.3
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(runnerWingLeft, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
});
tween(runnerWingRight, {
rotation: 0.3
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(runnerWingRight, {
rotation: -0.3
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(runnerWingRight, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
});
var runnerEyeLeft = self.attachAsset('runnerEyeLeft', {
anchorX: 0.5,
anchorY: 0.5,
x: -8,
y: -6
});
var runnerEyeRight = self.attachAsset('runnerEyeRight', {
anchorX: 0.5,
anchorY: 0.5,
x: 8,
y: -6
});
self.health = 50;
self.maxHealth = 50;
self.speed = 4;
self.reward = 5;
} else if (type === 'boss') {
self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
var bossEyeLeft = self.attachAsset('bossEyeLeft', {
anchorX: 0.5,
anchorY: 0.5,
x: -18,
y: -12
});
var bossEyeRight = self.attachAsset('bossEyeRight', {
anchorX: 0.5,
anchorY: 0.5,
x: 18,
y: -12
});
var bossMouth = self.attachAsset('bossMouth', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 12
});
var bossHealth = 500 + bossKillCount * 200;
self.health = bossHealth;
self.maxHealth = bossHealth;
self.speed = 1;
self.reward = 200;
}
// Create HP display text for enemy
self.hpText = new Text2(self.health + ' HP', {
size: 20,
fill: '#ff0000'
});
self.hpText.anchor.set(0.5, 0.5);
self.hpText.x = 0;
self.hpText.y = -40;
self.addChild(self.hpText);
// Add attack cooldown and special abilities
self.attackCooldown = 0;
self.specialAbilityCooldown = 0;
self.update = function () {
self.move();
// Update HP display
self.hpText.setText(self.health + ' HP');
// Reduce cooldowns
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.specialAbilityCooldown > 0) {
self.specialAbilityCooldown--;
}
// Special abilities for different enemy types
if (self.type === 'soldier' && self.specialAbilityCooldown <= 0) {
self.throwBomb();
self.specialAbilityCooldown = 180; // 3 seconds
} else if (self.type === 'tank' && self.attackCooldown <= 0) {
self.fireTower();
self.attackCooldown = 120; // 2 seconds
} else if (self.type === 'boss' && self.attackCooldown <= 0) {
self.fireMissile();
self.attackCooldown = 90; // 1.5 seconds
}
// Continuous wing flapping for runners to make wings more visible
if (self.type === 'runner') {
self.wingFlapTimer++;
if (self.wingFlapTimer >= 90) {
// Every 1.5 seconds
var wingLeft = self.children[0]; // runnerWingLeft
var wingRight = self.children[1]; // runnerWingRight
tween(wingLeft, {
rotation: -0.4
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(wingLeft, {
rotation: 0.4
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(wingLeft, {
rotation: 0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
});
tween(wingRight, {
rotation: 0.4
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(wingRight, {
rotation: -0.4
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(wingRight, {
rotation: 0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
});
self.wingFlapTimer = 0;
}
}
};
self.move = function () {
if (self.pathIndex >= path.length - 1) {
self.reachedEnd();
return;
}
// Check for tower collisions and damage them
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < 50) {
// Collision distance
var damage = 0;
if (self.type === 'runner') {
damage = 20;
} else if (self.type === 'soldier') {
damage = 35;
} else if (self.type === 'tank') {
damage = 45;
} else if (self.type === 'boss') {
damage = 70;
}
tower.hp -= damage;
if (tower.hp <= 0) {
// Remove tower from game
for (var j = towers.length - 1; j >= 0; j--) {
if (towers[j] === tower) {
towers.splice(j, 1);
break;
}
}
tower.destroy();
}
// Enemy dies after attacking tower
self.die();
return;
}
}
var targetPoint = path[self.pathIndex + 1];
var dx = targetPoint.x - self.x;
var dy = targetPoint.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 5) {
self.pathIndex++;
self.lastPathIndex = self.pathIndex;
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (damage) {
// Shield absorbs damage for soldiers
if (self.type === 'soldier' && self.hasShield && self.shieldGraphics) {
// Shield absorbs 50% of damage
var actualDamage = Math.ceil(damage * 0.5);
self.health -= actualDamage;
// Flash shield when taking damage
tween(self.shieldGraphics, {
tint: 0xff0000
}, {
duration: 150,
onFinish: function onFinish() {
tween(self.shieldGraphics, {
tint: 0xffffff
}, {
duration: 150
});
}
});
// Remove shield when health gets low
if (self.health <= 50 && self.shieldGraphics) {
// Shield breaks animation
tween(self.shieldGraphics, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
if (self.shieldGraphics) {
self.shieldGraphics.destroy();
self.shieldGraphics = null;
}
self.hasShield = false;
}
});
}
} else {
self.health -= damage;
}
if (self.health <= 0) {
self.die();
}
};
self.blastTowers = function (blastRadius, blastDamage) {
// Create visual blast effect
var blastEffect = LK.getAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.8
});
blastEffect.x = self.x;
blastEffect.y = self.y;
blastEffect.tint = 0xff4444;
game.addChild(blastEffect);
// Animate blast expanding
tween(blastEffect, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
blastEffect.destroy();
}
});
// Damage towers within blast radius
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance <= blastRadius) {
tower.hp -= blastDamage;
// Flash tower red to show damage
tween(tower, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(tower, {
tint: 0xffffff
}, {
duration: 200
});
}
});
if (tower.hp <= 0) {
// Remove tower from game
for (var j = towers.length - 1; j >= 0; j--) {
if (towers[j] === tower) {
towers.splice(j, 1);
break;
}
}
tower.destroy();
}
}
}
};
self.die = function () {
if (self.type === 'boss') {
bossKillCount++;
}
// Special death effects for different enemy types
if (self.type === 'runner') {
// Runner blasts with smaller radius and damage
self.blastTowers(120, 15);
} else if (self.type === 'soldier') {
// Soldier blasts with larger radius and damage
self.blastTowers(150, 25);
} else if (self.type === 'boss') {
// Boss blasts with massive radius and damage
self.blastTowers(200, 60);
}
money += self.reward;
moneyText.setText('Money: ' + money);
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
LK.getSound('enemyHit').play();
};
self.throwBomb = function () {
if (self.type !== 'soldier') return;
// Find nearest tower to throw bomb at
var nearestTower = null;
var nearestDistance = Infinity;
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < nearestDistance && distance <= 300) {
// 300 pixel throw range
nearestTower = tower;
nearestDistance = distance;
}
}
if (nearestTower) {
// Create bomb projectile
var bomb = LK.getAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
bomb.x = self.x;
bomb.y = self.y;
bomb.tint = 0x000000;
game.addChild(bomb);
// Animate bomb flying to tower
tween(bomb, {
x: nearestTower.x,
y: nearestTower.y
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Explode at tower location
var blastEffect = LK.getAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.8
});
blastEffect.x = bomb.x;
blastEffect.y = bomb.y;
blastEffect.tint = 0xff8800;
game.addChild(blastEffect);
// Animate explosion
tween(blastEffect, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
blastEffect.destroy();
}
});
// Damage towers in blast radius
for (var j = 0; j < towers.length; j++) {
var tower = towers[j];
var distance = Math.sqrt(Math.pow(tower.x - bomb.x, 2) + Math.pow(tower.y - bomb.y, 2));
if (distance <= 100) {
// Bomb blast radius
tower.hp -= 30;
// Flash tower red
tween(tower, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(tower, {
tint: 0xffffff
}, {
duration: 200
});
}
});
if (tower.hp <= 0) {
// Remove tower from game
for (var k = towers.length - 1; k >= 0; k--) {
if (towers[k] === tower) {
towers.splice(k, 1);
break;
}
}
tower.destroy();
}
}
}
bomb.destroy();
}
});
}
};
self.fireTower = function () {
if (self.type !== 'tank') return;
// Find nearest tower to fire at
var nearestTower = null;
var nearestDistance = Infinity;
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < nearestDistance && distance <= 400) {
// 400 pixel firing range
nearestTower = tower;
nearestDistance = distance;
}
}
if (nearestTower) {
// Create tank projectile
var tankBullet = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
tankBullet.x = self.x;
tankBullet.y = self.y;
tankBullet.tint = 0x8b572a;
game.addChild(tankBullet);
// Animate bullet flying to tower
tween(tankBullet, {
x: nearestTower.x,
y: nearestTower.y
}, {
duration: 600,
easing: tween.linear,
onFinish: function onFinish() {
// Damage the tower
nearestTower.hp -= 40;
// Flash tower red
tween(nearestTower, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(nearestTower, {
tint: 0xffffff
}, {
duration: 200
});
}
});
if (nearestTower.hp <= 0) {
// Remove tower from game
for (var j = towers.length - 1; j >= 0; j--) {
if (towers[j] === nearestTower) {
towers.splice(j, 1);
break;
}
}
nearestTower.destroy();
}
tankBullet.destroy();
}
});
}
};
self.fireMissile = function () {
if (self.type !== 'boss') return;
// Find nearest tower to fire missile at
var nearestTower = null;
var nearestDistance = Infinity;
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var distance = Math.sqrt(Math.pow(tower.x - self.x, 2) + Math.pow(tower.y - self.y, 2));
if (distance < nearestDistance && distance <= 500) {
// 500 pixel missile range
nearestTower = tower;
nearestDistance = distance;
}
}
if (nearestTower) {
// Create boss missile
var missile = LK.getAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4
});
missile.x = self.x;
missile.y = self.y;
missile.tint = 0xff0000;
game.addChild(missile);
// Animate missile flying to tower
tween(missile, {
x: nearestTower.x,
y: nearestTower.y
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create explosion effect
var explosionEffect = LK.getAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
alpha: 0.9
});
explosionEffect.x = missile.x;
explosionEffect.y = missile.y;
explosionEffect.tint = 0xffaa00;
game.addChild(explosionEffect);
// Animate explosion
tween(explosionEffect, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
explosionEffect.destroy();
}
});
// Damage towers in missile blast radius
for (var j = 0; j < towers.length; j++) {
var tower = towers[j];
var distance = Math.sqrt(Math.pow(tower.x - missile.x, 2) + Math.pow(tower.y - missile.y, 2));
if (distance <= 120) {
// Missile blast radius
tower.hp -= 50;
// Flash tower red
tween(tower, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(tower, {
tint: 0xffffff
}, {
duration: 200
});
}
});
if (tower.hp <= 0) {
// Remove tower from game
for (var k = towers.length - 1; k >= 0; k--) {
if (towers[k] === tower) {
towers.splice(k, 1);
break;
}
}
tower.destroy();
}
}
}
missile.destroy();
}
});
}
};
self.reachedEnd = function () {
lives--;
livesText.setText('Lives: ' + lives);
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
if (lives <= 0) {
LK.showGameOver();
}
};
return self;
});
var Tower = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.type = type;
self.x = x;
self.y = y;
self.range = 200;
self.shootCooldown = 0;
self.target = null;
if (type === 'cannon') {
self.attachAsset('cannon', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 30;
self.fireRate = 60;
self.range = 150;
self.hp = 190;
self.maxHp = 190;
} else if (type === 'sniper') {
self.attachAsset('sniper', {
anchorX: 0.5,
anchorY: 0.5
});
var sniperTriangle1 = self.attachAsset('sniperTriangle1', {
anchorX: 0.5,
anchorY: 0.5,
x: -15,
y: -10,
rotation: Math.PI / 4
});
var sniperTriangle2 = self.attachAsset('sniperTriangle2', {
anchorX: 0.5,
anchorY: 0.5,
x: 15,
y: -10,
rotation: -Math.PI / 4
});
self.damage = 80;
self.fireRate = 120;
self.range = 350;
self.hp = 240;
self.maxHp = 240;
} else if (type === 'laser') {
self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 15;
self.fireRate = 20;
self.hp = 150;
self.maxHp = 150;
}
// Create HP display text
self.hpText = new Text2(self.hp + ' HP', {
size: 25,
fill: '#ffffff'
});
self.hpText.anchor.set(0.5, 0.5);
self.hpText.x = 0;
self.hpText.y = -60;
self.addChild(self.hpText);
// Add HP regeneration timer
self.hpRegenTimer = 0;
if (type === 'laser') {
self.hpRegenRate = 120; // 2 seconds at 60 FPS
} else if (type === 'cannon') {
self.hpRegenRate = 165; // 2.75 seconds at 60 FPS
} else if (type === 'sniper') {
self.hpRegenRate = 225; // 3.75 seconds at 60 FPS
}
self.hpRegenAmount = Math.ceil(self.maxHp * 0.1); // Regenerate 10% of max HP
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
self.findTarget();
if (self.target && self.shootCooldown <= 0) {
self.shoot();
self.shootCooldown = self.fireRate;
}
// HP regeneration logic
if (self.hp < self.maxHp) {
self.hpRegenTimer++;
if (self.hpRegenTimer >= self.hpRegenRate) {
self.hp = Math.min(self.hp + self.hpRegenAmount, self.maxHp);
self.hpRegenTimer = 0;
// Visual regeneration effect
tween(self, {
tint: 0x00ff00
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 200
});
}
});
}
}
// Update HP display
self.hpText.setText(self.hp + ' HP');
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
if (distance <= self.range && distance < closestDistance) {
closestEnemy = enemy;
closestDistance = distance;
}
}
self.target = closestEnemy;
};
self.shoot = function () {
if (self.target) {
var bullet = new Bullet(self.x, self.y, self.target, self.damage);
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
};
self.updateFireArrow = function () {
// Arrow display disabled
};
return self;
});
var TowerSpot = Container.expand(function (x, y) {
var self = Container.call(this);
self.attachAsset('towerSpot', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.occupied = false;
self.tower = null;
self.down = function (localX, localY, obj) {
if (!self.occupied && selectedTowerType && canAffordTower(selectedTowerType)) {
self.placeTower(selectedTowerType);
}
};
self.placeTower = function (type) {
var cost = getTowerCost(type);
if (money >= cost) {
money -= cost;
moneyText.setText('Money: ' + money);
var tower = new Tower(type, self.x, self.y);
towers.push(tower);
game.addChild(tower);
self.occupied = true;
self.tower = tower;
self.alpha = 0.3;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var money = 200;
var lives = 20;
var wave = 1;
var waveTimer = 0;
var spawnTimer = 0;
var enemiesInWave = 0;
var enemiesSpawned = 0;
var selectedTowerType = null;
var selectedTower = null;
var rangeIndicator = null;
var bossKillCount = 0;
var towers = [];
var enemies = [];
var bullets = [];
var towerSpots = [];
var path = [{
x: 1024,
y: 0
}, {
x: 1024,
y: 200
}, {
x: 1600,
y: 200
}, {
x: 1600,
y: 400
}, {
x: 400,
y: 400
}, {
x: 400,
y: 600
}, {
x: 1700,
y: 600
}, {
x: 1700,
y: 800
}, {
x: 300,
y: 800
}, {
x: 300,
y: 1000
}, {
x: 1500,
y: 1000
}, {
x: 1500,
y: 1200
}, {
x: 500,
y: 1200
}, {
x: 500,
y: 1400
}, {
x: 1600,
y: 1400
}, {
x: 1600,
y: 1600
}, {
x: 200,
y: 1600
}, {
x: 200,
y: 1800
}, {
x: 1700,
y: 1800
}, {
x: 1700,
y: 2000
}, {
x: 600,
y: 2000
}, {
x: 600,
y: 2200
}, {
x: 1400,
y: 2200
}, {
x: 1400,
y: 2400
}, {
x: 1024,
y: 2400
}, {
x: 1024,
y: 2600
}];
// Create path visualization
for (var i = 0; i < path.length - 1; i++) {
var pathSegment = LK.getAsset('path', {
anchorX: 0.5,
anchorY: 0.5
});
pathSegment.x = (path[i].x + path[i + 1].x) / 2;
pathSegment.y = (path[i].y + path[i + 1].y) / 2;
var dx = path[i + 1].x - path[i].x;
var dy = path[i + 1].y - path[i].y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (Math.abs(dx) > Math.abs(dy)) {
pathSegment.width = distance;
pathSegment.height = 120;
} else {
pathSegment.width = 120;
pathSegment.height = distance;
}
game.addChild(pathSegment);
}
// UI Elements
var moneyText = new Text2('Money: ' + money, {
size: 60,
fill: '#ffffff'
});
moneyText.anchor.set(0, 0);
LK.gui.topLeft.addChild(moneyText);
moneyText.x = 120;
moneyText.y = 20;
var livesText = new Text2('Lives: ' + lives, {
size: 60,
fill: '#ffffff'
});
livesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesText);
livesText.x = 120;
livesText.y = 100;
var waveText = new Text2('Wave: ' + wave, {
size: 60,
fill: '#ffffff'
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
waveText.x = 120;
waveText.y = 180;
// Tower selection buttons
var cannonButton = LK.getAsset('cannon', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
cannonButton.x = 500;
cannonButton.y = 2500;
game.addChild(cannonButton);
var sniperButton = LK.getAsset('sniper', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
sniperButton.x = 900;
sniperButton.y = 2500;
game.addChild(sniperButton);
var laserButton = LK.getAsset('laser', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
laserButton.x = 1300;
laserButton.y = 2500;
game.addChild(laserButton);
var cannonNameText = new Text2('Cannon', {
size: 35,
fill: '#ffffff'
});
cannonNameText.anchor.set(0.5, 0.5);
cannonNameText.x = 500;
cannonNameText.y = 2660;
game.addChild(cannonNameText);
var sniperNameText = new Text2('Sniper', {
size: 35,
fill: '#ffffff'
});
sniperNameText.anchor.set(0.5, 0.5);
sniperNameText.x = 900;
sniperNameText.y = 2660;
game.addChild(sniperNameText);
var laserNameText = new Text2('Laser', {
size: 35,
fill: '#ffffff'
});
laserNameText.anchor.set(0.5, 0.5);
laserNameText.x = 1300;
laserNameText.y = 2660;
game.addChild(laserNameText);
var cannonCostText = new Text2('50', {
size: 40,
fill: '#ffffff'
});
cannonCostText.anchor.set(0.5, 0.5);
cannonCostText.x = 500;
cannonCostText.y = 2620;
game.addChild(cannonCostText);
var sniperCostText = new Text2('100', {
size: 40,
fill: '#ffffff'
});
sniperCostText.anchor.set(0.5, 0.5);
sniperCostText.x = 900;
sniperCostText.y = 2620;
game.addChild(sniperCostText);
var laserCostText = new Text2('30', {
size: 40,
fill: '#ffffff'
});
laserCostText.anchor.set(0.5, 0.5);
laserCostText.x = 1300;
laserCostText.y = 2620;
game.addChild(laserCostText);
function getTowerCost(type) {
if (type === 'cannon') return 50;
if (type === 'sniper') return 100;
if (type === 'laser') return 30;
return 0;
}
function canAffordTower(type) {
return money >= getTowerCost(type);
}
function updateButtonColors() {
cannonButton.tint = canAffordTower('cannon') ? 0xffffff : 0x666666;
sniperButton.tint = canAffordTower('sniper') ? 0xffffff : 0x666666;
laserButton.tint = canAffordTower('laser') ? 0xffffff : 0x666666;
}
function spawnEnemy() {
var enemyType;
if (wave >= 6 && enemiesSpawned === 0) {
// Spawn boss as first enemy after wave 6
enemyType = 'boss';
} else {
var rand = Math.random();
if (rand < 0.4) {
enemyType = 'soldier';
} else if (rand < 0.6) {
enemyType = 'tank';
} else {
enemyType = 'runner';
}
}
var enemy = new Enemy(enemyType);
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
}
function startWave() {
enemiesInWave = 5 + wave * 2;
enemiesSpawned = 0;
spawnTimer = 0;
}
game.down = function (x, y, obj) {
// Clear previous selection
if (rangeIndicator) {
rangeIndicator.destroy();
rangeIndicator = null;
}
selectedTower = null;
// Check tower button clicks
var buttonSize = 80;
if (y >= 2500 - buttonSize / 2 && y <= 2500 + buttonSize / 2) {
if (x >= 500 - buttonSize / 2 && x <= 500 + buttonSize / 2) {
selectedTowerType = 'cannon';
} else if (x >= 900 - buttonSize / 2 && x <= 900 + buttonSize / 2) {
selectedTowerType = 'sniper';
} else if (x >= 1300 - buttonSize / 2 && x <= 1300 + buttonSize / 2) {
selectedTowerType = 'laser';
}
} else {
// Check if clicking on existing tower
var clickedTower = null;
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var distance = Math.sqrt(Math.pow(tower.x - x, 2) + Math.pow(tower.y - y, 2));
if (distance <= 40) {
// Tower click radius
clickedTower = tower;
break;
}
}
if (clickedTower) {
// Select tower and show range
selectedTower = clickedTower;
rangeIndicator = LK.getAsset('towerSpot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: selectedTower.range / 50,
scaleY: selectedTower.range / 50,
alpha: 0.3
});
rangeIndicator.x = selectedTower.x;
rangeIndicator.y = selectedTower.y;
rangeIndicator.tint = 0x00ff00;
game.addChild(rangeIndicator);
} else if (selectedTowerType && canAffordTower(selectedTowerType)) {
// Place tower anywhere on click
var cost = getTowerCost(selectedTowerType);
if (money >= cost) {
money -= cost;
moneyText.setText('Money: ' + money);
var tower = new Tower(selectedTowerType, x, y);
towers.push(tower);
game.addChild(tower);
}
}
}
};
game.update = function () {
// Update all towers
for (var i = 0; i < towers.length; i++) {
towers[i].update();
}
// Update all enemies
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
// Update all bullets
for (var i = 0; i < bullets.length; i++) {
bullets[i].update();
}
// Wave management
if (enemies.length === 0 && enemiesSpawned >= enemiesInWave) {
waveTimer++;
if (waveTimer >= 180) {
// 3 seconds between waves
wave++;
waveText.setText('Wave: ' + wave);
startWave();
waveTimer = 0;
}
}
// Enemy spawning
if (enemiesSpawned < enemiesInWave) {
spawnTimer++;
if (spawnTimer >= 45) {
// Spawn every 0.75 seconds
spawnEnemy();
spawnTimer = 0;
}
}
// Update button colors based on affordability
updateButtonColors();
};
// Start first wave
startWave(); ===================================================================
--- original.js
+++ change.js
@@ -770,8 +770,9 @@
anchorY: 0.5
});
self.damage = 30;
self.fireRate = 60;
+ self.range = 150;
self.hp = 190;
self.maxHp = 190;
} else if (type === 'sniper') {
self.attachAsset('sniper', {