User prompt
Increase the size of the two a little bit
User prompt
Increase the size of 3 a little bit so that it is not equal to 2.
User prompt
2'nin boyutunu büyüt
User prompt
Change the size of 2 and 3 2 will be smaller than 3 3 will be larger than 2
User prompt
Reduce the size of 4 a lot, make the size of 2 the size of 3, reduce the size of 2 a little bit
User prompt
Increase the size of 3 and 4
User prompt
Let the dimension of 3 be 2 and shorten the dimension of the second machine but make it bigger than 1 Let the dimension of 3 be 4 but change the dimension of 3
User prompt
Reduce size of 1
User prompt
Don't just change the size of 1, change the size of all the other machines but they will all be bigger than each other
User prompt
increase the size of one a little bit until you reach the blocks
User prompt
Shorten the range of 1 and 2 1 will be shorter than 2 2 will be larger than 1
User prompt
The range of the second machine should be larger than the range of the first machine, a little bigger
User prompt
Let the range of 2 be less than 1
User prompt
Make the range of 3 quite small and the range of 2 a little small, but 3 will be bigger than 2.
User prompt
1 should be smaller than 2, 3 should be a little smaller, not too much.
User prompt
Look, the range of the fourth should be quite large, the second and third should be a little larger.
User prompt
Let the second one have a smaller range than the other 3 and 4, let the third one have a larger range than it, let the fourth one have a larger range than it but not that much.
User prompt
Reduce the range of the second one a bit and increase the range of the 3rd and 4th ones
User prompt
The first one is 50, the second one is 100, the third one is 200, the fourth one is 260
User prompt
Reduce the prices of the machines a little
User prompt
Increase the purchase prices of machines
User prompt
The selling price and update price of the thing we click on should come up, it should not sell immediately as soon as we click on it.
User prompt
Let there be some space between the buttons and write the sale price and the update price.
User prompt
Let there be some space between the buttons and write the sale price and the update price.
User prompt
Enlarge the buttons a little bit and when you press directly on the machine it will sell or update instantly
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BuildSpot = Container.expand(function () {
var self = Container.call(this);
var spotGraphics = self.attachAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.isOccupied = false;
self.turret = null;
self.previewRange = null;
self.move = function (x, y, obj) {
if (self.isOccupied) return;
if (!self.previewRange) {
// Create preview range indicator
self.previewRange = self.addChild(LK.getAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.15,
tint: selectedTowerType === 'laser' ? 0x4444FF : selectedTowerType === 'missile' ? 0xFF4444 : selectedTowerType === 'fire' ? 0xFF8800 : 0xFFFF00,
scaleX: selectedTowerType === 'laser' ? 4 : selectedTowerType === 'missile' ? 6 : selectedTowerType === 'fire' ? 3 : 3.6,
scaleY: selectedTowerType === 'laser' ? 4 : selectedTowerType === 'missile' ? 6 : selectedTowerType === 'fire' ? 3 : 3.6
}));
}
};
self.up = function (x, y, obj) {
if (self.previewRange) {
self.previewRange.destroy();
self.previewRange = null;
}
};
self.down = function (x, y, obj) {
if (self.isOccupied) return;
if (currency < selectedTowerCost) return;
// Build turret
var turret = new Turret();
turret.x = self.x;
turret.y = self.y;
turret.towerType = selectedTowerType;
turret.cost = selectedTowerCost;
turret.updateTowerProperties(); // Update properties based on tower type
self.turret = turret;
self.isOccupied = true;
currency -= selectedTowerCost;
updateCurrencyDisplay();
turrets.push(turret);
game.addChild(turret);
// Hide build spot
spotGraphics.alpha = 0;
// Flash green when built with tower type color
var flashColor = selectedTowerType === 'laser' ? 0x4444FF : selectedTowerType === 'missile' ? 0xFF4444 : selectedTowerType === 'fire' ? 0xFF8800 : 0xFFFF00;
LK.effects.flashObject(turret, flashColor, 500);
};
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 = 25;
self.damage = 75;
self.targetX = 0;
self.targetY = 0;
self.target = null;
self.isDestroyed = false;
self.update = function () {
if (self.isDestroyed) return;
// Track moving target for better accuracy
if (self.target && !self.target.isDead) {
self.targetX = self.target.x;
self.targetY = self.target.y;
}
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 8) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// Hit target
if (self.target && !self.target.isDead) {
self.target.takeDamage(self.damage);
// Create explosion effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
explosion.destroy();
}
});
LK.getSound('explosion').play();
}
self.isDestroyed = true;
}
};
return self;
});
var Turret = Container.expand(function () {
var self = Container.call(this);
var turretGraphics = self.attachAsset('turret', {
anchorX: 0.5,
anchorY: 0.5
});
// Add range indicator (will be updated based on tower type)
self.rangeIndicator = self.addChild(LK.getAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.25,
tint: 0x4444FF,
scaleX: 4,
scaleY: 4
}));
self.damage = 75;
self.range = 200;
self.fireRate = 15; // frames between shots
self.lastShot = 0;
self.target = null;
self.cost = 50;
self.sellPrice = 25; // 50% of cost back when sold
self.towerType = 'laser'; // Default type
self.upgradeLevel = 1; // Track upgrade level
self.upgradeCost = 50; // Cost to upgrade
self.updateTowerProperties = function () {
var upgradeMultiplier = 1 + (self.upgradeLevel - 1) * 0.5; // 50% increase per level
if (self.towerType === 'laser') {
self.range = 200 * upgradeMultiplier;
self.damage = 75 * upgradeMultiplier;
self.fireRate = Math.max(5, 15 - (self.upgradeLevel - 1) * 2); // Faster fire rate
self.rangeIndicator.tint = 0x4444FF;
self.rangeIndicator.scaleX = 4 * upgradeMultiplier;
self.rangeIndicator.scaleY = 4 * upgradeMultiplier;
self.sellPrice = Math.floor((50 + (self.upgradeLevel - 1) * 50) * 0.5); // 50% of total cost back
self.upgradeCost = 50 * self.upgradeLevel; // Increasing upgrade cost
} else if (self.towerType === 'missile') {
self.range = 300 * upgradeMultiplier;
self.damage = 120 * upgradeMultiplier;
self.fireRate = Math.max(8, 20 - (self.upgradeLevel - 1) * 3);
self.rangeIndicator.tint = 0xFF4444;
self.rangeIndicator.scaleX = 6 * upgradeMultiplier;
self.rangeIndicator.scaleY = 6 * upgradeMultiplier;
self.sellPrice = Math.floor((80 + (self.upgradeLevel - 1) * 80) * 0.5); // 50% of total cost back
self.upgradeCost = 80 * self.upgradeLevel;
} else if (self.towerType === 'fire') {
self.range = 150 * upgradeMultiplier;
self.damage = 90 * upgradeMultiplier;
self.fireRate = Math.max(4, 10 - (self.upgradeLevel - 1) * 2);
self.rangeIndicator.tint = 0xFF8800;
self.rangeIndicator.scaleX = 3 * upgradeMultiplier;
self.rangeIndicator.scaleY = 3 * upgradeMultiplier;
self.sellPrice = Math.floor((100 + (self.upgradeLevel - 1) * 100) * 0.5); // 50% of total cost back
self.upgradeCost = 100 * self.upgradeLevel;
} else if (self.towerType === 'electric') {
self.range = 180 * upgradeMultiplier;
self.damage = 60 * upgradeMultiplier;
self.fireRate = Math.max(6, 12 - (self.upgradeLevel - 1) * 2);
self.rangeIndicator.tint = 0xFFFF00;
self.rangeIndicator.scaleX = 3.6 * upgradeMultiplier;
self.rangeIndicator.scaleY = 3.6 * upgradeMultiplier;
self.sellPrice = Math.floor((70 + (self.upgradeLevel - 1) * 70) * 0.5); // 50% of total cost back
self.upgradeCost = 70 * self.upgradeLevel;
}
};
self.towerType = 'laser'; // Default type
self.findTarget = function () {
var closestZombie = null;
var closestDistance = self.range;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (zombie.isDead) continue;
var dx = zombie.x - self.x;
var dy = zombie.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestZombie = zombie;
}
}
return closestZombie;
};
self.shoot = function (target) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
bullet.target = target;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
// Flash blue when shooting
LK.effects.flashObject(self, 0x4444ff, 200);
};
self.down = function (x, y, obj) {
// Check if shift key is held or double-tap for upgrade, otherwise sell
if (obj.event && obj.event.shiftKey) {
// Upgrade turret directly
if (self.upgradeLevel >= 5) return; // Max upgrade level
if (currency < self.upgradeCost) return; // Not enough money
// Deduct cost
currency -= self.upgradeCost;
updateCurrencyDisplay();
// Upgrade turret
self.upgradeLevel++;
self.updateTowerProperties();
// Visual effects
LK.effects.flashObject(self, 0x00FFFF, 500);
// Change turret color based on upgrade level
if (self.upgradeLevel >= 3) {
self.children[0].tint = 0xFFFFFF; // White for high level
} else if (self.upgradeLevel >= 2) {
self.children[0].tint = 0xFFFF00; // Yellow for mid level
}
} else {
// Sell turret directly
currency += self.sellPrice;
updateCurrencyDisplay();
// Remove turret from game
for (var i = turrets.length - 1; i >= 0; i--) {
if (turrets[i] === self) {
turrets.splice(i, 1);
break;
}
}
self.destroy();
// Flash green effect
LK.effects.flashScreen(0x00FF00, 300);
}
};
self.update = function () {
self.lastShot++;
if (self.lastShot >= self.fireRate) {
var target = self.findTarget();
if (target) {
self.shoot(target);
self.lastShot = 0;
}
}
};
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 1;
self.reward = 10;
self.pathIndex = 0;
self.targetX = 0;
self.targetY = 0;
self.isDead = false;
// Create health bar
self.healthBar = self.addChild(LK.getAsset('buildSpot', {
anchorX: 0,
anchorY: 0.5,
x: -25,
y: -40,
width: 50,
height: 6,
color: 0x44FF44
}));
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.isDead = true;
currency += self.reward;
updateCurrencyDisplay();
LK.getSound('zombieHit').play();
// Flash red when dying
LK.effects.flashObject(self, 0xff0000, 300);
}
};
self.update = function () {
if (self.isDead) return;
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// Reached current target, move to next path point
self.pathIndex++;
if (self.pathIndex >= gamePath.length) {
// Reached end - damage base
lives--;
updateLivesDisplay();
if (lives <= 0) {
LK.showGameOver();
}
self.isDead = true;
} else {
self.targetX = gamePath[self.pathIndex].x;
self.targetY = gamePath[self.pathIndex].y;
}
}
// Update health bar if it exists
if (self.healthBar) {
var healthPercent = self.health / self.maxHealth;
self.healthBar.scaleX = healthPercent;
self.healthBar.tint = healthPercent > 0.5 ? 0x44FF44 : healthPercent > 0.25 ? 0xFFFF44 : 0xFF4444;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
var zombies = [];
var turrets = [];
var bullets = [];
var buildSpots = [];
var gamePath = [];
var currency = 100;
var lives = 10;
var wave = 1;
var zombiesSpawned = 0;
var zombiesToSpawn = 5;
var spawnTimer = 0;
var spawnRate = 120; // frames between spawns
var waveActive = false;
var waveCompleted = false;
var selectedTowerType = 'laser';
var selectedTowerCost = 50;
// Create path points for zombies to follow - Shorter strategic path
gamePath = [{
x: 0,
y: 1366
}, {
x: 400,
y: 1366
}, {
x: 400,
y: 1000
}, {
x: 800,
y: 1000
}, {
x: 800,
y: 1500
}, {
x: 1200,
y: 1500
}, {
x: 1200,
y: 800
}, {
x: 1600,
y: 800
}, {
x: 1600,
y: 400
}, {
x: 1000,
y: 400
}, {
x: 1000,
y: 1800
}, {
x: 1400,
y: 1800
}, {
x: 2048,
y: 1800
}];
// Create visual path
for (var i = 0; i < gamePath.length - 1; i++) {
var start = gamePath[i];
var end = gamePath[i + 1];
var steps = Math.floor(Math.sqrt((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / 120);
for (var j = 0; j <= steps; j++) {
var t = j / steps;
var pathX = start.x + (end.x - start.x) * t;
var pathY = start.y + (end.y - start.y) * t;
var pathTile = game.addChild(LK.getAsset('path', {
anchorX: 0.5,
anchorY: 0.5,
x: pathX,
y: pathY,
alpha: 0.3
}));
}
}
// Build spots are no longer needed - turrets can be placed anywhere
// buildSpots array is kept for compatibility but not used
// UI Elements
var currencyTxt = new Text2('Money: $' + currency, {
size: 72,
fill: 0x00FFFF
});
currencyTxt.anchor.set(0, 0);
currencyTxt.x = 120; // Offset from left edge to avoid platform menu
currencyTxt.y = 100;
LK.gui.topLeft.addChild(currencyTxt);
// Add glowing effect to currency
LK.effects.flashObject(currencyTxt, 0x00FFFF, 2000);
var livesTxt = new Text2('Lives: ' + lives, {
size: 60,
fill: 0xFF4444
});
livesTxt.anchor.set(0, 0);
livesTxt.x = 120; // Offset from left edge to avoid platform menu
livesTxt.y = 20;
LK.gui.topLeft.addChild(livesTxt);
// Tower purchase menu at bottom
var towerMenuBg = game.addChild(LK.getAsset('buildSpot', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2450,
width: 2048,
height: 282,
alpha: 0.9,
tint: 0x1a1a1a
}));
var laserTurretBtn = new Text2('Laser Gun\n$50', {
size: 48,
fill: 0x4444FF
});
laserTurretBtn.anchor.set(0.5, 0.5);
laserTurretBtn.x = 256;
laserTurretBtn.y = 2591;
game.addChild(laserTurretBtn);
var missileLauncherBtn = new Text2('Missile Tower\n$80', {
size: 48,
fill: 0xFF4444
});
missileLauncherBtn.anchor.set(0.5, 0.5);
missileLauncherBtn.x = 682;
missileLauncherBtn.y = 2591;
game.addChild(missileLauncherBtn);
var fireDroneBtn = new Text2('Fire Blaster\n$100', {
size: 48,
fill: 0xFF8800
});
fireDroneBtn.anchor.set(0.5, 0.5);
fireDroneBtn.x = 1366;
fireDroneBtn.y = 2591;
game.addChild(fireDroneBtn);
var electricTrapBtn = new Text2('Electric Field\n$70', {
size: 48,
fill: 0xFFFF00
});
electricTrapBtn.anchor.set(0.5, 0.5);
electricTrapBtn.x = 1792;
electricTrapBtn.y = 2591;
game.addChild(electricTrapBtn);
var waveTxt = new Text2('Level ' + wave, {
size: 80,
fill: 0x44FF44
});
waveTxt.anchor.set(0.5, 0);
waveTxt.y = 20;
LK.gui.top.addChild(waveTxt);
// Bomb system
var bombsLeft = 3;
var bombTxt = new Text2('Bombs: ' + bombsLeft, {
size: 72,
fill: 0xFF0000
});
bombTxt.anchor.set(1, 0);
bombTxt.x = -20;
bombTxt.y = -80;
LK.gui.topRight.addChild(bombTxt);
var bombBtn = new Text2('💣 BOMB', {
size: 80,
fill: 0xFF4444
});
bombBtn.anchor.set(1, 1);
bombBtn.x = -20;
bombBtn.y = -20;
LK.gui.bottomRight.addChild(bombBtn);
var startWaveBtn = new Text2('START WAVE', {
size: 80,
fill: 0xFFFFFF
});
startWaveBtn.anchor.set(0.5, 0.5);
startWaveBtn.x = 1024;
startWaveBtn.y = 2600;
game.addChild(startWaveBtn);
var sellBtn = new Text2('SELL\nTURRET', {
size: 64,
fill: 0xFFAA00
});
sellBtn.anchor.set(0.5, 0.5);
sellBtn.x = 900; // Position to the left of center
sellBtn.y = 2400; // Move up slightly
sellBtn.alpha = 0.5; // Start dimmed
game.addChild(sellBtn);
var upgradeBtn = new Text2('UPGRADE\nTURRET', {
size: 64,
fill: 0x00FF00
});
upgradeBtn.anchor.set(0.5, 0.5);
upgradeBtn.x = 1148; // Position to the right of center
upgradeBtn.y = 2400; // Same height as sell button
upgradeBtn.alpha = 0.5; // Start dimmed
game.addChild(upgradeBtn);
function distanceToLineSegment(px, py, x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
var length = Math.sqrt(dx * dx + dy * dy);
if (length === 0) return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
var t = ((px - x1) * dx + (py - y1) * dy) / (length * length);
t = Math.max(0, Math.min(1, t));
var projX = x1 + t * dx;
var projY = y1 + t * dy;
return Math.sqrt((px - projX) * (px - projX) + (py - projY) * (py - projY));
}
function updateCurrencyDisplay() {
currencyTxt.setText('Money: $' + currency);
// Add glowing effect when currency changes
LK.effects.flashObject(currencyTxt, 0x00FFFF, 500);
}
function updateBombDisplay() {
bombTxt.setText('Bombs: ' + bombsLeft);
}
function useBomb() {
if (bombsLeft <= 0) return;
bombsLeft--;
updateBombDisplay();
// Create massive explosion effect
var bombExplosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 10,
scaleY: 10,
alpha: 0.8
}));
// Damage all zombies significantly
for (var i = 0; i < zombies.length; i++) {
if (!zombies[i].isDead) {
zombies[i].takeDamage(150);
LK.effects.flashObject(zombies[i], 0xFF0000, 500);
}
}
// Animate explosion
tween(bombExplosion, {
alpha: 0,
scaleX: 15,
scaleY: 15
}, {
duration: 1000,
onFinish: function onFinish() {
bombExplosion.destroy();
}
});
LK.getSound('explosion').play();
LK.effects.flashScreen(0xFF4444, 800);
}
function updateLivesDisplay() {
livesTxt.setText('Lives: ' + lives);
}
function updateWaveDisplay() {
waveTxt.setText('Level ' + wave);
}
function startWave() {
if (waveActive) return;
waveActive = true;
waveCompleted = false;
zombiesSpawned = 0;
zombiesToSpawn = 5 + wave * 2;
spawnTimer = 0;
startWaveBtn.alpha = 0.3;
// Increase zombie health each wave
Zombie.prototype.baseHealth = 100 + wave * 25;
}
function spawnZombie() {
if (zombiesSpawned >= zombiesToSpawn) return;
var zombie = new Zombie();
zombie.x = gamePath[0].x;
zombie.y = gamePath[0].y;
zombie.targetX = gamePath[1].x;
zombie.targetY = gamePath[1].y;
zombie.health = 100 + wave * 25;
zombie.maxHealth = zombie.health;
zombie.speed = 1 + wave * 0.2;
zombie.reward = 10 + wave * 5;
// Add visual effects for higher levels
if (wave >= 5) {
// Add glowing red eyes effect
LK.effects.flashObject(zombie, 0xFF0000, 1000);
if (wave >= 8) {
// Add armor glow for very high levels
zombie.attachAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
tint: 0xFFFFFF,
scaleX: 1.2,
scaleY: 1.2
});
}
}
zombies.push(zombie);
game.addChild(zombie);
zombiesSpawned++;
}
function checkWaveComplete() {
if (!waveActive) return;
var aliveZombies = 0;
for (var i = 0; i < zombies.length; i++) {
if (!zombies[i].isDead) {
aliveZombies++;
}
}
if (zombiesSpawned >= zombiesToSpawn && aliveZombies === 0) {
waveActive = false;
waveCompleted = true;
wave++;
updateWaveDisplay();
currency += 50; // Wave completion bonus
updateCurrencyDisplay();
startWaveBtn.alpha = 1;
// Flash screen green for wave completion
LK.effects.flashScreen(0x44ff44, 1000);
// Check win condition
if (wave > 10) {
LK.showYouWin();
}
}
}
// Start wave button interaction
startWaveBtn.down = function (x, y, obj) {
startWave();
};
// Bomb button interaction
bombBtn.down = function (x, y, obj) {
useBomb();
};
// Sell button interaction
sellBtn.down = function (x, y, obj) {
sellTurret();
};
// Upgrade button interaction
upgradeBtn.down = function (x, y, obj) {
upgradeTurret();
};
// Tower selection highlighting
var selectedTowerBtn = laserTurretBtn;
function highlightSelectedTower() {
// Reset all tower buttons
laserTurretBtn.alpha = selectedTowerType === 'laser' ? 1.0 : 0.7;
missileLauncherBtn.alpha = selectedTowerType === 'missile' ? 1.0 : 0.7;
fireDroneBtn.alpha = selectedTowerType === 'fire' ? 1.0 : 0.7;
electricTrapBtn.alpha = selectedTowerType === 'electric' ? 1.0 : 0.7;
// Add glow effect to selected tower
if (selectedTowerType === 'laser') {
LK.effects.flashObject(laserTurretBtn, 0x4444FF, 500);
} else if (selectedTowerType === 'missile') {
LK.effects.flashObject(missileLauncherBtn, 0xFF4444, 500);
} else if (selectedTowerType === 'fire') {
LK.effects.flashObject(fireDroneBtn, 0xFF8800, 500);
} else if (selectedTowerType === 'electric') {
LK.effects.flashObject(electricTrapBtn, 0xFFFF00, 500);
}
}
// Initial highlight
highlightSelectedTower();
// Tower menu interactions
laserTurretBtn.down = function (x, y, obj) {
selectedTowerType = 'laser';
selectedTowerCost = 50;
highlightSelectedTower();
};
missileLauncherBtn.down = function (x, y, obj) {
selectedTowerType = 'missile';
selectedTowerCost = 80;
highlightSelectedTower();
};
fireDroneBtn.down = function (x, y, obj) {
selectedTowerType = 'fire';
selectedTowerCost = 100;
highlightSelectedTower();
};
electricTrapBtn.down = function (x, y, obj) {
selectedTowerType = 'electric';
selectedTowerCost = 70;
highlightSelectedTower();
};
var selectedTurret = null;
function selectTurret(turret) {
// Deselect previous turret
if (selectedTurret) {
selectedTurret.rangeIndicator.alpha = 0.25;
}
selectedTurret = turret;
// Highlight selected turret
selectedTurret.rangeIndicator.alpha = 0.5;
sellBtn.alpha = 1.0; // Enable sell button
upgradeBtn.alpha = 1.0; // Enable upgrade button
// Update upgrade button text with cost
upgradeBtn.setText('UPGRADE\nLv.' + selectedTurret.upgradeLevel + ' → ' + (selectedTurret.upgradeLevel + 1) + '\n$' + selectedTurret.upgradeCost);
LK.effects.flashObject(selectedTurret, 0x00FF00, 300);
}
function deselectTurret() {
if (selectedTurret) {
selectedTurret.rangeIndicator.alpha = 0.25;
}
selectedTurret = null;
sellBtn.alpha = 0.5; // Disable sell button
upgradeBtn.alpha = 0.5; // Disable upgrade button
upgradeBtn.setText('UPGRADE\nTURRET'); // Reset text
}
function sellTurret() {
if (!selectedTurret) return;
// Give money back
currency += selectedTurret.sellPrice;
updateCurrencyDisplay();
// Remove turret from game
for (var i = turrets.length - 1; i >= 0; i--) {
if (turrets[i] === selectedTurret) {
turrets.splice(i, 1);
break;
}
}
selectedTurret.destroy();
// Flash green effect
LK.effects.flashScreen(0x00FF00, 300);
deselectTurret();
}
function upgradeTurret() {
if (!selectedTurret) return;
if (selectedTurret.upgradeLevel >= 5) return; // Max upgrade level
if (currency < selectedTurret.upgradeCost) return; // Not enough money
// Deduct cost
currency -= selectedTurret.upgradeCost;
updateCurrencyDisplay();
// Upgrade turret
selectedTurret.upgradeLevel++;
selectedTurret.updateTowerProperties();
// Update upgrade button text
upgradeBtn.setText('UPGRADE\nLv.' + selectedTurret.upgradeLevel + ' → ' + (selectedTurret.upgradeLevel + 1) + '\n$' + selectedTurret.upgradeCost);
// Visual effects
LK.effects.flashObject(selectedTurret, 0x00FFFF, 500);
// Change turret color based on upgrade level
if (selectedTurret.upgradeLevel >= 3) {
selectedTurret.children[0].tint = 0xFFFFFF; // White for high level
} else if (selectedTurret.upgradeLevel >= 2) {
selectedTurret.children[0].tint = 0xFFFF00; // Yellow for mid level
}
}
// Game-wide click handler for placing turrets anywhere
game.down = function (x, y, obj) {
// Check if click is in game area (not on UI elements)
if (y > 2400) return; // Don't place on bottom UI
// Check if clicking on existing turret to select it
var clickedTurret = null;
for (var i = 0; i < turrets.length; i++) {
var dx = turrets[i].x - x;
var dy = turrets[i].y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 40) {
// Within turret bounds
clickedTurret = turrets[i];
break;
}
}
if (clickedTurret) {
// Select the turret
selectTurret(clickedTurret);
return;
} else {
// Deselect any selected turret
deselectTurret();
}
if (currency < selectedTowerCost) return;
// Check if placement is too close to the zombie path
var tooCloseToPath = false;
for (var i = 0; i < gamePath.length - 1; i++) {
var start = gamePath[i];
var end = gamePath[i + 1];
var pathDistance = distanceToLineSegment(x, y, start.x, start.y, end.x, end.y);
if (pathDistance < 100) {
// Minimum distance from path
tooCloseToPath = true;
break;
}
}
if (tooCloseToPath) return;
// Check if there's already a turret at this position
var tooClose = false;
for (var i = 0; i < turrets.length; i++) {
var dx = turrets[i].x - x;
var dy = turrets[i].y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
// Minimum distance between turrets
tooClose = true;
break;
}
}
if (tooClose) return;
// Build turret at clicked position
var turret = new Turret();
turret.x = x;
turret.y = y;
turret.towerType = selectedTowerType;
turret.cost = selectedTowerCost;
turret.updateTowerProperties();
currency -= selectedTowerCost;
updateCurrencyDisplay();
turrets.push(turret);
game.addChild(turret);
// Flash green when built with tower type color
var flashColor = selectedTowerType === 'laser' ? 0x4444FF : selectedTowerType === 'missile' ? 0xFF4444 : selectedTowerType === 'fire' ? 0xFF8800 : 0xFFFF00;
LK.effects.flashObject(turret, flashColor, 500);
};
game.update = function () {
// Spawn zombies
if (waveActive && zombiesSpawned < zombiesToSpawn) {
spawnTimer++;
if (spawnTimer >= spawnRate) {
spawnZombie();
spawnTimer = 0;
}
}
// Clean up dead zombies
for (var i = zombies.length - 1; i >= 0; i--) {
if (zombies[i].isDead) {
zombies[i].destroy();
zombies.splice(i, 1);
}
}
// Clean up destroyed bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i].isDestroyed) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
checkWaveComplete();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BuildSpot = Container.expand(function () {
var self = Container.call(this);
var spotGraphics = self.attachAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.isOccupied = false;
self.turret = null;
self.previewRange = null;
self.move = function (x, y, obj) {
if (self.isOccupied) return;
if (!self.previewRange) {
// Create preview range indicator
self.previewRange = self.addChild(LK.getAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.15,
tint: selectedTowerType === 'laser' ? 0x4444FF : selectedTowerType === 'missile' ? 0xFF4444 : selectedTowerType === 'fire' ? 0xFF8800 : 0xFFFF00,
scaleX: selectedTowerType === 'laser' ? 4 : selectedTowerType === 'missile' ? 6 : selectedTowerType === 'fire' ? 3 : 3.6,
scaleY: selectedTowerType === 'laser' ? 4 : selectedTowerType === 'missile' ? 6 : selectedTowerType === 'fire' ? 3 : 3.6
}));
}
};
self.up = function (x, y, obj) {
if (self.previewRange) {
self.previewRange.destroy();
self.previewRange = null;
}
};
self.down = function (x, y, obj) {
if (self.isOccupied) return;
if (currency < selectedTowerCost) return;
// Build turret
var turret = new Turret();
turret.x = self.x;
turret.y = self.y;
turret.towerType = selectedTowerType;
turret.cost = selectedTowerCost;
turret.updateTowerProperties(); // Update properties based on tower type
self.turret = turret;
self.isOccupied = true;
currency -= selectedTowerCost;
updateCurrencyDisplay();
turrets.push(turret);
game.addChild(turret);
// Hide build spot
spotGraphics.alpha = 0;
// Flash green when built with tower type color
var flashColor = selectedTowerType === 'laser' ? 0x4444FF : selectedTowerType === 'missile' ? 0xFF4444 : selectedTowerType === 'fire' ? 0xFF8800 : 0xFFFF00;
LK.effects.flashObject(turret, flashColor, 500);
};
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 = 25;
self.damage = 75;
self.targetX = 0;
self.targetY = 0;
self.target = null;
self.isDestroyed = false;
self.update = function () {
if (self.isDestroyed) return;
// Track moving target for better accuracy
if (self.target && !self.target.isDead) {
self.targetX = self.target.x;
self.targetY = self.target.y;
}
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 8) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// Hit target
if (self.target && !self.target.isDead) {
self.target.takeDamage(self.damage);
// Create explosion effect
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
}));
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
explosion.destroy();
}
});
LK.getSound('explosion').play();
}
self.isDestroyed = true;
}
};
return self;
});
var Turret = Container.expand(function () {
var self = Container.call(this);
var turretGraphics = self.attachAsset('turret', {
anchorX: 0.5,
anchorY: 0.5
});
// Add range indicator (will be updated based on tower type)
self.rangeIndicator = self.addChild(LK.getAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.25,
tint: 0x4444FF,
scaleX: 4,
scaleY: 4
}));
self.damage = 75;
self.range = 200;
self.fireRate = 15; // frames between shots
self.lastShot = 0;
self.target = null;
self.cost = 50;
self.sellPrice = 25; // 50% of cost back when sold
self.towerType = 'laser'; // Default type
self.upgradeLevel = 1; // Track upgrade level
self.upgradeCost = 50; // Cost to upgrade
self.updateTowerProperties = function () {
var upgradeMultiplier = 1 + (self.upgradeLevel - 1) * 0.5; // 50% increase per level
if (self.towerType === 'laser') {
self.range = 200 * upgradeMultiplier;
self.damage = 75 * upgradeMultiplier;
self.fireRate = Math.max(5, 15 - (self.upgradeLevel - 1) * 2); // Faster fire rate
self.rangeIndicator.tint = 0x4444FF;
self.rangeIndicator.scaleX = 4 * upgradeMultiplier;
self.rangeIndicator.scaleY = 4 * upgradeMultiplier;
self.sellPrice = Math.floor((50 + (self.upgradeLevel - 1) * 50) * 0.5); // 50% of total cost back
self.upgradeCost = 50 * self.upgradeLevel; // Increasing upgrade cost
} else if (self.towerType === 'missile') {
self.range = 300 * upgradeMultiplier;
self.damage = 120 * upgradeMultiplier;
self.fireRate = Math.max(8, 20 - (self.upgradeLevel - 1) * 3);
self.rangeIndicator.tint = 0xFF4444;
self.rangeIndicator.scaleX = 6 * upgradeMultiplier;
self.rangeIndicator.scaleY = 6 * upgradeMultiplier;
self.sellPrice = Math.floor((80 + (self.upgradeLevel - 1) * 80) * 0.5); // 50% of total cost back
self.upgradeCost = 80 * self.upgradeLevel;
} else if (self.towerType === 'fire') {
self.range = 150 * upgradeMultiplier;
self.damage = 90 * upgradeMultiplier;
self.fireRate = Math.max(4, 10 - (self.upgradeLevel - 1) * 2);
self.rangeIndicator.tint = 0xFF8800;
self.rangeIndicator.scaleX = 3 * upgradeMultiplier;
self.rangeIndicator.scaleY = 3 * upgradeMultiplier;
self.sellPrice = Math.floor((100 + (self.upgradeLevel - 1) * 100) * 0.5); // 50% of total cost back
self.upgradeCost = 100 * self.upgradeLevel;
} else if (self.towerType === 'electric') {
self.range = 180 * upgradeMultiplier;
self.damage = 60 * upgradeMultiplier;
self.fireRate = Math.max(6, 12 - (self.upgradeLevel - 1) * 2);
self.rangeIndicator.tint = 0xFFFF00;
self.rangeIndicator.scaleX = 3.6 * upgradeMultiplier;
self.rangeIndicator.scaleY = 3.6 * upgradeMultiplier;
self.sellPrice = Math.floor((70 + (self.upgradeLevel - 1) * 70) * 0.5); // 50% of total cost back
self.upgradeCost = 70 * self.upgradeLevel;
}
};
self.towerType = 'laser'; // Default type
self.findTarget = function () {
var closestZombie = null;
var closestDistance = self.range;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (zombie.isDead) continue;
var dx = zombie.x - self.x;
var dy = zombie.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestZombie = zombie;
}
}
return closestZombie;
};
self.shoot = function (target) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = target.x;
bullet.targetY = target.y;
bullet.damage = self.damage;
bullet.target = target;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
// Flash blue when shooting
LK.effects.flashObject(self, 0x4444ff, 200);
};
self.down = function (x, y, obj) {
// Check if shift key is held or double-tap for upgrade, otherwise sell
if (obj.event && obj.event.shiftKey) {
// Upgrade turret directly
if (self.upgradeLevel >= 5) return; // Max upgrade level
if (currency < self.upgradeCost) return; // Not enough money
// Deduct cost
currency -= self.upgradeCost;
updateCurrencyDisplay();
// Upgrade turret
self.upgradeLevel++;
self.updateTowerProperties();
// Visual effects
LK.effects.flashObject(self, 0x00FFFF, 500);
// Change turret color based on upgrade level
if (self.upgradeLevel >= 3) {
self.children[0].tint = 0xFFFFFF; // White for high level
} else if (self.upgradeLevel >= 2) {
self.children[0].tint = 0xFFFF00; // Yellow for mid level
}
} else {
// Sell turret directly
currency += self.sellPrice;
updateCurrencyDisplay();
// Remove turret from game
for (var i = turrets.length - 1; i >= 0; i--) {
if (turrets[i] === self) {
turrets.splice(i, 1);
break;
}
}
self.destroy();
// Flash green effect
LK.effects.flashScreen(0x00FF00, 300);
}
};
self.update = function () {
self.lastShot++;
if (self.lastShot >= self.fireRate) {
var target = self.findTarget();
if (target) {
self.shoot(target);
self.lastShot = 0;
}
}
};
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 1;
self.reward = 10;
self.pathIndex = 0;
self.targetX = 0;
self.targetY = 0;
self.isDead = false;
// Create health bar
self.healthBar = self.addChild(LK.getAsset('buildSpot', {
anchorX: 0,
anchorY: 0.5,
x: -25,
y: -40,
width: 50,
height: 6,
color: 0x44FF44
}));
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.isDead = true;
currency += self.reward;
updateCurrencyDisplay();
LK.getSound('zombieHit').play();
// Flash red when dying
LK.effects.flashObject(self, 0xff0000, 300);
}
};
self.update = function () {
if (self.isDead) return;
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// Reached current target, move to next path point
self.pathIndex++;
if (self.pathIndex >= gamePath.length) {
// Reached end - damage base
lives--;
updateLivesDisplay();
if (lives <= 0) {
LK.showGameOver();
}
self.isDead = true;
} else {
self.targetX = gamePath[self.pathIndex].x;
self.targetY = gamePath[self.pathIndex].y;
}
}
// Update health bar if it exists
if (self.healthBar) {
var healthPercent = self.health / self.maxHealth;
self.healthBar.scaleX = healthPercent;
self.healthBar.tint = healthPercent > 0.5 ? 0x44FF44 : healthPercent > 0.25 ? 0xFFFF44 : 0xFF4444;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
var zombies = [];
var turrets = [];
var bullets = [];
var buildSpots = [];
var gamePath = [];
var currency = 100;
var lives = 10;
var wave = 1;
var zombiesSpawned = 0;
var zombiesToSpawn = 5;
var spawnTimer = 0;
var spawnRate = 120; // frames between spawns
var waveActive = false;
var waveCompleted = false;
var selectedTowerType = 'laser';
var selectedTowerCost = 50;
// Create path points for zombies to follow - Shorter strategic path
gamePath = [{
x: 0,
y: 1366
}, {
x: 400,
y: 1366
}, {
x: 400,
y: 1000
}, {
x: 800,
y: 1000
}, {
x: 800,
y: 1500
}, {
x: 1200,
y: 1500
}, {
x: 1200,
y: 800
}, {
x: 1600,
y: 800
}, {
x: 1600,
y: 400
}, {
x: 1000,
y: 400
}, {
x: 1000,
y: 1800
}, {
x: 1400,
y: 1800
}, {
x: 2048,
y: 1800
}];
// Create visual path
for (var i = 0; i < gamePath.length - 1; i++) {
var start = gamePath[i];
var end = gamePath[i + 1];
var steps = Math.floor(Math.sqrt((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / 120);
for (var j = 0; j <= steps; j++) {
var t = j / steps;
var pathX = start.x + (end.x - start.x) * t;
var pathY = start.y + (end.y - start.y) * t;
var pathTile = game.addChild(LK.getAsset('path', {
anchorX: 0.5,
anchorY: 0.5,
x: pathX,
y: pathY,
alpha: 0.3
}));
}
}
// Build spots are no longer needed - turrets can be placed anywhere
// buildSpots array is kept for compatibility but not used
// UI Elements
var currencyTxt = new Text2('Money: $' + currency, {
size: 72,
fill: 0x00FFFF
});
currencyTxt.anchor.set(0, 0);
currencyTxt.x = 120; // Offset from left edge to avoid platform menu
currencyTxt.y = 100;
LK.gui.topLeft.addChild(currencyTxt);
// Add glowing effect to currency
LK.effects.flashObject(currencyTxt, 0x00FFFF, 2000);
var livesTxt = new Text2('Lives: ' + lives, {
size: 60,
fill: 0xFF4444
});
livesTxt.anchor.set(0, 0);
livesTxt.x = 120; // Offset from left edge to avoid platform menu
livesTxt.y = 20;
LK.gui.topLeft.addChild(livesTxt);
// Tower purchase menu at bottom
var towerMenuBg = game.addChild(LK.getAsset('buildSpot', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2450,
width: 2048,
height: 282,
alpha: 0.9,
tint: 0x1a1a1a
}));
var laserTurretBtn = new Text2('Laser Gun\n$50', {
size: 48,
fill: 0x4444FF
});
laserTurretBtn.anchor.set(0.5, 0.5);
laserTurretBtn.x = 256;
laserTurretBtn.y = 2591;
game.addChild(laserTurretBtn);
var missileLauncherBtn = new Text2('Missile Tower\n$80', {
size: 48,
fill: 0xFF4444
});
missileLauncherBtn.anchor.set(0.5, 0.5);
missileLauncherBtn.x = 682;
missileLauncherBtn.y = 2591;
game.addChild(missileLauncherBtn);
var fireDroneBtn = new Text2('Fire Blaster\n$100', {
size: 48,
fill: 0xFF8800
});
fireDroneBtn.anchor.set(0.5, 0.5);
fireDroneBtn.x = 1366;
fireDroneBtn.y = 2591;
game.addChild(fireDroneBtn);
var electricTrapBtn = new Text2('Electric Field\n$70', {
size: 48,
fill: 0xFFFF00
});
electricTrapBtn.anchor.set(0.5, 0.5);
electricTrapBtn.x = 1792;
electricTrapBtn.y = 2591;
game.addChild(electricTrapBtn);
var waveTxt = new Text2('Level ' + wave, {
size: 80,
fill: 0x44FF44
});
waveTxt.anchor.set(0.5, 0);
waveTxt.y = 20;
LK.gui.top.addChild(waveTxt);
// Bomb system
var bombsLeft = 3;
var bombTxt = new Text2('Bombs: ' + bombsLeft, {
size: 72,
fill: 0xFF0000
});
bombTxt.anchor.set(1, 0);
bombTxt.x = -20;
bombTxt.y = -80;
LK.gui.topRight.addChild(bombTxt);
var bombBtn = new Text2('💣 BOMB', {
size: 80,
fill: 0xFF4444
});
bombBtn.anchor.set(1, 1);
bombBtn.x = -20;
bombBtn.y = -20;
LK.gui.bottomRight.addChild(bombBtn);
var startWaveBtn = new Text2('START WAVE', {
size: 80,
fill: 0xFFFFFF
});
startWaveBtn.anchor.set(0.5, 0.5);
startWaveBtn.x = 1024;
startWaveBtn.y = 2600;
game.addChild(startWaveBtn);
var sellBtn = new Text2('SELL\nTURRET', {
size: 64,
fill: 0xFFAA00
});
sellBtn.anchor.set(0.5, 0.5);
sellBtn.x = 900; // Position to the left of center
sellBtn.y = 2400; // Move up slightly
sellBtn.alpha = 0.5; // Start dimmed
game.addChild(sellBtn);
var upgradeBtn = new Text2('UPGRADE\nTURRET', {
size: 64,
fill: 0x00FF00
});
upgradeBtn.anchor.set(0.5, 0.5);
upgradeBtn.x = 1148; // Position to the right of center
upgradeBtn.y = 2400; // Same height as sell button
upgradeBtn.alpha = 0.5; // Start dimmed
game.addChild(upgradeBtn);
function distanceToLineSegment(px, py, x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
var length = Math.sqrt(dx * dx + dy * dy);
if (length === 0) return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
var t = ((px - x1) * dx + (py - y1) * dy) / (length * length);
t = Math.max(0, Math.min(1, t));
var projX = x1 + t * dx;
var projY = y1 + t * dy;
return Math.sqrt((px - projX) * (px - projX) + (py - projY) * (py - projY));
}
function updateCurrencyDisplay() {
currencyTxt.setText('Money: $' + currency);
// Add glowing effect when currency changes
LK.effects.flashObject(currencyTxt, 0x00FFFF, 500);
}
function updateBombDisplay() {
bombTxt.setText('Bombs: ' + bombsLeft);
}
function useBomb() {
if (bombsLeft <= 0) return;
bombsLeft--;
updateBombDisplay();
// Create massive explosion effect
var bombExplosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 10,
scaleY: 10,
alpha: 0.8
}));
// Damage all zombies significantly
for (var i = 0; i < zombies.length; i++) {
if (!zombies[i].isDead) {
zombies[i].takeDamage(150);
LK.effects.flashObject(zombies[i], 0xFF0000, 500);
}
}
// Animate explosion
tween(bombExplosion, {
alpha: 0,
scaleX: 15,
scaleY: 15
}, {
duration: 1000,
onFinish: function onFinish() {
bombExplosion.destroy();
}
});
LK.getSound('explosion').play();
LK.effects.flashScreen(0xFF4444, 800);
}
function updateLivesDisplay() {
livesTxt.setText('Lives: ' + lives);
}
function updateWaveDisplay() {
waveTxt.setText('Level ' + wave);
}
function startWave() {
if (waveActive) return;
waveActive = true;
waveCompleted = false;
zombiesSpawned = 0;
zombiesToSpawn = 5 + wave * 2;
spawnTimer = 0;
startWaveBtn.alpha = 0.3;
// Increase zombie health each wave
Zombie.prototype.baseHealth = 100 + wave * 25;
}
function spawnZombie() {
if (zombiesSpawned >= zombiesToSpawn) return;
var zombie = new Zombie();
zombie.x = gamePath[0].x;
zombie.y = gamePath[0].y;
zombie.targetX = gamePath[1].x;
zombie.targetY = gamePath[1].y;
zombie.health = 100 + wave * 25;
zombie.maxHealth = zombie.health;
zombie.speed = 1 + wave * 0.2;
zombie.reward = 10 + wave * 5;
// Add visual effects for higher levels
if (wave >= 5) {
// Add glowing red eyes effect
LK.effects.flashObject(zombie, 0xFF0000, 1000);
if (wave >= 8) {
// Add armor glow for very high levels
zombie.attachAsset('buildSpot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
tint: 0xFFFFFF,
scaleX: 1.2,
scaleY: 1.2
});
}
}
zombies.push(zombie);
game.addChild(zombie);
zombiesSpawned++;
}
function checkWaveComplete() {
if (!waveActive) return;
var aliveZombies = 0;
for (var i = 0; i < zombies.length; i++) {
if (!zombies[i].isDead) {
aliveZombies++;
}
}
if (zombiesSpawned >= zombiesToSpawn && aliveZombies === 0) {
waveActive = false;
waveCompleted = true;
wave++;
updateWaveDisplay();
currency += 50; // Wave completion bonus
updateCurrencyDisplay();
startWaveBtn.alpha = 1;
// Flash screen green for wave completion
LK.effects.flashScreen(0x44ff44, 1000);
// Check win condition
if (wave > 10) {
LK.showYouWin();
}
}
}
// Start wave button interaction
startWaveBtn.down = function (x, y, obj) {
startWave();
};
// Bomb button interaction
bombBtn.down = function (x, y, obj) {
useBomb();
};
// Sell button interaction
sellBtn.down = function (x, y, obj) {
sellTurret();
};
// Upgrade button interaction
upgradeBtn.down = function (x, y, obj) {
upgradeTurret();
};
// Tower selection highlighting
var selectedTowerBtn = laserTurretBtn;
function highlightSelectedTower() {
// Reset all tower buttons
laserTurretBtn.alpha = selectedTowerType === 'laser' ? 1.0 : 0.7;
missileLauncherBtn.alpha = selectedTowerType === 'missile' ? 1.0 : 0.7;
fireDroneBtn.alpha = selectedTowerType === 'fire' ? 1.0 : 0.7;
electricTrapBtn.alpha = selectedTowerType === 'electric' ? 1.0 : 0.7;
// Add glow effect to selected tower
if (selectedTowerType === 'laser') {
LK.effects.flashObject(laserTurretBtn, 0x4444FF, 500);
} else if (selectedTowerType === 'missile') {
LK.effects.flashObject(missileLauncherBtn, 0xFF4444, 500);
} else if (selectedTowerType === 'fire') {
LK.effects.flashObject(fireDroneBtn, 0xFF8800, 500);
} else if (selectedTowerType === 'electric') {
LK.effects.flashObject(electricTrapBtn, 0xFFFF00, 500);
}
}
// Initial highlight
highlightSelectedTower();
// Tower menu interactions
laserTurretBtn.down = function (x, y, obj) {
selectedTowerType = 'laser';
selectedTowerCost = 50;
highlightSelectedTower();
};
missileLauncherBtn.down = function (x, y, obj) {
selectedTowerType = 'missile';
selectedTowerCost = 80;
highlightSelectedTower();
};
fireDroneBtn.down = function (x, y, obj) {
selectedTowerType = 'fire';
selectedTowerCost = 100;
highlightSelectedTower();
};
electricTrapBtn.down = function (x, y, obj) {
selectedTowerType = 'electric';
selectedTowerCost = 70;
highlightSelectedTower();
};
var selectedTurret = null;
function selectTurret(turret) {
// Deselect previous turret
if (selectedTurret) {
selectedTurret.rangeIndicator.alpha = 0.25;
}
selectedTurret = turret;
// Highlight selected turret
selectedTurret.rangeIndicator.alpha = 0.5;
sellBtn.alpha = 1.0; // Enable sell button
upgradeBtn.alpha = 1.0; // Enable upgrade button
// Update upgrade button text with cost
upgradeBtn.setText('UPGRADE\nLv.' + selectedTurret.upgradeLevel + ' → ' + (selectedTurret.upgradeLevel + 1) + '\n$' + selectedTurret.upgradeCost);
LK.effects.flashObject(selectedTurret, 0x00FF00, 300);
}
function deselectTurret() {
if (selectedTurret) {
selectedTurret.rangeIndicator.alpha = 0.25;
}
selectedTurret = null;
sellBtn.alpha = 0.5; // Disable sell button
upgradeBtn.alpha = 0.5; // Disable upgrade button
upgradeBtn.setText('UPGRADE\nTURRET'); // Reset text
}
function sellTurret() {
if (!selectedTurret) return;
// Give money back
currency += selectedTurret.sellPrice;
updateCurrencyDisplay();
// Remove turret from game
for (var i = turrets.length - 1; i >= 0; i--) {
if (turrets[i] === selectedTurret) {
turrets.splice(i, 1);
break;
}
}
selectedTurret.destroy();
// Flash green effect
LK.effects.flashScreen(0x00FF00, 300);
deselectTurret();
}
function upgradeTurret() {
if (!selectedTurret) return;
if (selectedTurret.upgradeLevel >= 5) return; // Max upgrade level
if (currency < selectedTurret.upgradeCost) return; // Not enough money
// Deduct cost
currency -= selectedTurret.upgradeCost;
updateCurrencyDisplay();
// Upgrade turret
selectedTurret.upgradeLevel++;
selectedTurret.updateTowerProperties();
// Update upgrade button text
upgradeBtn.setText('UPGRADE\nLv.' + selectedTurret.upgradeLevel + ' → ' + (selectedTurret.upgradeLevel + 1) + '\n$' + selectedTurret.upgradeCost);
// Visual effects
LK.effects.flashObject(selectedTurret, 0x00FFFF, 500);
// Change turret color based on upgrade level
if (selectedTurret.upgradeLevel >= 3) {
selectedTurret.children[0].tint = 0xFFFFFF; // White for high level
} else if (selectedTurret.upgradeLevel >= 2) {
selectedTurret.children[0].tint = 0xFFFF00; // Yellow for mid level
}
}
// Game-wide click handler for placing turrets anywhere
game.down = function (x, y, obj) {
// Check if click is in game area (not on UI elements)
if (y > 2400) return; // Don't place on bottom UI
// Check if clicking on existing turret to select it
var clickedTurret = null;
for (var i = 0; i < turrets.length; i++) {
var dx = turrets[i].x - x;
var dy = turrets[i].y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 40) {
// Within turret bounds
clickedTurret = turrets[i];
break;
}
}
if (clickedTurret) {
// Select the turret
selectTurret(clickedTurret);
return;
} else {
// Deselect any selected turret
deselectTurret();
}
if (currency < selectedTowerCost) return;
// Check if placement is too close to the zombie path
var tooCloseToPath = false;
for (var i = 0; i < gamePath.length - 1; i++) {
var start = gamePath[i];
var end = gamePath[i + 1];
var pathDistance = distanceToLineSegment(x, y, start.x, start.y, end.x, end.y);
if (pathDistance < 100) {
// Minimum distance from path
tooCloseToPath = true;
break;
}
}
if (tooCloseToPath) return;
// Check if there's already a turret at this position
var tooClose = false;
for (var i = 0; i < turrets.length; i++) {
var dx = turrets[i].x - x;
var dy = turrets[i].y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
// Minimum distance between turrets
tooClose = true;
break;
}
}
if (tooClose) return;
// Build turret at clicked position
var turret = new Turret();
turret.x = x;
turret.y = y;
turret.towerType = selectedTowerType;
turret.cost = selectedTowerCost;
turret.updateTowerProperties();
currency -= selectedTowerCost;
updateCurrencyDisplay();
turrets.push(turret);
game.addChild(turret);
// Flash green when built with tower type color
var flashColor = selectedTowerType === 'laser' ? 0x4444FF : selectedTowerType === 'missile' ? 0xFF4444 : selectedTowerType === 'fire' ? 0xFF8800 : 0xFFFF00;
LK.effects.flashObject(turret, flashColor, 500);
};
game.update = function () {
// Spawn zombies
if (waveActive && zombiesSpawned < zombiesToSpawn) {
spawnTimer++;
if (spawnTimer >= spawnRate) {
spawnZombie();
spawnTimer = 0;
}
}
// Clean up dead zombies
for (var i = zombies.length - 1; i >= 0; i--) {
if (zombies[i].isDead) {
zombies[i].destroy();
zombies.splice(i, 1);
}
}
// Clean up destroyed bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i].isDestroyed) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
checkWaveComplete();
};