/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Bullet = Container.expand(function (type, damage, speed, tower) {
	var self = Container.call(this);
	self.type = type || 'normal';
	self.damage = damage || 10;
	self.speed = speed || 8;
	self.tower = tower;
	self.target = null;
	self.destroyed = false;
	var bulletGraphics;
	if (self.type === 'ice') {
		bulletGraphics = self.attachAsset('iceBullet', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'cannon') {
		bulletGraphics = self.attachAsset('cannonBall', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		bulletGraphics = self.attachAsset('bullet', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	self.update = function () {
		// Don't update if bullet is already destroyed
		if (self.destroyed) {
			return;
		}
		if (self.target && !self.target.destroyed) {
			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 - mark bullet as destroyed first to prevent multiple hits
				self.destroyed = true;
				// Apply damage to target
				self.target.takeDamage(self.damage);
				// Apply special effects based on bullet type
				if (self.type === 'ice') {
					self.target.slow(0.5, 2000); // 50% speed for 2 seconds
					self.target.applyIceEffect(); // Apply blue visual effect
				} else if (self.type === 'cannon') {
					// Splash damage
					for (var i = 0; i < enemies.length; i++) {
						var enemy = enemies[i];
						var splashDx = enemy.x - self.x;
						var splashDy = enemy.y - self.y;
						var splashDistance = Math.sqrt(splashDx * splashDx + splashDy * splashDy);
						if (splashDistance < 60 && enemy !== self.target) {
							enemy.takeDamage(self.damage * 0.5);
						}
					}
				}
				LK.getSound('enemyHit').play();
				self.destroy();
				return;
			}
			var angle = Math.atan2(dy, dx);
			self.x += Math.cos(angle) * self.speed;
			self.y += Math.sin(angle) * self.speed;
		} else {
			self.destroyed = true;
			self.destroy();
		}
	};
	return self;
});
var Enemy = Container.expand(function (type, path) {
	var self = Container.call(this);
	self.type = type || 'basic';
	self.path = path;
	self.pathIndex = 0;
	self.health = 0;
	self.maxHealth = 0;
	self.speed = 0;
	self.baseSpeed = 0;
	self.reward = 0;
	self.slowFactor = 1;
	self.slowEndTime = 0;
	self.destroyed = false;
	self.healAmount = 0;
	self.hasHealed = false;
	// Enemy stats based on type
	var stats = {
		basic: {
			health: 60,
			speed: 1.5,
			reward: 10
		},
		fast: {
			health: 40,
			speed: 2.5,
			reward: 15
		},
		tank: {
			health: 160,
			speed: 1,
			reward: 25
		},
		boss: {
			health: 500,
			speed: 0.8,
			reward: 100
		}
	};
	var enemyStats = stats[self.type];
	// Double health after wave 5
	var healthMultiplier = currentWave > 5 ? 2 : 1;
	self.health = enemyStats.health * healthMultiplier;
	self.maxHealth = enemyStats.health * healthMultiplier;
	self.speed = enemyStats.speed;
	self.baseSpeed = enemyStats.speed;
	self.reward = enemyStats.reward;
	if (self.type === 'boss') {
		if (currentWave === 5) {
			self.healAmount = 3000;
		} else if (currentWave === 10) {
			self.healAmount = 10000;
		}
	}
	var enemyGraphics;
	if (self.type === 'fast') {
		enemyGraphics = self.attachAsset('fastEnemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'tank') {
		enemyGraphics = self.attachAsset('tankEnemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'boss') {
		if (currentWave === 5) {
			enemyGraphics = self.attachAsset('Bos1', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		} else if (currentWave === 10) {
			enemyGraphics = self.attachAsset('Bos2', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		enemyGraphics.scaleX = 1.5;
		enemyGraphics.scaleY = 1.5;
	} else {
		enemyGraphics = self.attachAsset('basicEnemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	// Health bar
	self.healthBarBg = LK.getAsset('gridCell', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.6,
		scaleY: 0.1
	});
	self.healthBarBg.tint = 0x000000;
	self.healthBarBg.y = -30;
	self.addChild(self.healthBarBg);
	self.healthBar = LK.getAsset('gridCell', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.6,
		scaleY: 0.1
	});
	self.healthBar.tint = 0x00FF00;
	self.healthBar.y = -30;
	self.addChild(self.healthBar);
	self.takeDamage = function (damage) {
		self.health -= damage;
		self.updateHealthBar();
		if (self.health <= 0) {
			self.die();
		}
	};
	self.updateHealthBar = function () {
		var healthPercent = self.health / self.maxHealth;
		self.healthBar.scaleX = 0.6 * healthPercent;
		if (healthPercent > 0.6) {
			self.healthBar.tint = 0x00FF00;
		} else if (healthPercent > 0.3) {
			self.healthBar.tint = 0xFFFF00;
		} else {
			self.healthBar.tint = 0xFF0000;
		}
	};
	self.slow = function (factor, duration) {
		self.slowFactor = factor;
		self.slowEndTime = Date.now() + duration;
	};
	self.applyIceEffect = function () {
		// Stop any existing ice effect tween
		tween.stop(enemyGraphics, {
			tint: true
		});
		// Apply blue tint immediately
		enemyGraphics.tint = 0x4169E1; // Royal blue color
		// Tween back to normal color after 2 seconds
		tween(enemyGraphics, {
			tint: 0xFFFFFF
		}, {
			duration: 2000,
			easing: tween.easeOut
		});
	};
	self.die = function () {
		self.destroyed = true;
		// Stop any ongoing tween effects
		tween.stop(enemyGraphics, {
			tint: true
		});
		playerMoney += self.reward;
		LK.getSound('enemyDestroyed').play();
		updateUI();
		self.destroy();
	};
	self.reachBase = function () {
		self.destroyed = true;
		playerLives--;
		updateUI();
		if (playerLives <= 0) {
			gameState = 'gameOver';
			LK.showGameOver();
		}
		self.destroy();
	};
	self.update = function () {
		// Boss healing logic
		if (self.type === 'boss' && !self.hasHealed && self.health > 0 && self.health / self.maxHealth <= 0.5) {
			self.health += self.healAmount;
			if (self.health > self.maxHealth) {
				self.health = self.maxHealth;
			}
			self.hasHealed = true;
			self.updateHealthBar();
			// Visual effect for healing - flash green
			tween.stop(enemyGraphics, {
				tint: true
			});
			enemyGraphics.tint = 0x00FF00;
			tween(enemyGraphics, {
				tint: 0xFFFFFF
			}, {
				duration: 500
			});
		}
		// Handle slow effect
		if (Date.now() > self.slowEndTime) {
			self.slowFactor = 1;
		}
		var currentSpeed = self.baseSpeed * self.slowFactor;
		if (self.pathIndex < self.path.length - 1) {
			var target = self.path[self.pathIndex + 1];
			var dx = target.x - self.x;
			var dy = target.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < 5) {
				self.pathIndex++;
				if (self.pathIndex >= self.path.length - 1) {
					self.reachBase();
					return;
				}
			} else {
				var angle = Math.atan2(dy, dx);
				self.x += Math.cos(angle) * currentSpeed;
				self.y += Math.sin(angle) * currentSpeed;
			}
		} else {
			self.reachBase();
		}
	};
	return self;
});
var MoneyCoin = Container.expand(function (value) {
	var self = Container.call(this);
	self.value = value || 25;
	self.collected = false;
	var coinGraphics = self.attachAsset('moneyCoin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	coinGraphics.tint = 0xFFD700; // Gold color
	// Add value text
	self.valueText = new Text2('$' + self.value, {
		size: 20,
		fill: 0xFFFFFF
	});
	self.valueText.anchor.set(0.5, 0.5);
	self.valueText.x = 0;
	self.valueText.y = -25;
	self.addChild(self.valueText);
	self.collect = function () {
		if (self.collected) return;
		self.collected = true;
		// Add money to player
		playerMoney += self.value;
		// If this coin was from a money tree, decrement its counter
		if (self.sourceTree) {
			self.sourceTree.currentMoney--;
		}
		// Play collection sound
		LK.getSound('coinCollect').play();
		// Collection animation - fly up and fade out
		tween(self, {
			y: self.y - 100,
			alpha: 0,
			scaleX: 1.5,
			scaleY: 1.5
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
		// Update UI
		updateUI();
	};
	self.down = function (x, y, obj) {
		self.collect();
	};
	return self;
});
var MoneyTree = Container.expand(function (gridX, gridY) {
	var self = Container.call(this);
	self.type = 'moneyTree';
	self.gridX = gridX;
	self.gridY = gridY;
	self.lastDropTime = 0;
	self.dropInterval = 5000; // Drop money every 5 seconds
	self.moneyAmount = 25; // Amount of money to drop
	self.maxMoney = 2; // Maximum number of money coins that can be accumulated
	self.currentMoney = 0; // Current number of money coins from this tree
	var treeGraphics = self.attachAsset('moneyTree', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add glow effect to distinguish money trees
	treeGraphics.tint = 0xFFD700; // Gold tint
	self.dropMoney = function () {
		// Only drop money if under the limit
		if (self.currentMoney >= self.maxMoney) {
			return; // Don't drop more money if at maximum
		}
		// Create money coin
		var coin = new MoneyCoin(self.moneyAmount);
		coin.x = self.x;
		coin.y = self.y - 30; // Start above the tree
		coin.sourceTree = self; // Reference to the tree that created this coin
		// Increment the tree's money count
		self.currentMoney++;
		// Add to game
		moneyCoins.push(coin);
		game.addChild(coin);
		// Animate coin dropping with bounce
		var targetY = self.y + 50;
		tween(coin, {
			y: targetY
		}, {
			duration: 800,
			easing: tween.bounceOut
		});
		// Add floating effect after landing
		LK.setTimeout(function () {
			tween(coin, {
				y: targetY - 10
			}, {
				duration: 1000,
				repeat: -1,
				yoyo: true,
				easing: tween.easeInOut
			});
		}, 800);
	};
	self.getTotalCost = function () {
		return 200; // Cost of money tree is fixed at 200
	};
	self.sell = function () {
		var sellValue = Math.floor(self.getTotalCost() * 0.75);
		playerMoney += sellValue;
		// Mark grid cell as unoccupied
		grid[self.gridX][self.gridY].occupied = false;
		// Remove from moneyTrees array
		for (var i = moneyTrees.length - 1; i >= 0; i--) {
			if (moneyTrees[i] === self) {
				moneyTrees.splice(i, 1);
				break;
			}
		}
		// Clear selection
		selectedTower = null;
		showUpgradeUI = false;
		// Update UI
		updateUI();
		// Destroy tree
		self.destroy();
	};
	self.down = function (x, y, obj) {
		if (gameState === 'playing') {
			selectedTower = self;
			showUpgradeUI = true;
		}
	};
	self.update = function () {
		var currentTime = Date.now();
		if (currentTime - self.lastDropTime >= self.dropInterval) {
			self.dropMoney();
			self.lastDropTime = currentTime;
		}
	};
	return self;
});
var Tower = Container.expand(function (type, gridX, gridY) {
	var self = Container.call(this);
	self.type = type || 'archer';
	self.gridX = gridX;
	self.gridY = gridY;
	self.level = 1;
	self.lastShotTime = 0;
	// Tower stats based on type and level
	self.getStats = function () {
		var stats = {
			archer: {
				damage: 15 * self.level,
				range: 240 + self.level * 20,
				fireRate: 800 - self.level * 100,
				// ms between shots
				cost: 50,
				upgradeCost: self.level * 60
			},
			ice: {
				damage: 8 * self.level,
				range: 135 + self.level * 15,
				fireRate: 1200 - self.level * 150,
				cost: 75,
				upgradeCost: self.level * 90
			},
			cannon: {
				damage: 40 * self.level,
				range: 90 + self.level * 10,
				fireRate: 1500 - self.level * 200,
				cost: 100,
				upgradeCost: self.level * 120
			}
		};
		return stats[self.type];
	};
	var towerGraphics;
	if (self.type === 'ice') {
		towerGraphics = self.attachAsset('iceTower', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'cannon') {
		towerGraphics = self.attachAsset('cannonTower', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		towerGraphics = self.attachAsset('archerTower', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	// Level indicator
	self.levelText = new Text2(self.level.toString(), {
		size: 20,
		fill: 0xFFFFFF
	});
	self.levelText.anchor.set(0.5, 0.5);
	self.levelText.x = 0;
	self.levelText.y = -30;
	self.addChild(self.levelText);
	self.findTarget = function () {
		var stats = self.getStats();
		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 <= stats.range && distance < closestDistance) {
				closestDistance = distance;
				closestEnemy = enemy;
			}
		}
		return closestEnemy;
	};
	self.shoot = function (target) {
		var stats = self.getStats();
		var bullet = new Bullet(self.type, stats.damage, 8, self);
		bullet.target = target;
		bullet.x = self.x;
		bullet.y = self.y;
		bullets.push(bullet);
		game.addChild(bullet);
		LK.getSound('shoot').play();
	};
	self.getTotalCost = function () {
		var stats = self.getStats();
		var totalCost = stats.cost;
		// Add upgrade costs for each level beyond 1
		for (var i = 1; i < self.level; i++) {
			totalCost += i * (stats.cost * 0.6); // Upgrade cost formula
		}
		return totalCost;
	};
	self.upgrade = function () {
		var stats = self.getStats();
		if (playerMoney >= stats.upgradeCost) {
			playerMoney -= stats.upgradeCost;
			self.level++;
			self.levelText.setText(self.level.toString());
			updateUI();
		}
	};
	self.sell = function () {
		var sellValue = Math.floor(self.getTotalCost() * 0.75);
		playerMoney += sellValue;
		// Mark grid cell as unoccupied
		grid[self.gridX][self.gridY].occupied = false;
		// Remove from towers array
		for (var i = towers.length - 1; i >= 0; i--) {
			if (towers[i] === self) {
				towers.splice(i, 1);
				break;
			}
		}
		// Clear selection
		selectedTower = null;
		showUpgradeUI = false;
		// Update UI
		updateUI();
		// Destroy tower
		self.destroy();
	};
	self.down = function (x, y, obj) {
		if (gameState === 'playing') {
			selectedTower = self;
			showUpgradeUI = true;
		}
	};
	self.update = function () {
		var stats = self.getStats();
		var currentTime = Date.now();
		if (currentTime - self.lastShotTime >= stats.fireRate) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.lastShotTime = currentTime;
			}
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x228B22
});
/**** 
* Game Code
****/ 
// Game state
var gameState = 'playing'; // 'playing', 'gameOver', 'victory'
var playerMoney = 200;
var playerLives = 20;
var currentWave = 1;
var maxWaves = 10;
var waveInProgress = false;
var nextWaveTimer = 0;
var enemySpawnTimer = 0;
var enemiesInWave = 0;
var enemiesSpawned = 0;
// Game objects
var towers = [];
var enemies = [];
var bullets = [];
var moneyTrees = [];
var moneyCoins = [];
var selectedTower = null;
var showUpgradeUI = false;
// Grid system
var gridSize = 80;
var gridWidth = Math.floor(2048 / gridSize);
var gridHeight = Math.floor(2732 / gridSize);
var grid = [];
// Path definition (from top to bottom with some turns)
var pathPoints = [{
	x: 0,
	y: 5
}, {
	x: 3,
	y: 5
}, {
	x: 3,
	y: 10
}, {
	x: 8,
	y: 10
}, {
	x: 8,
	y: 15
}, {
	x: 15,
	y: 15
}, {
	x: 15,
	y: 20
}, {
	x: 20,
	y: 20
}, {
	x: 20,
	y: 25
}, {
	x: 25,
	y: 25
}];
// Convert grid coordinates to world coordinates
function gridToWorld(gridX, gridY) {
	return {
		x: gridX * gridSize + gridSize / 2,
		y: gridY * gridSize + gridSize / 2
	};
}
// Convert world coordinates to grid coordinates
function worldToGrid(worldX, worldY) {
	return {
		x: Math.floor(worldX / gridSize),
		y: Math.floor(worldY / gridSize)
	};
}
// Initialize grid
function initializeGrid() {
	for (var x = 0; x < gridWidth; x++) {
		grid[x] = [];
		for (var y = 0; y < gridHeight; y++) {
			grid[x][y] = {
				occupied: false,
				isPath: false
			};
		}
	}
	// Mark path cells - create continuous path between all points
	for (var i = 0; i < pathPoints.length; i++) {
		var point = pathPoints[i];
		if (point.x < gridWidth && point.y < gridHeight) {
			grid[point.x][point.y].isPath = true;
		}
		// If not the last point, draw line to next point
		if (i < pathPoints.length - 1) {
			var nextPoint = pathPoints[i + 1];
			var startX = point.x;
			var startY = point.y;
			var endX = nextPoint.x;
			var endY = nextPoint.y;
			// Draw horizontal line first, then vertical
			if (startX !== endX) {
				var minX = Math.min(startX, endX);
				var maxX = Math.max(startX, endX);
				for (var x = minX; x <= maxX; x++) {
					if (x < gridWidth && startY < gridHeight) {
						grid[x][startY].isPath = true;
					}
				}
			}
			if (startY !== endY) {
				var minY = Math.min(startY, endY);
				var maxY = Math.max(startY, endY);
				for (var y = minY; y <= maxY; y++) {
					if (endX < gridWidth && y < gridHeight) {
						grid[endX][y].isPath = true;
					}
				}
			}
		}
	}
}
// Draw grid
function drawGrid() {
	for (var x = 0; x < gridWidth; x++) {
		for (var y = 0; y < gridHeight; y++) {
			var worldPos = gridToWorld(x, y);
			var cell;
			if (grid[x][y].isPath) {
				cell = LK.getAsset('pathCell', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: worldPos.x,
					y: worldPos.y,
					alpha: 0.8
				});
			} else {
				cell = LK.getAsset('gridCell', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: worldPos.x,
					y: worldPos.y,
					alpha: 0.3
				});
			}
			game.addChild(cell);
		}
	}
}
// Create path for enemies
function createPath() {
	var path = [];
	for (var i = 0; i < pathPoints.length; i++) {
		var point = pathPoints[i];
		var worldPos = gridToWorld(point.x, point.y);
		path.push(worldPos);
	}
	return path;
}
// Place base at the end of path
function placeBase() {
	var lastPoint = pathPoints[pathPoints.length - 1];
	var worldPos = gridToWorld(lastPoint.x, lastPoint.y);
	var base = LK.getAsset('base', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: worldPos.x,
		y: worldPos.y
	});
	game.addChild(base);
}
// Place money trees at strategic locations - removed automatic placement for player purchase
function placeMoneyTrees() {
	// Money trees are now purchased by player, no automatic placement
}
// UI elements
var moneyText = new Text2('Money: $' + playerMoney, {
	size: 40,
	fill: 0xFFFFFF
});
moneyText.anchor.set(0, 0);
moneyText.x = 120;
moneyText.y = 20;
LK.gui.topLeft.addChild(moneyText);
var livesText = new Text2('Lives: ' + playerLives, {
	size: 40,
	fill: 0xFFFFFF
});
livesText.anchor.set(1, 0);
livesText.x = -20;
livesText.y = 20;
LK.gui.topRight.addChild(livesText);
var waveText = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
	size: 40,
	fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
waveText.x = 0;
waveText.y = 20;
LK.gui.top.addChild(waveText);
// Tower shop with button assets positioned at bottom corner
var shopY = -300; // Position from bottom
var buttonSize = 80;
var buttonSpacing = 100;
// Archer button (Buton1)
var archerButton = LK.getAsset('Buton1', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing,
	y: shopY
});
// Add direct click handler to archer button
archerButton.down = function (x, y, obj) {
	selectedTowerType = 'archer';
	showRangeCircle = true;
	console.log('Archer button clicked directly');
	// Add click animation
	tween(archerButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(archerButton);
var archerText = new Text2('Archer', {
	size: 25,
	fill: 0xFFFFFF
});
archerText.anchor.set(0.5, 0.5);
archerText.x = buttonSpacing;
archerText.y = shopY;
LK.gui.bottomLeft.addChild(archerText);
// Ice button (Buton2)
var iceButton = LK.getAsset('Buton2', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing * 2,
	y: shopY
});
// Add direct click handler to ice button
iceButton.down = function (x, y, obj) {
	selectedTowerType = 'ice';
	showRangeCircle = true;
	console.log('Ice button clicked directly');
	// Add click animation
	tween(iceButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(iceButton);
var iceText = new Text2('Ice', {
	size: 25,
	fill: 0xFFFFFF
});
iceText.anchor.set(0.5, 0.5);
iceText.x = buttonSpacing * 2;
iceText.y = shopY;
LK.gui.bottomLeft.addChild(iceText);
// Cannon button (Buton3)
var cannonButton = LK.getAsset('Buton3', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing * 3,
	y: shopY
});
// Add direct click handler to cannon button
cannonButton.down = function (x, y, obj) {
	selectedTowerType = 'cannon';
	showRangeCircle = true;
	console.log('Cannon button clicked directly');
	// Add click animation
	tween(cannonButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(cannonButton);
var cannonText = new Text2('Cannon', {
	size: 25,
	fill: 0xFFFFFF
});
cannonText.anchor.set(0.5, 0.5);
cannonText.x = buttonSpacing * 3;
cannonText.y = shopY;
LK.gui.bottomLeft.addChild(cannonText);
// Money Tree button (fourth button)
var moneyTreeButton = LK.getAsset('Buton1', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing * 4,
	y: shopY
});
moneyTreeButton.tint = 0xFFD700; // Gold color for money tree
// Add direct click handler to money tree button
moneyTreeButton.down = function (x, y, obj) {
	selectedTowerType = 'moneyTree';
	showRangeCircle = false; // No range circle for money trees
	console.log('Money Tree button clicked directly');
	// Add click animation
	tween(moneyTreeButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(moneyTreeButton);
var moneyTreeText = new Text2('Money Tree', {
	size: 20,
	fill: 0xFFFFFF
});
moneyTreeText.anchor.set(0.5, 0.5);
moneyTreeText.x = buttonSpacing * 4;
moneyTreeText.y = shopY;
LK.gui.bottomLeft.addChild(moneyTreeText);
// Selected tower info
var selectedTowerType = 'archer';
var rangeCircle = null;
var showRangeCircle = false;
// Add status text to show selected tower type
var selectedTowerText = new Text2('Selected: Archer Tower ($50)', {
	size: 30,
	fill: 0x00FF00
});
selectedTowerText.anchor.set(1, 0);
selectedTowerText.x = -20;
selectedTowerText.y = 80;
LK.gui.topRight.addChild(selectedTowerText);
function showTowerRange(x, y) {
	if (!showRangeCircle) return;
	// Get range for selected tower type
	var towerRanges = {
		archer: 240,
		ice: 135,
		cannon: 90
	};
	var range = towerRanges[selectedTowerType];
	// Remove existing range circle
	if (rangeCircle) {
		rangeCircle.destroy();
		rangeCircle = null;
	}
	// Create new range circle
	rangeCircle = LK.getAsset('gridCell', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: range / 40,
		// Scale to match range (gridCell is 80px, so 40 is radius)
		scaleY: range / 40,
		alpha: 0.3,
		x: x,
		y: y
	});
	rangeCircle.tint = 0x0080FF; // Semi-transparent blue
	game.addChild(rangeCircle);
}
function hideRangeCircle() {
	showRangeCircle = false;
	if (rangeCircle) {
		rangeCircle.destroy();
		rangeCircle = null;
	}
}
function updateTowerSelection() {
	// Stop any existing tweens on buttons
	tween.stop(archerButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	tween.stop(iceButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	tween.stop(cannonButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	tween.stop(moneyTreeButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	// Reset all button colors and scales
	archerButton.tint = 0xFFFFFF;
	iceButton.tint = 0xFFFFFF;
	cannonButton.tint = 0xFFFFFF;
	moneyTreeButton.tint = 0xFFD700; // Gold base color for money tree
	archerButton.scaleX = archerButton.scaleY = 1;
	iceButton.scaleX = iceButton.scaleY = 1;
	cannonButton.scaleX = cannonButton.scaleY = 1;
	moneyTreeButton.scaleX = moneyTreeButton.scaleY = 1;
	// Highlight selected button with bright green glow and scale
	if (selectedTowerType === 'archer') {
		archerButton.tint = 0x00FF00; // Bright green for selected
		archerButton.scaleX = archerButton.scaleY = 1.2;
		// Add pulsing effect
		tween(archerButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else if (selectedTowerType === 'ice') {
		iceButton.tint = 0x00FF00; // Bright green for selected
		iceButton.scaleX = iceButton.scaleY = 1.2;
		// Add pulsing effect
		tween(iceButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else if (selectedTowerType === 'cannon') {
		cannonButton.tint = 0x00FF00; // Bright green for selected
		cannonButton.scaleX = cannonButton.scaleY = 1.2;
		// Add pulsing effect
		tween(cannonButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else if (selectedTowerType === 'moneyTree') {
		moneyTreeButton.tint = 0x00FF00; // Bright green for selected
		moneyTreeButton.scaleX = moneyTreeButton.scaleY = 1.2;
		// Add pulsing effect
		tween(moneyTreeButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	}
	// Update status text
	var towerCosts = {
		archer: 50,
		ice: 75,
		cannon: 100,
		moneyTree: 200
	};
	var cost = towerCosts[selectedTowerType];
	var towerName = selectedTowerType === 'moneyTree' ? 'Money Tree' : selectedTowerType.charAt(0).toUpperCase() + selectedTowerType.slice(1);
	var canAfford = playerMoney >= cost;
	var statusColor = canAfford ? 0x00FF00 : 0xFF0000;
	selectedTowerText.tint = statusColor;
	var itemType = selectedTowerType === 'moneyTree' ? '' : ' Tower';
	selectedTowerText.setText('Selected: ' + towerName + itemType + ' ($' + cost + ') - Click grid to place');
}
// Upgrade UI Canvas Background
var upgradeCanvas = LK.getAsset('gridCell', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 6,
	scaleY: 4,
	alpha: 0.7
});
upgradeCanvas.tint = 0x333333; // Semi-transparent gray
upgradeCanvas.x = 0;
upgradeCanvas.y = 280;
LK.gui.center.addChild(upgradeCanvas);
// Upgrade UI Title
var upgradeTitle = new Text2('TOWER INFO', {
	size: 32,
	fill: 0xFFFFFF
});
upgradeTitle.anchor.set(0.5, 0.5);
upgradeTitle.x = 0;
upgradeTitle.y = 180;
LK.gui.center.addChild(upgradeTitle);
// Tower stats display
var upgradeText = new Text2('', {
	size: 28,
	fill: 0xFFFFFF
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.x = 0;
upgradeText.y = 250;
LK.gui.center.addChild(upgradeText);
// Upgrade button with background
var upgradeButtonBg = LK.getAsset('gridCell', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 2.5,
	scaleY: 0.8,
	alpha: 0.8
});
upgradeButtonBg.tint = 0xFFD700;
upgradeButtonBg.x = 0;
upgradeButtonBg.y = 350;
LK.gui.center.addChild(upgradeButtonBg);
var upgradeButton = new Text2('', {
	size: 30,
	fill: 0x000000
});
upgradeButton.anchor.set(0.5, 0.5);
upgradeButton.x = 0;
upgradeButton.y = 350;
upgradeButton.scaleX = 1;
upgradeButton.scaleY = 1;
LK.gui.center.addChild(upgradeButton);
// Sell button with background
var sellButtonBg = LK.getAsset('gridCell', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 2.5,
	scaleY: 0.8,
	alpha: 0.8
});
sellButtonBg.tint = 0xFF4444;
sellButtonBg.x = 0;
sellButtonBg.y = 410;
LK.gui.center.addChild(sellButtonBg);
var sellButton = new Text2('', {
	size: 30,
	fill: 0xFFFFFF
});
sellButton.anchor.set(0.5, 0.5);
sellButton.x = 0;
sellButton.y = 410;
sellButton.scaleX = 1;
sellButton.scaleY = 1;
LK.gui.center.addChild(sellButton);
upgradeButton.down = function () {
	if (showUpgradeUI && selectedTower) {
		var stats = selectedTower.getStats();
		if (playerMoney >= stats.upgradeCost) {
			// Animate both button and background
			tween(upgradeButton, {
				scaleX: 1.1,
				scaleY: 1.1
			}, {
				duration: 100,
				onFinish: function onFinish() {
					tween(upgradeButton, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 100
					});
				}
			});
			tween(upgradeButtonBg, {
				scaleX: 2.7,
				scaleY: 0.9
			}, {
				duration: 100,
				onFinish: function onFinish() {
					tween(upgradeButtonBg, {
						scaleX: 2.5,
						scaleY: 0.8
					}, {
						duration: 100
					});
				}
			});
			selectedTower.upgrade();
		}
	}
};
sellButton.down = function () {
	if (showUpgradeUI && selectedTower) {
		// Animate both button and background
		tween(sellButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 100,
			onFinish: function onFinish() {
				tween(sellButton, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 100
				});
			}
		});
		tween(sellButtonBg, {
			scaleX: 2.7,
			scaleY: 0.9
		}, {
			duration: 100,
			onFinish: function onFinish() {
				tween(sellButtonBg, {
					scaleX: 2.5,
					scaleY: 0.8
				}, {
					duration: 100
				});
			}
		});
		selectedTower.sell();
	}
};
function updateUI() {
	moneyText.setText('Money: $' + playerMoney);
	livesText.setText('Lives: ' + playerLives);
	waveText.setText('Wave: ' + currentWave + '/' + maxWaves);
	updateTowerSelection(); // Update selection display when money changes
	if (showUpgradeUI && selectedTower) {
		var isMoneyTree = selectedTower.type === 'moneyTree';
		var sellValue = Math.floor(selectedTower.getTotalCost() * 0.75);
		// Show canvas and UI elements
		upgradeCanvas.alpha = 0.7;
		upgradeTitle.alpha = 1;
		upgradeText.alpha = 1;
		upgradeButton.alpha = isMoneyTree ? 0 : 1;
		sellButton.alpha = 1;
		upgradeButtonBg.alpha = isMoneyTree ? 0 : 0.8;
		sellButtonBg.alpha = 0.8;
		sellButton.setText('SELL $' + sellValue);
		if (isMoneyTree) {
			// Update text content for Money Tree
			upgradeTitle.setText('MONEY TREE');
			var infoText = 'Generates $' + selectedTower.moneyAmount + ' every ' + selectedTower.dropInterval / 1000 + 's.\n';
			infoText += 'Max ' + selectedTower.maxMoney + ' coins can accumulate.';
			upgradeText.setText(infoText);
		} else {
			// Update text content for normal towers
			var stats = selectedTower.getStats();
			var towerName = selectedTower.type.charAt(0).toUpperCase() + selectedTower.type.slice(1);
			upgradeTitle.setText(towerName.toUpperCase() + ' TOWER');
			upgradeText.setText('Damage: ' + stats.damage + '\nRange: ' + stats.range + '\nFire Rate: ' + Math.round(1000 / stats.fireRate * 60) + '/sec');
			upgradeButton.setText('UPGRADE $' + stats.upgradeCost);
			// Visual feedback for upgrade affordability
			if (playerMoney >= stats.upgradeCost) {
				upgradeButtonBg.tint = 0xFFD700; // Gold when affordable
				upgradeButton.tint = 0x000000; // Black text on gold background
			} else {
				upgradeButtonBg.tint = 0x666666; // Gray when not affordable
				upgradeButton.tint = 0xFFFFFF; // White text on gray background
			}
		}
		// Sell button is always available
		sellButtonBg.tint = 0xFF4444;
		sellButton.tint = 0xFFFFFF;
	} else {
		upgradeCanvas.alpha = 0;
		upgradeTitle.alpha = 0;
		upgradeText.alpha = 0;
		upgradeButton.alpha = 0;
		sellButton.alpha = 0;
		upgradeButtonBg.alpha = 0;
		sellButtonBg.alpha = 0;
	}
}
// Wave management
function getWaveData(waveNumber) {
	if (waveNumber === 5 || waveNumber === 10) {
		var waveEnemies = ['boss'];
		var escortTypes = ['basic', 'fast', 'tank'];
		var numEscorts = waveNumber === 5 ? 8 : 12;
		for (var i = 0; i < numEscorts; i++) {
			var type = escortTypes[Math.floor(Math.random() * escortTypes.length)];
			waveEnemies.push(type);
		}
		// Shuffle the wave so boss doesn't always appear first
		for (var i = waveEnemies.length - 1; i > 0; i--) {
			var j = Math.floor(Math.random() * (i + 1));
			var temp = waveEnemies[i];
			waveEnemies[i] = waveEnemies[j];
			waveEnemies[j] = temp;
		}
		return waveEnemies;
	}
	var baseEnemies = 5 + waveNumber * 2;
	var enemyTypes = ['basic'];
	if (waveNumber >= 3) enemyTypes.push('fast');
	if (waveNumber >= 5) enemyTypes.push('tank');
	var waveEnemies = [];
	for (var i = 0; i < baseEnemies; i++) {
		var type = enemyTypes[Math.floor(Math.random() * enemyTypes.length)];
		waveEnemies.push(type);
	}
	return waveEnemies;
}
function startWave() {
	if (currentWave > maxWaves) {
		gameState = 'victory';
		LK.showYouWin();
		return;
	}
	waveInProgress = true;
	var waveData = getWaveData(currentWave);
	enemiesInWave = waveData.length;
	enemiesSpawned = 0;
	enemySpawnTimer = 0;
	// Store wave data for spawning
	game.currentWaveData = waveData;
}
function spawnEnemy() {
	if (!waveInProgress || enemiesSpawned >= enemiesInWave) return;
	var enemyType = game.currentWaveData[enemiesSpawned];
	var path = createPath();
	var enemy = new Enemy(enemyType, path);
	enemy.x = path[0].x;
	enemy.y = path[0].y;
	enemies.push(enemy);
	game.addChild(enemy);
	enemiesSpawned++;
}
function checkWaveComplete() {
	if (waveInProgress && enemies.length === 0 && enemiesSpawned >= enemiesInWave) {
		waveInProgress = false;
		currentWave++;
		nextWaveTimer = LK.ticks + 180; // 3 seconds delay
		updateUI();
	}
}
// Mouse move handler for range circle
game.move = function (x, y, obj) {
	if (showRangeCircle && gameState === 'playing') {
		showTowerRange(x, y);
	}
};
// Game input handling
game.down = function (x, y, obj) {
	if (gameState !== 'playing') return;
	console.log('Click detected at raw coordinates:', x, y);
	// Use the click coordinates directly as they're already in game space
	var gameX = x;
	var gameY = y;
	console.log('Game coordinates:', gameX, gameY);
	// Check tower shop buttons - convert screen coordinates to GUI coordinates
	var screenPoint = {
		x: x,
		y: y
	};
	var guiPoint = LK.gui.bottomLeft.toLocal(screenPoint);
	console.log('GUI click coordinates:', guiPoint.x, guiPoint.y);
	// Check archer button (Buton1) - expanded click area for better touch detection
	if (guiPoint.x >= 50 && guiPoint.x <= 150 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'archer';
		showRangeCircle = true;
		console.log('Selected tower type: archer');
		// Add click animation
		tween(archerButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Check ice button (Buton2) - expanded click area for better touch detection
	else if (guiPoint.x >= 150 && guiPoint.x <= 250 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'ice';
		showRangeCircle = true;
		console.log('Selected tower type: ice');
		// Add click animation
		tween(iceButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Check cannon button (Buton3) - expanded click area for better touch detection
	else if (guiPoint.x >= 250 && guiPoint.x <= 350 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'cannon';
		showRangeCircle = true;
		console.log('Selected tower type: cannon');
		// Add click animation
		tween(cannonButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Check money tree button - expanded click area for better touch detection
	else if (guiPoint.x >= 350 && guiPoint.x <= 450 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'moneyTree';
		showRangeCircle = false; // No range circle for money trees
		console.log('Selected tower type: money tree');
		// Add click animation
		tween(moneyTreeButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Upgrade and Sell button clicks are now handled by their own .down methods.
	var centerPos = LK.gui.center.toLocal({
		x: x,
		y: y
	});
	// Hide upgrade UI if clicking elsewhere
	if (showUpgradeUI) {
		showUpgradeUI = false;
		selectedTower = null;
		updateUI();
	}
	// Hide range circle when clicking elsewhere (cancelling purchase)
	hideRangeCircle();
	// Try to place tower using game coordinates
	var gridPos = worldToGrid(gameX, gameY);
	console.log('Grid position:', gridPos.x, gridPos.y);
	console.log('Grid bounds check:', gridPos.x >= 0, gridPos.x < gridWidth, gridPos.y >= 0, gridPos.y < gridHeight);
	if (gridPos.x >= 0 && gridPos.x < gridWidth && gridPos.y >= 0 && gridPos.y < gridHeight) {
		console.log('Grid cell occupied:', grid[gridPos.x][gridPos.y].occupied);
		console.log('Grid cell is path:', grid[gridPos.x][gridPos.y].isPath);
		if (!grid[gridPos.x][gridPos.y].occupied && !grid[gridPos.x][gridPos.y].isPath) {
			var towerCosts = {
				archer: 50,
				ice: 75,
				cannon: 100,
				moneyTree: 200
			};
			var cost = towerCosts[selectedTowerType];
			console.log('Tower cost:', cost, 'Player money:', playerMoney);
			if (playerMoney >= cost) {
				console.log('Placing', selectedTowerType, 'at grid:', gridPos.x, gridPos.y);
				var worldPos = gridToWorld(gridPos.x, gridPos.y);
				console.log('World position:', worldPos.x, worldPos.y);
				if (selectedTowerType === 'moneyTree') {
					// Place money tree
					var tree = new MoneyTree(gridPos.x, gridPos.y);
					tree.x = worldPos.x;
					tree.y = worldPos.y;
					// Add placement animation
					tree.scaleX = 0;
					tree.scaleY = 0;
					tween(tree, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 300,
						easing: tween.bounceOut
					});
					moneyTrees.push(tree);
					game.addChild(tree);
				} else {
					// Place tower
					var tower = new Tower(selectedTowerType, gridPos.x, gridPos.y);
					tower.x = worldPos.x;
					tower.y = worldPos.y;
					// Add placement animation
					tower.scaleX = 0;
					tower.scaleY = 0;
					tween(tower, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 300,
						easing: tween.bounceOut
					});
					towers.push(tower);
					game.addChild(tower);
				}
				grid[gridPos.x][gridPos.y].occupied = true;
				playerMoney -= cost;
				hideRangeCircle(); // Hide range circle after placing tower
				updateUI();
				console.log(selectedTowerType, 'placed successfully!');
			} else {
				console.log('Not enough money to place', selectedTowerType);
			}
		} else {
			console.log('Grid cell is occupied or on path');
		}
	} else {
		console.log('Click outside grid bounds');
	}
};
// Initialize game
initializeGrid();
drawGrid();
placeBase();
placeMoneyTrees();
updateUI();
updateTowerSelection();
startWave();
// Main game loop
game.update = function () {
	if (gameState !== 'playing') return;
	// Update all towers (this enables shooting!)
	for (var i = 0; i < towers.length; i++) {
		towers[i].update();
	}
	// Update all bullets (this enables bullet movement and collision detection!)
	for (var i = 0; i < bullets.length; i++) {
		bullets[i].update();
	}
	// Update all enemies
	for (var i = 0; i < enemies.length; i++) {
		enemies[i].update();
	}
	// Update all money trees
	for (var i = 0; i < moneyTrees.length; i++) {
		moneyTrees[i].update();
	}
	// Clean up collected money coins
	for (var i = moneyCoins.length - 1; i >= 0; i--) {
		if (moneyCoins[i].collected) {
			moneyCoins.splice(i, 1);
		}
	}
	// Spawn enemies
	if (waveInProgress && LK.ticks % 60 === 0) {
		// Every second
		spawnEnemy();
	}
	// Start next wave
	if (!waveInProgress && LK.ticks >= nextWaveTimer) {
		startWave();
	}
	// Clean up destroyed enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		if (enemies[i].destroyed) {
			enemies.splice(i, 1);
		}
	}
	// Clean up destroyed bullets
	for (var i = bullets.length - 1; i >= 0; i--) {
		if (bullets[i].destroyed) {
			bullets.splice(i, 1);
		}
	}
	checkWaveComplete();
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Bullet = Container.expand(function (type, damage, speed, tower) {
	var self = Container.call(this);
	self.type = type || 'normal';
	self.damage = damage || 10;
	self.speed = speed || 8;
	self.tower = tower;
	self.target = null;
	self.destroyed = false;
	var bulletGraphics;
	if (self.type === 'ice') {
		bulletGraphics = self.attachAsset('iceBullet', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'cannon') {
		bulletGraphics = self.attachAsset('cannonBall', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		bulletGraphics = self.attachAsset('bullet', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	self.update = function () {
		// Don't update if bullet is already destroyed
		if (self.destroyed) {
			return;
		}
		if (self.target && !self.target.destroyed) {
			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 - mark bullet as destroyed first to prevent multiple hits
				self.destroyed = true;
				// Apply damage to target
				self.target.takeDamage(self.damage);
				// Apply special effects based on bullet type
				if (self.type === 'ice') {
					self.target.slow(0.5, 2000); // 50% speed for 2 seconds
					self.target.applyIceEffect(); // Apply blue visual effect
				} else if (self.type === 'cannon') {
					// Splash damage
					for (var i = 0; i < enemies.length; i++) {
						var enemy = enemies[i];
						var splashDx = enemy.x - self.x;
						var splashDy = enemy.y - self.y;
						var splashDistance = Math.sqrt(splashDx * splashDx + splashDy * splashDy);
						if (splashDistance < 60 && enemy !== self.target) {
							enemy.takeDamage(self.damage * 0.5);
						}
					}
				}
				LK.getSound('enemyHit').play();
				self.destroy();
				return;
			}
			var angle = Math.atan2(dy, dx);
			self.x += Math.cos(angle) * self.speed;
			self.y += Math.sin(angle) * self.speed;
		} else {
			self.destroyed = true;
			self.destroy();
		}
	};
	return self;
});
var Enemy = Container.expand(function (type, path) {
	var self = Container.call(this);
	self.type = type || 'basic';
	self.path = path;
	self.pathIndex = 0;
	self.health = 0;
	self.maxHealth = 0;
	self.speed = 0;
	self.baseSpeed = 0;
	self.reward = 0;
	self.slowFactor = 1;
	self.slowEndTime = 0;
	self.destroyed = false;
	self.healAmount = 0;
	self.hasHealed = false;
	// Enemy stats based on type
	var stats = {
		basic: {
			health: 60,
			speed: 1.5,
			reward: 10
		},
		fast: {
			health: 40,
			speed: 2.5,
			reward: 15
		},
		tank: {
			health: 160,
			speed: 1,
			reward: 25
		},
		boss: {
			health: 500,
			speed: 0.8,
			reward: 100
		}
	};
	var enemyStats = stats[self.type];
	// Double health after wave 5
	var healthMultiplier = currentWave > 5 ? 2 : 1;
	self.health = enemyStats.health * healthMultiplier;
	self.maxHealth = enemyStats.health * healthMultiplier;
	self.speed = enemyStats.speed;
	self.baseSpeed = enemyStats.speed;
	self.reward = enemyStats.reward;
	if (self.type === 'boss') {
		if (currentWave === 5) {
			self.healAmount = 3000;
		} else if (currentWave === 10) {
			self.healAmount = 10000;
		}
	}
	var enemyGraphics;
	if (self.type === 'fast') {
		enemyGraphics = self.attachAsset('fastEnemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'tank') {
		enemyGraphics = self.attachAsset('tankEnemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'boss') {
		if (currentWave === 5) {
			enemyGraphics = self.attachAsset('Bos1', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		} else if (currentWave === 10) {
			enemyGraphics = self.attachAsset('Bos2', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		enemyGraphics.scaleX = 1.5;
		enemyGraphics.scaleY = 1.5;
	} else {
		enemyGraphics = self.attachAsset('basicEnemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	// Health bar
	self.healthBarBg = LK.getAsset('gridCell', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.6,
		scaleY: 0.1
	});
	self.healthBarBg.tint = 0x000000;
	self.healthBarBg.y = -30;
	self.addChild(self.healthBarBg);
	self.healthBar = LK.getAsset('gridCell', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.6,
		scaleY: 0.1
	});
	self.healthBar.tint = 0x00FF00;
	self.healthBar.y = -30;
	self.addChild(self.healthBar);
	self.takeDamage = function (damage) {
		self.health -= damage;
		self.updateHealthBar();
		if (self.health <= 0) {
			self.die();
		}
	};
	self.updateHealthBar = function () {
		var healthPercent = self.health / self.maxHealth;
		self.healthBar.scaleX = 0.6 * healthPercent;
		if (healthPercent > 0.6) {
			self.healthBar.tint = 0x00FF00;
		} else if (healthPercent > 0.3) {
			self.healthBar.tint = 0xFFFF00;
		} else {
			self.healthBar.tint = 0xFF0000;
		}
	};
	self.slow = function (factor, duration) {
		self.slowFactor = factor;
		self.slowEndTime = Date.now() + duration;
	};
	self.applyIceEffect = function () {
		// Stop any existing ice effect tween
		tween.stop(enemyGraphics, {
			tint: true
		});
		// Apply blue tint immediately
		enemyGraphics.tint = 0x4169E1; // Royal blue color
		// Tween back to normal color after 2 seconds
		tween(enemyGraphics, {
			tint: 0xFFFFFF
		}, {
			duration: 2000,
			easing: tween.easeOut
		});
	};
	self.die = function () {
		self.destroyed = true;
		// Stop any ongoing tween effects
		tween.stop(enemyGraphics, {
			tint: true
		});
		playerMoney += self.reward;
		LK.getSound('enemyDestroyed').play();
		updateUI();
		self.destroy();
	};
	self.reachBase = function () {
		self.destroyed = true;
		playerLives--;
		updateUI();
		if (playerLives <= 0) {
			gameState = 'gameOver';
			LK.showGameOver();
		}
		self.destroy();
	};
	self.update = function () {
		// Boss healing logic
		if (self.type === 'boss' && !self.hasHealed && self.health > 0 && self.health / self.maxHealth <= 0.5) {
			self.health += self.healAmount;
			if (self.health > self.maxHealth) {
				self.health = self.maxHealth;
			}
			self.hasHealed = true;
			self.updateHealthBar();
			// Visual effect for healing - flash green
			tween.stop(enemyGraphics, {
				tint: true
			});
			enemyGraphics.tint = 0x00FF00;
			tween(enemyGraphics, {
				tint: 0xFFFFFF
			}, {
				duration: 500
			});
		}
		// Handle slow effect
		if (Date.now() > self.slowEndTime) {
			self.slowFactor = 1;
		}
		var currentSpeed = self.baseSpeed * self.slowFactor;
		if (self.pathIndex < self.path.length - 1) {
			var target = self.path[self.pathIndex + 1];
			var dx = target.x - self.x;
			var dy = target.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < 5) {
				self.pathIndex++;
				if (self.pathIndex >= self.path.length - 1) {
					self.reachBase();
					return;
				}
			} else {
				var angle = Math.atan2(dy, dx);
				self.x += Math.cos(angle) * currentSpeed;
				self.y += Math.sin(angle) * currentSpeed;
			}
		} else {
			self.reachBase();
		}
	};
	return self;
});
var MoneyCoin = Container.expand(function (value) {
	var self = Container.call(this);
	self.value = value || 25;
	self.collected = false;
	var coinGraphics = self.attachAsset('moneyCoin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	coinGraphics.tint = 0xFFD700; // Gold color
	// Add value text
	self.valueText = new Text2('$' + self.value, {
		size: 20,
		fill: 0xFFFFFF
	});
	self.valueText.anchor.set(0.5, 0.5);
	self.valueText.x = 0;
	self.valueText.y = -25;
	self.addChild(self.valueText);
	self.collect = function () {
		if (self.collected) return;
		self.collected = true;
		// Add money to player
		playerMoney += self.value;
		// If this coin was from a money tree, decrement its counter
		if (self.sourceTree) {
			self.sourceTree.currentMoney--;
		}
		// Play collection sound
		LK.getSound('coinCollect').play();
		// Collection animation - fly up and fade out
		tween(self, {
			y: self.y - 100,
			alpha: 0,
			scaleX: 1.5,
			scaleY: 1.5
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
		// Update UI
		updateUI();
	};
	self.down = function (x, y, obj) {
		self.collect();
	};
	return self;
});
var MoneyTree = Container.expand(function (gridX, gridY) {
	var self = Container.call(this);
	self.type = 'moneyTree';
	self.gridX = gridX;
	self.gridY = gridY;
	self.lastDropTime = 0;
	self.dropInterval = 5000; // Drop money every 5 seconds
	self.moneyAmount = 25; // Amount of money to drop
	self.maxMoney = 2; // Maximum number of money coins that can be accumulated
	self.currentMoney = 0; // Current number of money coins from this tree
	var treeGraphics = self.attachAsset('moneyTree', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add glow effect to distinguish money trees
	treeGraphics.tint = 0xFFD700; // Gold tint
	self.dropMoney = function () {
		// Only drop money if under the limit
		if (self.currentMoney >= self.maxMoney) {
			return; // Don't drop more money if at maximum
		}
		// Create money coin
		var coin = new MoneyCoin(self.moneyAmount);
		coin.x = self.x;
		coin.y = self.y - 30; // Start above the tree
		coin.sourceTree = self; // Reference to the tree that created this coin
		// Increment the tree's money count
		self.currentMoney++;
		// Add to game
		moneyCoins.push(coin);
		game.addChild(coin);
		// Animate coin dropping with bounce
		var targetY = self.y + 50;
		tween(coin, {
			y: targetY
		}, {
			duration: 800,
			easing: tween.bounceOut
		});
		// Add floating effect after landing
		LK.setTimeout(function () {
			tween(coin, {
				y: targetY - 10
			}, {
				duration: 1000,
				repeat: -1,
				yoyo: true,
				easing: tween.easeInOut
			});
		}, 800);
	};
	self.getTotalCost = function () {
		return 200; // Cost of money tree is fixed at 200
	};
	self.sell = function () {
		var sellValue = Math.floor(self.getTotalCost() * 0.75);
		playerMoney += sellValue;
		// Mark grid cell as unoccupied
		grid[self.gridX][self.gridY].occupied = false;
		// Remove from moneyTrees array
		for (var i = moneyTrees.length - 1; i >= 0; i--) {
			if (moneyTrees[i] === self) {
				moneyTrees.splice(i, 1);
				break;
			}
		}
		// Clear selection
		selectedTower = null;
		showUpgradeUI = false;
		// Update UI
		updateUI();
		// Destroy tree
		self.destroy();
	};
	self.down = function (x, y, obj) {
		if (gameState === 'playing') {
			selectedTower = self;
			showUpgradeUI = true;
		}
	};
	self.update = function () {
		var currentTime = Date.now();
		if (currentTime - self.lastDropTime >= self.dropInterval) {
			self.dropMoney();
			self.lastDropTime = currentTime;
		}
	};
	return self;
});
var Tower = Container.expand(function (type, gridX, gridY) {
	var self = Container.call(this);
	self.type = type || 'archer';
	self.gridX = gridX;
	self.gridY = gridY;
	self.level = 1;
	self.lastShotTime = 0;
	// Tower stats based on type and level
	self.getStats = function () {
		var stats = {
			archer: {
				damage: 15 * self.level,
				range: 240 + self.level * 20,
				fireRate: 800 - self.level * 100,
				// ms between shots
				cost: 50,
				upgradeCost: self.level * 60
			},
			ice: {
				damage: 8 * self.level,
				range: 135 + self.level * 15,
				fireRate: 1200 - self.level * 150,
				cost: 75,
				upgradeCost: self.level * 90
			},
			cannon: {
				damage: 40 * self.level,
				range: 90 + self.level * 10,
				fireRate: 1500 - self.level * 200,
				cost: 100,
				upgradeCost: self.level * 120
			}
		};
		return stats[self.type];
	};
	var towerGraphics;
	if (self.type === 'ice') {
		towerGraphics = self.attachAsset('iceTower', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else if (self.type === 'cannon') {
		towerGraphics = self.attachAsset('cannonTower', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		towerGraphics = self.attachAsset('archerTower', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	// Level indicator
	self.levelText = new Text2(self.level.toString(), {
		size: 20,
		fill: 0xFFFFFF
	});
	self.levelText.anchor.set(0.5, 0.5);
	self.levelText.x = 0;
	self.levelText.y = -30;
	self.addChild(self.levelText);
	self.findTarget = function () {
		var stats = self.getStats();
		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 <= stats.range && distance < closestDistance) {
				closestDistance = distance;
				closestEnemy = enemy;
			}
		}
		return closestEnemy;
	};
	self.shoot = function (target) {
		var stats = self.getStats();
		var bullet = new Bullet(self.type, stats.damage, 8, self);
		bullet.target = target;
		bullet.x = self.x;
		bullet.y = self.y;
		bullets.push(bullet);
		game.addChild(bullet);
		LK.getSound('shoot').play();
	};
	self.getTotalCost = function () {
		var stats = self.getStats();
		var totalCost = stats.cost;
		// Add upgrade costs for each level beyond 1
		for (var i = 1; i < self.level; i++) {
			totalCost += i * (stats.cost * 0.6); // Upgrade cost formula
		}
		return totalCost;
	};
	self.upgrade = function () {
		var stats = self.getStats();
		if (playerMoney >= stats.upgradeCost) {
			playerMoney -= stats.upgradeCost;
			self.level++;
			self.levelText.setText(self.level.toString());
			updateUI();
		}
	};
	self.sell = function () {
		var sellValue = Math.floor(self.getTotalCost() * 0.75);
		playerMoney += sellValue;
		// Mark grid cell as unoccupied
		grid[self.gridX][self.gridY].occupied = false;
		// Remove from towers array
		for (var i = towers.length - 1; i >= 0; i--) {
			if (towers[i] === self) {
				towers.splice(i, 1);
				break;
			}
		}
		// Clear selection
		selectedTower = null;
		showUpgradeUI = false;
		// Update UI
		updateUI();
		// Destroy tower
		self.destroy();
	};
	self.down = function (x, y, obj) {
		if (gameState === 'playing') {
			selectedTower = self;
			showUpgradeUI = true;
		}
	};
	self.update = function () {
		var stats = self.getStats();
		var currentTime = Date.now();
		if (currentTime - self.lastShotTime >= stats.fireRate) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.lastShotTime = currentTime;
			}
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x228B22
});
/**** 
* Game Code
****/ 
// Game state
var gameState = 'playing'; // 'playing', 'gameOver', 'victory'
var playerMoney = 200;
var playerLives = 20;
var currentWave = 1;
var maxWaves = 10;
var waveInProgress = false;
var nextWaveTimer = 0;
var enemySpawnTimer = 0;
var enemiesInWave = 0;
var enemiesSpawned = 0;
// Game objects
var towers = [];
var enemies = [];
var bullets = [];
var moneyTrees = [];
var moneyCoins = [];
var selectedTower = null;
var showUpgradeUI = false;
// Grid system
var gridSize = 80;
var gridWidth = Math.floor(2048 / gridSize);
var gridHeight = Math.floor(2732 / gridSize);
var grid = [];
// Path definition (from top to bottom with some turns)
var pathPoints = [{
	x: 0,
	y: 5
}, {
	x: 3,
	y: 5
}, {
	x: 3,
	y: 10
}, {
	x: 8,
	y: 10
}, {
	x: 8,
	y: 15
}, {
	x: 15,
	y: 15
}, {
	x: 15,
	y: 20
}, {
	x: 20,
	y: 20
}, {
	x: 20,
	y: 25
}, {
	x: 25,
	y: 25
}];
// Convert grid coordinates to world coordinates
function gridToWorld(gridX, gridY) {
	return {
		x: gridX * gridSize + gridSize / 2,
		y: gridY * gridSize + gridSize / 2
	};
}
// Convert world coordinates to grid coordinates
function worldToGrid(worldX, worldY) {
	return {
		x: Math.floor(worldX / gridSize),
		y: Math.floor(worldY / gridSize)
	};
}
// Initialize grid
function initializeGrid() {
	for (var x = 0; x < gridWidth; x++) {
		grid[x] = [];
		for (var y = 0; y < gridHeight; y++) {
			grid[x][y] = {
				occupied: false,
				isPath: false
			};
		}
	}
	// Mark path cells - create continuous path between all points
	for (var i = 0; i < pathPoints.length; i++) {
		var point = pathPoints[i];
		if (point.x < gridWidth && point.y < gridHeight) {
			grid[point.x][point.y].isPath = true;
		}
		// If not the last point, draw line to next point
		if (i < pathPoints.length - 1) {
			var nextPoint = pathPoints[i + 1];
			var startX = point.x;
			var startY = point.y;
			var endX = nextPoint.x;
			var endY = nextPoint.y;
			// Draw horizontal line first, then vertical
			if (startX !== endX) {
				var minX = Math.min(startX, endX);
				var maxX = Math.max(startX, endX);
				for (var x = minX; x <= maxX; x++) {
					if (x < gridWidth && startY < gridHeight) {
						grid[x][startY].isPath = true;
					}
				}
			}
			if (startY !== endY) {
				var minY = Math.min(startY, endY);
				var maxY = Math.max(startY, endY);
				for (var y = minY; y <= maxY; y++) {
					if (endX < gridWidth && y < gridHeight) {
						grid[endX][y].isPath = true;
					}
				}
			}
		}
	}
}
// Draw grid
function drawGrid() {
	for (var x = 0; x < gridWidth; x++) {
		for (var y = 0; y < gridHeight; y++) {
			var worldPos = gridToWorld(x, y);
			var cell;
			if (grid[x][y].isPath) {
				cell = LK.getAsset('pathCell', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: worldPos.x,
					y: worldPos.y,
					alpha: 0.8
				});
			} else {
				cell = LK.getAsset('gridCell', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: worldPos.x,
					y: worldPos.y,
					alpha: 0.3
				});
			}
			game.addChild(cell);
		}
	}
}
// Create path for enemies
function createPath() {
	var path = [];
	for (var i = 0; i < pathPoints.length; i++) {
		var point = pathPoints[i];
		var worldPos = gridToWorld(point.x, point.y);
		path.push(worldPos);
	}
	return path;
}
// Place base at the end of path
function placeBase() {
	var lastPoint = pathPoints[pathPoints.length - 1];
	var worldPos = gridToWorld(lastPoint.x, lastPoint.y);
	var base = LK.getAsset('base', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: worldPos.x,
		y: worldPos.y
	});
	game.addChild(base);
}
// Place money trees at strategic locations - removed automatic placement for player purchase
function placeMoneyTrees() {
	// Money trees are now purchased by player, no automatic placement
}
// UI elements
var moneyText = new Text2('Money: $' + playerMoney, {
	size: 40,
	fill: 0xFFFFFF
});
moneyText.anchor.set(0, 0);
moneyText.x = 120;
moneyText.y = 20;
LK.gui.topLeft.addChild(moneyText);
var livesText = new Text2('Lives: ' + playerLives, {
	size: 40,
	fill: 0xFFFFFF
});
livesText.anchor.set(1, 0);
livesText.x = -20;
livesText.y = 20;
LK.gui.topRight.addChild(livesText);
var waveText = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
	size: 40,
	fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
waveText.x = 0;
waveText.y = 20;
LK.gui.top.addChild(waveText);
// Tower shop with button assets positioned at bottom corner
var shopY = -300; // Position from bottom
var buttonSize = 80;
var buttonSpacing = 100;
// Archer button (Buton1)
var archerButton = LK.getAsset('Buton1', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing,
	y: shopY
});
// Add direct click handler to archer button
archerButton.down = function (x, y, obj) {
	selectedTowerType = 'archer';
	showRangeCircle = true;
	console.log('Archer button clicked directly');
	// Add click animation
	tween(archerButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(archerButton);
var archerText = new Text2('Archer', {
	size: 25,
	fill: 0xFFFFFF
});
archerText.anchor.set(0.5, 0.5);
archerText.x = buttonSpacing;
archerText.y = shopY;
LK.gui.bottomLeft.addChild(archerText);
// Ice button (Buton2)
var iceButton = LK.getAsset('Buton2', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing * 2,
	y: shopY
});
// Add direct click handler to ice button
iceButton.down = function (x, y, obj) {
	selectedTowerType = 'ice';
	showRangeCircle = true;
	console.log('Ice button clicked directly');
	// Add click animation
	tween(iceButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(iceButton);
var iceText = new Text2('Ice', {
	size: 25,
	fill: 0xFFFFFF
});
iceText.anchor.set(0.5, 0.5);
iceText.x = buttonSpacing * 2;
iceText.y = shopY;
LK.gui.bottomLeft.addChild(iceText);
// Cannon button (Buton3)
var cannonButton = LK.getAsset('Buton3', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing * 3,
	y: shopY
});
// Add direct click handler to cannon button
cannonButton.down = function (x, y, obj) {
	selectedTowerType = 'cannon';
	showRangeCircle = true;
	console.log('Cannon button clicked directly');
	// Add click animation
	tween(cannonButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(cannonButton);
var cannonText = new Text2('Cannon', {
	size: 25,
	fill: 0xFFFFFF
});
cannonText.anchor.set(0.5, 0.5);
cannonText.x = buttonSpacing * 3;
cannonText.y = shopY;
LK.gui.bottomLeft.addChild(cannonText);
// Money Tree button (fourth button)
var moneyTreeButton = LK.getAsset('Buton1', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: buttonSpacing * 4,
	y: shopY
});
moneyTreeButton.tint = 0xFFD700; // Gold color for money tree
// Add direct click handler to money tree button
moneyTreeButton.down = function (x, y, obj) {
	selectedTowerType = 'moneyTree';
	showRangeCircle = false; // No range circle for money trees
	console.log('Money Tree button clicked directly');
	// Add click animation
	tween(moneyTreeButton, {
		scaleX: 1.3,
		scaleY: 1.3
	}, {
		duration: 100,
		onFinish: function onFinish() {
			updateTowerSelection();
		}
	});
	updateTowerSelection();
};
LK.gui.bottomLeft.addChild(moneyTreeButton);
var moneyTreeText = new Text2('Money Tree', {
	size: 20,
	fill: 0xFFFFFF
});
moneyTreeText.anchor.set(0.5, 0.5);
moneyTreeText.x = buttonSpacing * 4;
moneyTreeText.y = shopY;
LK.gui.bottomLeft.addChild(moneyTreeText);
// Selected tower info
var selectedTowerType = 'archer';
var rangeCircle = null;
var showRangeCircle = false;
// Add status text to show selected tower type
var selectedTowerText = new Text2('Selected: Archer Tower ($50)', {
	size: 30,
	fill: 0x00FF00
});
selectedTowerText.anchor.set(1, 0);
selectedTowerText.x = -20;
selectedTowerText.y = 80;
LK.gui.topRight.addChild(selectedTowerText);
function showTowerRange(x, y) {
	if (!showRangeCircle) return;
	// Get range for selected tower type
	var towerRanges = {
		archer: 240,
		ice: 135,
		cannon: 90
	};
	var range = towerRanges[selectedTowerType];
	// Remove existing range circle
	if (rangeCircle) {
		rangeCircle.destroy();
		rangeCircle = null;
	}
	// Create new range circle
	rangeCircle = LK.getAsset('gridCell', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: range / 40,
		// Scale to match range (gridCell is 80px, so 40 is radius)
		scaleY: range / 40,
		alpha: 0.3,
		x: x,
		y: y
	});
	rangeCircle.tint = 0x0080FF; // Semi-transparent blue
	game.addChild(rangeCircle);
}
function hideRangeCircle() {
	showRangeCircle = false;
	if (rangeCircle) {
		rangeCircle.destroy();
		rangeCircle = null;
	}
}
function updateTowerSelection() {
	// Stop any existing tweens on buttons
	tween.stop(archerButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	tween.stop(iceButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	tween.stop(cannonButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	tween.stop(moneyTreeButton, {
		tint: true,
		scaleX: true,
		scaleY: true
	});
	// Reset all button colors and scales
	archerButton.tint = 0xFFFFFF;
	iceButton.tint = 0xFFFFFF;
	cannonButton.tint = 0xFFFFFF;
	moneyTreeButton.tint = 0xFFD700; // Gold base color for money tree
	archerButton.scaleX = archerButton.scaleY = 1;
	iceButton.scaleX = iceButton.scaleY = 1;
	cannonButton.scaleX = cannonButton.scaleY = 1;
	moneyTreeButton.scaleX = moneyTreeButton.scaleY = 1;
	// Highlight selected button with bright green glow and scale
	if (selectedTowerType === 'archer') {
		archerButton.tint = 0x00FF00; // Bright green for selected
		archerButton.scaleX = archerButton.scaleY = 1.2;
		// Add pulsing effect
		tween(archerButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else if (selectedTowerType === 'ice') {
		iceButton.tint = 0x00FF00; // Bright green for selected
		iceButton.scaleX = iceButton.scaleY = 1.2;
		// Add pulsing effect
		tween(iceButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else if (selectedTowerType === 'cannon') {
		cannonButton.tint = 0x00FF00; // Bright green for selected
		cannonButton.scaleX = cannonButton.scaleY = 1.2;
		// Add pulsing effect
		tween(cannonButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else if (selectedTowerType === 'moneyTree') {
		moneyTreeButton.tint = 0x00FF00; // Bright green for selected
		moneyTreeButton.scaleX = moneyTreeButton.scaleY = 1.2;
		// Add pulsing effect
		tween(moneyTreeButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	}
	// Update status text
	var towerCosts = {
		archer: 50,
		ice: 75,
		cannon: 100,
		moneyTree: 200
	};
	var cost = towerCosts[selectedTowerType];
	var towerName = selectedTowerType === 'moneyTree' ? 'Money Tree' : selectedTowerType.charAt(0).toUpperCase() + selectedTowerType.slice(1);
	var canAfford = playerMoney >= cost;
	var statusColor = canAfford ? 0x00FF00 : 0xFF0000;
	selectedTowerText.tint = statusColor;
	var itemType = selectedTowerType === 'moneyTree' ? '' : ' Tower';
	selectedTowerText.setText('Selected: ' + towerName + itemType + ' ($' + cost + ') - Click grid to place');
}
// Upgrade UI Canvas Background
var upgradeCanvas = LK.getAsset('gridCell', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 6,
	scaleY: 4,
	alpha: 0.7
});
upgradeCanvas.tint = 0x333333; // Semi-transparent gray
upgradeCanvas.x = 0;
upgradeCanvas.y = 280;
LK.gui.center.addChild(upgradeCanvas);
// Upgrade UI Title
var upgradeTitle = new Text2('TOWER INFO', {
	size: 32,
	fill: 0xFFFFFF
});
upgradeTitle.anchor.set(0.5, 0.5);
upgradeTitle.x = 0;
upgradeTitle.y = 180;
LK.gui.center.addChild(upgradeTitle);
// Tower stats display
var upgradeText = new Text2('', {
	size: 28,
	fill: 0xFFFFFF
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.x = 0;
upgradeText.y = 250;
LK.gui.center.addChild(upgradeText);
// Upgrade button with background
var upgradeButtonBg = LK.getAsset('gridCell', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 2.5,
	scaleY: 0.8,
	alpha: 0.8
});
upgradeButtonBg.tint = 0xFFD700;
upgradeButtonBg.x = 0;
upgradeButtonBg.y = 350;
LK.gui.center.addChild(upgradeButtonBg);
var upgradeButton = new Text2('', {
	size: 30,
	fill: 0x000000
});
upgradeButton.anchor.set(0.5, 0.5);
upgradeButton.x = 0;
upgradeButton.y = 350;
upgradeButton.scaleX = 1;
upgradeButton.scaleY = 1;
LK.gui.center.addChild(upgradeButton);
// Sell button with background
var sellButtonBg = LK.getAsset('gridCell', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 2.5,
	scaleY: 0.8,
	alpha: 0.8
});
sellButtonBg.tint = 0xFF4444;
sellButtonBg.x = 0;
sellButtonBg.y = 410;
LK.gui.center.addChild(sellButtonBg);
var sellButton = new Text2('', {
	size: 30,
	fill: 0xFFFFFF
});
sellButton.anchor.set(0.5, 0.5);
sellButton.x = 0;
sellButton.y = 410;
sellButton.scaleX = 1;
sellButton.scaleY = 1;
LK.gui.center.addChild(sellButton);
upgradeButton.down = function () {
	if (showUpgradeUI && selectedTower) {
		var stats = selectedTower.getStats();
		if (playerMoney >= stats.upgradeCost) {
			// Animate both button and background
			tween(upgradeButton, {
				scaleX: 1.1,
				scaleY: 1.1
			}, {
				duration: 100,
				onFinish: function onFinish() {
					tween(upgradeButton, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 100
					});
				}
			});
			tween(upgradeButtonBg, {
				scaleX: 2.7,
				scaleY: 0.9
			}, {
				duration: 100,
				onFinish: function onFinish() {
					tween(upgradeButtonBg, {
						scaleX: 2.5,
						scaleY: 0.8
					}, {
						duration: 100
					});
				}
			});
			selectedTower.upgrade();
		}
	}
};
sellButton.down = function () {
	if (showUpgradeUI && selectedTower) {
		// Animate both button and background
		tween(sellButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 100,
			onFinish: function onFinish() {
				tween(sellButton, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 100
				});
			}
		});
		tween(sellButtonBg, {
			scaleX: 2.7,
			scaleY: 0.9
		}, {
			duration: 100,
			onFinish: function onFinish() {
				tween(sellButtonBg, {
					scaleX: 2.5,
					scaleY: 0.8
				}, {
					duration: 100
				});
			}
		});
		selectedTower.sell();
	}
};
function updateUI() {
	moneyText.setText('Money: $' + playerMoney);
	livesText.setText('Lives: ' + playerLives);
	waveText.setText('Wave: ' + currentWave + '/' + maxWaves);
	updateTowerSelection(); // Update selection display when money changes
	if (showUpgradeUI && selectedTower) {
		var isMoneyTree = selectedTower.type === 'moneyTree';
		var sellValue = Math.floor(selectedTower.getTotalCost() * 0.75);
		// Show canvas and UI elements
		upgradeCanvas.alpha = 0.7;
		upgradeTitle.alpha = 1;
		upgradeText.alpha = 1;
		upgradeButton.alpha = isMoneyTree ? 0 : 1;
		sellButton.alpha = 1;
		upgradeButtonBg.alpha = isMoneyTree ? 0 : 0.8;
		sellButtonBg.alpha = 0.8;
		sellButton.setText('SELL $' + sellValue);
		if (isMoneyTree) {
			// Update text content for Money Tree
			upgradeTitle.setText('MONEY TREE');
			var infoText = 'Generates $' + selectedTower.moneyAmount + ' every ' + selectedTower.dropInterval / 1000 + 's.\n';
			infoText += 'Max ' + selectedTower.maxMoney + ' coins can accumulate.';
			upgradeText.setText(infoText);
		} else {
			// Update text content for normal towers
			var stats = selectedTower.getStats();
			var towerName = selectedTower.type.charAt(0).toUpperCase() + selectedTower.type.slice(1);
			upgradeTitle.setText(towerName.toUpperCase() + ' TOWER');
			upgradeText.setText('Damage: ' + stats.damage + '\nRange: ' + stats.range + '\nFire Rate: ' + Math.round(1000 / stats.fireRate * 60) + '/sec');
			upgradeButton.setText('UPGRADE $' + stats.upgradeCost);
			// Visual feedback for upgrade affordability
			if (playerMoney >= stats.upgradeCost) {
				upgradeButtonBg.tint = 0xFFD700; // Gold when affordable
				upgradeButton.tint = 0x000000; // Black text on gold background
			} else {
				upgradeButtonBg.tint = 0x666666; // Gray when not affordable
				upgradeButton.tint = 0xFFFFFF; // White text on gray background
			}
		}
		// Sell button is always available
		sellButtonBg.tint = 0xFF4444;
		sellButton.tint = 0xFFFFFF;
	} else {
		upgradeCanvas.alpha = 0;
		upgradeTitle.alpha = 0;
		upgradeText.alpha = 0;
		upgradeButton.alpha = 0;
		sellButton.alpha = 0;
		upgradeButtonBg.alpha = 0;
		sellButtonBg.alpha = 0;
	}
}
// Wave management
function getWaveData(waveNumber) {
	if (waveNumber === 5 || waveNumber === 10) {
		var waveEnemies = ['boss'];
		var escortTypes = ['basic', 'fast', 'tank'];
		var numEscorts = waveNumber === 5 ? 8 : 12;
		for (var i = 0; i < numEscorts; i++) {
			var type = escortTypes[Math.floor(Math.random() * escortTypes.length)];
			waveEnemies.push(type);
		}
		// Shuffle the wave so boss doesn't always appear first
		for (var i = waveEnemies.length - 1; i > 0; i--) {
			var j = Math.floor(Math.random() * (i + 1));
			var temp = waveEnemies[i];
			waveEnemies[i] = waveEnemies[j];
			waveEnemies[j] = temp;
		}
		return waveEnemies;
	}
	var baseEnemies = 5 + waveNumber * 2;
	var enemyTypes = ['basic'];
	if (waveNumber >= 3) enemyTypes.push('fast');
	if (waveNumber >= 5) enemyTypes.push('tank');
	var waveEnemies = [];
	for (var i = 0; i < baseEnemies; i++) {
		var type = enemyTypes[Math.floor(Math.random() * enemyTypes.length)];
		waveEnemies.push(type);
	}
	return waveEnemies;
}
function startWave() {
	if (currentWave > maxWaves) {
		gameState = 'victory';
		LK.showYouWin();
		return;
	}
	waveInProgress = true;
	var waveData = getWaveData(currentWave);
	enemiesInWave = waveData.length;
	enemiesSpawned = 0;
	enemySpawnTimer = 0;
	// Store wave data for spawning
	game.currentWaveData = waveData;
}
function spawnEnemy() {
	if (!waveInProgress || enemiesSpawned >= enemiesInWave) return;
	var enemyType = game.currentWaveData[enemiesSpawned];
	var path = createPath();
	var enemy = new Enemy(enemyType, path);
	enemy.x = path[0].x;
	enemy.y = path[0].y;
	enemies.push(enemy);
	game.addChild(enemy);
	enemiesSpawned++;
}
function checkWaveComplete() {
	if (waveInProgress && enemies.length === 0 && enemiesSpawned >= enemiesInWave) {
		waveInProgress = false;
		currentWave++;
		nextWaveTimer = LK.ticks + 180; // 3 seconds delay
		updateUI();
	}
}
// Mouse move handler for range circle
game.move = function (x, y, obj) {
	if (showRangeCircle && gameState === 'playing') {
		showTowerRange(x, y);
	}
};
// Game input handling
game.down = function (x, y, obj) {
	if (gameState !== 'playing') return;
	console.log('Click detected at raw coordinates:', x, y);
	// Use the click coordinates directly as they're already in game space
	var gameX = x;
	var gameY = y;
	console.log('Game coordinates:', gameX, gameY);
	// Check tower shop buttons - convert screen coordinates to GUI coordinates
	var screenPoint = {
		x: x,
		y: y
	};
	var guiPoint = LK.gui.bottomLeft.toLocal(screenPoint);
	console.log('GUI click coordinates:', guiPoint.x, guiPoint.y);
	// Check archer button (Buton1) - expanded click area for better touch detection
	if (guiPoint.x >= 50 && guiPoint.x <= 150 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'archer';
		showRangeCircle = true;
		console.log('Selected tower type: archer');
		// Add click animation
		tween(archerButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Check ice button (Buton2) - expanded click area for better touch detection
	else if (guiPoint.x >= 150 && guiPoint.x <= 250 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'ice';
		showRangeCircle = true;
		console.log('Selected tower type: ice');
		// Add click animation
		tween(iceButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Check cannon button (Buton3) - expanded click area for better touch detection
	else if (guiPoint.x >= 250 && guiPoint.x <= 350 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'cannon';
		showRangeCircle = true;
		console.log('Selected tower type: cannon');
		// Add click animation
		tween(cannonButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Check money tree button - expanded click area for better touch detection
	else if (guiPoint.x >= 350 && guiPoint.x <= 450 && guiPoint.y >= shopY - 50 && guiPoint.y <= shopY + 50) {
		selectedTowerType = 'moneyTree';
		showRangeCircle = false; // No range circle for money trees
		console.log('Selected tower type: money tree');
		// Add click animation
		tween(moneyTreeButton, {
			scaleX: 1.3,
			scaleY: 1.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				updateTowerSelection(); // This will reset scale based on selection
			}
		});
		updateTowerSelection();
		return;
	}
	// Upgrade and Sell button clicks are now handled by their own .down methods.
	var centerPos = LK.gui.center.toLocal({
		x: x,
		y: y
	});
	// Hide upgrade UI if clicking elsewhere
	if (showUpgradeUI) {
		showUpgradeUI = false;
		selectedTower = null;
		updateUI();
	}
	// Hide range circle when clicking elsewhere (cancelling purchase)
	hideRangeCircle();
	// Try to place tower using game coordinates
	var gridPos = worldToGrid(gameX, gameY);
	console.log('Grid position:', gridPos.x, gridPos.y);
	console.log('Grid bounds check:', gridPos.x >= 0, gridPos.x < gridWidth, gridPos.y >= 0, gridPos.y < gridHeight);
	if (gridPos.x >= 0 && gridPos.x < gridWidth && gridPos.y >= 0 && gridPos.y < gridHeight) {
		console.log('Grid cell occupied:', grid[gridPos.x][gridPos.y].occupied);
		console.log('Grid cell is path:', grid[gridPos.x][gridPos.y].isPath);
		if (!grid[gridPos.x][gridPos.y].occupied && !grid[gridPos.x][gridPos.y].isPath) {
			var towerCosts = {
				archer: 50,
				ice: 75,
				cannon: 100,
				moneyTree: 200
			};
			var cost = towerCosts[selectedTowerType];
			console.log('Tower cost:', cost, 'Player money:', playerMoney);
			if (playerMoney >= cost) {
				console.log('Placing', selectedTowerType, 'at grid:', gridPos.x, gridPos.y);
				var worldPos = gridToWorld(gridPos.x, gridPos.y);
				console.log('World position:', worldPos.x, worldPos.y);
				if (selectedTowerType === 'moneyTree') {
					// Place money tree
					var tree = new MoneyTree(gridPos.x, gridPos.y);
					tree.x = worldPos.x;
					tree.y = worldPos.y;
					// Add placement animation
					tree.scaleX = 0;
					tree.scaleY = 0;
					tween(tree, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 300,
						easing: tween.bounceOut
					});
					moneyTrees.push(tree);
					game.addChild(tree);
				} else {
					// Place tower
					var tower = new Tower(selectedTowerType, gridPos.x, gridPos.y);
					tower.x = worldPos.x;
					tower.y = worldPos.y;
					// Add placement animation
					tower.scaleX = 0;
					tower.scaleY = 0;
					tween(tower, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 300,
						easing: tween.bounceOut
					});
					towers.push(tower);
					game.addChild(tower);
				}
				grid[gridPos.x][gridPos.y].occupied = true;
				playerMoney -= cost;
				hideRangeCircle(); // Hide range circle after placing tower
				updateUI();
				console.log(selectedTowerType, 'placed successfully!');
			} else {
				console.log('Not enough money to place', selectedTowerType);
			}
		} else {
			console.log('Grid cell is occupied or on path');
		}
	} else {
		console.log('Click outside grid bounds');
	}
};
// Initialize game
initializeGrid();
drawGrid();
placeBase();
placeMoneyTrees();
updateUI();
updateTowerSelection();
startWave();
// Main game loop
game.update = function () {
	if (gameState !== 'playing') return;
	// Update all towers (this enables shooting!)
	for (var i = 0; i < towers.length; i++) {
		towers[i].update();
	}
	// Update all bullets (this enables bullet movement and collision detection!)
	for (var i = 0; i < bullets.length; i++) {
		bullets[i].update();
	}
	// Update all enemies
	for (var i = 0; i < enemies.length; i++) {
		enemies[i].update();
	}
	// Update all money trees
	for (var i = 0; i < moneyTrees.length; i++) {
		moneyTrees[i].update();
	}
	// Clean up collected money coins
	for (var i = moneyCoins.length - 1; i >= 0; i--) {
		if (moneyCoins[i].collected) {
			moneyCoins.splice(i, 1);
		}
	}
	// Spawn enemies
	if (waveInProgress && LK.ticks % 60 === 0) {
		// Every second
		spawnEnemy();
	}
	// Start next wave
	if (!waveInProgress && LK.ticks >= nextWaveTimer) {
		startWave();
	}
	// Clean up destroyed enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		if (enemies[i].destroyed) {
			enemies.splice(i, 1);
		}
	}
	// Clean up destroyed bullets
	for (var i = bullets.length - 1; i >= 0; i--) {
		if (bullets[i].destroyed) {
			bullets.splice(i, 1);
		}
	}
	checkWaveComplete();
};
:quality(85)/https://cdn.frvr.ai/6872257bf9cfb7d87c1a4e3f.png%3F3) 
 bow with arrow. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/68722716f9cfb7d87c1a4e93.png%3F3) 
 ice tower. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/687233bee78be552f07e492e.png%3F3) 
 medieval soldier. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68725f54861c2b322f41bb2e.png%3F3) 
 cannon. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68726042861c2b322f41bb44.png%3F3) 
 knight with horse. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68726639bb801c490ff32510.png%3F3) 
 cannonball. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68726692bb801c490ff3251b.png%3F3) 
 arrow. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/687266e5bb801c490ff32528.png%3F3) 
 ice bullet. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68726793bb801c490ff32534.png%3F3) 
 build a tower from a bird's eye view. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68726846bb801c490ff3253f.png%3F3) 
 giant. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68726f7fbb801c490ff32567.png%3F3) 
 bird's eye view of grass. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68727248bb801c490ff32589.png%3F3) 
 soil bird's eye view. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68728cba62fcbfba1e361258.png%3F3) 
 money. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68728d0762fcbfba1e361268.png%3F3) 
 money tree. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6872915762fcbfba1e3612a1.png%3F3) 
 giand mosnter. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/687291b662fcbfba1e3612ad.png%3F3) 
 bad wizard. In-Game asset. 2d. High contrast. No shadows