/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AreaTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('areaTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 160;
self.damage = 2;
self.areaDamage = 100; // Area damage radius
self.fireRate = 90; // Slower fire rate due to area effect
self.lastShot = 0;
self.cost = 100;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.explode = function (targetX, targetY) {
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: targetX,
y: targetY
}));
// Animate explosion
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - targetX;
var dy = enemy.y - targetY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.areaDamage) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
self.explode(target.x, target.y);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomba', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200; // Detection range
self.explosionRadius = 150; // Explosion area
self.damage = 200; // Explosion damage
self.cost = 150;
self.hasExploded = false;
self.checkExplosion = function () {
if (self.hasExploded) {
return;
}
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
self.explode();
return;
}
}
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
// Animate explosion
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 600,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in explosion area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
// Remove bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
self.checkExplosion();
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.target = null;
self.damage = 1;
self.update = function () {
if (!self.target || self.target.health <= 0) {
return;
}
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20) {
// Hit target
if (self.target.takeDamage(self.damage, self.fromCactusTower)) {
// Enemy died, give reward
playerMoney += self.target.reward;
updateMoneyDisplay();
}
return true; // Mark for removal
}
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
};
return self;
});
var CactusBomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bombacaptus', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200; // Detection range for balloons
self.damage = 50; // Damage per bullet
self.cost = 100;
self.hasExploded = false;
self.bulletCount = 8; // Number of bullets to shoot in all directions
self.checkExplosion = function () {
if (self.hasExploded) {
return;
}
// Check for balloon enemies in range
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Only target balloon enemies
if (enemy.constructor !== BalloonEnemy) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
self.explode();
return;
}
}
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
// Animate explosion
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Launch bullets in all directions
for (var i = 0; i < self.bulletCount; i++) {
var angle = i / self.bulletCount * 2 * Math.PI;
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.damage = self.damage;
bullet.speed = 6;
// Create a fake target for directional movement
bullet.target = {
x: self.x + Math.cos(angle) * 1000,
y: self.y + Math.sin(angle) * 1000,
health: 1
};
// Override bullet update for directional movement
bullet.update = function () {
var dx = this.target.x - this.x;
var dy = this.target.y - this.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
return true; // Mark for removal
}
// Check collision with balloon enemies
for (var j = 0; j < enemies.length; j++) {
var enemy = enemies[j];
if (enemy.constructor === BalloonEnemy) {
var enemyDx = enemy.x - this.x;
var enemyDy = enemy.y - this.y;
var enemyDistance = Math.sqrt(enemyDx * enemyDx + enemyDy * enemyDy);
if (enemyDistance < 30) {
if (enemy.takeDamage(this.damage, true)) {
// Mark as from cactus
playerMoney += enemy.reward;
updateMoneyDisplay();
}
return true; // Mark for removal
}
}
}
this.x += dx / distance * this.speed;
this.y += dy / distance * this.speed;
};
bullets.push(bullet);
game.addChild(bullet);
}
// Remove bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
self.checkExplosion();
};
return self;
});
var CactusTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('captus', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x228B22; // Forest green color for cactus tower
self.range = 2732; // Very long range - full screen
self.damage = 12; // Good damage
self.fireRate = 80; // Faster than long range tower
self.lastShot = 0;
self.cost = 1000; // High cost
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = 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 <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullet.fromCactusTower = true; // Mark as cactus tower bullet
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var DoubleCannon = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('doble', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 300; // Long range
self.damage = 8; // High damage per bullet
self.fireRate = 90; // Moderate fire rate
self.lastShot = 0;
self.cost = 500;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
// Fire two bullets simultaneously
for (var i = 0; i < 2; i++) {
var bullet = new Bullet();
bullet.x = self.x + (i === 0 ? -10 : 10); // Offset bullets slightly
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
}
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.speed = 2;
self.pathIndex = 0;
self.reward = 10;
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
self.update = function () {
// Create health bar if it doesn't exist
if (!self.healthBarBg) {
// Health bar background (red)
self.healthBarBg = self.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -50,
scaleX: 0.4,
scaleY: 0.15
}));
self.healthBarBg.tint = 0xFF0000;
// Health bar foreground (green)
self.healthBarFg = self.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -50,
scaleX: 0.4,
scaleY: 0.15
}));
self.healthBarFg.tint = 0x4CAF50;
}
// Update health bar
var healthPercent = self.health / self.maxHealth;
self.healthBarFg.scaleX = 0.4 * healthPercent;
// Hide health bar if at full health
if (healthPercent >= 1.0) {
self.healthBarBg.visible = false;
self.healthBarFg.visible = false;
} else {
self.healthBarBg.visible = true;
self.healthBarFg.visible = true;
}
// Check if freeze effect should end
if (self.isFrozen && LK.ticks >= self.freezeEndTick) {
self.speed = self.originalSpeed;
self.isFrozen = false;
// Remove freeze tint
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 200
});
}
// Check if slow effect should end
if (self.isSlowed && LK.ticks >= self.slowEndTick) {
self.speed = self.originalSpeed;
self.isSlowed = false;
// Remove blue tint
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 200
});
}
// Handle poison effect
if (self.isPoisoned) {
if (LK.ticks >= self.poisonEndTick) {
self.isPoisoned = false;
// Remove green tint
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 200
});
} else if (LK.ticks >= self.lastPoisonTick + self.poisonTickInterval) {
if (self.takeDamage(self.poisonDamage)) {
playerMoney += self.reward;
updateMoneyDisplay();
}
self.lastPoisonTick = LK.ticks;
}
}
if (self.pathIndex >= enemyPath.length) {
return;
}
var targetPoint = enemyPath[self.pathIndex];
var dx = targetPoint.x - self.x;
var dy = targetPoint.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.pathIndex++;
if (self.pathIndex >= enemyPath.length) {
// Enemy reached base
playerLives--;
return;
}
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var TankEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with different color and size
self.children[0].destroy();
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
enemyGraphics.tint = 0x9c27b0; // Purple color
self.health = 40;
self.maxHealth = 40;
self.speed = 1; // Slower than normal enemy
self.reward = 25; // Higher reward
return self;
});
var TankBossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('tankboss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
enemyGraphics.tint = 0x263238; // Very dark grey for extreme tank boss
self.health = 1000; // Extremely high health
self.maxHealth = 1000;
self.speed = 0.4; // Very slow due to extreme armor
self.reward = 100; // Very high reward for extreme difficulty
self.armor = 0.5; // Takes 50% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash red when hit with special armor effect
tween(self.children[0], {
tint: 0x795548
}, {
duration: 150,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x263238
}, {
duration: 150
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossObsidianEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with obsidian tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('obcidiaa', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 3.0
});
enemyGraphics.tint = 0x1a1a1a; // Very dark color for obsidian tank boss
self.health = 6000; // Extremely high health
self.maxHealth = 6000;
self.speed = 0.2; // Extremely slow due to obsidian armor
self.reward = 500; // Highest reward for ultimate difficulty
self.armor = 0.9; // Takes 90% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash purple when hit with special obsidian effect
tween(self.children[0], {
tint: 0x9C27B0
}, {
duration: 250,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x1a1a1a
}, {
duration: 250
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossObsidianArmorEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with obsidian armor tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('obcidiaaarmor', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.5,
scaleY: 3.5
});
enemyGraphics.tint = 0x0a0a0a; // Ultra dark color for obsidian armor tank boss
self.health = 10000; // Ultimate high health
self.maxHealth = 10000;
self.speed = 0.15; // Extremely slow due to ultimate armor
self.reward = 800; // Ultimate reward for ultimate difficulty
self.armor = 0.95; // Takes 95% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash gold when hit with special obsidian armor effect
tween(self.children[0], {
tint: 0xFFD700
}, {
duration: 300,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x0a0a0a
}, {
duration: 300
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossGoldEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with gold tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('gold', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 4.0
});
enemyGraphics.tint = 0xFFD700; // Gold color for ultimate tank boss
self.health = 15000; // Maximum health
self.maxHealth = 15000;
self.speed = 0.1; // Extremely slow due to ultimate weight
self.reward = 1200; // Maximum reward for ultimate difficulty
self.armor = 0.98; // Takes 98% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash white when hit with special gold effect
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 400,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0xFFD700
}, {
duration: 400
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossArmorEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with armor tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('armor', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
enemyGraphics.tint = 0x424242; // Dark grey color for armor tank boss
self.health = 4000; // Very high health
self.maxHealth = 4000;
self.speed = 0.25; // Very slow due to heavy armor
self.reward = 300; // Very high reward for extreme difficulty
self.armor = 0.8; // Takes 80% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash red when hit with special armor effect
tween(self.children[0], {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x424242
}, {
duration: 200
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBoss2Enemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('super', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
enemyGraphics.tint = 0x8B0000; // Dark red color for super tank boss
self.health = 2000; // Extremely high health
self.maxHealth = 2000;
self.speed = 0.3; // Very slow due to massive armor
self.reward = 200; // Very high reward for extreme difficulty
self.armor = 0.7; // Takes 70% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash red when hit with special armor effect
tween(self.children[0], {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x8B0000
}, {
duration: 200
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperOmegaTankBossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super omega tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('omega', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 4.0
});
enemyGraphics.tint = 0x8B008B; // Dark magenta color for super omega tank boss
self.health = 30000; // Massive health
self.maxHealth = 30000;
self.speed = 0.08; // Extremely slow due to massive size
self.reward = 2000; // Extreme reward for ultimate difficulty
self.armor = 0.99; // Takes 99% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash bright white when hit with special omega effect
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 500,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x8B008B
}, {
duration: 500
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperOmegaArmorTankBossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super omega armor tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('omegaarmor', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5.0,
scaleY: 5.0
});
enemyGraphics.tint = 0x4B0082; // Indigo color for super omega armor tank boss
self.health = 50000; // Ultimate health
self.maxHealth = 50000;
self.speed = 0.05; // Extremely slow due to ultimate armor
self.reward = 3000; // Ultimate reward for ultimate difficulty
self.armor = 0.995; // Takes 99.5% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash rainbow colors when hit with special omega armor effect
tween(self.children[0], {
tint: 0xFF00FF
}, {
duration: 600,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x4B0082
}, {
duration: 600
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperMageEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super mage appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('supermago', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0x8A2BE2; // Purple color for super mage
self.health = 8; // Higher resistance than normal mage
self.maxHealth = 8;
self.speed = 2.0; // Good speed
self.reward = 50; // Higher reward
self.hasTeleported = false; // Track if super mage has teleported
self.teleportCount = 0; // Track number of teleports
self.maxTeleports = 2; // Can teleport twice
self.teleport = function () {
if (self.teleportCount >= self.maxTeleports || self.pathIndex >= enemyPath.length - 2) {
return;
}
// Calculate larger teleport distance (jump forward 5-8 path points)
var teleportDistance = 5 + Math.floor(Math.random() * 4);
var newPathIndex = Math.min(self.pathIndex + teleportDistance, enemyPath.length - 1);
// Enhanced visual teleport effect - flash purple and create magical effect
tween(self.children[0], {
tint: 0xFF00FF,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.1,
rotation: Math.PI * 2
}, {
duration: 500,
onFinish: function onFinish() {
// Move to new position instantly
self.x = enemyPath[newPathIndex].x;
self.y = enemyPath[newPathIndex].y;
self.pathIndex = newPathIndex;
// Reappear with enhanced effect
tween(self.children[0], {
tint: 0x8A2BE2,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0,
rotation: 0
}, {
duration: 500
});
}
});
self.teleportCount++;
};
// Override update to include enhanced teleport logic
var originalUpdate = self.update;
self.update = function () {
// Teleport more frequently - at 25% and 75% of path
var pathProgress = self.pathIndex / (enemyPath.length - 1);
if (self.teleportCount === 0 && pathProgress >= 0.25) {
self.teleport();
} else if (self.teleportCount === 1 && pathProgress >= 0.75) {
self.teleport();
}
originalUpdate.call(self);
};
return self;
});
var SpawnerEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with spawner head appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('cabeza', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 25;
self.maxHealth = 25;
self.speed = 1.0;
self.reward = 50;
self.isInvulnerable = true; // Start invulnerable
self.pathProgress = 0; // Track progress along path (0 to 1)
self.vulnerabilityThreshold = 0.5; // Becomes vulnerable at 50% of path
self.lastSpawnTime = 0; // Track last spawn time
self.spawnInterval = 300; // 5 seconds (5 * 60 ticks)
// Override takeDamage to handle invulnerability
self.takeDamage = function (damage) {
if (self.isInvulnerable) {
return false; // No damage taken while invulnerable
}
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
if (self.health <= 0) {
// Spawn 3 fast enemies when dying
self.spawnEnemiesOnDeath();
return true;
}
return false;
};
self.spawnEnemiesOnDeath = function () {
for (var i = 0; i < 3; i++) {
var spawnedEnemy = new FastEnemy();
// Override graphics with famtasma asset
spawnedEnemy.children[0].destroy();
var spawnedGraphics = spawnedEnemy.attachAsset('famtasma', {
anchorX: 0.5,
anchorY: 0.5
});
spawnedEnemy.x = self.x + (Math.random() - 0.5) * 60; // Random positioning around spawner
spawnedEnemy.y = self.y + (Math.random() - 0.5) * 60;
spawnedEnemy.pathIndex = self.pathIndex; // Start from same path position
enemies.push(spawnedEnemy);
game.addChild(spawnedEnemy);
}
};
self.spawnEnemy = function () {
if (LK.ticks - self.lastSpawnTime >= self.spawnInterval) {
var spawnedEnemy = new FastEnemy();
// Override graphics with famtasma asset
spawnedEnemy.children[0].destroy();
var spawnedGraphics = spawnedEnemy.attachAsset('famtasma', {
anchorX: 0.5,
anchorY: 0.5
});
spawnedEnemy.x = self.x;
spawnedEnemy.y = self.y;
spawnedEnemy.pathIndex = self.pathIndex; // Start from same path position
enemies.push(spawnedEnemy);
game.addChild(spawnedEnemy);
self.lastSpawnTime = LK.ticks;
}
};
// Override update to handle vulnerability transition and spawning
var originalUpdate = self.update;
self.update = function () {
// Calculate progress along path
if (enemyPath.length > 1) {
self.pathProgress = self.pathIndex / (enemyPath.length - 1);
}
// Check if should become vulnerable
if (self.isInvulnerable && self.pathProgress >= self.vulnerabilityThreshold) {
self.isInvulnerable = false;
// Flash to indicate vulnerability change
tween(enemyGraphics, {
tint: 0x00FF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 300
});
}
});
}
// Spawn enemies every 5 seconds while alive
self.spawnEnemy();
// Call original update
originalUpdate.call(self);
};
return self;
});
var SkeletonEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with skeleton appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('skeleton', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0xf5f5f5; // Light grey/white color for skeleton
self.health = 1;
self.maxHealth = 1;
self.speed = 2.5; // Slightly faster than normal enemy
self.reward = 8; // Lower reward since they come in groups
return self;
});
var PigEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with pig enemy asset
self.children[0].destroy();
var enemyGraphics = self.attachAsset('pigEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 1.2; // Slightly slower than normal enemy
self.reward = 30; // High reward for very tough enemy
return self;
});
var MoleEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with mole appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('topo', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 5;
self.maxHealth = 5;
self.speed = 1.5;
self.reward = 25;
self.isInvulnerable = true; // Start invulnerable
self.pathProgress = 0; // Track progress along path (0 to 1)
self.vulnerabilityThreshold = 0.5; // Becomes vulnerable at 50% of path
// Override takeDamage to handle invulnerability
self.takeDamage = function (damage) {
if (self.isInvulnerable) {
return false; // No damage taken while invulnerable
}
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
// Override update to handle vulnerability transition
var originalUpdate = self.update;
self.update = function () {
// Calculate progress along path
if (enemyPath.length > 1) {
self.pathProgress = self.pathIndex / (enemyPath.length - 1);
}
// Check if should become vulnerable
if (self.isInvulnerable && self.pathProgress >= self.vulnerabilityThreshold) {
self.isInvulnerable = false;
// Change graphics to vulnerable state
enemyGraphics.destroy();
enemyGraphics = self.attachAsset('topo2', {
anchorX: 0.5,
anchorY: 0.5
});
// Flash to indicate vulnerability change
tween(enemyGraphics, {
tint: 0x00FF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 300
});
}
});
}
// Call original update
originalUpdate.call(self);
};
return self;
});
var MageEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with mage appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('mage', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 4;
self.maxHealth = 4;
self.speed = 1.8;
self.reward = 20;
self.hasTeleported = false; // Track if mage has teleported
self.teleport = function () {
if (self.hasTeleported || self.pathIndex >= enemyPath.length - 2) {
return;
}
// Calculate teleport distance (jump forward 3-6 path points)
var teleportDistance = 3 + Math.floor(Math.random() * 4);
var newPathIndex = Math.min(self.pathIndex + teleportDistance, enemyPath.length - 1);
// Visual teleport effect - flash purple and disappear
tween(self.children[0], {
tint: 0x9c27b0,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.2
}, {
duration: 300,
onFinish: function onFinish() {
// Move to new position instantly
self.x = enemyPath[newPathIndex].x;
self.y = enemyPath[newPathIndex].y;
self.pathIndex = newPathIndex;
// Reappear with effect
tween(self.children[0], {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
}, {
duration: 300
});
}
});
self.hasTeleported = true;
};
// Override update to include teleport logic
var originalUpdate = self.update;
self.update = function () {
// Teleport immediately when the mage appears (after first update tick)
if (!self.hasTeleported && LK.ticks > 0) {
self.teleport();
}
originalUpdate.call(self);
};
return self;
});
var FastEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with dedicated fast enemy asset
self.children[0].destroy();
var enemyGraphics = self.attachAsset('fastEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.maxHealth = 2;
self.speed = 5; // Much faster than normal enemy
self.reward = 15; // Higher reward
return self;
});
var BossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with different color and much larger size
self.children[0].destroy();
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
enemyGraphics.tint = 0x000000; // Black color for boss
self.health = 15;
self.maxHealth = 15;
self.speed = 0.8; // Very slow but very tough
self.reward = 50; // High reward for boss
return self;
});
var BalloonEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with balloon appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('globo', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0xFF69B4; // Pink color for balloon
self.health = 15;
self.maxHealth = 15;
self.speed = 1.8; // Fairly fast
self.reward = 40; // Good reward
self.isInvulnerable = true; // Invulnerable to all towers except cactus
// Override takeDamage to handle invulnerability
self.takeDamage = function (damage, fromCactusTower) {
// Only take damage from cactus towers
if (!fromCactusTower) {
return false; // No damage taken from other towers
}
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFF69B4
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var ArmoredEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with different color and size
self.children[0].destroy();
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
enemyGraphics.tint = 0x607d8b; // Blue-grey color for armor
self.health = 5;
self.maxHealth = 5;
self.speed = 1.5; // Slightly slower than normal enemy
self.reward = 20; // Higher reward for tougher enemy
return self;
});
var FreezeTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('stop', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2048; // Full screen range
self.freezeDuration = 600; // 10 seconds (10 * 60 ticks)
self.fireRate = 1800; // 30 seconds between shots (30 * 60 ticks)
self.lastShot = 0;
self.cost = 150;
self.frozenEnemy = null; // Track currently frozen enemy
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
// Only target if no enemy is currently frozen
if (self.frozenEnemy && self.frozenEnemy.isFrozen) {
return null; // Can't freeze another enemy while one is frozen
}
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance && !enemy.isFrozen) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.freezeEnemy = function (target) {
if (!self.canShoot()) {
return;
}
// Apply freeze effect
target.isFrozen = true;
target.originalSpeed = target.speed;
target.speed = 0; // Stop the enemy
target.freezeEndTick = LK.ticks + self.freezeDuration;
self.frozenEnemy = target; // Track this frozen enemy
// Visual effect - tint enemy light blue
tween(target.children[0], {
tint: 0x87CEEB
}, {
duration: 300
});
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
// Check if frozen enemy is no longer frozen
if (self.frozenEnemy && (!self.frozenEnemy.isFrozen || self.frozenEnemy.health <= 0)) {
self.frozenEnemy = null;
}
var target = self.findTarget();
if (target) {
self.freezeEnemy(target);
}
};
return self;
});
var HeavyTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('heavyTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x795548; // Brown color for heavy tower
self.range = 180;
self.damage = 15; // High damage
self.fireRate = 300; // Very slow fire rate (5 seconds)
self.lastShot = 0;
self.cost = 150;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var LongRangeTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('longRangeTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2732; // Full screen range (height of screen)
self.damage = 2;
self.fireRate = 90; // Moderate fire rate
self.lastShot = 0;
self.cost = 110;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var MegaSuperTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0xFF0000; // Red color for mega super tower
self.range = 2732; // Full screen range
self.damage = 500; // Massive damage
self.fireRate = 1800; // 30 seconds (30 * 60 ticks)
self.lastShot = 0;
self.cost = 2000;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var strongestEnemy = null;
var highestHealth = 0;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && enemy.health > highestHealth) {
highestHealth = enemy.health;
strongestEnemy = enemy;
}
}
return strongestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
// Special visual effect for mega super shot
tween(towerGraphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFFFFF
}, {
duration: 500,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFF0000
}, {
duration: 500
});
}
});
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var MultiTargetTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('triple', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2732; // Full screen range
self.damage = 300; // High damage per bullet
self.fireRate = 120; // Moderate fire rate
self.lastShot = 0;
self.cost = 7500;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findAllTargets = function () {
var targetsInRange = [];
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
targetsInRange.push(enemy);
}
}
return targetsInRange;
};
self.shootAtAllTargets = function () {
if (!self.canShoot()) {
return;
}
var targets = self.findAllTargets();
if (targets.length === 0) {
return;
}
// Fire a bullet at each enemy simultaneously
for (var i = 0; i < targets.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = targets[i];
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
}
self.lastShot = LK.ticks;
// Special visual effect for multi-shot
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 300,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFF00FF
}, {
duration: 300
});
}
});
LK.getSound('shoot').play();
};
self.update = function () {
self.shootAtAllTargets();
};
return self;
});
var NuclearBomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('nuclear', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
self.damage = 5000; // Massive damage
self.cost = 10000;
self.hasExploded = false;
self.isGrowing = false;
self.growthTimer = 0;
self.maxGrowthTime = 60; // 1 second to grow
// Start growing animation immediately when placed
self.startGrowing = function () {
if (self.isGrowing) {
return;
}
self.isGrowing = true;
self.growthTimer = 0;
// Start growing animation
tween(bombGraphics, {
scaleX: 3.0,
scaleY: 3.0,
tint: 0xFFFFFF
}, {
duration: self.maxGrowthTime,
easing: tween.easeOut
});
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create massive nuclear explosion covering entire screen
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 30,
scaleY: 30
}));
explosion.tint = 0x00FF00;
// Animate massive explosion
tween(explosion, {
scaleX: 40,
scaleY: 40,
alpha: 0
}, {
duration: 3000,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage ALL enemies on screen (full screen range)
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
// Remove nuclear bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
if (self.hasExploded) {
return;
}
if (self.isGrowing) {
self.growthTimer++;
if (self.growthTimer >= self.maxGrowthTime) {
self.explode();
}
}
};
// Start growing immediately when created
self.startGrowing();
return self;
});
var PoisonTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('poisonTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 150;
self.poisonDamage = 1;
self.poisonDuration = 180; // 3 seconds of poison
self.fireRate = 120; // Slower fire rate
self.lastShot = 0;
self.cost = 80;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTargetsInRange = function () {
var targetsInRange = [];
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
targetsInRange.push(enemy);
}
}
return targetsInRange;
};
self.applyPoison = function () {
if (!self.canShoot()) {
return;
}
var targets = self.findTargetsInRange();
for (var i = 0; i < targets.length; i++) {
var enemy = targets[i];
if (!enemy.isPoisoned) {
enemy.isPoisoned = true;
enemy.poisonDamage = self.poisonDamage;
enemy.poisonEndTick = LK.ticks + self.poisonDuration;
enemy.poisonTickInterval = 30; // Damage every 0.5 seconds
enemy.lastPoisonTick = LK.ticks;
// Visual effect - tint enemy green
tween(enemy.children[0], {
tint: 0x4caf50
}, {
duration: 200
});
}
}
self.lastShot = LK.ticks;
};
self.update = function () {
self.applyPoison();
};
return self;
});
var RapidTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('rapida', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200; // Increased range
self.damage = 1; // Low damage but very fast
self.fireRate = 15; // Very fast fire rate
self.lastShot = 0;
self.cost = 100;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var SlowTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('slowTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 180;
self.slowEffect = 0.5; // Reduces enemy speed by 50%
self.effectDuration = 120; // Effect lasts 2 seconds (120 ticks)
self.fireRate = 90; // Slower than basic tower
self.lastShot = 0;
self.cost = 75;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTargetsInRange = function () {
var targetsInRange = [];
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
targetsInRange.push(enemy);
}
}
return targetsInRange;
};
self.applySlowEffect = function () {
if (!self.canShoot()) {
return;
}
var targets = self.findTargetsInRange();
for (var i = 0; i < targets.length; i++) {
var enemy = targets[i];
if (!enemy.isSlowed) {
enemy.isSlowed = true;
enemy.originalSpeed = enemy.speed;
enemy.speed = enemy.originalSpeed * self.slowEffect;
enemy.slowEndTick = LK.ticks + self.effectDuration;
// Visual effect - tint enemy blue
tween(enemy.children[0], {
tint: 0x2196f3
}, {
duration: 200
});
}
}
self.lastShot = LK.ticks;
};
self.update = function () {
self.applySlowEffect();
};
return self;
});
var SuperBomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('superbomba', {
anchorX: 0.5,
anchorY: 0.5
});
bombGraphics.tint = 0x000000; // Black color for super bomb
self.range = 250; // Detection range
self.explosionRadius = 300; // Massive explosion area
self.damage = 1000; // Massive explosion damage
self.cost = 2000;
self.hasExploded = false;
self.checkExplosion = function () {
if (self.hasExploded) {
return;
}
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
self.explode();
return;
}
}
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create massive explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
// Animate massive explosion
tween(explosion, {
scaleX: 5,
scaleY: 5,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in massive explosion area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
// Remove super bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
self.checkExplosion();
};
return self;
});
var SuperCannon = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('canon', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2732; // Full screen range
self.damage = 3; // Lower damage per target but area effect
self.areaDamage = 200; // Increased area damage radius
self.fireRate = 120; // Slower fire rate due to area effect
self.lastShot = 0;
self.cost = 500;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.explode = function (targetX, targetY) {
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: targetX,
y: targetY
}));
// Animate explosion
tween(explosion, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in large area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - targetX;
var dy = enemy.y - targetY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.areaDamage) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
self.explode(target.x, target.y);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var SuperTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x9c27b0; // Purple color for super tower
self.range = 250;
self.damage = 200; // Extreme damage
self.hasFiredThisWave = false;
self.lastWave = 0;
self.cost = 300;
self.canShoot = function () {
// Check if it's a new wave
if (currentWave > self.lastWave) {
self.hasFiredThisWave = false;
self.lastWave = currentWave;
}
return !self.hasFiredThisWave;
};
self.findTarget = function () {
var strongestEnemy = null;
var highestHealth = 0;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && enemy.health > highestHealth) {
highestHealth = enemy.health;
strongestEnemy = enemy;
}
}
return strongestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.hasFiredThisWave = true;
// Special visual effect for super shot
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 200,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0x9c27b0
}, {
duration: 200
});
}
});
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var Tower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('tower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200;
self.damage = 1;
self.fireRate = 60; // ticks between shots
self.lastShot = 0;
self.cost = 50;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E7D32
});
/****
* Game Code
****/
// Game variables
var playerMoney = 200;
var playerLives = 10;
var currentWave = 1;
var waveInProgress = false;
var shopOpen = false;
var placingTower = false;
var selectedTowerType = null;
var gameStarted = false;
var showingWaveSelect = false;
var selectedStartWave = 1;
var sandboxMode = false;
var showingEnemyShop = false;
// Game arrays
var towers = [];
var enemies = [];
var bullets = [];
var pathSegments = [];
// Enemy path (comprehensive brown winding path covering the entire screen)
var enemyPath = [{
x: 0,
y: 300
}, {
x: 400,
y: 300
}, {
x: 400,
y: 600
}, {
x: 800,
y: 600
}, {
x: 800,
y: 200
}, {
x: 1200,
y: 200
}, {
x: 1200,
y: 900
}, {
x: 1600,
y: 900
}, {
x: 1600,
y: 500
}, {
x: 2000,
y: 500
}, {
x: 2000,
y: 1100
}, {
x: 1400,
y: 1100
}, {
x: 1400,
y: 1400
}, {
x: 600,
y: 1400
}, {
x: 600,
y: 1800
}, {
x: 1000,
y: 1800
}, {
x: 1000,
y: 2200
}, {
x: 1800,
y: 2200
}, {
x: 1800,
y: 1600
}, {
x: 2048,
y: 1600
}];
// Create visual path segments
for (var i = 0; i < enemyPath.length - 1; i++) {
var startPoint = enemyPath[i];
var endPoint = enemyPath[i + 1];
var segments = Math.ceil(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)) / 80);
for (var j = 0; j <= segments; j++) {
var t = j / segments;
var pathX = startPoint.x + (endPoint.x - startPoint.x) * t;
var pathY = startPoint.y + (endPoint.y - startPoint.y) * t;
var pathSegment = game.addChild(LK.getAsset('pathSegment', {
anchorX: 0.5,
anchorY: 0.5,
x: pathX,
y: pathY
}));
pathSegment.alpha = 0.7;
pathSegments.push(pathSegment);
}
}
// Create base at end of path
var base = game.addChild(LK.getAsset('base', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyPath[enemyPath.length - 1].x,
y: enemyPath[enemyPath.length - 1].y
}));
// Move all game assets to back so shop elements appear on top
// First move all path segments to the very back (index 0)
for (var i = 0; i < pathSegments.length; i++) {
game.setChildIndex(pathSegments[i], 0);
}
// Then move base on top of path segments but still behind other elements
game.setChildIndex(base, pathSegments.length);
// Ensure all UI elements are moved to the front to appear on top of assets
// Helper function to safely move child to top if it exists
function moveToTop(child) {
if (child && child.parent === game) {
game.setChildIndex(child, game.children.length - 1);
}
}
moveToTop(shopBtn);
moveToTop(shopBtnText);
moveToTop(readyBtn);
moveToTop(readyBtnText);
moveToTop(shopPanel);
moveToTop(shopTitle);
moveToTop(basicTowerBtn);
moveToTop(basicTowerText);
moveToTop(slowTowerBtn);
moveToTop(slowTowerText);
moveToTop(areaTowerBtn);
moveToTop(areaTowerText);
moveToTop(poisonTowerBtn);
moveToTop(poisonTowerText);
moveToTop(longRangeTowerBtn);
moveToTop(longRangeTowerText);
moveToTop(heavyTowerBtn);
moveToTop(heavyTowerText);
moveToTop(superTowerBtn);
moveToTop(superTowerText);
moveToTop(doubleCannonBtn);
moveToTop(doubleCannonText);
moveToTop(superCannonBtn);
moveToTop(superCannonText);
moveToTop(rapidTowerBtn);
moveToTop(rapidTowerText);
moveToTop(freezeTowerBtn);
moveToTop(freezeTowerText);
moveToTop(cactusBombBtn);
moveToTop(cactusBombText);
moveToTop(cactusTowerBtn);
moveToTop(cactusTowerText);
moveToTop(megaSuperTowerBtn);
moveToTop(megaSuperTowerText);
moveToTop(bombBtn);
moveToTop(bombText);
moveToTop(superBombBtn);
moveToTop(superBombText);
moveToTop(nuclearBombBtn);
moveToTop(nuclearBombText);
moveToTop(multiTargetBtn);
moveToTop(multiTargetText);
moveToTop(closeShopBtn);
moveToTop(closeShopText);
moveToTop(startMenuTitle);
moveToTop(playBtn);
moveToTop(playBtnText);
moveToTop(waveSelectBtn);
moveToTop(waveSelectBtnText);
moveToTop(waveSelectTitle);
moveToTop(waveMinusBtn);
moveToTop(waveMinusText);
moveToTop(waveDisplayText);
moveToTop(wavePlusBtn);
moveToTop(wavePlusText);
moveToTop(startGameBtn);
moveToTop(startGameBtnText);
moveToTop(sandboxBtn);
moveToTop(sandboxBtnText);
moveToTop(backBtn);
moveToTop(backBtnText);
moveToTop(enemyShopBtn);
moveToTop(enemyShopBtnText);
// UI Elements
var moneyText = new Text2('Money: $' + playerMoney, {
size: 60,
fill: 0xFFFFFF
});
moneyText.anchor.set(0, 0);
moneyText.x = 120;
moneyText.y = 50;
LK.gui.topLeft.addChild(moneyText);
var livesText = new Text2('Lives: ' + playerLives, {
size: 60,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
livesText.x = 120;
livesText.y = 130;
LK.gui.topLeft.addChild(livesText);
var waveText = new Text2('wave: ' + currentWave, {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(1, 0);
LK.gui.topRight.addChild(waveText);
// Shop button
var shopBtn = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2500
}));
var shopBtnText = new Text2('SHOP', {
size: 40,
fill: 0xFFFFFF
});
shopBtnText.anchor.set(0.5, 0.5);
shopBtnText.x = shopBtn.x;
shopBtnText.y = shopBtn.y;
game.addChild(shopBtnText);
// Ready button
var readyBtn = game.addChild(LK.getAsset('readyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 500,
y: 2500
}));
var readyBtnText = new Text2('READY', {
size: 40,
fill: 0xFFFFFF
});
readyBtnText.anchor.set(0.5, 0.5);
readyBtnText.x = readyBtn.x;
readyBtnText.y = readyBtn.y;
game.addChild(readyBtnText);
// Shop panel (initially hidden)
var shopPanel = game.addChild(LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
shopPanel.visible = false;
var shopTitle = new Text2('TOWER SHOP', {
size: 50,
fill: 0xFFFFFF
});
shopTitle.anchor.set(0.5, 0);
shopTitle.x = shopPanel.x;
shopTitle.y = shopPanel.y - 450;
game.addChild(shopTitle);
// Tower shop layout - 3 towers per row with increased spacing
// Row 1: Basic, Slow, Area
var basicTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y - 450,
scaleX: 2.2,
scaleY: 2.2
}));
basicTowerBtn.visible = false;
var basicTowerText = new Text2('Basic Tower\n$50', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
basicTowerText.anchor.set(0.5, 0.5);
basicTowerText.x = basicTowerBtn.x;
basicTowerText.y = basicTowerBtn.y;
game.addChild(basicTowerText);
var slowTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y - 450,
color: 0x2196f3,
scaleX: 2.2,
scaleY: 2.2
}));
slowTowerBtn.visible = false;
var slowTowerText = new Text2('Slow Tower\n$75', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
slowTowerText.anchor.set(0.5, 0.5);
slowTowerText.x = slowTowerBtn.x;
slowTowerText.y = slowTowerBtn.y;
game.addChild(slowTowerText);
var areaTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y - 450,
color: 0xff9800,
scaleX: 2.2,
scaleY: 2.2
}));
areaTowerBtn.visible = false;
var areaTowerText = new Text2('Area Tower\n$100', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
areaTowerText.anchor.set(0.5, 0.5);
areaTowerText.x = areaTowerBtn.x;
areaTowerText.y = areaTowerBtn.y;
game.addChild(areaTowerText);
// Row 2: Poison, Long Range, Heavy
var poisonTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y - 250,
color: 0x4caf50,
scaleX: 2.2,
scaleY: 2.2
}));
poisonTowerBtn.visible = false;
var poisonTowerText = new Text2('Poison Tower\n$80', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
poisonTowerText.anchor.set(0.5, 0.5);
poisonTowerText.x = poisonTowerBtn.x;
poisonTowerText.y = poisonTowerBtn.y;
game.addChild(poisonTowerText);
var longRangeTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y - 250,
color: 0x607d8b,
scaleX: 2.2,
scaleY: 2.2
}));
longRangeTowerBtn.visible = false;
var longRangeTowerText = new Text2('Long Range\n$110', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
longRangeTowerText.anchor.set(0.5, 0.5);
longRangeTowerText.x = longRangeTowerBtn.x;
longRangeTowerText.y = longRangeTowerBtn.y;
game.addChild(longRangeTowerText);
var heavyTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y - 250,
color: 0x795548,
scaleX: 2.2,
scaleY: 2.2
}));
heavyTowerBtn.visible = false;
var heavyTowerText = new Text2('Heavy Tower\n$150', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
heavyTowerText.anchor.set(0.5, 0.5);
heavyTowerText.x = heavyTowerBtn.x;
heavyTowerText.y = heavyTowerBtn.y;
game.addChild(heavyTowerText);
// Row 3: Super Tower (centered)
var superTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y - 50,
color: 0x9c27b0,
scaleX: 2.2,
scaleY: 2.2
}));
superTowerBtn.visible = false;
var superTowerText = new Text2('Super Tower\n$300', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
superTowerText.anchor.set(0.5, 0.5);
superTowerText.x = superTowerBtn.x;
superTowerText.y = superTowerBtn.y;
game.addChild(superTowerText);
// Row 4: New towers
var doubleCannonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y + 150,
color: 0x795548,
scaleX: 2.2,
scaleY: 2.2
}));
doubleCannonBtn.visible = false;
var doubleCannonText = new Text2('Doble Cañón\n$500', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
doubleCannonText.anchor.set(0.5, 0.5);
doubleCannonText.x = doubleCannonBtn.x;
doubleCannonText.y = doubleCannonBtn.y;
game.addChild(doubleCannonText);
var superCannonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 150,
color: 0xFF5722,
scaleX: 2.2,
scaleY: 2.2
}));
superCannonBtn.visible = false;
var superCannonText = new Text2('Super Cañón\n$500', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
superCannonText.anchor.set(0.5, 0.5);
superCannonText.x = superCannonBtn.x;
superCannonText.y = superCannonBtn.y;
game.addChild(superCannonText);
var rapidTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y + 150,
color: 0x2196F3,
scaleX: 2.2,
scaleY: 2.2
}));
rapidTowerBtn.visible = false;
var rapidTowerText = new Text2('Torre Rápida\n$100', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
rapidTowerText.anchor.set(0.5, 0.5);
rapidTowerText.x = rapidTowerBtn.x;
rapidTowerText.y = rapidTowerBtn.y;
game.addChild(rapidTowerText);
// Row 5: Freeze Tower and Cactus Tower
var freezeTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y + 350,
color: 0x00BCD4,
scaleX: 2.2,
scaleY: 2.2
}));
freezeTowerBtn.visible = false;
var freezeTowerText = new Text2('Torre Hielo\n$150', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
freezeTowerText.anchor.set(0.5, 0.5);
freezeTowerText.x = freezeTowerBtn.x;
freezeTowerText.y = freezeTowerBtn.y;
game.addChild(freezeTowerText);
var cactusBombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y - 50,
color: 0xccec80,
scaleX: 2.2,
scaleY: 2.2
}));
cactusBombBtn.visible = false;
var cactusBombText = new Text2('Bomba Cactus\n$100', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
cactusBombText.anchor.set(0.5, 0.5);
cactusBombText.x = cactusBombBtn.x;
cactusBombText.y = cactusBombBtn.y;
game.addChild(cactusBombText);
var cactusTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y - 50,
color: 0x228B22,
scaleX: 2.2,
scaleY: 2.2
}));
cactusTowerBtn.visible = false;
var cactusTowerText = new Text2('Torre Cactus\n$1000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
cactusTowerText.anchor.set(0.5, 0.5);
cactusTowerText.x = cactusTowerBtn.x;
cactusTowerText.y = cactusTowerBtn.y;
game.addChild(cactusTowerText);
var megaSuperTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 350,
color: 0xFF0000,
scaleX: 2.2,
scaleY: 2.2
}));
megaSuperTowerBtn.visible = false;
var megaSuperTowerText = new Text2('Mega Super\n$2000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
megaSuperTowerText.anchor.set(0.5, 0.5);
megaSuperTowerText.x = megaSuperTowerBtn.x;
megaSuperTowerText.y = megaSuperTowerBtn.y;
game.addChild(megaSuperTowerText);
var bombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y + 350,
color: 0x795548,
scaleX: 2.2,
scaleY: 2.2
}));
bombBtn.visible = false;
var bombText = new Text2('Bomba\n$150', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
bombText.anchor.set(0.5, 0.5);
bombText.x = bombBtn.x;
bombText.y = bombBtn.y;
game.addChild(bombText);
// Row 6: Super Bomb
var superBombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y + 550,
color: 0x000000,
scaleX: 2.2,
scaleY: 2.2
}));
superBombBtn.visible = false;
var superBombText = new Text2('Super Bomba\n$2000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
superBombText.anchor.set(0.5, 0.5);
superBombText.x = superBombBtn.x;
superBombText.y = superBombBtn.y;
game.addChild(superBombText);
var nuclearBombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 550,
color: 0x00FF00,
scaleX: 2.2,
scaleY: 2.2
}));
nuclearBombBtn.visible = false;
var nuclearBombText = new Text2('Nuclear\n$10000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
nuclearBombText.anchor.set(0.5, 0.5);
nuclearBombText.x = nuclearBombBtn.x;
nuclearBombText.y = nuclearBombBtn.y;
game.addChild(nuclearBombText);
var multiTargetBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y + 550,
color: 0xFF00FF,
scaleX: 2.2,
scaleY: 2.2
}));
multiTargetBtn.visible = false;
var multiTargetText = new Text2('Multi Target\n$1500', {
size: 40,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
multiTargetText.anchor.set(0.5, 0.5);
multiTargetText.x = multiTargetBtn.x;
multiTargetText.y = multiTargetBtn.y;
game.addChild(multiTargetText);
// Close shop button
var closeShopBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 850,
color: 0xFF5722,
scaleX: 2.2,
scaleY: 2.2
}));
closeShopBtn.visible = false;
var closeShopText = new Text2('CLOSE', {
size: 50,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
closeShopText.anchor.set(0.5, 0.5);
closeShopText.x = closeShopBtn.x;
closeShopText.y = closeShopBtn.y;
game.addChild(closeShopText);
// Start Menu Elements
var startMenuTitle = new Text2('TOWER DEFENSE', {
size: 80,
fill: 0xFFFFFF
});
startMenuTitle.anchor.set(0.5, 0.5);
startMenuTitle.x = 1024;
startMenuTitle.y = 800;
game.addChild(startMenuTitle);
var playBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
}));
var playBtnText = new Text2('JUGAR', {
size: 40,
fill: 0xFFFFFF
});
playBtnText.anchor.set(0.5, 0.5);
playBtnText.x = playBtn.x;
playBtnText.y = playBtn.y;
game.addChild(playBtnText);
var waveSelectBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1450,
color: 0x2196F3,
scaleX: 1.5,
scaleY: 1.5
}));
var waveSelectBtnText = new Text2('ELEGIR OLEADA', {
size: 35,
fill: 0xFFFFFF
});
waveSelectBtnText.anchor.set(0.5, 0.5);
waveSelectBtnText.x = waveSelectBtn.x;
waveSelectBtnText.y = waveSelectBtn.y;
game.addChild(waveSelectBtnText);
// Wave Selection Menu Elements
var waveSelectTitle = new Text2('ELEGIR OLEADA INICIAL', {
size: 60,
fill: 0xFFFFFF
});
waveSelectTitle.anchor.set(0.5, 0.5);
waveSelectTitle.x = 1024;
waveSelectTitle.y = 600;
waveSelectTitle.visible = false;
game.addChild(waveSelectTitle);
var waveMinusBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 1200,
color: 0xFF5722,
width: 100,
height: 100
}));
waveMinusBtn.visible = false;
var waveMinusText = new Text2('-', {
size: 60,
fill: 0xFFFFFF
});
waveMinusText.anchor.set(0.5, 0.5);
waveMinusText.x = waveMinusBtn.x;
waveMinusText.y = waveMinusBtn.y;
waveMinusText.visible = false;
game.addChild(waveMinusText);
var waveDisplayText = new Text2('Oleada: ' + selectedStartWave, {
size: 50,
fill: 0xFFFFFF
});
waveDisplayText.anchor.set(0.5, 0.5);
waveDisplayText.x = 1024;
waveDisplayText.y = 1200;
waveDisplayText.visible = false;
game.addChild(waveDisplayText);
var wavePlusBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1348,
y: 1200,
color: 0x4CAF50,
width: 100,
height: 100
}));
wavePlusBtn.visible = false;
var wavePlusText = new Text2('+', {
size: 60,
fill: 0xFFFFFF
});
wavePlusText.anchor.set(0.5, 0.5);
wavePlusText.x = wavePlusBtn.x;
wavePlusText.y = wavePlusBtn.y;
wavePlusText.visible = false;
game.addChild(wavePlusText);
var startGameBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
}));
startGameBtn.visible = false;
var startGameBtnText = new Text2('COMENZAR', {
size: 40,
fill: 0xFFFFFF
});
startGameBtnText.anchor.set(0.5, 0.5);
startGameBtnText.x = startGameBtn.x;
startGameBtnText.y = startGameBtn.y;
startGameBtnText.visible = false;
game.addChild(startGameBtnText);
var sandboxBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1700,
color: 0xFFC107,
scaleX: 1.5,
scaleY: 1.5
}));
var sandboxBtnText = new Text2('SANDBOX', {
size: 40,
fill: 0xFFFFFF
});
sandboxBtnText.anchor.set(0.5, 0.5);
sandboxBtnText.x = sandboxBtn.x;
sandboxBtnText.y = sandboxBtn.y;
game.addChild(sandboxBtnText);
var backBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800,
color: 0x795548
}));
backBtn.visible = false;
var backBtnText = new Text2('VOLVER', {
size: 30,
fill: 0xFFFFFF
});
backBtnText.anchor.set(0.5, 0.5);
backBtnText.x = backBtn.x;
backBtnText.y = backBtn.y;
backBtnText.visible = false;
game.addChild(backBtnText);
// Enemy Shop Panel for Sandbox Mode
var enemyShopPanel = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
enemyShopPanel.visible = false;
var enemyShopTitle = new Text2('ENEMY SHOP', {
size: 50,
fill: 0xFFFFFF
});
enemyShopTitle.anchor.set(0.5, 0);
enemyShopTitle.x = enemyShopPanel.x;
enemyShopTitle.y = enemyShopPanel.y - 450;
enemyShopTitle.visible = false;
game.addChild(enemyShopTitle);
// Enemy buttons - Row 1
var spawnEnemyBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 250,
y: enemyShopPanel.y - 350,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
});
spawnEnemyBtn.visible = false;
var spawnEnemyText = new Text2('Basic Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnEnemyText.anchor.set(0.5, 0.5);
spawnEnemyText.x = spawnEnemyBtn.x;
spawnEnemyText.y = spawnEnemyBtn.y;
spawnEnemyText.visible = false;
var spawnFastBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y - 350,
color: 0x2196F3,
scaleX: 1.5,
scaleY: 1.5
});
spawnFastBtn.visible = false;
var spawnFastText = new Text2('Fast Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnFastText.anchor.set(0.5, 0.5);
spawnFastText.x = spawnFastBtn.x;
spawnFastText.y = spawnFastBtn.y;
spawnFastText.visible = false;
var spawnTankBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 250,
y: enemyShopPanel.y - 350,
color: 0x9C27B0,
scaleX: 1.5,
scaleY: 1.5
});
spawnTankBtn.visible = false;
var spawnTankText = new Text2('Tank Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnTankText.anchor.set(0.5, 0.5);
spawnTankText.x = spawnTankBtn.x;
spawnTankText.y = spawnTankBtn.y;
spawnTankText.visible = false;
game.addChild(spawnTankText);
// Enemy buttons - Row 2
var spawnBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y - 150,
color: 0x000000
}));
spawnBossBtn.visible = false;
var spawnBossText = new Text2('Boss Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnBossText.anchor.set(0.5, 0.5);
spawnBossText.x = spawnBossBtn.x;
spawnBossText.y = spawnBossBtn.y;
spawnBossText.visible = false;
game.addChild(spawnBossText);
var spawnMageBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y - 150,
color: 0x795548
}));
spawnMageBtn.visible = false;
var spawnMageText = new Text2('Mage Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnMageText.anchor.set(0.5, 0.5);
spawnMageText.x = spawnMageBtn.x;
spawnMageText.y = spawnMageBtn.y;
spawnMageText.visible = false;
game.addChild(spawnMageText);
var spawnSuperMageBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y - 150,
color: 0x8A2BE2
}));
spawnSuperMageBtn.visible = false;
var spawnSuperMageText = new Text2('Super Mage', {
size: 22,
fill: 0xFFFFFF
});
spawnSuperMageText.anchor.set(0.5, 0.5);
spawnSuperMageText.x = spawnSuperMageBtn.x;
spawnSuperMageText.y = spawnSuperMageBtn.y;
spawnSuperMageText.visible = false;
game.addChild(spawnSuperMageText);
var spawnTankBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y - 150,
color: 0x263238
}));
spawnTankBossBtn.visible = false;
var spawnTankBossText = new Text2('Tank Boss', {
size: 25,
fill: 0xFFFFFF
});
spawnTankBossText.anchor.set(0.5, 0.5);
spawnTankBossText.x = spawnTankBossBtn.x;
spawnTankBossText.y = spawnTankBossBtn.y;
spawnTankBossText.visible = false;
game.addChild(spawnTankBossText);
// Enemy buttons - Row 3
var spawnArmoredBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y + 50,
color: 0x607d8b
}));
spawnArmoredBtn.visible = false;
var spawnArmoredText = new Text2('Armored', {
size: 25,
fill: 0xFFFFFF
});
spawnArmoredText.anchor.set(0.5, 0.5);
spawnArmoredText.x = spawnArmoredBtn.x;
spawnArmoredText.y = spawnArmoredBtn.y;
spawnArmoredText.visible = false;
game.addChild(spawnArmoredText);
var spawnPigBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 50,
color: 0xE91E63
}));
spawnPigBtn.visible = false;
var spawnPigText = new Text2('Pig Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnPigText.anchor.set(0.5, 0.5);
spawnPigText.x = spawnPigBtn.x;
spawnPigText.y = spawnPigBtn.y;
spawnPigText.visible = false;
game.addChild(spawnPigText);
var spawnMoleBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 200,
y: enemyShopPanel.y + 50,
color: 0x8D6E63
}));
spawnMoleBtn.visible = false;
var spawnMoleText = new Text2('Mole Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnMoleText.anchor.set(0.5, 0.5);
spawnMoleText.x = spawnMoleBtn.x;
spawnMoleText.y = spawnMoleBtn.y;
spawnMoleText.visible = false;
game.addChild(spawnMoleText);
// Enemy buttons - Row 4
var spawnSkeletonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y + 200,
color: 0xF5F5F5
}));
spawnSkeletonBtn.visible = false;
var spawnSkeletonText = new Text2('Skeleton', {
size: 25,
fill: 0x000000
});
spawnSkeletonText.anchor.set(0.5, 0.5);
spawnSkeletonText.x = spawnSkeletonBtn.x;
spawnSkeletonText.y = spawnSkeletonBtn.y;
spawnSkeletonText.visible = false;
game.addChild(spawnSkeletonText);
var spawnSuperTank2Btn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 200,
color: 0x8B0000
}));
spawnSuperTank2Btn.visible = false;
var spawnSuperTank2Text = new Text2('Super Tank2', {
size: 22,
fill: 0xFFFFFF
});
spawnSuperTank2Text.anchor.set(0.5, 0.5);
spawnSuperTank2Text.x = spawnSuperTank2Btn.x;
spawnSuperTank2Text.y = spawnSuperTank2Btn.y;
spawnSuperTank2Text.visible = false;
game.addChild(spawnSuperTank2Text);
var spawnArmorBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 200,
y: enemyShopPanel.y + 200,
color: 0x424242
}));
spawnArmorBossBtn.visible = false;
var spawnArmorBossText = new Text2('Armor Boss', {
size: 22,
fill: 0xFFFFFF
});
spawnArmorBossText.anchor.set(0.5, 0.5);
spawnArmorBossText.x = spawnArmorBossBtn.x;
spawnArmorBossText.y = spawnArmorBossBtn.y;
spawnArmorBossText.visible = false;
game.addChild(spawnArmorBossText);
// Enemy buttons - Row 5
var spawnObsidianBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y + 350,
color: 0x1a1a1a
}));
spawnObsidianBossBtn.visible = false;
var spawnObsidianBossText = new Text2('Obsidian Boss', {
size: 20,
fill: 0xFFFFFF
});
spawnObsidianBossText.anchor.set(0.5, 0.5);
spawnObsidianBossText.x = spawnObsidianBossBtn.x;
spawnObsidianBossText.y = spawnObsidianBossBtn.y;
spawnObsidianBossText.visible = false;
game.addChild(spawnObsidianBossText);
var spawnObsidianArmorBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 350,
color: 0x0a0a0a
}));
spawnObsidianArmorBtn.visible = false;
var spawnObsidianArmorText = new Text2('Obsidian Armor', {
size: 18,
fill: 0xFFFFFF
});
spawnObsidianArmorText.anchor.set(0.5, 0.5);
spawnObsidianArmorText.x = spawnObsidianArmorBtn.x;
spawnObsidianArmorText.y = spawnObsidianArmorBtn.y;
spawnObsidianArmorText.visible = false;
game.addChild(spawnObsidianArmorText);
var spawnGoldBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 200,
y: enemyShopPanel.y + 350,
color: 0xFFD700
}));
spawnGoldBossBtn.visible = false;
var spawnGoldBossText = new Text2('Gold Boss', {
size: 20,
fill: 0x000000
});
spawnGoldBossText.anchor.set(0.5, 0.5);
spawnGoldBossText.x = spawnGoldBossBtn.x;
spawnGoldBossText.y = spawnGoldBossBtn.y;
spawnGoldBossText.visible = false;
game.addChild(spawnGoldBossText);
// Enemy buttons - Row 6
var spawnSuperOmegaTankBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y + 500,
color: 0x8B008B
}));
spawnSuperOmegaTankBtn.visible = false;
var spawnSuperOmegaTankText = new Text2('Super Omega', {
size: 18,
fill: 0xFFFFFF
});
spawnSuperOmegaTankText.anchor.set(0.5, 0.5);
spawnSuperOmegaTankText.x = spawnSuperOmegaTankBtn.x;
spawnSuperOmegaTankText.y = spawnSuperOmegaTankBtn.y;
spawnSuperOmegaTankText.visible = false;
game.addChild(spawnSuperOmegaTankText);
var spawnSuperOmegaArmorBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y + 500,
color: 0x4B0082
}));
spawnSuperOmegaArmorBtn.visible = false;
var spawnSuperOmegaArmorText = new Text2('Omega Armor', {
size: 18,
fill: 0xFFFFFF
});
spawnSuperOmegaArmorText.anchor.set(0.5, 0.5);
spawnSuperOmegaArmorText.x = spawnSuperOmegaArmorBtn.x;
spawnSuperOmegaArmorText.y = spawnSuperOmegaArmorBtn.y;
spawnSuperOmegaArmorText.visible = false;
game.addChild(spawnSuperOmegaArmorText);
// Enemy buttons - Row 7
var spawnSpawnerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y + 650,
color: 0xFF6600
}));
spawnSpawnerBtn.visible = false;
var spawnSpawnerText = new Text2('Spawner', {
size: 20,
fill: 0xFFFFFF
});
spawnSpawnerText.anchor.set(0.5, 0.5);
spawnSpawnerText.x = spawnSpawnerBtn.x;
spawnSpawnerText.y = spawnSpawnerBtn.y;
spawnSpawnerText.visible = false;
game.addChild(spawnSpawnerText);
var spawnBalloonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y + 650,
color: 0xFF69B4
}));
spawnBalloonBtn.visible = false;
var spawnBalloonText = new Text2('Globo', {
size: 20,
fill: 0xFFFFFF
});
spawnBalloonText.anchor.set(0.5, 0.5);
spawnBalloonText.x = spawnBalloonBtn.x;
spawnBalloonText.y = spawnBalloonBtn.y;
spawnBalloonText.visible = false;
game.addChild(spawnBalloonText);
// Enemy Shop close button
var closeEnemyShopBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 800,
color: 0xFF5722
}));
closeEnemyShopBtn.visible = false;
var closeEnemyShopText = new Text2('CLOSE', {
size: 30,
fill: 0xFFFFFF
});
closeEnemyShopText.anchor.set(0.5, 0.5);
closeEnemyShopText.x = closeEnemyShopBtn.x;
closeEnemyShopText.y = closeEnemyShopBtn.y;
closeEnemyShopText.visible = false;
game.addChild(closeEnemyShopText);
// Sandbox UI elements
var enemyShopBtn = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: 2500,
color: 0xFFC107
}));
enemyShopBtn.visible = false;
var enemyShopBtnText = new Text2('ENEMIES', {
size: 40,
fill: 0xFFFFFF
});
enemyShopBtnText.anchor.set(0.5, 0.5);
enemyShopBtnText.x = enemyShopBtn.x;
enemyShopBtnText.y = enemyShopBtn.y;
enemyShopBtnText.visible = false;
game.addChild(enemyShopBtnText);
// Functions
function hideStartMenu() {
startMenuTitle.visible = false;
playBtn.visible = false;
playBtnText.visible = false;
waveSelectBtn.visible = false;
waveSelectBtnText.visible = false;
sandboxBtn.visible = false;
sandboxBtnText.visible = false;
}
function showStartMenu() {
startMenuTitle.visible = true;
playBtn.visible = true;
playBtnText.visible = true;
waveSelectBtn.visible = true;
waveSelectBtnText.visible = true;
sandboxBtn.visible = true;
sandboxBtnText.visible = true;
}
function hideWaveSelect() {
waveSelectTitle.visible = false;
waveMinusBtn.visible = false;
waveMinusText.visible = false;
waveDisplayText.visible = false;
wavePlusBtn.visible = false;
wavePlusText.visible = false;
startGameBtn.visible = false;
startGameBtnText.visible = false;
backBtn.visible = false;
backBtnText.visible = false;
}
function showWaveSelect() {
waveSelectTitle.visible = true;
waveMinusBtn.visible = true;
waveMinusText.visible = true;
waveDisplayText.visible = true;
wavePlusBtn.visible = true;
wavePlusText.visible = true;
startGameBtn.visible = true;
startGameBtnText.visible = true;
backBtn.visible = true;
backBtnText.visible = true;
}
function updateWaveDisplay() {
if (gameStarted) {
waveDisplayText.setText('Oleada: ' + currentWave);
} else {
waveDisplayText.setText('Oleada: ' + selectedStartWave);
}
}
function toggleEnemyShop() {
showingEnemyShop = !showingEnemyShop;
if (showingEnemyShop) {
// Add all enemy shop elements to game with proper layering
game.addChild(enemyShopPanel);
enemyShopPanel.visible = true;
game.addChild(enemyShopTitle);
enemyShopTitle.visible = true;
game.addChild(spawnEnemyBtn);
spawnEnemyBtn.visible = true;
game.addChild(spawnEnemyText);
spawnEnemyText.visible = true;
game.addChild(spawnFastBtn);
spawnFastBtn.visible = true;
game.addChild(spawnFastText);
spawnFastText.visible = true;
game.addChild(spawnTankBtn);
spawnTankBtn.visible = true;
game.addChild(spawnTankText);
spawnTankText.visible = true;
game.addChild(spawnBossBtn);
spawnBossBtn.visible = true;
game.addChild(spawnBossText);
spawnBossText.visible = true;
game.addChild(spawnMageBtn);
spawnMageBtn.visible = true;
game.addChild(spawnMageText);
spawnMageText.visible = true;
game.addChild(spawnSuperMageBtn);
spawnSuperMageBtn.visible = true;
game.addChild(spawnSuperMageText);
spawnSuperMageText.visible = true;
game.addChild(spawnTankBossBtn);
spawnTankBossBtn.visible = true;
game.addChild(spawnTankBossText);
spawnTankBossText.visible = true;
game.addChild(spawnArmoredBtn);
spawnArmoredBtn.visible = true;
game.addChild(spawnArmoredText);
spawnArmoredText.visible = true;
game.addChild(spawnPigBtn);
spawnPigBtn.visible = true;
game.addChild(spawnPigText);
spawnPigText.visible = true;
game.addChild(spawnMoleBtn);
spawnMoleBtn.visible = true;
game.addChild(spawnMoleText);
spawnMoleText.visible = true;
game.addChild(spawnSkeletonBtn);
spawnSkeletonBtn.visible = true;
game.addChild(spawnSkeletonText);
spawnSkeletonText.visible = true;
game.addChild(spawnSuperTank2Btn);
spawnSuperTank2Btn.visible = true;
game.addChild(spawnSuperTank2Text);
spawnSuperTank2Text.visible = true;
game.addChild(spawnArmorBossBtn);
spawnArmorBossBtn.visible = true;
game.addChild(spawnArmorBossText);
spawnArmorBossText.visible = true;
game.addChild(spawnObsidianBossBtn);
spawnObsidianBossBtn.visible = true;
game.addChild(spawnObsidianBossText);
spawnObsidianBossText.visible = true;
game.addChild(spawnObsidianArmorBtn);
spawnObsidianArmorBtn.visible = true;
game.addChild(spawnObsidianArmorText);
spawnObsidianArmorText.visible = true;
game.addChild(spawnGoldBossBtn);
spawnGoldBossBtn.visible = true;
game.addChild(spawnGoldBossText);
spawnGoldBossText.visible = true;
game.addChild(spawnSuperOmegaTankBtn);
spawnSuperOmegaTankBtn.visible = true;
game.addChild(spawnSuperOmegaTankText);
spawnSuperOmegaTankText.visible = true;
game.addChild(spawnSuperOmegaArmorBtn);
spawnSuperOmegaArmorBtn.visible = true;
game.addChild(spawnSuperOmegaArmorText);
spawnSuperOmegaArmorText.visible = true;
game.addChild(spawnSpawnerBtn);
spawnSpawnerBtn.visible = true;
game.addChild(spawnSpawnerText);
spawnSpawnerText.visible = true;
game.addChild(spawnBalloonBtn);
spawnBalloonBtn.visible = true;
game.addChild(spawnBalloonText);
spawnBalloonText.visible = true;
game.addChild(closeEnemyShopBtn);
closeEnemyShopBtn.visible = true;
game.addChild(closeEnemyShopText);
closeEnemyShopText.visible = true;
} else {
// Remove all enemy shop elements from game
enemyShopPanel.destroy();
enemyShopTitle.destroy();
spawnEnemyBtn.destroy();
spawnEnemyText.destroy();
spawnFastBtn.destroy();
spawnFastText.destroy();
spawnTankBtn.destroy();
spawnTankText.destroy();
spawnBossBtn.destroy();
spawnBossText.destroy();
spawnMageBtn.destroy();
spawnMageText.destroy();
spawnSuperMageBtn.destroy();
spawnSuperMageText.destroy();
spawnTankBossBtn.destroy();
spawnTankBossText.destroy();
spawnArmoredBtn.destroy();
spawnArmoredText.destroy();
spawnPigBtn.destroy();
spawnPigText.destroy();
spawnMoleBtn.destroy();
spawnMoleText.destroy();
spawnSkeletonBtn.destroy();
spawnSkeletonText.destroy();
spawnSuperTank2Btn.destroy();
spawnSuperTank2Text.destroy();
spawnArmorBossBtn.destroy();
spawnArmorBossText.destroy();
spawnObsidianBossBtn.destroy();
spawnObsidianBossText.destroy();
spawnObsidianArmorBtn.destroy();
spawnObsidianArmorText.destroy();
spawnGoldBossBtn.destroy();
spawnGoldBossText.destroy();
spawnSuperOmegaTankBtn.destroy();
spawnSuperOmegaTankText.destroy();
spawnSuperOmegaArmorBtn.destroy();
spawnSuperOmegaArmorText.destroy();
spawnSpawnerBtn.destroy();
spawnSpawnerText.destroy();
spawnBalloonBtn.destroy();
spawnBalloonText.destroy();
closeEnemyShopBtn.destroy();
closeEnemyShopText.destroy();
// Recreate elements for next time
enemyShopPanel = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
enemyShopTitle = new Text2('ENEMY SHOP', {
size: 50,
fill: 0xFFFFFF
});
enemyShopTitle.anchor.set(0.5, 0);
enemyShopTitle.x = enemyShopPanel.x;
enemyShopTitle.y = enemyShopPanel.y - 450;
spawnEnemyBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 250,
y: enemyShopPanel.y - 350,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
});
spawnEnemyText = new Text2('Basic Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnEnemyText.anchor.set(0.5, 0.5);
spawnEnemyText.x = spawnEnemyBtn.x;
spawnEnemyText.y = spawnEnemyBtn.y;
spawnFastBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y - 350,
color: 0x2196F3,
scaleX: 1.5,
scaleY: 1.5
});
spawnFastText = new Text2('Fast Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnFastText.anchor.set(0.5, 0.5);
spawnFastText.x = spawnFastBtn.x;
spawnFastText.y = spawnFastBtn.y;
spawnTankBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 250,
y: enemyShopPanel.y - 350,
color: 0x9C27B0,
scaleX: 1.5,
scaleY: 1.5
});
spawnTankText = new Text2('Tank Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnTankText.anchor.set(0.5, 0.5);
spawnTankText.x = spawnTankBtn.x;
spawnTankText.y = spawnTankBtn.y;
spawnSuperMageBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y - 150,
color: 0x8A2BE2
});
spawnSuperMageText = new Text2('Super Mage', {
size: 22,
fill: 0xFFFFFF
});
spawnSuperMageText.anchor.set(0.5, 0.5);
spawnSuperMageText.x = spawnSuperMageBtn.x;
spawnSuperMageText.y = spawnSuperMageBtn.y;
spawnSpawnerBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y + 650,
color: 0xFF6600
});
spawnSpawnerText = new Text2('Spawner', {
size: 20,
fill: 0xFFFFFF
});
spawnSpawnerText.anchor.set(0.5, 0.5);
spawnSpawnerText.x = spawnSpawnerBtn.x;
spawnSpawnerText.y = spawnSpawnerBtn.y;
spawnBalloonBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y + 650,
color: 0xFF69B4
});
spawnBalloonText = new Text2('Globo', {
size: 20,
fill: 0xFFFFFF
});
spawnBalloonText.anchor.set(0.5, 0.5);
spawnBalloonText.x = spawnBalloonBtn.x;
spawnBalloonText.y = spawnBalloonBtn.y;
closeEnemyShopBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 800,
color: 0xFF5722,
scaleX: 1.5,
scaleY: 1.5
});
closeEnemyShopText = new Text2('CLOSE', {
size: 30,
fill: 0xFFFFFF
});
closeEnemyShopText.anchor.set(0.5, 0.5);
closeEnemyShopText.x = closeEnemyShopBtn.x;
closeEnemyShopText.y = closeEnemyShopBtn.y;
}
}
function startSandboxMode() {
gameStarted = true;
sandboxMode = true;
playerMoney = 999999; // Infinite money
hideStartMenu();
hideWaveSelect();
showingWaveSelect = false;
updateWaveDisplay();
updateMoneyDisplay();
}
function spawnEnemy(enemyType) {
var enemy;
switch (enemyType) {
case 'basic':
enemy = new Enemy();
break;
case 'fast':
enemy = new FastEnemy();
break;
case 'tank':
enemy = new TankEnemy();
break;
case 'boss':
enemy = new BossEnemy();
break;
case 'mage':
enemy = new MageEnemy();
break;
case 'supermage':
enemy = new SuperMageEnemy();
break;
case 'tankboss':
enemy = new TankBossEnemy();
break;
case 'armored':
enemy = new ArmoredEnemy();
break;
case 'pig':
enemy = new PigEnemy();
break;
case 'mole':
enemy = new MoleEnemy();
break;
case 'skeleton':
enemy = new SkeletonEnemy();
break;
case 'supertank2':
enemy = new SuperTankBoss2Enemy();
break;
case 'armorboss':
enemy = new SuperTankBossArmorEnemy();
break;
case 'obsidianboss':
enemy = new SuperTankBossObsidianEnemy();
break;
case 'obsidianarmor':
enemy = new SuperTankBossObsidianArmorEnemy();
break;
case 'goldboss':
enemy = new SuperTankBossGoldEnemy();
break;
case 'superomegatank':
enemy = new SuperOmegaTankBossEnemy();
break;
case 'superomegaarmor':
enemy = new SuperOmegaArmorTankBossEnemy();
break;
case 'spawner':
enemy = new SpawnerEnemy();
break;
case 'balloon':
enemy = new BalloonEnemy();
break;
default:
enemy = new Enemy();
}
enemy.x = enemyPath[0].x;
enemy.y = enemyPath[0].y;
enemies.push(enemy);
game.addChild(enemy);
// Move enemy above path segments (path segments are at indices 0 to pathSegments.length-1)
// but below towers and UI elements
game.setChildIndex(enemy, pathSegments.length + towers.length);
}
function startGame() {
gameStarted = true;
currentWave = selectedStartWave;
hideStartMenu();
hideWaveSelect();
showingWaveSelect = false;
updateWaveDisplay();
waveText.setText('Wave: ' + currentWave); // Update the actual game wave display
}
function updateMoneyDisplay() {
moneyText.setText('Money: $' + playerMoney);
}
function updateLivesDisplay() {
livesText.setText('Lives: ' + playerLives);
}
function toggleShop() {
shopOpen = !shopOpen;
shopPanel.visible = shopOpen;
shopTitle.visible = shopOpen;
basicTowerBtn.visible = shopOpen;
basicTowerText.visible = shopOpen;
slowTowerBtn.visible = shopOpen;
slowTowerText.visible = shopOpen;
areaTowerBtn.visible = shopOpen;
areaTowerText.visible = shopOpen;
poisonTowerBtn.visible = shopOpen;
poisonTowerText.visible = shopOpen;
longRangeTowerBtn.visible = shopOpen;
longRangeTowerText.visible = shopOpen;
heavyTowerBtn.visible = shopOpen;
heavyTowerText.visible = shopOpen;
superTowerBtn.visible = shopOpen;
superTowerText.visible = shopOpen;
doubleCannonBtn.visible = shopOpen;
doubleCannonText.visible = shopOpen;
superCannonBtn.visible = shopOpen;
superCannonText.visible = shopOpen;
rapidTowerBtn.visible = shopOpen;
rapidTowerText.visible = shopOpen;
freezeTowerBtn.visible = shopOpen;
freezeTowerText.visible = shopOpen;
cactusBombBtn.visible = shopOpen;
cactusBombText.visible = shopOpen;
cactusTowerBtn.visible = shopOpen;
cactusTowerText.visible = shopOpen;
megaSuperTowerBtn.visible = shopOpen;
megaSuperTowerText.visible = shopOpen;
bombBtn.visible = shopOpen;
bombText.visible = shopOpen;
superBombBtn.visible = shopOpen;
superBombText.visible = shopOpen;
nuclearBombBtn.visible = shopOpen;
nuclearBombText.visible = shopOpen;
multiTargetBtn.visible = shopOpen;
multiTargetText.visible = shopOpen;
closeShopBtn.visible = shopOpen;
closeShopText.visible = shopOpen;
}
function startWave() {
if (waveInProgress) {
return;
}
waveInProgress = true;
var enemiesToSpawn = 3 + currentWave;
var spawnDelay = 0;
for (var i = 0; i < enemiesToSpawn; i++) {
LK.setTimeout(function () {
var enemy;
var enemyType = Math.random();
// Calculate increased spawn rates for rare enemies after wave 11
var waveMultiplier = currentWave > 11 ? Math.min(2.0, 1 + (currentWave - 11) * 0.1) : 1;
var superOmegaArmorChance = currentWave >= 45 ? 0.0005 * Math.max(1, (currentWave - 45) * 0.02) : 0; // Ultra ultra rare chance starting at wave 45, increases each wave
var superOmegaTankChance = currentWave >= 43 ? 0.0008 * Math.max(1, (currentWave - 43) * 0.025) : 0; // Ultra rare chance starting at wave 43, increases each wave
var superTankBossGoldChance = currentWave >= 40 ? 0.001 * Math.max(1, (currentWave - 40) * 0.03) : 0; // Ultra rare chance starting at wave 40, increases each wave
var superTankBossObsidianArmorChance = currentWave >= 30 ? 0.002 * Math.max(1, (currentWave - 30) * 0.04) : 0; // Extremely low chance starting at wave 30, increases each wave
var superTankBossObsidianChance = currentWave >= 25 ? 0.003 * Math.max(1, (currentWave - 25) * 0.05) : 0; // Very low chance starting at wave 25, increases each wave
var superTankBossArmorChance = currentWave >= 15 ? 0.005 * Math.max(1, (currentWave - 15) * 0.05) : 0; // Low chance starting at wave 15, increases each wave
var balloonChance = currentWave >= 8 ? 0.08 * waveMultiplier : 0; // Balloon enemy appears after wave 8
var superTankBoss2Chance = currentWave >= 8 ? 0.005 * waveMultiplier : 0; // Very low chance, increases after wave 11
var superMageChance = currentWave >= 10 ? 0.06 * waveMultiplier : 0; // Super mage appears after wave 10
var tankBossChance = currentWave >= 10 ? 0.01 * waveMultiplier : 0;
var bossChance = currentWave >= 7 ? 0.05 * waveMultiplier : 0;
var pigChance = currentWave >= 6 ? 0.10 * waveMultiplier : 0;
var mageChance = currentWave >= 3 ? 0.12 * waveMultiplier : 0;
var armoredChance = currentWave >= 4 ? 0.15 * waveMultiplier : 0;
var moleChance = currentWave >= 3 ? 0.08 * waveMultiplier : 0;
var skeletonChance = currentWave >= 2 ? 0.10 * waveMultiplier : 0;
var fastChance = currentWave >= 2 ? 0.15 * waveMultiplier : 0;
var tankChance = currentWave >= 5 ? 0.17 * waveMultiplier : 0;
if (enemyType < superOmegaArmorChance) {
// Super Omega Armor Tank Boss enemy with ultra ultra rare chance starting at wave 45
enemy = new SuperOmegaArmorTankBossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance) {
// Super Omega Tank Boss enemy with ultra rare chance starting at wave 43
enemy = new SuperOmegaTankBossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance) {
// Super Tank Boss Gold enemy with ultra rare chance starting at wave 40
enemy = new SuperTankBossGoldEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance) {
// Super Tank Boss Obsidian Armor enemy with extremely low chance starting at wave 30
enemy = new SuperTankBossObsidianArmorEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance) {
// Super Tank Boss Obsidian enemy with very low chance starting at wave 25
enemy = new SuperTankBossObsidianEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance) {
// Super Tank Boss Armor enemy with low chance starting at wave 15
enemy = new SuperTankBossArmorEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance) {
// Super Tank Boss 2 enemy with very low chance, increases after wave 11
enemy = new SuperTankBoss2Enemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance) {
// Tank boss enemy with increased chance after wave 11
enemy = new TankBossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance) {
// Boss enemy with increased chance after wave 11
enemy = new BossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance) {
// Pig enemy with increased chance after wave 11
enemy = new PigEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance) {
// Super mage enemy with chance after wave 10
enemy = new SuperMageEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance) {
// Mage enemy with increased chance after wave 11
enemy = new MageEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance) {
// Armored enemy with increased chance after wave 11
enemy = new ArmoredEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance) {
// Mole enemy with invulnerability until 50% of path
enemy = new MoleEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance + skeletonChance) {
// Skeleton group with increased chance after wave 11
var skeletonCount = 3 + Math.floor(Math.random() * 3);
for (var j = 0; j < skeletonCount; j++) {
var skeleton = new SkeletonEnemy();
skeleton.x = enemyPath[0].x + (Math.random() - 0.5) * 40; // Slight random positioning
skeleton.y = enemyPath[0].y + (Math.random() - 0.5) * 40;
skeleton.health += Math.floor(currentWave / 4); // Slower health increase for skeletons
skeleton.maxHealth = skeleton.health;
enemies.push(skeleton);
game.addChild(skeleton);
}
return; // Skip the normal enemy spawn below
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance + skeletonChance + fastChance) {
// Fast enemy with increased chance after wave 11
enemy = new FastEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance + skeletonChance + fastChance + tankChance + balloonChance) {
// Balloon enemy - invulnerable to all towers except cactus
enemy = new BalloonEnemy();
} else {
enemy = new Enemy();
}
enemy.x = enemyPath[0].x;
enemy.y = enemyPath[0].y;
enemy.health += Math.floor(currentWave / 3); // Increase health every 3 waves
enemy.maxHealth = enemy.health;
enemies.push(enemy);
game.addChild(enemy);
// Move enemy above path segments but below towers and UI elements
game.setChildIndex(enemy, pathSegments.length + towers.length);
}, spawnDelay);
spawnDelay += 1000; // 1 second between spawns
}
}
function checkWaveComplete() {
if (waveInProgress && enemies.length === 0) {
waveInProgress = false;
currentWave++;
updateWaveDisplay();
waveText.setText('Wave: ' + currentWave); // Update the actual game wave display
waveDisplayText.setText('Oleada: ' + currentWave); // Update wave select display as well
playerMoney += 50; // Wave completion bonus
updateMoneyDisplay();
}
}
function placeTower(x, y) {
var towerCost = 50;
if (selectedTowerType === 'slow') {
towerCost = 75;
} else if (selectedTowerType === 'area') {
towerCost = 100;
} else if (selectedTowerType === 'poison') {
towerCost = 80;
} else if (selectedTowerType === 'longrange') {
towerCost = 110;
} else if (selectedTowerType === 'heavy') {
towerCost = 150;
} else if (selectedTowerType === 'super') {
towerCost = 300;
} else if (selectedTowerType === 'doublecannon') {
towerCost = 500;
} else if (selectedTowerType === 'supercannon') {
towerCost = 500;
} else if (selectedTowerType === 'rapid') {
towerCost = 100;
} else if (selectedTowerType === 'freeze') {
towerCost = 150;
} else if (selectedTowerType === 'cactusbomb') {
towerCost = 100;
} else if (selectedTowerType === 'cactus') {
towerCost = 1000;
} else if (selectedTowerType === 'megasuper') {
towerCost = 2000;
} else if (selectedTowerType === 'bomb') {
towerCost = 150;
} else if (selectedTowerType === 'superbomb') {
towerCost = 2000;
} else if (selectedTowerType === 'nuclear') {
towerCost = 10000;
} else if (selectedTowerType === 'multitarget') {
towerCost = 1500;
}
if (!placingTower || playerMoney < towerCost) {
return false;
}
// Check if position is valid (not on path)
for (var i = 0; i < pathSegments.length; i++) {
var pathSegment = pathSegments[i];
var dx = pathSegment.x - x;
var dy = pathSegment.y - y;
if (Math.sqrt(dx * dx + dy * dy) < 80) {
return false; // Too close to path
}
}
// Check if position is valid (not too close to other towers)
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - x;
var dy = tower.y - y;
if (Math.sqrt(dx * dx + dy * dy) < 100) {
return false; // Too close to another tower
}
}
var tower;
if (selectedTowerType === 'slow') {
tower = new SlowTower();
} else if (selectedTowerType === 'area') {
tower = new AreaTower();
} else if (selectedTowerType === 'poison') {
tower = new PoisonTower();
} else if (selectedTowerType === 'longrange') {
tower = new LongRangeTower();
} else if (selectedTowerType === 'heavy') {
tower = new HeavyTower();
} else if (selectedTowerType === 'super') {
tower = new SuperTower();
} else if (selectedTowerType === 'doublecannon') {
tower = new DoubleCannon();
} else if (selectedTowerType === 'supercannon') {
tower = new SuperCannon();
} else if (selectedTowerType === 'rapid') {
tower = new RapidTower();
} else if (selectedTowerType === 'freeze') {
tower = new FreezeTower();
} else if (selectedTowerType === 'cactusbomb') {
tower = new CactusBomb();
} else if (selectedTowerType === 'cactus') {
tower = new CactusTower();
} else if (selectedTowerType === 'megasuper') {
tower = new MegaSuperTower();
} else if (selectedTowerType === 'bomb') {
tower = new Bomb();
} else if (selectedTowerType === 'superbomb') {
tower = new SuperBomb();
} else if (selectedTowerType === 'nuclear') {
tower = new NuclearBomb();
} else if (selectedTowerType === 'multitarget') {
tower = new MultiTargetTower();
} else {
tower = new Tower();
}
tower.x = x;
tower.y = y;
towers.push(tower);
game.addChild(tower);
// Move tower to back so it appears behind UI elements
for (var j = 0; j < pathSegments.length; j++) {
game.setChildIndex(tower, j + 1);
break;
}
playerMoney -= tower.cost;
updateMoneyDisplay();
// Only stop placing if player doesn't have enough money for another tower
if (playerMoney < towerCost) {
placingTower = false;
}
return true;
}
// Event handlers
shopBtn.down = function (x, y, obj) {
toggleShop();
};
readyBtn.down = function (x, y, obj) {
if (!waveInProgress) {
startWave();
}
};
basicTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 50) {
placingTower = true;
selectedTowerType = 'basic';
}
};
slowTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 75) {
placingTower = true;
selectedTowerType = 'slow';
}
};
areaTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 100) {
placingTower = true;
selectedTowerType = 'area';
}
};
poisonTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 80) {
placingTower = true;
selectedTowerType = 'poison';
}
};
longRangeTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 110) {
placingTower = true;
selectedTowerType = 'longrange';
}
};
heavyTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 150) {
placingTower = true;
selectedTowerType = 'heavy';
}
};
superTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 300) {
placingTower = true;
selectedTowerType = 'super';
}
};
doubleCannonBtn.down = function (x, y, obj) {
if (playerMoney >= 500) {
placingTower = true;
selectedTowerType = 'doublecannon';
}
};
superCannonBtn.down = function (x, y, obj) {
if (playerMoney >= 500) {
placingTower = true;
selectedTowerType = 'supercannon';
}
};
rapidTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 100) {
placingTower = true;
selectedTowerType = 'rapid';
}
};
freezeTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 150) {
placingTower = true;
selectedTowerType = 'freeze';
}
};
cactusBombBtn.down = function (x, y, obj) {
if (playerMoney >= 100) {
placingTower = true;
selectedTowerType = 'cactusbomb';
}
};
cactusTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 1000) {
placingTower = true;
selectedTowerType = 'cactus';
}
};
megaSuperTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 2000) {
placingTower = true;
selectedTowerType = 'megasuper';
}
};
bombBtn.down = function (x, y, obj) {
if (playerMoney >= 150) {
placingTower = true;
selectedTowerType = 'bomb';
}
};
superBombBtn.down = function (x, y, obj) {
if (playerMoney >= 2000) {
placingTower = true;
selectedTowerType = 'superbomb';
}
};
nuclearBombBtn.down = function (x, y, obj) {
if (playerMoney >= 10000) {
placingTower = true;
selectedTowerType = 'nuclear';
}
};
multiTargetBtn.down = function (x, y, obj) {
if (playerMoney >= 1500) {
placingTower = true;
selectedTowerType = 'multitarget';
}
};
closeShopBtn.down = function (x, y, obj) {
toggleShop();
};
// Start Menu Event Handlers
playBtn.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
}
};
waveSelectBtn.down = function (x, y, obj) {
if (!gameStarted) {
hideStartMenu();
showWaveSelect();
showingWaveSelect = true;
}
};
waveMinusBtn.down = function (x, y, obj) {
if (showingWaveSelect && selectedStartWave > 1) {
selectedStartWave--;
updateWaveDisplay();
}
};
wavePlusBtn.down = function (x, y, obj) {
if (showingWaveSelect && selectedStartWave < 50) {
selectedStartWave++;
updateWaveDisplay();
}
};
startGameBtn.down = function (x, y, obj) {
if (showingWaveSelect) {
startGame();
}
};
backBtn.down = function (x, y, obj) {
if (showingWaveSelect) {
hideWaveSelect();
showStartMenu();
showingWaveSelect = false;
}
};
// Sandbox mode event handlers
sandboxBtn.down = function (x, y, obj) {
if (!gameStarted) {
startSandboxMode();
}
};
enemyShopBtn.down = function (x, y, obj) {
if (sandboxMode) {
toggleEnemyShop();
}
};
spawnEnemyBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('basic');
}
};
spawnFastBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('fast');
}
};
spawnTankBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('tank');
}
};
spawnBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('boss');
}
};
spawnMageBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('mage');
}
};
spawnSuperMageBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('supermage');
}
};
spawnTankBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('tankboss');
}
};
spawnArmoredBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('armored');
}
};
spawnPigBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('pig');
}
};
spawnMoleBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('mole');
}
};
spawnSkeletonBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('skeleton');
}
};
spawnSuperTank2Btn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('supertank2');
}
};
spawnArmorBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('armorboss');
}
};
spawnObsidianBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('obsidianboss');
}
};
spawnObsidianArmorBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('obsidianarmor');
}
};
spawnGoldBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('goldboss');
}
};
spawnSuperOmegaTankBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('superomegatank');
}
};
spawnSuperOmegaArmorBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('superomegaarmor');
}
};
spawnSpawnerBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('spawner');
}
};
spawnBalloonBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('balloon');
}
};
closeEnemyShopBtn.down = function (x, y, obj) {
if (sandboxMode) {
toggleEnemyShop();
}
};
// Initially hide game UI elements
moneyText.visible = false;
livesText.visible = false;
waveText.visible = false;
shopBtn.visible = false;
shopBtnText.visible = false;
readyBtn.visible = false;
readyBtnText.visible = false;
// Initially hide all shop text elements
basicTowerText.visible = false;
slowTowerText.visible = false;
areaTowerText.visible = false;
poisonTowerText.visible = false;
longRangeTowerText.visible = false;
heavyTowerText.visible = false;
superTowerText.visible = false;
doubleCannonText.visible = false;
superCannonText.visible = false;
rapidTowerText.visible = false;
freezeTowerText.visible = false;
cactusBombText.visible = false;
cactusTowerText.visible = false;
megaSuperTowerText.visible = false;
bombText.visible = false;
superBombText.visible = false;
nuclearBombText.visible = false;
multiTargetText.visible = false;
closeShopText.visible = false;
shopTitle.visible = false;
game.down = function (x, y, obj) {
// Don't handle game clicks if not started or in menu
if (!gameStarted || showingWaveSelect) {
return;
}
// Don't place towers if clicking on UI elements (shop area or buttons)
if (y > 2400) {
return; // Clicking in UI area at bottom
}
// Don't place towers if clicking on shop button
if (x >= 100 && x <= 300 && y >= 2460 && y <= 2540) {
return; // Clicking on shop button
}
// Don't place towers if clicking on ready button
if (x >= 400 && x <= 600 && y >= 2460 && y <= 2540) {
return; // Clicking on ready button
}
// Don't place towers if clicking on enemy shop button (sandbox mode)
if (sandboxMode && x >= 700 && x <= 900 && y >= 2460 && y <= 2540) {
return; // Clicking on enemy shop button
}
// Don't place towers if shop is open and clicking in entire expanded shop area
if (shopOpen) {
// Check for all shop button areas with proper scaling (scaleX: 2.2, scaleY: 2.2)
// Basic tower button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 450 - 100 * 2.2 / 2 && y <= shopPanel.y - 450 + 100 * 2.2 / 2) {
return;
}
// Slow tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y - 450 - 100 * 2.2 / 2 && y <= shopPanel.y - 450 + 100 * 2.2 / 2) {
return;
}
// Area tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 450 - 100 * 2.2 / 2 && y <= shopPanel.y - 450 + 100 * 2.2 / 2) {
return;
}
// Poison tower button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 250 - 100 * 2.2 / 2 && y <= shopPanel.y - 250 + 100 * 2.2 / 2) {
return;
}
// Long range tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y - 250 - 100 * 2.2 / 2 && y <= shopPanel.y - 250 + 100 * 2.2 / 2) {
return;
}
// Heavy tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 250 - 100 * 2.2 / 2 && y <= shopPanel.y - 250 + 100 * 2.2 / 2) {
return;
}
// Super tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y - 50 - 100 * 2.2 / 2 && y <= shopPanel.y - 50 + 100 * 2.2 / 2) {
return;
}
// Double cannon button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 150 - 100 * 2.2 / 2 && y <= shopPanel.y + 150 + 100 * 2.2 / 2) {
return;
}
// Super cannon button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 150 - 100 * 2.2 / 2 && y <= shopPanel.y + 150 + 100 * 2.2 / 2) {
return;
}
// Rapid tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 150 - 100 * 2.2 / 2 && y <= shopPanel.y + 150 + 100 * 2.2 / 2) {
return;
}
// Freeze tower button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 350 - 100 * 2.2 / 2 && y <= shopPanel.y + 350 + 100 * 2.2 / 2) {
return;
}
// Cactus bomb button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 50 - 100 * 2.2 / 2 && y <= shopPanel.y - 50 + 100 * 2.2 / 2) {
return;
}
// Cactus tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 50 - 100 * 2.2 / 2 && y <= shopPanel.y - 50 + 100 * 2.2 / 2) {
return;
}
// Mega super tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 350 - 100 * 2.2 / 2 && y <= shopPanel.y + 350 + 100 * 2.2 / 2) {
return;
}
// Bomb button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 350 - 100 * 2.2 / 2 && y <= shopPanel.y + 350 + 100 * 2.2 / 2) {
return;
}
// Super bomb button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 550 - 100 * 2.2 / 2 && y <= shopPanel.y + 550 + 100 * 2.2 / 2) {
return;
}
// Nuclear bomb button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 550 - 100 * 2.2 / 2 && y <= shopPanel.y + 550 + 100 * 2.2 / 2) {
return;
}
// Multi target button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 550 - 100 * 2.2 / 2 && y <= shopPanel.y + 550 + 100 * 2.2 / 2) {
return;
}
// Close shop button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 850 - 100 * 2.2 / 2 && y <= shopPanel.y + 850 + 100 * 2.2 / 2) {
return;
}
}
// Don't place towers if enemy shop is open and clicking in enemy shop area
if (showingEnemyShop && x > 724 && x < 1324 && y > 866 && y < 1866) {
return; // Clicking inside enemy shop panel
}
if (placingTower) {
placeTower(x, y);
} else {
// Check if clicking on an existing tower to remove it
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - x;
var dy = tower.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If clicking within tower bounds (75px radius)
if (distance <= 75) {
// Refund the tower cost
playerMoney += tower.cost;
updateMoneyDisplay();
// Remove tower from game and array
tower.destroy();
towers.splice(i, 1);
return; // Exit after removing first tower found
}
}
}
};
game.up = function (x, y, obj) {
// Don't handle game clicks if not started or in menu
if (!gameStarted || showingWaveSelect) {
return;
}
// Double tap to cancel tower placement
if (placingTower && obj.doubleTap) {
placingTower = false;
selectedTowerType = null;
}
};
// Main game loop
game.update = function () {
// Don't update game logic if not started
if (!gameStarted) {
return;
}
// Show game UI when game starts
if (gameStarted && !moneyText.visible) {
moneyText.visible = true;
livesText.visible = !sandboxMode; // Hide lives in sandbox mode
waveText.visible = !sandboxMode; // Hide wave text in sandbox mode
shopBtn.visible = true;
shopBtnText.visible = true;
readyBtn.visible = !sandboxMode; // Hide ready button in sandbox mode
readyBtnText.visible = !sandboxMode;
enemyShopBtn.visible = sandboxMode; // Show enemy shop in sandbox mode
enemyShopBtnText.visible = sandboxMode;
updateWaveDisplay();
}
// Update towers
for (var i = 0; i < towers.length; i++) {
towers[i].update();
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.update();
// Remove dead enemies
if (enemy.health <= 0) {
enemy.destroy();
enemies.splice(i, 1);
}
// Remove enemies that reached the end
else if (enemy.pathIndex >= enemyPath.length) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
var shouldRemove = bullet.update();
if (shouldRemove || !bullet.target || bullet.target.health <= 0) {
bullet.destroy();
bullets.splice(i, 1);
}
}
// Check for game over (only in normal mode)
if (!sandboxMode && playerLives <= 0) {
LK.showGameOver();
}
// Keep money infinite in sandbox mode
if (sandboxMode && playerMoney < 999999) {
playerMoney = 999999;
updateMoneyDisplay();
}
// Update lives display if changed
updateLivesDisplay();
// Check if wave is complete
checkWaveComplete();
// Game continues indefinitely - no win condition
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AreaTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('areaTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 160;
self.damage = 2;
self.areaDamage = 100; // Area damage radius
self.fireRate = 90; // Slower fire rate due to area effect
self.lastShot = 0;
self.cost = 100;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.explode = function (targetX, targetY) {
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: targetX,
y: targetY
}));
// Animate explosion
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - targetX;
var dy = enemy.y - targetY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.areaDamage) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
self.explode(target.x, target.y);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomba', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200; // Detection range
self.explosionRadius = 150; // Explosion area
self.damage = 200; // Explosion damage
self.cost = 150;
self.hasExploded = false;
self.checkExplosion = function () {
if (self.hasExploded) {
return;
}
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
self.explode();
return;
}
}
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
// Animate explosion
tween(explosion, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 600,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in explosion area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
// Remove bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
self.checkExplosion();
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.target = null;
self.damage = 1;
self.update = function () {
if (!self.target || self.target.health <= 0) {
return;
}
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20) {
// Hit target
if (self.target.takeDamage(self.damage, self.fromCactusTower)) {
// Enemy died, give reward
playerMoney += self.target.reward;
updateMoneyDisplay();
}
return true; // Mark for removal
}
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
};
return self;
});
var CactusBomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bombacaptus', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200; // Detection range for balloons
self.damage = 50; // Damage per bullet
self.cost = 100;
self.hasExploded = false;
self.bulletCount = 8; // Number of bullets to shoot in all directions
self.checkExplosion = function () {
if (self.hasExploded) {
return;
}
// Check for balloon enemies in range
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Only target balloon enemies
if (enemy.constructor !== BalloonEnemy) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
self.explode();
return;
}
}
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
// Animate explosion
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Launch bullets in all directions
for (var i = 0; i < self.bulletCount; i++) {
var angle = i / self.bulletCount * 2 * Math.PI;
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.damage = self.damage;
bullet.speed = 6;
// Create a fake target for directional movement
bullet.target = {
x: self.x + Math.cos(angle) * 1000,
y: self.y + Math.sin(angle) * 1000,
health: 1
};
// Override bullet update for directional movement
bullet.update = function () {
var dx = this.target.x - this.x;
var dy = this.target.y - this.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
return true; // Mark for removal
}
// Check collision with balloon enemies
for (var j = 0; j < enemies.length; j++) {
var enemy = enemies[j];
if (enemy.constructor === BalloonEnemy) {
var enemyDx = enemy.x - this.x;
var enemyDy = enemy.y - this.y;
var enemyDistance = Math.sqrt(enemyDx * enemyDx + enemyDy * enemyDy);
if (enemyDistance < 30) {
if (enemy.takeDamage(this.damage, true)) {
// Mark as from cactus
playerMoney += enemy.reward;
updateMoneyDisplay();
}
return true; // Mark for removal
}
}
}
this.x += dx / distance * this.speed;
this.y += dy / distance * this.speed;
};
bullets.push(bullet);
game.addChild(bullet);
}
// Remove bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
self.checkExplosion();
};
return self;
});
var CactusTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('captus', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x228B22; // Forest green color for cactus tower
self.range = 2732; // Very long range - full screen
self.damage = 12; // Good damage
self.fireRate = 80; // Faster than long range tower
self.lastShot = 0;
self.cost = 1000; // High cost
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = 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 <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullet.fromCactusTower = true; // Mark as cactus tower bullet
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var DoubleCannon = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('doble', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 300; // Long range
self.damage = 8; // High damage per bullet
self.fireRate = 90; // Moderate fire rate
self.lastShot = 0;
self.cost = 500;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
// Fire two bullets simultaneously
for (var i = 0; i < 2; i++) {
var bullet = new Bullet();
bullet.x = self.x + (i === 0 ? -10 : 10); // Offset bullets slightly
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
}
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.speed = 2;
self.pathIndex = 0;
self.reward = 10;
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
self.update = function () {
// Create health bar if it doesn't exist
if (!self.healthBarBg) {
// Health bar background (red)
self.healthBarBg = self.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -50,
scaleX: 0.4,
scaleY: 0.15
}));
self.healthBarBg.tint = 0xFF0000;
// Health bar foreground (green)
self.healthBarFg = self.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -50,
scaleX: 0.4,
scaleY: 0.15
}));
self.healthBarFg.tint = 0x4CAF50;
}
// Update health bar
var healthPercent = self.health / self.maxHealth;
self.healthBarFg.scaleX = 0.4 * healthPercent;
// Hide health bar if at full health
if (healthPercent >= 1.0) {
self.healthBarBg.visible = false;
self.healthBarFg.visible = false;
} else {
self.healthBarBg.visible = true;
self.healthBarFg.visible = true;
}
// Check if freeze effect should end
if (self.isFrozen && LK.ticks >= self.freezeEndTick) {
self.speed = self.originalSpeed;
self.isFrozen = false;
// Remove freeze tint
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 200
});
}
// Check if slow effect should end
if (self.isSlowed && LK.ticks >= self.slowEndTick) {
self.speed = self.originalSpeed;
self.isSlowed = false;
// Remove blue tint
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 200
});
}
// Handle poison effect
if (self.isPoisoned) {
if (LK.ticks >= self.poisonEndTick) {
self.isPoisoned = false;
// Remove green tint
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 200
});
} else if (LK.ticks >= self.lastPoisonTick + self.poisonTickInterval) {
if (self.takeDamage(self.poisonDamage)) {
playerMoney += self.reward;
updateMoneyDisplay();
}
self.lastPoisonTick = LK.ticks;
}
}
if (self.pathIndex >= enemyPath.length) {
return;
}
var targetPoint = enemyPath[self.pathIndex];
var dx = targetPoint.x - self.x;
var dy = targetPoint.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.pathIndex++;
if (self.pathIndex >= enemyPath.length) {
// Enemy reached base
playerLives--;
return;
}
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var TankEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with different color and size
self.children[0].destroy();
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
enemyGraphics.tint = 0x9c27b0; // Purple color
self.health = 40;
self.maxHealth = 40;
self.speed = 1; // Slower than normal enemy
self.reward = 25; // Higher reward
return self;
});
var TankBossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('tankboss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
enemyGraphics.tint = 0x263238; // Very dark grey for extreme tank boss
self.health = 1000; // Extremely high health
self.maxHealth = 1000;
self.speed = 0.4; // Very slow due to extreme armor
self.reward = 100; // Very high reward for extreme difficulty
self.armor = 0.5; // Takes 50% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash red when hit with special armor effect
tween(self.children[0], {
tint: 0x795548
}, {
duration: 150,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x263238
}, {
duration: 150
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossObsidianEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with obsidian tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('obcidiaa', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 3.0
});
enemyGraphics.tint = 0x1a1a1a; // Very dark color for obsidian tank boss
self.health = 6000; // Extremely high health
self.maxHealth = 6000;
self.speed = 0.2; // Extremely slow due to obsidian armor
self.reward = 500; // Highest reward for ultimate difficulty
self.armor = 0.9; // Takes 90% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash purple when hit with special obsidian effect
tween(self.children[0], {
tint: 0x9C27B0
}, {
duration: 250,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x1a1a1a
}, {
duration: 250
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossObsidianArmorEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with obsidian armor tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('obcidiaaarmor', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.5,
scaleY: 3.5
});
enemyGraphics.tint = 0x0a0a0a; // Ultra dark color for obsidian armor tank boss
self.health = 10000; // Ultimate high health
self.maxHealth = 10000;
self.speed = 0.15; // Extremely slow due to ultimate armor
self.reward = 800; // Ultimate reward for ultimate difficulty
self.armor = 0.95; // Takes 95% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash gold when hit with special obsidian armor effect
tween(self.children[0], {
tint: 0xFFD700
}, {
duration: 300,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x0a0a0a
}, {
duration: 300
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossGoldEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with gold tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('gold', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 4.0
});
enemyGraphics.tint = 0xFFD700; // Gold color for ultimate tank boss
self.health = 15000; // Maximum health
self.maxHealth = 15000;
self.speed = 0.1; // Extremely slow due to ultimate weight
self.reward = 1200; // Maximum reward for ultimate difficulty
self.armor = 0.98; // Takes 98% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash white when hit with special gold effect
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 400,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0xFFD700
}, {
duration: 400
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBossArmorEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with armor tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('armor', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
enemyGraphics.tint = 0x424242; // Dark grey color for armor tank boss
self.health = 4000; // Very high health
self.maxHealth = 4000;
self.speed = 0.25; // Very slow due to heavy armor
self.reward = 300; // Very high reward for extreme difficulty
self.armor = 0.8; // Takes 80% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash red when hit with special armor effect
tween(self.children[0], {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x424242
}, {
duration: 200
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperTankBoss2Enemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('super', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
enemyGraphics.tint = 0x8B0000; // Dark red color for super tank boss
self.health = 2000; // Extremely high health
self.maxHealth = 2000;
self.speed = 0.3; // Very slow due to massive armor
self.reward = 200; // Very high reward for extreme difficulty
self.armor = 0.7; // Takes 70% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash red when hit with special armor effect
tween(self.children[0], {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x8B0000
}, {
duration: 200
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperOmegaTankBossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super omega tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('omega', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 4.0
});
enemyGraphics.tint = 0x8B008B; // Dark magenta color for super omega tank boss
self.health = 30000; // Massive health
self.maxHealth = 30000;
self.speed = 0.08; // Extremely slow due to massive size
self.reward = 2000; // Extreme reward for ultimate difficulty
self.armor = 0.99; // Takes 99% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash bright white when hit with special omega effect
tween(self.children[0], {
tint: 0xFFFFFF
}, {
duration: 500,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x8B008B
}, {
duration: 500
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperOmegaArmorTankBossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super omega armor tank boss appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('omegaarmor', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5.0,
scaleY: 5.0
});
enemyGraphics.tint = 0x4B0082; // Indigo color for super omega armor tank boss
self.health = 50000; // Ultimate health
self.maxHealth = 50000;
self.speed = 0.05; // Extremely slow due to ultimate armor
self.reward = 3000; // Ultimate reward for ultimate difficulty
self.armor = 0.995; // Takes 99.5% less damage from all sources
// Override takeDamage to apply armor reduction
self.takeDamage = function (damage) {
var reducedDamage = Math.max(1, Math.floor(damage * (1 - self.armor)));
self.health -= reducedDamage;
// Flash rainbow colors when hit with special omega armor effect
tween(self.children[0], {
tint: 0xFF00FF
}, {
duration: 600,
onFinish: function onFinish() {
tween(self.children[0], {
tint: 0x4B0082
}, {
duration: 600
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var SuperMageEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with super mage appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('supermago', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0x8A2BE2; // Purple color for super mage
self.health = 8; // Higher resistance than normal mage
self.maxHealth = 8;
self.speed = 2.0; // Good speed
self.reward = 50; // Higher reward
self.hasTeleported = false; // Track if super mage has teleported
self.teleportCount = 0; // Track number of teleports
self.maxTeleports = 2; // Can teleport twice
self.teleport = function () {
if (self.teleportCount >= self.maxTeleports || self.pathIndex >= enemyPath.length - 2) {
return;
}
// Calculate larger teleport distance (jump forward 5-8 path points)
var teleportDistance = 5 + Math.floor(Math.random() * 4);
var newPathIndex = Math.min(self.pathIndex + teleportDistance, enemyPath.length - 1);
// Enhanced visual teleport effect - flash purple and create magical effect
tween(self.children[0], {
tint: 0xFF00FF,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.1,
rotation: Math.PI * 2
}, {
duration: 500,
onFinish: function onFinish() {
// Move to new position instantly
self.x = enemyPath[newPathIndex].x;
self.y = enemyPath[newPathIndex].y;
self.pathIndex = newPathIndex;
// Reappear with enhanced effect
tween(self.children[0], {
tint: 0x8A2BE2,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0,
rotation: 0
}, {
duration: 500
});
}
});
self.teleportCount++;
};
// Override update to include enhanced teleport logic
var originalUpdate = self.update;
self.update = function () {
// Teleport more frequently - at 25% and 75% of path
var pathProgress = self.pathIndex / (enemyPath.length - 1);
if (self.teleportCount === 0 && pathProgress >= 0.25) {
self.teleport();
} else if (self.teleportCount === 1 && pathProgress >= 0.75) {
self.teleport();
}
originalUpdate.call(self);
};
return self;
});
var SpawnerEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with spawner head appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('cabeza', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 25;
self.maxHealth = 25;
self.speed = 1.0;
self.reward = 50;
self.isInvulnerable = true; // Start invulnerable
self.pathProgress = 0; // Track progress along path (0 to 1)
self.vulnerabilityThreshold = 0.5; // Becomes vulnerable at 50% of path
self.lastSpawnTime = 0; // Track last spawn time
self.spawnInterval = 300; // 5 seconds (5 * 60 ticks)
// Override takeDamage to handle invulnerability
self.takeDamage = function (damage) {
if (self.isInvulnerable) {
return false; // No damage taken while invulnerable
}
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
if (self.health <= 0) {
// Spawn 3 fast enemies when dying
self.spawnEnemiesOnDeath();
return true;
}
return false;
};
self.spawnEnemiesOnDeath = function () {
for (var i = 0; i < 3; i++) {
var spawnedEnemy = new FastEnemy();
// Override graphics with famtasma asset
spawnedEnemy.children[0].destroy();
var spawnedGraphics = spawnedEnemy.attachAsset('famtasma', {
anchorX: 0.5,
anchorY: 0.5
});
spawnedEnemy.x = self.x + (Math.random() - 0.5) * 60; // Random positioning around spawner
spawnedEnemy.y = self.y + (Math.random() - 0.5) * 60;
spawnedEnemy.pathIndex = self.pathIndex; // Start from same path position
enemies.push(spawnedEnemy);
game.addChild(spawnedEnemy);
}
};
self.spawnEnemy = function () {
if (LK.ticks - self.lastSpawnTime >= self.spawnInterval) {
var spawnedEnemy = new FastEnemy();
// Override graphics with famtasma asset
spawnedEnemy.children[0].destroy();
var spawnedGraphics = spawnedEnemy.attachAsset('famtasma', {
anchorX: 0.5,
anchorY: 0.5
});
spawnedEnemy.x = self.x;
spawnedEnemy.y = self.y;
spawnedEnemy.pathIndex = self.pathIndex; // Start from same path position
enemies.push(spawnedEnemy);
game.addChild(spawnedEnemy);
self.lastSpawnTime = LK.ticks;
}
};
// Override update to handle vulnerability transition and spawning
var originalUpdate = self.update;
self.update = function () {
// Calculate progress along path
if (enemyPath.length > 1) {
self.pathProgress = self.pathIndex / (enemyPath.length - 1);
}
// Check if should become vulnerable
if (self.isInvulnerable && self.pathProgress >= self.vulnerabilityThreshold) {
self.isInvulnerable = false;
// Flash to indicate vulnerability change
tween(enemyGraphics, {
tint: 0x00FF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 300
});
}
});
}
// Spawn enemies every 5 seconds while alive
self.spawnEnemy();
// Call original update
originalUpdate.call(self);
};
return self;
});
var SkeletonEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with skeleton appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('skeleton', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0xf5f5f5; // Light grey/white color for skeleton
self.health = 1;
self.maxHealth = 1;
self.speed = 2.5; // Slightly faster than normal enemy
self.reward = 8; // Lower reward since they come in groups
return self;
});
var PigEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with pig enemy asset
self.children[0].destroy();
var enemyGraphics = self.attachAsset('pigEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 1.2; // Slightly slower than normal enemy
self.reward = 30; // High reward for very tough enemy
return self;
});
var MoleEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with mole appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('topo', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 5;
self.maxHealth = 5;
self.speed = 1.5;
self.reward = 25;
self.isInvulnerable = true; // Start invulnerable
self.pathProgress = 0; // Track progress along path (0 to 1)
self.vulnerabilityThreshold = 0.5; // Becomes vulnerable at 50% of path
// Override takeDamage to handle invulnerability
self.takeDamage = function (damage) {
if (self.isInvulnerable) {
return false; // No damage taken while invulnerable
}
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
// Override update to handle vulnerability transition
var originalUpdate = self.update;
self.update = function () {
// Calculate progress along path
if (enemyPath.length > 1) {
self.pathProgress = self.pathIndex / (enemyPath.length - 1);
}
// Check if should become vulnerable
if (self.isInvulnerable && self.pathProgress >= self.vulnerabilityThreshold) {
self.isInvulnerable = false;
// Change graphics to vulnerable state
enemyGraphics.destroy();
enemyGraphics = self.attachAsset('topo2', {
anchorX: 0.5,
anchorY: 0.5
});
// Flash to indicate vulnerability change
tween(enemyGraphics, {
tint: 0x00FF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 300
});
}
});
}
// Call original update
originalUpdate.call(self);
};
return self;
});
var MageEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with mage appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('mage', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 4;
self.maxHealth = 4;
self.speed = 1.8;
self.reward = 20;
self.hasTeleported = false; // Track if mage has teleported
self.teleport = function () {
if (self.hasTeleported || self.pathIndex >= enemyPath.length - 2) {
return;
}
// Calculate teleport distance (jump forward 3-6 path points)
var teleportDistance = 3 + Math.floor(Math.random() * 4);
var newPathIndex = Math.min(self.pathIndex + teleportDistance, enemyPath.length - 1);
// Visual teleport effect - flash purple and disappear
tween(self.children[0], {
tint: 0x9c27b0,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.2
}, {
duration: 300,
onFinish: function onFinish() {
// Move to new position instantly
self.x = enemyPath[newPathIndex].x;
self.y = enemyPath[newPathIndex].y;
self.pathIndex = newPathIndex;
// Reappear with effect
tween(self.children[0], {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
}, {
duration: 300
});
}
});
self.hasTeleported = true;
};
// Override update to include teleport logic
var originalUpdate = self.update;
self.update = function () {
// Teleport immediately when the mage appears (after first update tick)
if (!self.hasTeleported && LK.ticks > 0) {
self.teleport();
}
originalUpdate.call(self);
};
return self;
});
var FastEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with dedicated fast enemy asset
self.children[0].destroy();
var enemyGraphics = self.attachAsset('fastEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.maxHealth = 2;
self.speed = 5; // Much faster than normal enemy
self.reward = 15; // Higher reward
return self;
});
var BossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with different color and much larger size
self.children[0].destroy();
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
enemyGraphics.tint = 0x000000; // Black color for boss
self.health = 15;
self.maxHealth = 15;
self.speed = 0.8; // Very slow but very tough
self.reward = 50; // High reward for boss
return self;
});
var BalloonEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with balloon appearance
self.children[0].destroy();
var enemyGraphics = self.attachAsset('globo', {
anchorX: 0.5,
anchorY: 0.5
});
enemyGraphics.tint = 0xFF69B4; // Pink color for balloon
self.health = 15;
self.maxHealth = 15;
self.speed = 1.8; // Fairly fast
self.reward = 40; // Good reward
self.isInvulnerable = true; // Invulnerable to all towers except cactus
// Override takeDamage to handle invulnerability
self.takeDamage = function (damage, fromCactusTower) {
// Only take damage from cactus towers
if (!fromCactusTower) {
return false; // No damage taken from other towers
}
self.health -= damage;
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFF69B4
}, {
duration: 100
});
}
});
LK.getSound('enemyHit').play();
return self.health <= 0;
};
return self;
});
var ArmoredEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Override graphics with different color and size
self.children[0].destroy();
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
enemyGraphics.tint = 0x607d8b; // Blue-grey color for armor
self.health = 5;
self.maxHealth = 5;
self.speed = 1.5; // Slightly slower than normal enemy
self.reward = 20; // Higher reward for tougher enemy
return self;
});
var FreezeTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('stop', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2048; // Full screen range
self.freezeDuration = 600; // 10 seconds (10 * 60 ticks)
self.fireRate = 1800; // 30 seconds between shots (30 * 60 ticks)
self.lastShot = 0;
self.cost = 150;
self.frozenEnemy = null; // Track currently frozen enemy
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
// Only target if no enemy is currently frozen
if (self.frozenEnemy && self.frozenEnemy.isFrozen) {
return null; // Can't freeze another enemy while one is frozen
}
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance && !enemy.isFrozen) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.freezeEnemy = function (target) {
if (!self.canShoot()) {
return;
}
// Apply freeze effect
target.isFrozen = true;
target.originalSpeed = target.speed;
target.speed = 0; // Stop the enemy
target.freezeEndTick = LK.ticks + self.freezeDuration;
self.frozenEnemy = target; // Track this frozen enemy
// Visual effect - tint enemy light blue
tween(target.children[0], {
tint: 0x87CEEB
}, {
duration: 300
});
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
// Check if frozen enemy is no longer frozen
if (self.frozenEnemy && (!self.frozenEnemy.isFrozen || self.frozenEnemy.health <= 0)) {
self.frozenEnemy = null;
}
var target = self.findTarget();
if (target) {
self.freezeEnemy(target);
}
};
return self;
});
var HeavyTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('heavyTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x795548; // Brown color for heavy tower
self.range = 180;
self.damage = 15; // High damage
self.fireRate = 300; // Very slow fire rate (5 seconds)
self.lastShot = 0;
self.cost = 150;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var LongRangeTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('longRangeTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2732; // Full screen range (height of screen)
self.damage = 2;
self.fireRate = 90; // Moderate fire rate
self.lastShot = 0;
self.cost = 110;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var MegaSuperTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0xFF0000; // Red color for mega super tower
self.range = 2732; // Full screen range
self.damage = 500; // Massive damage
self.fireRate = 1800; // 30 seconds (30 * 60 ticks)
self.lastShot = 0;
self.cost = 2000;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var strongestEnemy = null;
var highestHealth = 0;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && enemy.health > highestHealth) {
highestHealth = enemy.health;
strongestEnemy = enemy;
}
}
return strongestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
// Special visual effect for mega super shot
tween(towerGraphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFFFFF
}, {
duration: 500,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFF0000
}, {
duration: 500
});
}
});
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var MultiTargetTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('triple', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2732; // Full screen range
self.damage = 300; // High damage per bullet
self.fireRate = 120; // Moderate fire rate
self.lastShot = 0;
self.cost = 7500;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findAllTargets = function () {
var targetsInRange = [];
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
targetsInRange.push(enemy);
}
}
return targetsInRange;
};
self.shootAtAllTargets = function () {
if (!self.canShoot()) {
return;
}
var targets = self.findAllTargets();
if (targets.length === 0) {
return;
}
// Fire a bullet at each enemy simultaneously
for (var i = 0; i < targets.length; i++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = targets[i];
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
}
self.lastShot = LK.ticks;
// Special visual effect for multi-shot
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 300,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFF00FF
}, {
duration: 300
});
}
});
LK.getSound('shoot').play();
};
self.update = function () {
self.shootAtAllTargets();
};
return self;
});
var NuclearBomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('nuclear', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
self.damage = 5000; // Massive damage
self.cost = 10000;
self.hasExploded = false;
self.isGrowing = false;
self.growthTimer = 0;
self.maxGrowthTime = 60; // 1 second to grow
// Start growing animation immediately when placed
self.startGrowing = function () {
if (self.isGrowing) {
return;
}
self.isGrowing = true;
self.growthTimer = 0;
// Start growing animation
tween(bombGraphics, {
scaleX: 3.0,
scaleY: 3.0,
tint: 0xFFFFFF
}, {
duration: self.maxGrowthTime,
easing: tween.easeOut
});
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create massive nuclear explosion covering entire screen
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 30,
scaleY: 30
}));
explosion.tint = 0x00FF00;
// Animate massive explosion
tween(explosion, {
scaleX: 40,
scaleY: 40,
alpha: 0
}, {
duration: 3000,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage ALL enemies on screen (full screen range)
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
// Remove nuclear bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
if (self.hasExploded) {
return;
}
if (self.isGrowing) {
self.growthTimer++;
if (self.growthTimer >= self.maxGrowthTime) {
self.explode();
}
}
};
// Start growing immediately when created
self.startGrowing();
return self;
});
var PoisonTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('poisonTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 150;
self.poisonDamage = 1;
self.poisonDuration = 180; // 3 seconds of poison
self.fireRate = 120; // Slower fire rate
self.lastShot = 0;
self.cost = 80;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTargetsInRange = function () {
var targetsInRange = [];
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
targetsInRange.push(enemy);
}
}
return targetsInRange;
};
self.applyPoison = function () {
if (!self.canShoot()) {
return;
}
var targets = self.findTargetsInRange();
for (var i = 0; i < targets.length; i++) {
var enemy = targets[i];
if (!enemy.isPoisoned) {
enemy.isPoisoned = true;
enemy.poisonDamage = self.poisonDamage;
enemy.poisonEndTick = LK.ticks + self.poisonDuration;
enemy.poisonTickInterval = 30; // Damage every 0.5 seconds
enemy.lastPoisonTick = LK.ticks;
// Visual effect - tint enemy green
tween(enemy.children[0], {
tint: 0x4caf50
}, {
duration: 200
});
}
}
self.lastShot = LK.ticks;
};
self.update = function () {
self.applyPoison();
};
return self;
});
var RapidTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('rapida', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200; // Increased range
self.damage = 1; // Low damage but very fast
self.fireRate = 15; // Very fast fire rate
self.lastShot = 0;
self.cost = 100;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var SlowTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('slowTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 180;
self.slowEffect = 0.5; // Reduces enemy speed by 50%
self.effectDuration = 120; // Effect lasts 2 seconds (120 ticks)
self.fireRate = 90; // Slower than basic tower
self.lastShot = 0;
self.cost = 75;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTargetsInRange = function () {
var targetsInRange = [];
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
targetsInRange.push(enemy);
}
}
return targetsInRange;
};
self.applySlowEffect = function () {
if (!self.canShoot()) {
return;
}
var targets = self.findTargetsInRange();
for (var i = 0; i < targets.length; i++) {
var enemy = targets[i];
if (!enemy.isSlowed) {
enemy.isSlowed = true;
enemy.originalSpeed = enemy.speed;
enemy.speed = enemy.originalSpeed * self.slowEffect;
enemy.slowEndTick = LK.ticks + self.effectDuration;
// Visual effect - tint enemy blue
tween(enemy.children[0], {
tint: 0x2196f3
}, {
duration: 200
});
}
}
self.lastShot = LK.ticks;
};
self.update = function () {
self.applySlowEffect();
};
return self;
});
var SuperBomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('superbomba', {
anchorX: 0.5,
anchorY: 0.5
});
bombGraphics.tint = 0x000000; // Black color for super bomb
self.range = 250; // Detection range
self.explosionRadius = 300; // Massive explosion area
self.damage = 1000; // Massive explosion damage
self.cost = 2000;
self.hasExploded = false;
self.checkExplosion = function () {
if (self.hasExploded) {
return;
}
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
self.explode();
return;
}
}
};
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Create massive explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
// Animate massive explosion
tween(explosion, {
scaleX: 5,
scaleY: 5,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in massive explosion area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
// Remove super bomb from towers array and destroy it
for (var j = 0; j < towers.length; j++) {
if (towers[j] === self) {
towers.splice(j, 1);
break;
}
}
self.destroy();
};
self.update = function () {
self.checkExplosion();
};
return self;
});
var SuperCannon = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('canon', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 2732; // Full screen range
self.damage = 3; // Lower damage per target but area effect
self.areaDamage = 200; // Increased area damage radius
self.fireRate = 120; // Slower fire rate due to area effect
self.lastShot = 0;
self.cost = 500;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.explode = function (targetX, targetY) {
// Create explosion visual effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: targetX,
y: targetY
}));
// Animate explosion
tween(explosion, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage all enemies in large area
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - targetX;
var dy = enemy.y - targetY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.areaDamage) {
if (enemy.takeDamage(self.damage)) {
playerMoney += enemy.reward;
updateMoneyDisplay();
}
}
}
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
self.explode(target.x, target.y);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var SuperTower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x9c27b0; // Purple color for super tower
self.range = 250;
self.damage = 200; // Extreme damage
self.hasFiredThisWave = false;
self.lastWave = 0;
self.cost = 300;
self.canShoot = function () {
// Check if it's a new wave
if (currentWave > self.lastWave) {
self.hasFiredThisWave = false;
self.lastWave = currentWave;
}
return !self.hasFiredThisWave;
};
self.findTarget = function () {
var strongestEnemy = null;
var highestHealth = 0;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && enemy.health > highestHealth) {
highestHealth = enemy.health;
strongestEnemy = enemy;
}
}
return strongestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.hasFiredThisWave = true;
// Special visual effect for super shot
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF
}, {
duration: 200,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0x9c27b0
}, {
duration: 200
});
}
});
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
var Tower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('tower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200;
self.damage = 1;
self.fireRate = 60; // ticks between shots
self.lastShot = 0;
self.cost = 50;
self.canShoot = function () {
return LK.ticks - self.lastShot >= self.fireRate;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Skip invulnerable mole enemies
if (enemy.isInvulnerable) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.shoot = function (target) {
if (!self.canShoot()) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.lastShot = LK.ticks;
LK.getSound('shoot').play();
};
self.update = function () {
var target = self.findTarget();
if (target) {
self.shoot(target);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E7D32
});
/****
* Game Code
****/
// Game variables
var playerMoney = 200;
var playerLives = 10;
var currentWave = 1;
var waveInProgress = false;
var shopOpen = false;
var placingTower = false;
var selectedTowerType = null;
var gameStarted = false;
var showingWaveSelect = false;
var selectedStartWave = 1;
var sandboxMode = false;
var showingEnemyShop = false;
// Game arrays
var towers = [];
var enemies = [];
var bullets = [];
var pathSegments = [];
// Enemy path (comprehensive brown winding path covering the entire screen)
var enemyPath = [{
x: 0,
y: 300
}, {
x: 400,
y: 300
}, {
x: 400,
y: 600
}, {
x: 800,
y: 600
}, {
x: 800,
y: 200
}, {
x: 1200,
y: 200
}, {
x: 1200,
y: 900
}, {
x: 1600,
y: 900
}, {
x: 1600,
y: 500
}, {
x: 2000,
y: 500
}, {
x: 2000,
y: 1100
}, {
x: 1400,
y: 1100
}, {
x: 1400,
y: 1400
}, {
x: 600,
y: 1400
}, {
x: 600,
y: 1800
}, {
x: 1000,
y: 1800
}, {
x: 1000,
y: 2200
}, {
x: 1800,
y: 2200
}, {
x: 1800,
y: 1600
}, {
x: 2048,
y: 1600
}];
// Create visual path segments
for (var i = 0; i < enemyPath.length - 1; i++) {
var startPoint = enemyPath[i];
var endPoint = enemyPath[i + 1];
var segments = Math.ceil(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)) / 80);
for (var j = 0; j <= segments; j++) {
var t = j / segments;
var pathX = startPoint.x + (endPoint.x - startPoint.x) * t;
var pathY = startPoint.y + (endPoint.y - startPoint.y) * t;
var pathSegment = game.addChild(LK.getAsset('pathSegment', {
anchorX: 0.5,
anchorY: 0.5,
x: pathX,
y: pathY
}));
pathSegment.alpha = 0.7;
pathSegments.push(pathSegment);
}
}
// Create base at end of path
var base = game.addChild(LK.getAsset('base', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyPath[enemyPath.length - 1].x,
y: enemyPath[enemyPath.length - 1].y
}));
// Move all game assets to back so shop elements appear on top
// First move all path segments to the very back (index 0)
for (var i = 0; i < pathSegments.length; i++) {
game.setChildIndex(pathSegments[i], 0);
}
// Then move base on top of path segments but still behind other elements
game.setChildIndex(base, pathSegments.length);
// Ensure all UI elements are moved to the front to appear on top of assets
// Helper function to safely move child to top if it exists
function moveToTop(child) {
if (child && child.parent === game) {
game.setChildIndex(child, game.children.length - 1);
}
}
moveToTop(shopBtn);
moveToTop(shopBtnText);
moveToTop(readyBtn);
moveToTop(readyBtnText);
moveToTop(shopPanel);
moveToTop(shopTitle);
moveToTop(basicTowerBtn);
moveToTop(basicTowerText);
moveToTop(slowTowerBtn);
moveToTop(slowTowerText);
moveToTop(areaTowerBtn);
moveToTop(areaTowerText);
moveToTop(poisonTowerBtn);
moveToTop(poisonTowerText);
moveToTop(longRangeTowerBtn);
moveToTop(longRangeTowerText);
moveToTop(heavyTowerBtn);
moveToTop(heavyTowerText);
moveToTop(superTowerBtn);
moveToTop(superTowerText);
moveToTop(doubleCannonBtn);
moveToTop(doubleCannonText);
moveToTop(superCannonBtn);
moveToTop(superCannonText);
moveToTop(rapidTowerBtn);
moveToTop(rapidTowerText);
moveToTop(freezeTowerBtn);
moveToTop(freezeTowerText);
moveToTop(cactusBombBtn);
moveToTop(cactusBombText);
moveToTop(cactusTowerBtn);
moveToTop(cactusTowerText);
moveToTop(megaSuperTowerBtn);
moveToTop(megaSuperTowerText);
moveToTop(bombBtn);
moveToTop(bombText);
moveToTop(superBombBtn);
moveToTop(superBombText);
moveToTop(nuclearBombBtn);
moveToTop(nuclearBombText);
moveToTop(multiTargetBtn);
moveToTop(multiTargetText);
moveToTop(closeShopBtn);
moveToTop(closeShopText);
moveToTop(startMenuTitle);
moveToTop(playBtn);
moveToTop(playBtnText);
moveToTop(waveSelectBtn);
moveToTop(waveSelectBtnText);
moveToTop(waveSelectTitle);
moveToTop(waveMinusBtn);
moveToTop(waveMinusText);
moveToTop(waveDisplayText);
moveToTop(wavePlusBtn);
moveToTop(wavePlusText);
moveToTop(startGameBtn);
moveToTop(startGameBtnText);
moveToTop(sandboxBtn);
moveToTop(sandboxBtnText);
moveToTop(backBtn);
moveToTop(backBtnText);
moveToTop(enemyShopBtn);
moveToTop(enemyShopBtnText);
// UI Elements
var moneyText = new Text2('Money: $' + playerMoney, {
size: 60,
fill: 0xFFFFFF
});
moneyText.anchor.set(0, 0);
moneyText.x = 120;
moneyText.y = 50;
LK.gui.topLeft.addChild(moneyText);
var livesText = new Text2('Lives: ' + playerLives, {
size: 60,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
livesText.x = 120;
livesText.y = 130;
LK.gui.topLeft.addChild(livesText);
var waveText = new Text2('wave: ' + currentWave, {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(1, 0);
LK.gui.topRight.addChild(waveText);
// Shop button
var shopBtn = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2500
}));
var shopBtnText = new Text2('SHOP', {
size: 40,
fill: 0xFFFFFF
});
shopBtnText.anchor.set(0.5, 0.5);
shopBtnText.x = shopBtn.x;
shopBtnText.y = shopBtn.y;
game.addChild(shopBtnText);
// Ready button
var readyBtn = game.addChild(LK.getAsset('readyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 500,
y: 2500
}));
var readyBtnText = new Text2('READY', {
size: 40,
fill: 0xFFFFFF
});
readyBtnText.anchor.set(0.5, 0.5);
readyBtnText.x = readyBtn.x;
readyBtnText.y = readyBtn.y;
game.addChild(readyBtnText);
// Shop panel (initially hidden)
var shopPanel = game.addChild(LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
shopPanel.visible = false;
var shopTitle = new Text2('TOWER SHOP', {
size: 50,
fill: 0xFFFFFF
});
shopTitle.anchor.set(0.5, 0);
shopTitle.x = shopPanel.x;
shopTitle.y = shopPanel.y - 450;
game.addChild(shopTitle);
// Tower shop layout - 3 towers per row with increased spacing
// Row 1: Basic, Slow, Area
var basicTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y - 450,
scaleX: 2.2,
scaleY: 2.2
}));
basicTowerBtn.visible = false;
var basicTowerText = new Text2('Basic Tower\n$50', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
basicTowerText.anchor.set(0.5, 0.5);
basicTowerText.x = basicTowerBtn.x;
basicTowerText.y = basicTowerBtn.y;
game.addChild(basicTowerText);
var slowTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y - 450,
color: 0x2196f3,
scaleX: 2.2,
scaleY: 2.2
}));
slowTowerBtn.visible = false;
var slowTowerText = new Text2('Slow Tower\n$75', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
slowTowerText.anchor.set(0.5, 0.5);
slowTowerText.x = slowTowerBtn.x;
slowTowerText.y = slowTowerBtn.y;
game.addChild(slowTowerText);
var areaTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y - 450,
color: 0xff9800,
scaleX: 2.2,
scaleY: 2.2
}));
areaTowerBtn.visible = false;
var areaTowerText = new Text2('Area Tower\n$100', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
areaTowerText.anchor.set(0.5, 0.5);
areaTowerText.x = areaTowerBtn.x;
areaTowerText.y = areaTowerBtn.y;
game.addChild(areaTowerText);
// Row 2: Poison, Long Range, Heavy
var poisonTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y - 250,
color: 0x4caf50,
scaleX: 2.2,
scaleY: 2.2
}));
poisonTowerBtn.visible = false;
var poisonTowerText = new Text2('Poison Tower\n$80', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
poisonTowerText.anchor.set(0.5, 0.5);
poisonTowerText.x = poisonTowerBtn.x;
poisonTowerText.y = poisonTowerBtn.y;
game.addChild(poisonTowerText);
var longRangeTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y - 250,
color: 0x607d8b,
scaleX: 2.2,
scaleY: 2.2
}));
longRangeTowerBtn.visible = false;
var longRangeTowerText = new Text2('Long Range\n$110', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
longRangeTowerText.anchor.set(0.5, 0.5);
longRangeTowerText.x = longRangeTowerBtn.x;
longRangeTowerText.y = longRangeTowerBtn.y;
game.addChild(longRangeTowerText);
var heavyTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y - 250,
color: 0x795548,
scaleX: 2.2,
scaleY: 2.2
}));
heavyTowerBtn.visible = false;
var heavyTowerText = new Text2('Heavy Tower\n$150', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
heavyTowerText.anchor.set(0.5, 0.5);
heavyTowerText.x = heavyTowerBtn.x;
heavyTowerText.y = heavyTowerBtn.y;
game.addChild(heavyTowerText);
// Row 3: Super Tower (centered)
var superTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y - 50,
color: 0x9c27b0,
scaleX: 2.2,
scaleY: 2.2
}));
superTowerBtn.visible = false;
var superTowerText = new Text2('Super Tower\n$300', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
superTowerText.anchor.set(0.5, 0.5);
superTowerText.x = superTowerBtn.x;
superTowerText.y = superTowerBtn.y;
game.addChild(superTowerText);
// Row 4: New towers
var doubleCannonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y + 150,
color: 0x795548,
scaleX: 2.2,
scaleY: 2.2
}));
doubleCannonBtn.visible = false;
var doubleCannonText = new Text2('Doble Cañón\n$500', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
doubleCannonText.anchor.set(0.5, 0.5);
doubleCannonText.x = doubleCannonBtn.x;
doubleCannonText.y = doubleCannonBtn.y;
game.addChild(doubleCannonText);
var superCannonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 150,
color: 0xFF5722,
scaleX: 2.2,
scaleY: 2.2
}));
superCannonBtn.visible = false;
var superCannonText = new Text2('Super Cañón\n$500', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
superCannonText.anchor.set(0.5, 0.5);
superCannonText.x = superCannonBtn.x;
superCannonText.y = superCannonBtn.y;
game.addChild(superCannonText);
var rapidTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y + 150,
color: 0x2196F3,
scaleX: 2.2,
scaleY: 2.2
}));
rapidTowerBtn.visible = false;
var rapidTowerText = new Text2('Torre Rápida\n$100', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
rapidTowerText.anchor.set(0.5, 0.5);
rapidTowerText.x = rapidTowerBtn.x;
rapidTowerText.y = rapidTowerBtn.y;
game.addChild(rapidTowerText);
// Row 5: Freeze Tower and Cactus Tower
var freezeTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y + 350,
color: 0x00BCD4,
scaleX: 2.2,
scaleY: 2.2
}));
freezeTowerBtn.visible = false;
var freezeTowerText = new Text2('Torre Hielo\n$150', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
freezeTowerText.anchor.set(0.5, 0.5);
freezeTowerText.x = freezeTowerBtn.x;
freezeTowerText.y = freezeTowerBtn.y;
game.addChild(freezeTowerText);
var cactusBombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y - 50,
color: 0xccec80,
scaleX: 2.2,
scaleY: 2.2
}));
cactusBombBtn.visible = false;
var cactusBombText = new Text2('Bomba Cactus\n$100', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
cactusBombText.anchor.set(0.5, 0.5);
cactusBombText.x = cactusBombBtn.x;
cactusBombText.y = cactusBombBtn.y;
game.addChild(cactusBombText);
var cactusTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y - 50,
color: 0x228B22,
scaleX: 2.2,
scaleY: 2.2
}));
cactusTowerBtn.visible = false;
var cactusTowerText = new Text2('Torre Cactus\n$1000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
cactusTowerText.anchor.set(0.5, 0.5);
cactusTowerText.x = cactusTowerBtn.x;
cactusTowerText.y = cactusTowerBtn.y;
game.addChild(cactusTowerText);
var megaSuperTowerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 350,
color: 0xFF0000,
scaleX: 2.2,
scaleY: 2.2
}));
megaSuperTowerBtn.visible = false;
var megaSuperTowerText = new Text2('Mega Super\n$2000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
megaSuperTowerText.anchor.set(0.5, 0.5);
megaSuperTowerText.x = megaSuperTowerBtn.x;
megaSuperTowerText.y = megaSuperTowerBtn.y;
game.addChild(megaSuperTowerText);
var bombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y + 350,
color: 0x795548,
scaleX: 2.2,
scaleY: 2.2
}));
bombBtn.visible = false;
var bombText = new Text2('Bomba\n$150', {
size: 45,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
bombText.anchor.set(0.5, 0.5);
bombText.x = bombBtn.x;
bombText.y = bombBtn.y;
game.addChild(bombText);
// Row 6: Super Bomb
var superBombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x - 350,
y: shopPanel.y + 550,
color: 0x000000,
scaleX: 2.2,
scaleY: 2.2
}));
superBombBtn.visible = false;
var superBombText = new Text2('Super Bomba\n$2000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
superBombText.anchor.set(0.5, 0.5);
superBombText.x = superBombBtn.x;
superBombText.y = superBombBtn.y;
game.addChild(superBombText);
var nuclearBombBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 550,
color: 0x00FF00,
scaleX: 2.2,
scaleY: 2.2
}));
nuclearBombBtn.visible = false;
var nuclearBombText = new Text2('Nuclear\n$10000', {
size: 42,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
nuclearBombText.anchor.set(0.5, 0.5);
nuclearBombText.x = nuclearBombBtn.x;
nuclearBombText.y = nuclearBombBtn.y;
game.addChild(nuclearBombText);
var multiTargetBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x + 350,
y: shopPanel.y + 550,
color: 0xFF00FF,
scaleX: 2.2,
scaleY: 2.2
}));
multiTargetBtn.visible = false;
var multiTargetText = new Text2('Multi Target\n$1500', {
size: 40,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
multiTargetText.anchor.set(0.5, 0.5);
multiTargetText.x = multiTargetBtn.x;
multiTargetText.y = multiTargetBtn.y;
game.addChild(multiTargetText);
// Close shop button
var closeShopBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: shopPanel.x,
y: shopPanel.y + 850,
color: 0xFF5722,
scaleX: 2.2,
scaleY: 2.2
}));
closeShopBtn.visible = false;
var closeShopText = new Text2('CLOSE', {
size: 50,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
closeShopText.anchor.set(0.5, 0.5);
closeShopText.x = closeShopBtn.x;
closeShopText.y = closeShopBtn.y;
game.addChild(closeShopText);
// Start Menu Elements
var startMenuTitle = new Text2('TOWER DEFENSE', {
size: 80,
fill: 0xFFFFFF
});
startMenuTitle.anchor.set(0.5, 0.5);
startMenuTitle.x = 1024;
startMenuTitle.y = 800;
game.addChild(startMenuTitle);
var playBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
}));
var playBtnText = new Text2('JUGAR', {
size: 40,
fill: 0xFFFFFF
});
playBtnText.anchor.set(0.5, 0.5);
playBtnText.x = playBtn.x;
playBtnText.y = playBtn.y;
game.addChild(playBtnText);
var waveSelectBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1450,
color: 0x2196F3,
scaleX: 1.5,
scaleY: 1.5
}));
var waveSelectBtnText = new Text2('ELEGIR OLEADA', {
size: 35,
fill: 0xFFFFFF
});
waveSelectBtnText.anchor.set(0.5, 0.5);
waveSelectBtnText.x = waveSelectBtn.x;
waveSelectBtnText.y = waveSelectBtn.y;
game.addChild(waveSelectBtnText);
// Wave Selection Menu Elements
var waveSelectTitle = new Text2('ELEGIR OLEADA INICIAL', {
size: 60,
fill: 0xFFFFFF
});
waveSelectTitle.anchor.set(0.5, 0.5);
waveSelectTitle.x = 1024;
waveSelectTitle.y = 600;
waveSelectTitle.visible = false;
game.addChild(waveSelectTitle);
var waveMinusBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 1200,
color: 0xFF5722,
width: 100,
height: 100
}));
waveMinusBtn.visible = false;
var waveMinusText = new Text2('-', {
size: 60,
fill: 0xFFFFFF
});
waveMinusText.anchor.set(0.5, 0.5);
waveMinusText.x = waveMinusBtn.x;
waveMinusText.y = waveMinusBtn.y;
waveMinusText.visible = false;
game.addChild(waveMinusText);
var waveDisplayText = new Text2('Oleada: ' + selectedStartWave, {
size: 50,
fill: 0xFFFFFF
});
waveDisplayText.anchor.set(0.5, 0.5);
waveDisplayText.x = 1024;
waveDisplayText.y = 1200;
waveDisplayText.visible = false;
game.addChild(waveDisplayText);
var wavePlusBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1348,
y: 1200,
color: 0x4CAF50,
width: 100,
height: 100
}));
wavePlusBtn.visible = false;
var wavePlusText = new Text2('+', {
size: 60,
fill: 0xFFFFFF
});
wavePlusText.anchor.set(0.5, 0.5);
wavePlusText.x = wavePlusBtn.x;
wavePlusText.y = wavePlusBtn.y;
wavePlusText.visible = false;
game.addChild(wavePlusText);
var startGameBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
}));
startGameBtn.visible = false;
var startGameBtnText = new Text2('COMENZAR', {
size: 40,
fill: 0xFFFFFF
});
startGameBtnText.anchor.set(0.5, 0.5);
startGameBtnText.x = startGameBtn.x;
startGameBtnText.y = startGameBtn.y;
startGameBtnText.visible = false;
game.addChild(startGameBtnText);
var sandboxBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1700,
color: 0xFFC107,
scaleX: 1.5,
scaleY: 1.5
}));
var sandboxBtnText = new Text2('SANDBOX', {
size: 40,
fill: 0xFFFFFF
});
sandboxBtnText.anchor.set(0.5, 0.5);
sandboxBtnText.x = sandboxBtn.x;
sandboxBtnText.y = sandboxBtn.y;
game.addChild(sandboxBtnText);
var backBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800,
color: 0x795548
}));
backBtn.visible = false;
var backBtnText = new Text2('VOLVER', {
size: 30,
fill: 0xFFFFFF
});
backBtnText.anchor.set(0.5, 0.5);
backBtnText.x = backBtn.x;
backBtnText.y = backBtn.y;
backBtnText.visible = false;
game.addChild(backBtnText);
// Enemy Shop Panel for Sandbox Mode
var enemyShopPanel = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
enemyShopPanel.visible = false;
var enemyShopTitle = new Text2('ENEMY SHOP', {
size: 50,
fill: 0xFFFFFF
});
enemyShopTitle.anchor.set(0.5, 0);
enemyShopTitle.x = enemyShopPanel.x;
enemyShopTitle.y = enemyShopPanel.y - 450;
enemyShopTitle.visible = false;
game.addChild(enemyShopTitle);
// Enemy buttons - Row 1
var spawnEnemyBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 250,
y: enemyShopPanel.y - 350,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
});
spawnEnemyBtn.visible = false;
var spawnEnemyText = new Text2('Basic Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnEnemyText.anchor.set(0.5, 0.5);
spawnEnemyText.x = spawnEnemyBtn.x;
spawnEnemyText.y = spawnEnemyBtn.y;
spawnEnemyText.visible = false;
var spawnFastBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y - 350,
color: 0x2196F3,
scaleX: 1.5,
scaleY: 1.5
});
spawnFastBtn.visible = false;
var spawnFastText = new Text2('Fast Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnFastText.anchor.set(0.5, 0.5);
spawnFastText.x = spawnFastBtn.x;
spawnFastText.y = spawnFastBtn.y;
spawnFastText.visible = false;
var spawnTankBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 250,
y: enemyShopPanel.y - 350,
color: 0x9C27B0,
scaleX: 1.5,
scaleY: 1.5
});
spawnTankBtn.visible = false;
var spawnTankText = new Text2('Tank Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnTankText.anchor.set(0.5, 0.5);
spawnTankText.x = spawnTankBtn.x;
spawnTankText.y = spawnTankBtn.y;
spawnTankText.visible = false;
game.addChild(spawnTankText);
// Enemy buttons - Row 2
var spawnBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y - 150,
color: 0x000000
}));
spawnBossBtn.visible = false;
var spawnBossText = new Text2('Boss Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnBossText.anchor.set(0.5, 0.5);
spawnBossText.x = spawnBossBtn.x;
spawnBossText.y = spawnBossBtn.y;
spawnBossText.visible = false;
game.addChild(spawnBossText);
var spawnMageBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y - 150,
color: 0x795548
}));
spawnMageBtn.visible = false;
var spawnMageText = new Text2('Mage Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnMageText.anchor.set(0.5, 0.5);
spawnMageText.x = spawnMageBtn.x;
spawnMageText.y = spawnMageBtn.y;
spawnMageText.visible = false;
game.addChild(spawnMageText);
var spawnSuperMageBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y - 150,
color: 0x8A2BE2
}));
spawnSuperMageBtn.visible = false;
var spawnSuperMageText = new Text2('Super Mage', {
size: 22,
fill: 0xFFFFFF
});
spawnSuperMageText.anchor.set(0.5, 0.5);
spawnSuperMageText.x = spawnSuperMageBtn.x;
spawnSuperMageText.y = spawnSuperMageBtn.y;
spawnSuperMageText.visible = false;
game.addChild(spawnSuperMageText);
var spawnTankBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y - 150,
color: 0x263238
}));
spawnTankBossBtn.visible = false;
var spawnTankBossText = new Text2('Tank Boss', {
size: 25,
fill: 0xFFFFFF
});
spawnTankBossText.anchor.set(0.5, 0.5);
spawnTankBossText.x = spawnTankBossBtn.x;
spawnTankBossText.y = spawnTankBossBtn.y;
spawnTankBossText.visible = false;
game.addChild(spawnTankBossText);
// Enemy buttons - Row 3
var spawnArmoredBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y + 50,
color: 0x607d8b
}));
spawnArmoredBtn.visible = false;
var spawnArmoredText = new Text2('Armored', {
size: 25,
fill: 0xFFFFFF
});
spawnArmoredText.anchor.set(0.5, 0.5);
spawnArmoredText.x = spawnArmoredBtn.x;
spawnArmoredText.y = spawnArmoredBtn.y;
spawnArmoredText.visible = false;
game.addChild(spawnArmoredText);
var spawnPigBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 50,
color: 0xE91E63
}));
spawnPigBtn.visible = false;
var spawnPigText = new Text2('Pig Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnPigText.anchor.set(0.5, 0.5);
spawnPigText.x = spawnPigBtn.x;
spawnPigText.y = spawnPigBtn.y;
spawnPigText.visible = false;
game.addChild(spawnPigText);
var spawnMoleBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 200,
y: enemyShopPanel.y + 50,
color: 0x8D6E63
}));
spawnMoleBtn.visible = false;
var spawnMoleText = new Text2('Mole Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnMoleText.anchor.set(0.5, 0.5);
spawnMoleText.x = spawnMoleBtn.x;
spawnMoleText.y = spawnMoleBtn.y;
spawnMoleText.visible = false;
game.addChild(spawnMoleText);
// Enemy buttons - Row 4
var spawnSkeletonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y + 200,
color: 0xF5F5F5
}));
spawnSkeletonBtn.visible = false;
var spawnSkeletonText = new Text2('Skeleton', {
size: 25,
fill: 0x000000
});
spawnSkeletonText.anchor.set(0.5, 0.5);
spawnSkeletonText.x = spawnSkeletonBtn.x;
spawnSkeletonText.y = spawnSkeletonBtn.y;
spawnSkeletonText.visible = false;
game.addChild(spawnSkeletonText);
var spawnSuperTank2Btn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 200,
color: 0x8B0000
}));
spawnSuperTank2Btn.visible = false;
var spawnSuperTank2Text = new Text2('Super Tank2', {
size: 22,
fill: 0xFFFFFF
});
spawnSuperTank2Text.anchor.set(0.5, 0.5);
spawnSuperTank2Text.x = spawnSuperTank2Btn.x;
spawnSuperTank2Text.y = spawnSuperTank2Btn.y;
spawnSuperTank2Text.visible = false;
game.addChild(spawnSuperTank2Text);
var spawnArmorBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 200,
y: enemyShopPanel.y + 200,
color: 0x424242
}));
spawnArmorBossBtn.visible = false;
var spawnArmorBossText = new Text2('Armor Boss', {
size: 22,
fill: 0xFFFFFF
});
spawnArmorBossText.anchor.set(0.5, 0.5);
spawnArmorBossText.x = spawnArmorBossBtn.x;
spawnArmorBossText.y = spawnArmorBossBtn.y;
spawnArmorBossText.visible = false;
game.addChild(spawnArmorBossText);
// Enemy buttons - Row 5
var spawnObsidianBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 200,
y: enemyShopPanel.y + 350,
color: 0x1a1a1a
}));
spawnObsidianBossBtn.visible = false;
var spawnObsidianBossText = new Text2('Obsidian Boss', {
size: 20,
fill: 0xFFFFFF
});
spawnObsidianBossText.anchor.set(0.5, 0.5);
spawnObsidianBossText.x = spawnObsidianBossBtn.x;
spawnObsidianBossText.y = spawnObsidianBossBtn.y;
spawnObsidianBossText.visible = false;
game.addChild(spawnObsidianBossText);
var spawnObsidianArmorBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 350,
color: 0x0a0a0a
}));
spawnObsidianArmorBtn.visible = false;
var spawnObsidianArmorText = new Text2('Obsidian Armor', {
size: 18,
fill: 0xFFFFFF
});
spawnObsidianArmorText.anchor.set(0.5, 0.5);
spawnObsidianArmorText.x = spawnObsidianArmorBtn.x;
spawnObsidianArmorText.y = spawnObsidianArmorBtn.y;
spawnObsidianArmorText.visible = false;
game.addChild(spawnObsidianArmorText);
var spawnGoldBossBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 200,
y: enemyShopPanel.y + 350,
color: 0xFFD700
}));
spawnGoldBossBtn.visible = false;
var spawnGoldBossText = new Text2('Gold Boss', {
size: 20,
fill: 0x000000
});
spawnGoldBossText.anchor.set(0.5, 0.5);
spawnGoldBossText.x = spawnGoldBossBtn.x;
spawnGoldBossText.y = spawnGoldBossBtn.y;
spawnGoldBossText.visible = false;
game.addChild(spawnGoldBossText);
// Enemy buttons - Row 6
var spawnSuperOmegaTankBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y + 500,
color: 0x8B008B
}));
spawnSuperOmegaTankBtn.visible = false;
var spawnSuperOmegaTankText = new Text2('Super Omega', {
size: 18,
fill: 0xFFFFFF
});
spawnSuperOmegaTankText.anchor.set(0.5, 0.5);
spawnSuperOmegaTankText.x = spawnSuperOmegaTankBtn.x;
spawnSuperOmegaTankText.y = spawnSuperOmegaTankBtn.y;
spawnSuperOmegaTankText.visible = false;
game.addChild(spawnSuperOmegaTankText);
var spawnSuperOmegaArmorBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y + 500,
color: 0x4B0082
}));
spawnSuperOmegaArmorBtn.visible = false;
var spawnSuperOmegaArmorText = new Text2('Omega Armor', {
size: 18,
fill: 0xFFFFFF
});
spawnSuperOmegaArmorText.anchor.set(0.5, 0.5);
spawnSuperOmegaArmorText.x = spawnSuperOmegaArmorBtn.x;
spawnSuperOmegaArmorText.y = spawnSuperOmegaArmorBtn.y;
spawnSuperOmegaArmorText.visible = false;
game.addChild(spawnSuperOmegaArmorText);
// Enemy buttons - Row 7
var spawnSpawnerBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y + 650,
color: 0xFF6600
}));
spawnSpawnerBtn.visible = false;
var spawnSpawnerText = new Text2('Spawner', {
size: 20,
fill: 0xFFFFFF
});
spawnSpawnerText.anchor.set(0.5, 0.5);
spawnSpawnerText.x = spawnSpawnerBtn.x;
spawnSpawnerText.y = spawnSpawnerBtn.y;
spawnSpawnerText.visible = false;
game.addChild(spawnSpawnerText);
var spawnBalloonBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y + 650,
color: 0xFF69B4
}));
spawnBalloonBtn.visible = false;
var spawnBalloonText = new Text2('Globo', {
size: 20,
fill: 0xFFFFFF
});
spawnBalloonText.anchor.set(0.5, 0.5);
spawnBalloonText.x = spawnBalloonBtn.x;
spawnBalloonText.y = spawnBalloonBtn.y;
spawnBalloonText.visible = false;
game.addChild(spawnBalloonText);
// Enemy Shop close button
var closeEnemyShopBtn = game.addChild(LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 800,
color: 0xFF5722
}));
closeEnemyShopBtn.visible = false;
var closeEnemyShopText = new Text2('CLOSE', {
size: 30,
fill: 0xFFFFFF
});
closeEnemyShopText.anchor.set(0.5, 0.5);
closeEnemyShopText.x = closeEnemyShopBtn.x;
closeEnemyShopText.y = closeEnemyShopBtn.y;
closeEnemyShopText.visible = false;
game.addChild(closeEnemyShopText);
// Sandbox UI elements
var enemyShopBtn = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: 2500,
color: 0xFFC107
}));
enemyShopBtn.visible = false;
var enemyShopBtnText = new Text2('ENEMIES', {
size: 40,
fill: 0xFFFFFF
});
enemyShopBtnText.anchor.set(0.5, 0.5);
enemyShopBtnText.x = enemyShopBtn.x;
enemyShopBtnText.y = enemyShopBtn.y;
enemyShopBtnText.visible = false;
game.addChild(enemyShopBtnText);
// Functions
function hideStartMenu() {
startMenuTitle.visible = false;
playBtn.visible = false;
playBtnText.visible = false;
waveSelectBtn.visible = false;
waveSelectBtnText.visible = false;
sandboxBtn.visible = false;
sandboxBtnText.visible = false;
}
function showStartMenu() {
startMenuTitle.visible = true;
playBtn.visible = true;
playBtnText.visible = true;
waveSelectBtn.visible = true;
waveSelectBtnText.visible = true;
sandboxBtn.visible = true;
sandboxBtnText.visible = true;
}
function hideWaveSelect() {
waveSelectTitle.visible = false;
waveMinusBtn.visible = false;
waveMinusText.visible = false;
waveDisplayText.visible = false;
wavePlusBtn.visible = false;
wavePlusText.visible = false;
startGameBtn.visible = false;
startGameBtnText.visible = false;
backBtn.visible = false;
backBtnText.visible = false;
}
function showWaveSelect() {
waveSelectTitle.visible = true;
waveMinusBtn.visible = true;
waveMinusText.visible = true;
waveDisplayText.visible = true;
wavePlusBtn.visible = true;
wavePlusText.visible = true;
startGameBtn.visible = true;
startGameBtnText.visible = true;
backBtn.visible = true;
backBtnText.visible = true;
}
function updateWaveDisplay() {
if (gameStarted) {
waveDisplayText.setText('Oleada: ' + currentWave);
} else {
waveDisplayText.setText('Oleada: ' + selectedStartWave);
}
}
function toggleEnemyShop() {
showingEnemyShop = !showingEnemyShop;
if (showingEnemyShop) {
// Add all enemy shop elements to game with proper layering
game.addChild(enemyShopPanel);
enemyShopPanel.visible = true;
game.addChild(enemyShopTitle);
enemyShopTitle.visible = true;
game.addChild(spawnEnemyBtn);
spawnEnemyBtn.visible = true;
game.addChild(spawnEnemyText);
spawnEnemyText.visible = true;
game.addChild(spawnFastBtn);
spawnFastBtn.visible = true;
game.addChild(spawnFastText);
spawnFastText.visible = true;
game.addChild(spawnTankBtn);
spawnTankBtn.visible = true;
game.addChild(spawnTankText);
spawnTankText.visible = true;
game.addChild(spawnBossBtn);
spawnBossBtn.visible = true;
game.addChild(spawnBossText);
spawnBossText.visible = true;
game.addChild(spawnMageBtn);
spawnMageBtn.visible = true;
game.addChild(spawnMageText);
spawnMageText.visible = true;
game.addChild(spawnSuperMageBtn);
spawnSuperMageBtn.visible = true;
game.addChild(spawnSuperMageText);
spawnSuperMageText.visible = true;
game.addChild(spawnTankBossBtn);
spawnTankBossBtn.visible = true;
game.addChild(spawnTankBossText);
spawnTankBossText.visible = true;
game.addChild(spawnArmoredBtn);
spawnArmoredBtn.visible = true;
game.addChild(spawnArmoredText);
spawnArmoredText.visible = true;
game.addChild(spawnPigBtn);
spawnPigBtn.visible = true;
game.addChild(spawnPigText);
spawnPigText.visible = true;
game.addChild(spawnMoleBtn);
spawnMoleBtn.visible = true;
game.addChild(spawnMoleText);
spawnMoleText.visible = true;
game.addChild(spawnSkeletonBtn);
spawnSkeletonBtn.visible = true;
game.addChild(spawnSkeletonText);
spawnSkeletonText.visible = true;
game.addChild(spawnSuperTank2Btn);
spawnSuperTank2Btn.visible = true;
game.addChild(spawnSuperTank2Text);
spawnSuperTank2Text.visible = true;
game.addChild(spawnArmorBossBtn);
spawnArmorBossBtn.visible = true;
game.addChild(spawnArmorBossText);
spawnArmorBossText.visible = true;
game.addChild(spawnObsidianBossBtn);
spawnObsidianBossBtn.visible = true;
game.addChild(spawnObsidianBossText);
spawnObsidianBossText.visible = true;
game.addChild(spawnObsidianArmorBtn);
spawnObsidianArmorBtn.visible = true;
game.addChild(spawnObsidianArmorText);
spawnObsidianArmorText.visible = true;
game.addChild(spawnGoldBossBtn);
spawnGoldBossBtn.visible = true;
game.addChild(spawnGoldBossText);
spawnGoldBossText.visible = true;
game.addChild(spawnSuperOmegaTankBtn);
spawnSuperOmegaTankBtn.visible = true;
game.addChild(spawnSuperOmegaTankText);
spawnSuperOmegaTankText.visible = true;
game.addChild(spawnSuperOmegaArmorBtn);
spawnSuperOmegaArmorBtn.visible = true;
game.addChild(spawnSuperOmegaArmorText);
spawnSuperOmegaArmorText.visible = true;
game.addChild(spawnSpawnerBtn);
spawnSpawnerBtn.visible = true;
game.addChild(spawnSpawnerText);
spawnSpawnerText.visible = true;
game.addChild(spawnBalloonBtn);
spawnBalloonBtn.visible = true;
game.addChild(spawnBalloonText);
spawnBalloonText.visible = true;
game.addChild(closeEnemyShopBtn);
closeEnemyShopBtn.visible = true;
game.addChild(closeEnemyShopText);
closeEnemyShopText.visible = true;
} else {
// Remove all enemy shop elements from game
enemyShopPanel.destroy();
enemyShopTitle.destroy();
spawnEnemyBtn.destroy();
spawnEnemyText.destroy();
spawnFastBtn.destroy();
spawnFastText.destroy();
spawnTankBtn.destroy();
spawnTankText.destroy();
spawnBossBtn.destroy();
spawnBossText.destroy();
spawnMageBtn.destroy();
spawnMageText.destroy();
spawnSuperMageBtn.destroy();
spawnSuperMageText.destroy();
spawnTankBossBtn.destroy();
spawnTankBossText.destroy();
spawnArmoredBtn.destroy();
spawnArmoredText.destroy();
spawnPigBtn.destroy();
spawnPigText.destroy();
spawnMoleBtn.destroy();
spawnMoleText.destroy();
spawnSkeletonBtn.destroy();
spawnSkeletonText.destroy();
spawnSuperTank2Btn.destroy();
spawnSuperTank2Text.destroy();
spawnArmorBossBtn.destroy();
spawnArmorBossText.destroy();
spawnObsidianBossBtn.destroy();
spawnObsidianBossText.destroy();
spawnObsidianArmorBtn.destroy();
spawnObsidianArmorText.destroy();
spawnGoldBossBtn.destroy();
spawnGoldBossText.destroy();
spawnSuperOmegaTankBtn.destroy();
spawnSuperOmegaTankText.destroy();
spawnSuperOmegaArmorBtn.destroy();
spawnSuperOmegaArmorText.destroy();
spawnSpawnerBtn.destroy();
spawnSpawnerText.destroy();
spawnBalloonBtn.destroy();
spawnBalloonText.destroy();
closeEnemyShopBtn.destroy();
closeEnemyShopText.destroy();
// Recreate elements for next time
enemyShopPanel = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
enemyShopTitle = new Text2('ENEMY SHOP', {
size: 50,
fill: 0xFFFFFF
});
enemyShopTitle.anchor.set(0.5, 0);
enemyShopTitle.x = enemyShopPanel.x;
enemyShopTitle.y = enemyShopPanel.y - 450;
spawnEnemyBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 250,
y: enemyShopPanel.y - 350,
color: 0x4CAF50,
scaleX: 1.5,
scaleY: 1.5
});
spawnEnemyText = new Text2('Basic Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnEnemyText.anchor.set(0.5, 0.5);
spawnEnemyText.x = spawnEnemyBtn.x;
spawnEnemyText.y = spawnEnemyBtn.y;
spawnFastBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y - 350,
color: 0x2196F3,
scaleX: 1.5,
scaleY: 1.5
});
spawnFastText = new Text2('Fast Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnFastText.anchor.set(0.5, 0.5);
spawnFastText.x = spawnFastBtn.x;
spawnFastText.y = spawnFastBtn.y;
spawnTankBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 250,
y: enemyShopPanel.y - 350,
color: 0x9C27B0,
scaleX: 1.5,
scaleY: 1.5
});
spawnTankText = new Text2('Tank Enemy', {
size: 25,
fill: 0xFFFFFF
});
spawnTankText.anchor.set(0.5, 0.5);
spawnTankText.x = spawnTankBtn.x;
spawnTankText.y = spawnTankBtn.y;
spawnSuperMageBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y - 150,
color: 0x8A2BE2
});
spawnSuperMageText = new Text2('Super Mage', {
size: 22,
fill: 0xFFFFFF
});
spawnSuperMageText.anchor.set(0.5, 0.5);
spawnSuperMageText.x = spawnSuperMageBtn.x;
spawnSuperMageText.y = spawnSuperMageBtn.y;
spawnSpawnerBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x - 100,
y: enemyShopPanel.y + 650,
color: 0xFF6600
});
spawnSpawnerText = new Text2('Spawner', {
size: 20,
fill: 0xFFFFFF
});
spawnSpawnerText.anchor.set(0.5, 0.5);
spawnSpawnerText.x = spawnSpawnerBtn.x;
spawnSpawnerText.y = spawnSpawnerBtn.y;
spawnBalloonBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x + 100,
y: enemyShopPanel.y + 650,
color: 0xFF69B4
});
spawnBalloonText = new Text2('Globo', {
size: 20,
fill: 0xFFFFFF
});
spawnBalloonText.anchor.set(0.5, 0.5);
spawnBalloonText.x = spawnBalloonBtn.x;
spawnBalloonText.y = spawnBalloonBtn.y;
closeEnemyShopBtn = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyShopPanel.x,
y: enemyShopPanel.y + 800,
color: 0xFF5722,
scaleX: 1.5,
scaleY: 1.5
});
closeEnemyShopText = new Text2('CLOSE', {
size: 30,
fill: 0xFFFFFF
});
closeEnemyShopText.anchor.set(0.5, 0.5);
closeEnemyShopText.x = closeEnemyShopBtn.x;
closeEnemyShopText.y = closeEnemyShopBtn.y;
}
}
function startSandboxMode() {
gameStarted = true;
sandboxMode = true;
playerMoney = 999999; // Infinite money
hideStartMenu();
hideWaveSelect();
showingWaveSelect = false;
updateWaveDisplay();
updateMoneyDisplay();
}
function spawnEnemy(enemyType) {
var enemy;
switch (enemyType) {
case 'basic':
enemy = new Enemy();
break;
case 'fast':
enemy = new FastEnemy();
break;
case 'tank':
enemy = new TankEnemy();
break;
case 'boss':
enemy = new BossEnemy();
break;
case 'mage':
enemy = new MageEnemy();
break;
case 'supermage':
enemy = new SuperMageEnemy();
break;
case 'tankboss':
enemy = new TankBossEnemy();
break;
case 'armored':
enemy = new ArmoredEnemy();
break;
case 'pig':
enemy = new PigEnemy();
break;
case 'mole':
enemy = new MoleEnemy();
break;
case 'skeleton':
enemy = new SkeletonEnemy();
break;
case 'supertank2':
enemy = new SuperTankBoss2Enemy();
break;
case 'armorboss':
enemy = new SuperTankBossArmorEnemy();
break;
case 'obsidianboss':
enemy = new SuperTankBossObsidianEnemy();
break;
case 'obsidianarmor':
enemy = new SuperTankBossObsidianArmorEnemy();
break;
case 'goldboss':
enemy = new SuperTankBossGoldEnemy();
break;
case 'superomegatank':
enemy = new SuperOmegaTankBossEnemy();
break;
case 'superomegaarmor':
enemy = new SuperOmegaArmorTankBossEnemy();
break;
case 'spawner':
enemy = new SpawnerEnemy();
break;
case 'balloon':
enemy = new BalloonEnemy();
break;
default:
enemy = new Enemy();
}
enemy.x = enemyPath[0].x;
enemy.y = enemyPath[0].y;
enemies.push(enemy);
game.addChild(enemy);
// Move enemy above path segments (path segments are at indices 0 to pathSegments.length-1)
// but below towers and UI elements
game.setChildIndex(enemy, pathSegments.length + towers.length);
}
function startGame() {
gameStarted = true;
currentWave = selectedStartWave;
hideStartMenu();
hideWaveSelect();
showingWaveSelect = false;
updateWaveDisplay();
waveText.setText('Wave: ' + currentWave); // Update the actual game wave display
}
function updateMoneyDisplay() {
moneyText.setText('Money: $' + playerMoney);
}
function updateLivesDisplay() {
livesText.setText('Lives: ' + playerLives);
}
function toggleShop() {
shopOpen = !shopOpen;
shopPanel.visible = shopOpen;
shopTitle.visible = shopOpen;
basicTowerBtn.visible = shopOpen;
basicTowerText.visible = shopOpen;
slowTowerBtn.visible = shopOpen;
slowTowerText.visible = shopOpen;
areaTowerBtn.visible = shopOpen;
areaTowerText.visible = shopOpen;
poisonTowerBtn.visible = shopOpen;
poisonTowerText.visible = shopOpen;
longRangeTowerBtn.visible = shopOpen;
longRangeTowerText.visible = shopOpen;
heavyTowerBtn.visible = shopOpen;
heavyTowerText.visible = shopOpen;
superTowerBtn.visible = shopOpen;
superTowerText.visible = shopOpen;
doubleCannonBtn.visible = shopOpen;
doubleCannonText.visible = shopOpen;
superCannonBtn.visible = shopOpen;
superCannonText.visible = shopOpen;
rapidTowerBtn.visible = shopOpen;
rapidTowerText.visible = shopOpen;
freezeTowerBtn.visible = shopOpen;
freezeTowerText.visible = shopOpen;
cactusBombBtn.visible = shopOpen;
cactusBombText.visible = shopOpen;
cactusTowerBtn.visible = shopOpen;
cactusTowerText.visible = shopOpen;
megaSuperTowerBtn.visible = shopOpen;
megaSuperTowerText.visible = shopOpen;
bombBtn.visible = shopOpen;
bombText.visible = shopOpen;
superBombBtn.visible = shopOpen;
superBombText.visible = shopOpen;
nuclearBombBtn.visible = shopOpen;
nuclearBombText.visible = shopOpen;
multiTargetBtn.visible = shopOpen;
multiTargetText.visible = shopOpen;
closeShopBtn.visible = shopOpen;
closeShopText.visible = shopOpen;
}
function startWave() {
if (waveInProgress) {
return;
}
waveInProgress = true;
var enemiesToSpawn = 3 + currentWave;
var spawnDelay = 0;
for (var i = 0; i < enemiesToSpawn; i++) {
LK.setTimeout(function () {
var enemy;
var enemyType = Math.random();
// Calculate increased spawn rates for rare enemies after wave 11
var waveMultiplier = currentWave > 11 ? Math.min(2.0, 1 + (currentWave - 11) * 0.1) : 1;
var superOmegaArmorChance = currentWave >= 45 ? 0.0005 * Math.max(1, (currentWave - 45) * 0.02) : 0; // Ultra ultra rare chance starting at wave 45, increases each wave
var superOmegaTankChance = currentWave >= 43 ? 0.0008 * Math.max(1, (currentWave - 43) * 0.025) : 0; // Ultra rare chance starting at wave 43, increases each wave
var superTankBossGoldChance = currentWave >= 40 ? 0.001 * Math.max(1, (currentWave - 40) * 0.03) : 0; // Ultra rare chance starting at wave 40, increases each wave
var superTankBossObsidianArmorChance = currentWave >= 30 ? 0.002 * Math.max(1, (currentWave - 30) * 0.04) : 0; // Extremely low chance starting at wave 30, increases each wave
var superTankBossObsidianChance = currentWave >= 25 ? 0.003 * Math.max(1, (currentWave - 25) * 0.05) : 0; // Very low chance starting at wave 25, increases each wave
var superTankBossArmorChance = currentWave >= 15 ? 0.005 * Math.max(1, (currentWave - 15) * 0.05) : 0; // Low chance starting at wave 15, increases each wave
var balloonChance = currentWave >= 8 ? 0.08 * waveMultiplier : 0; // Balloon enemy appears after wave 8
var superTankBoss2Chance = currentWave >= 8 ? 0.005 * waveMultiplier : 0; // Very low chance, increases after wave 11
var superMageChance = currentWave >= 10 ? 0.06 * waveMultiplier : 0; // Super mage appears after wave 10
var tankBossChance = currentWave >= 10 ? 0.01 * waveMultiplier : 0;
var bossChance = currentWave >= 7 ? 0.05 * waveMultiplier : 0;
var pigChance = currentWave >= 6 ? 0.10 * waveMultiplier : 0;
var mageChance = currentWave >= 3 ? 0.12 * waveMultiplier : 0;
var armoredChance = currentWave >= 4 ? 0.15 * waveMultiplier : 0;
var moleChance = currentWave >= 3 ? 0.08 * waveMultiplier : 0;
var skeletonChance = currentWave >= 2 ? 0.10 * waveMultiplier : 0;
var fastChance = currentWave >= 2 ? 0.15 * waveMultiplier : 0;
var tankChance = currentWave >= 5 ? 0.17 * waveMultiplier : 0;
if (enemyType < superOmegaArmorChance) {
// Super Omega Armor Tank Boss enemy with ultra ultra rare chance starting at wave 45
enemy = new SuperOmegaArmorTankBossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance) {
// Super Omega Tank Boss enemy with ultra rare chance starting at wave 43
enemy = new SuperOmegaTankBossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance) {
// Super Tank Boss Gold enemy with ultra rare chance starting at wave 40
enemy = new SuperTankBossGoldEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance) {
// Super Tank Boss Obsidian Armor enemy with extremely low chance starting at wave 30
enemy = new SuperTankBossObsidianArmorEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance) {
// Super Tank Boss Obsidian enemy with very low chance starting at wave 25
enemy = new SuperTankBossObsidianEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance) {
// Super Tank Boss Armor enemy with low chance starting at wave 15
enemy = new SuperTankBossArmorEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance) {
// Super Tank Boss 2 enemy with very low chance, increases after wave 11
enemy = new SuperTankBoss2Enemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance) {
// Tank boss enemy with increased chance after wave 11
enemy = new TankBossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance) {
// Boss enemy with increased chance after wave 11
enemy = new BossEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance) {
// Pig enemy with increased chance after wave 11
enemy = new PigEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance) {
// Super mage enemy with chance after wave 10
enemy = new SuperMageEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance) {
// Mage enemy with increased chance after wave 11
enemy = new MageEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance) {
// Armored enemy with increased chance after wave 11
enemy = new ArmoredEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance) {
// Mole enemy with invulnerability until 50% of path
enemy = new MoleEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance + skeletonChance) {
// Skeleton group with increased chance after wave 11
var skeletonCount = 3 + Math.floor(Math.random() * 3);
for (var j = 0; j < skeletonCount; j++) {
var skeleton = new SkeletonEnemy();
skeleton.x = enemyPath[0].x + (Math.random() - 0.5) * 40; // Slight random positioning
skeleton.y = enemyPath[0].y + (Math.random() - 0.5) * 40;
skeleton.health += Math.floor(currentWave / 4); // Slower health increase for skeletons
skeleton.maxHealth = skeleton.health;
enemies.push(skeleton);
game.addChild(skeleton);
}
return; // Skip the normal enemy spawn below
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance + skeletonChance + fastChance) {
// Fast enemy with increased chance after wave 11
enemy = new FastEnemy();
} else if (enemyType < superOmegaArmorChance + superOmegaTankChance + superTankBossGoldChance + superTankBossObsidianArmorChance + superTankBossObsidianChance + superTankBossArmorChance + superTankBoss2Chance + tankBossChance + bossChance + pigChance + superMageChance + mageChance + armoredChance + moleChance + skeletonChance + fastChance + tankChance + balloonChance) {
// Balloon enemy - invulnerable to all towers except cactus
enemy = new BalloonEnemy();
} else {
enemy = new Enemy();
}
enemy.x = enemyPath[0].x;
enemy.y = enemyPath[0].y;
enemy.health += Math.floor(currentWave / 3); // Increase health every 3 waves
enemy.maxHealth = enemy.health;
enemies.push(enemy);
game.addChild(enemy);
// Move enemy above path segments but below towers and UI elements
game.setChildIndex(enemy, pathSegments.length + towers.length);
}, spawnDelay);
spawnDelay += 1000; // 1 second between spawns
}
}
function checkWaveComplete() {
if (waveInProgress && enemies.length === 0) {
waveInProgress = false;
currentWave++;
updateWaveDisplay();
waveText.setText('Wave: ' + currentWave); // Update the actual game wave display
waveDisplayText.setText('Oleada: ' + currentWave); // Update wave select display as well
playerMoney += 50; // Wave completion bonus
updateMoneyDisplay();
}
}
function placeTower(x, y) {
var towerCost = 50;
if (selectedTowerType === 'slow') {
towerCost = 75;
} else if (selectedTowerType === 'area') {
towerCost = 100;
} else if (selectedTowerType === 'poison') {
towerCost = 80;
} else if (selectedTowerType === 'longrange') {
towerCost = 110;
} else if (selectedTowerType === 'heavy') {
towerCost = 150;
} else if (selectedTowerType === 'super') {
towerCost = 300;
} else if (selectedTowerType === 'doublecannon') {
towerCost = 500;
} else if (selectedTowerType === 'supercannon') {
towerCost = 500;
} else if (selectedTowerType === 'rapid') {
towerCost = 100;
} else if (selectedTowerType === 'freeze') {
towerCost = 150;
} else if (selectedTowerType === 'cactusbomb') {
towerCost = 100;
} else if (selectedTowerType === 'cactus') {
towerCost = 1000;
} else if (selectedTowerType === 'megasuper') {
towerCost = 2000;
} else if (selectedTowerType === 'bomb') {
towerCost = 150;
} else if (selectedTowerType === 'superbomb') {
towerCost = 2000;
} else if (selectedTowerType === 'nuclear') {
towerCost = 10000;
} else if (selectedTowerType === 'multitarget') {
towerCost = 1500;
}
if (!placingTower || playerMoney < towerCost) {
return false;
}
// Check if position is valid (not on path)
for (var i = 0; i < pathSegments.length; i++) {
var pathSegment = pathSegments[i];
var dx = pathSegment.x - x;
var dy = pathSegment.y - y;
if (Math.sqrt(dx * dx + dy * dy) < 80) {
return false; // Too close to path
}
}
// Check if position is valid (not too close to other towers)
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - x;
var dy = tower.y - y;
if (Math.sqrt(dx * dx + dy * dy) < 100) {
return false; // Too close to another tower
}
}
var tower;
if (selectedTowerType === 'slow') {
tower = new SlowTower();
} else if (selectedTowerType === 'area') {
tower = new AreaTower();
} else if (selectedTowerType === 'poison') {
tower = new PoisonTower();
} else if (selectedTowerType === 'longrange') {
tower = new LongRangeTower();
} else if (selectedTowerType === 'heavy') {
tower = new HeavyTower();
} else if (selectedTowerType === 'super') {
tower = new SuperTower();
} else if (selectedTowerType === 'doublecannon') {
tower = new DoubleCannon();
} else if (selectedTowerType === 'supercannon') {
tower = new SuperCannon();
} else if (selectedTowerType === 'rapid') {
tower = new RapidTower();
} else if (selectedTowerType === 'freeze') {
tower = new FreezeTower();
} else if (selectedTowerType === 'cactusbomb') {
tower = new CactusBomb();
} else if (selectedTowerType === 'cactus') {
tower = new CactusTower();
} else if (selectedTowerType === 'megasuper') {
tower = new MegaSuperTower();
} else if (selectedTowerType === 'bomb') {
tower = new Bomb();
} else if (selectedTowerType === 'superbomb') {
tower = new SuperBomb();
} else if (selectedTowerType === 'nuclear') {
tower = new NuclearBomb();
} else if (selectedTowerType === 'multitarget') {
tower = new MultiTargetTower();
} else {
tower = new Tower();
}
tower.x = x;
tower.y = y;
towers.push(tower);
game.addChild(tower);
// Move tower to back so it appears behind UI elements
for (var j = 0; j < pathSegments.length; j++) {
game.setChildIndex(tower, j + 1);
break;
}
playerMoney -= tower.cost;
updateMoneyDisplay();
// Only stop placing if player doesn't have enough money for another tower
if (playerMoney < towerCost) {
placingTower = false;
}
return true;
}
// Event handlers
shopBtn.down = function (x, y, obj) {
toggleShop();
};
readyBtn.down = function (x, y, obj) {
if (!waveInProgress) {
startWave();
}
};
basicTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 50) {
placingTower = true;
selectedTowerType = 'basic';
}
};
slowTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 75) {
placingTower = true;
selectedTowerType = 'slow';
}
};
areaTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 100) {
placingTower = true;
selectedTowerType = 'area';
}
};
poisonTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 80) {
placingTower = true;
selectedTowerType = 'poison';
}
};
longRangeTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 110) {
placingTower = true;
selectedTowerType = 'longrange';
}
};
heavyTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 150) {
placingTower = true;
selectedTowerType = 'heavy';
}
};
superTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 300) {
placingTower = true;
selectedTowerType = 'super';
}
};
doubleCannonBtn.down = function (x, y, obj) {
if (playerMoney >= 500) {
placingTower = true;
selectedTowerType = 'doublecannon';
}
};
superCannonBtn.down = function (x, y, obj) {
if (playerMoney >= 500) {
placingTower = true;
selectedTowerType = 'supercannon';
}
};
rapidTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 100) {
placingTower = true;
selectedTowerType = 'rapid';
}
};
freezeTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 150) {
placingTower = true;
selectedTowerType = 'freeze';
}
};
cactusBombBtn.down = function (x, y, obj) {
if (playerMoney >= 100) {
placingTower = true;
selectedTowerType = 'cactusbomb';
}
};
cactusTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 1000) {
placingTower = true;
selectedTowerType = 'cactus';
}
};
megaSuperTowerBtn.down = function (x, y, obj) {
if (playerMoney >= 2000) {
placingTower = true;
selectedTowerType = 'megasuper';
}
};
bombBtn.down = function (x, y, obj) {
if (playerMoney >= 150) {
placingTower = true;
selectedTowerType = 'bomb';
}
};
superBombBtn.down = function (x, y, obj) {
if (playerMoney >= 2000) {
placingTower = true;
selectedTowerType = 'superbomb';
}
};
nuclearBombBtn.down = function (x, y, obj) {
if (playerMoney >= 10000) {
placingTower = true;
selectedTowerType = 'nuclear';
}
};
multiTargetBtn.down = function (x, y, obj) {
if (playerMoney >= 1500) {
placingTower = true;
selectedTowerType = 'multitarget';
}
};
closeShopBtn.down = function (x, y, obj) {
toggleShop();
};
// Start Menu Event Handlers
playBtn.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
}
};
waveSelectBtn.down = function (x, y, obj) {
if (!gameStarted) {
hideStartMenu();
showWaveSelect();
showingWaveSelect = true;
}
};
waveMinusBtn.down = function (x, y, obj) {
if (showingWaveSelect && selectedStartWave > 1) {
selectedStartWave--;
updateWaveDisplay();
}
};
wavePlusBtn.down = function (x, y, obj) {
if (showingWaveSelect && selectedStartWave < 50) {
selectedStartWave++;
updateWaveDisplay();
}
};
startGameBtn.down = function (x, y, obj) {
if (showingWaveSelect) {
startGame();
}
};
backBtn.down = function (x, y, obj) {
if (showingWaveSelect) {
hideWaveSelect();
showStartMenu();
showingWaveSelect = false;
}
};
// Sandbox mode event handlers
sandboxBtn.down = function (x, y, obj) {
if (!gameStarted) {
startSandboxMode();
}
};
enemyShopBtn.down = function (x, y, obj) {
if (sandboxMode) {
toggleEnemyShop();
}
};
spawnEnemyBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('basic');
}
};
spawnFastBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('fast');
}
};
spawnTankBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('tank');
}
};
spawnBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('boss');
}
};
spawnMageBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('mage');
}
};
spawnSuperMageBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('supermage');
}
};
spawnTankBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('tankboss');
}
};
spawnArmoredBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('armored');
}
};
spawnPigBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('pig');
}
};
spawnMoleBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('mole');
}
};
spawnSkeletonBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('skeleton');
}
};
spawnSuperTank2Btn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('supertank2');
}
};
spawnArmorBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('armorboss');
}
};
spawnObsidianBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('obsidianboss');
}
};
spawnObsidianArmorBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('obsidianarmor');
}
};
spawnGoldBossBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('goldboss');
}
};
spawnSuperOmegaTankBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('superomegatank');
}
};
spawnSuperOmegaArmorBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('superomegaarmor');
}
};
spawnSpawnerBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('spawner');
}
};
spawnBalloonBtn.down = function (x, y, obj) {
if (sandboxMode) {
spawnEnemy('balloon');
}
};
closeEnemyShopBtn.down = function (x, y, obj) {
if (sandboxMode) {
toggleEnemyShop();
}
};
// Initially hide game UI elements
moneyText.visible = false;
livesText.visible = false;
waveText.visible = false;
shopBtn.visible = false;
shopBtnText.visible = false;
readyBtn.visible = false;
readyBtnText.visible = false;
// Initially hide all shop text elements
basicTowerText.visible = false;
slowTowerText.visible = false;
areaTowerText.visible = false;
poisonTowerText.visible = false;
longRangeTowerText.visible = false;
heavyTowerText.visible = false;
superTowerText.visible = false;
doubleCannonText.visible = false;
superCannonText.visible = false;
rapidTowerText.visible = false;
freezeTowerText.visible = false;
cactusBombText.visible = false;
cactusTowerText.visible = false;
megaSuperTowerText.visible = false;
bombText.visible = false;
superBombText.visible = false;
nuclearBombText.visible = false;
multiTargetText.visible = false;
closeShopText.visible = false;
shopTitle.visible = false;
game.down = function (x, y, obj) {
// Don't handle game clicks if not started or in menu
if (!gameStarted || showingWaveSelect) {
return;
}
// Don't place towers if clicking on UI elements (shop area or buttons)
if (y > 2400) {
return; // Clicking in UI area at bottom
}
// Don't place towers if clicking on shop button
if (x >= 100 && x <= 300 && y >= 2460 && y <= 2540) {
return; // Clicking on shop button
}
// Don't place towers if clicking on ready button
if (x >= 400 && x <= 600 && y >= 2460 && y <= 2540) {
return; // Clicking on ready button
}
// Don't place towers if clicking on enemy shop button (sandbox mode)
if (sandboxMode && x >= 700 && x <= 900 && y >= 2460 && y <= 2540) {
return; // Clicking on enemy shop button
}
// Don't place towers if shop is open and clicking in entire expanded shop area
if (shopOpen) {
// Check for all shop button areas with proper scaling (scaleX: 2.2, scaleY: 2.2)
// Basic tower button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 450 - 100 * 2.2 / 2 && y <= shopPanel.y - 450 + 100 * 2.2 / 2) {
return;
}
// Slow tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y - 450 - 100 * 2.2 / 2 && y <= shopPanel.y - 450 + 100 * 2.2 / 2) {
return;
}
// Area tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 450 - 100 * 2.2 / 2 && y <= shopPanel.y - 450 + 100 * 2.2 / 2) {
return;
}
// Poison tower button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 250 - 100 * 2.2 / 2 && y <= shopPanel.y - 250 + 100 * 2.2 / 2) {
return;
}
// Long range tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y - 250 - 100 * 2.2 / 2 && y <= shopPanel.y - 250 + 100 * 2.2 / 2) {
return;
}
// Heavy tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 250 - 100 * 2.2 / 2 && y <= shopPanel.y - 250 + 100 * 2.2 / 2) {
return;
}
// Super tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y - 50 - 100 * 2.2 / 2 && y <= shopPanel.y - 50 + 100 * 2.2 / 2) {
return;
}
// Double cannon button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 150 - 100 * 2.2 / 2 && y <= shopPanel.y + 150 + 100 * 2.2 / 2) {
return;
}
// Super cannon button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 150 - 100 * 2.2 / 2 && y <= shopPanel.y + 150 + 100 * 2.2 / 2) {
return;
}
// Rapid tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 150 - 100 * 2.2 / 2 && y <= shopPanel.y + 150 + 100 * 2.2 / 2) {
return;
}
// Freeze tower button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 350 - 100 * 2.2 / 2 && y <= shopPanel.y + 350 + 100 * 2.2 / 2) {
return;
}
// Cactus bomb button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 50 - 100 * 2.2 / 2 && y <= shopPanel.y - 50 + 100 * 2.2 / 2) {
return;
}
// Cactus tower button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y - 50 - 100 * 2.2 / 2 && y <= shopPanel.y - 50 + 100 * 2.2 / 2) {
return;
}
// Mega super tower button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 350 - 100 * 2.2 / 2 && y <= shopPanel.y + 350 + 100 * 2.2 / 2) {
return;
}
// Bomb button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 350 - 100 * 2.2 / 2 && y <= shopPanel.y + 350 + 100 * 2.2 / 2) {
return;
}
// Super bomb button area
if (x >= shopPanel.x - 350 - 180 * 2.2 / 2 && x <= shopPanel.x - 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 550 - 100 * 2.2 / 2 && y <= shopPanel.y + 550 + 100 * 2.2 / 2) {
return;
}
// Nuclear bomb button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 550 - 100 * 2.2 / 2 && y <= shopPanel.y + 550 + 100 * 2.2 / 2) {
return;
}
// Multi target button area
if (x >= shopPanel.x + 350 - 180 * 2.2 / 2 && x <= shopPanel.x + 350 + 180 * 2.2 / 2 && y >= shopPanel.y + 550 - 100 * 2.2 / 2 && y <= shopPanel.y + 550 + 100 * 2.2 / 2) {
return;
}
// Close shop button area
if (x >= shopPanel.x - 180 * 2.2 / 2 && x <= shopPanel.x + 180 * 2.2 / 2 && y >= shopPanel.y + 850 - 100 * 2.2 / 2 && y <= shopPanel.y + 850 + 100 * 2.2 / 2) {
return;
}
}
// Don't place towers if enemy shop is open and clicking in enemy shop area
if (showingEnemyShop && x > 724 && x < 1324 && y > 866 && y < 1866) {
return; // Clicking inside enemy shop panel
}
if (placingTower) {
placeTower(x, y);
} else {
// Check if clicking on an existing tower to remove it
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - x;
var dy = tower.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If clicking within tower bounds (75px radius)
if (distance <= 75) {
// Refund the tower cost
playerMoney += tower.cost;
updateMoneyDisplay();
// Remove tower from game and array
tower.destroy();
towers.splice(i, 1);
return; // Exit after removing first tower found
}
}
}
};
game.up = function (x, y, obj) {
// Don't handle game clicks if not started or in menu
if (!gameStarted || showingWaveSelect) {
return;
}
// Double tap to cancel tower placement
if (placingTower && obj.doubleTap) {
placingTower = false;
selectedTowerType = null;
}
};
// Main game loop
game.update = function () {
// Don't update game logic if not started
if (!gameStarted) {
return;
}
// Show game UI when game starts
if (gameStarted && !moneyText.visible) {
moneyText.visible = true;
livesText.visible = !sandboxMode; // Hide lives in sandbox mode
waveText.visible = !sandboxMode; // Hide wave text in sandbox mode
shopBtn.visible = true;
shopBtnText.visible = true;
readyBtn.visible = !sandboxMode; // Hide ready button in sandbox mode
readyBtnText.visible = !sandboxMode;
enemyShopBtn.visible = sandboxMode; // Show enemy shop in sandbox mode
enemyShopBtnText.visible = sandboxMode;
updateWaveDisplay();
}
// Update towers
for (var i = 0; i < towers.length; i++) {
towers[i].update();
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.update();
// Remove dead enemies
if (enemy.health <= 0) {
enemy.destroy();
enemies.splice(i, 1);
}
// Remove enemies that reached the end
else if (enemy.pathIndex >= enemyPath.length) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
var shouldRemove = bullet.update();
if (shouldRemove || !bullet.target || bullet.target.health <= 0) {
bullet.destroy();
bullets.splice(i, 1);
}
}
// Check for game over (only in normal mode)
if (!sandboxMode && playerLives <= 0) {
LK.showGameOver();
}
// Keep money infinite in sandbox mode
if (sandboxMode && playerMoney < 999999) {
playerMoney = 999999;
updateMoneyDisplay();
}
// Update lives display if changed
updateLivesDisplay();
// Check if wave is complete
checkWaveComplete();
// Game continues indefinitely - no win condition
};
castillo desde arriba. In-Game asset. 2d. High contrast. No shadows
torrre de fuego desde arriba. In-Game asset. 2d. High contrast. No shadows
torre de hielo desde arriba. In-Game asset. 2d. High contrast. No shadows
cañon desde arriba. In-Game asset. 2d. High contrast. No shadows
torrre con serpientes desde arriba. In-Game asset. 2d. High contrast. No shadows
torre con cristal encima desde arriba. In-Game asset. 2d. High contrast. No shadows
torre con cañones desde arriba. In-Game asset. 2d. High contrast. No shadows
torre con un cañon gigante desde arriba. In-Game asset. 2d. High contrast. No shadows
montruo volado. In-Game asset. 2d. High contrast. No shadows
mostruo con visor sobre moto. In-Game asset. 2d. High contrast. No shadows
auto con 3 esqueletos. In-Game asset. 2d. High contrast. No shadows
mago. In-Game asset. 2d. High contrast. No shadows
cerdo en 2 patas musculoso con armadura. In-Game asset. 2d. High contrast. No shadows
mostruo musculoso zombie. In-Game asset. 2d. High contrast. No shadows
blast. In-Game asset. 2d. High contrast. No shadows
piso marron. In-Game asset. 2d. High contrast. No shadows
con la piel toda roja y con los ojos rojos
tierrra,le salen unos ojos con un casco. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
de cuerpo completo
con piel de obsidiana
con una armadura negra y casco
con una armadura
con una armadura dorada y casco
montruo blanco de ojos negros con dos cabezas con flora en el cuerpo. In-Game asset. 2d. High contrast. No shadows
montruo blanco de ojos negros de dos cabezas musculoso esqueletico. In-Game asset. 2d. High contrast. No shadows
con 4 cabezas y armadura
explosion nuclear. In-Game asset. 2d. High contrast. No shadows
cabeza de esqueleto con montruos blancos en la boca. In-Game asset. 2d. High contrast. No shadows
doble cañon. In-Game asset. 2d. High contrast. No shadows
cañon gigante desde frete. In-Game asset. 2d. High contrast. No shadows
torre con 1 cañon con las balas de minigun desde arriba. In-Game asset. 2d. High contrast. No shadows
bomba. In-Game asset. 2d. High contrast. No shadows
torre con hielo y nieve desde arriba. In-Game asset. 2d. High contrast. No shadows
torre con 10 cañones desde arriba. In-Game asset. 2d. High contrast. No shadows
bomba nuclear. In-Game asset. 2d. High contrast. No shadows
torre con captus desde arriba. In-Game asset. 2d. High contrast. No shadows
globo con cara enojada. In-Game asset. 2d. High contrast. No shadows
con el traje de color rojo