/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Bomb = Container.expand(function () {
	var self = Container.call(this);
	var bombBase = self.attachAsset('bomb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var fuse = self.attachAsset('bombFuse', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 0,
		y: -35
	});
	var spark = self.attachAsset('bombSpark', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 0,
		y: -40
	});
	self.health = 25;
	self.exploded = false;
	self.sparkOffset = 0;
	self.update = function () {
		// Animate the spark on the fuse
		self.sparkOffset += 0.15;
		spark.alpha = 0.8 + Math.sin(self.sparkOffset) * 0.2;
		spark.scaleX = 0.8 + Math.sin(self.sparkOffset * 2) * 0.3;
		spark.scaleY = 0.8 + Math.sin(self.sparkOffset * 2) * 0.3;
		// Gentle bobbing animation
		self.y += Math.sin(LK.ticks * 0.05) * 0.3;
	};
	self.explode = function () {
		if (self.exploded) return;
		self.exploded = true;
		// Create explosion effect
		LK.effects.flashScreen(0xff4500, 300);
		// Damage nearby enemies and player
		var explosionRadius = 150;
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance < explosionRadius) {
				if (zombie.takeDamage(75)) {
					LK.getSound('zombieDeath').play();
					LK.setScore(LK.getScore() + 10);
					zombie.destroy();
					zombies.splice(i, 1);
					i--;
				}
			}
		}
		// Check boss damage
		if (boss) {
			var bossDistance = Math.sqrt(Math.pow(boss.x - self.x, 2) + Math.pow(boss.y - self.y, 2));
			if (bossDistance < explosionRadius) {
				boss.takeDamage(100);
			}
		}
		// Check player damage
		if (player) {
			var playerDistance = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2));
			if (playerDistance < explosionRadius) {
				player.takeDamage(30);
			}
		}
		// Remove bomb
		self.destroy();
		var index = bombs.indexOf(self);
		if (index > -1) bombs.splice(index, 1);
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 100);
		if (self.health <= 0) {
			self.explode();
			return true;
		}
		return false;
	};
	return self;
});
var Boss = Container.expand(function (type) {
	var self = Container.call(this);
	var bossAsset = type === 5 ? 'finalBoss' : 'boss' + type;
	var bossGraphics = self.attachAsset(bossAsset, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add unique design elements for each boss
	if (type === 1) {
		// Speed boss with spikes
		var eyes1 = self.attachAsset('boss1Eyes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -15,
			y: -10
		});
		var eyes2 = self.attachAsset('boss1Eyes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 15,
			y: -10
		});
		var spike1 = self.attachAsset('boss1Spikes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: -35,
			rotation: 0
		});
		var spike2 = self.attachAsset('boss1Spikes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -25,
			y: 0,
			rotation: 1.57
		});
		var spike3 = self.attachAsset('boss1Spikes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 25,
			y: 0,
			rotation: -1.57
		});
	} else if (type === 2) {
		// Summoner boss with horns and claws
		var horn = self.attachAsset('boss2Horn', {
			anchorX: 0.5,
			anchorY: 1,
			x: 0,
			y: -40
		});
		var claw1 = self.attachAsset('boss2Claws', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -35,
			y: 0
		});
		var claw2 = self.attachAsset('boss2Claws', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 35,
			y: 0
		});
	} else if (type === 3) {
		// Screamer boss with armor and gem
		var armor = self.attachAsset('boss3Armor', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: 0
		});
		var gem = self.attachAsset('boss3Gem', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: -20
		});
		self.gemRef = gem; // Store reference for pulsing animation
	} else if (type === 4) {
		// Healer boss with wings and crown
		var wing1 = self.attachAsset('boss4Wings', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -50,
			y: 0
		});
		var wing2 = self.attachAsset('boss4Wings', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 50,
			y: 0
		});
		var crown = self.attachAsset('boss4Crown', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: -50
		});
		self.wing1Ref = wing1;
		self.wing2Ref = wing2;
	}
	self.type = type;
	self.health = 150 + type * 50;
	// Make final boss extra tough
	if (type === 5) {
		self.health = 500; // Much higher health for final boss
	}
	self.maxHealth = self.health;
	self.speed = 0.8 + type * 0.2;
	self.damage = 15 + type * 5;
	// Increase final boss damage
	if (type === 5) {
		self.damage = 40; // Much higher damage for final boss
	}
	self.lastAttack = 0;
	self.attackCooldown = 90 - type * 10;
	self.lastSpecial = 0;
	self.specialCooldown = 300;
	self.update = function () {
		// Boss-specific animations
		if (self.type === 3 && self.gemRef) {
			// Pulsing gem animation for screamer boss
			self.gemRef.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.3;
			self.gemRef.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.3;
		} else if (self.type === 4 && self.wing1Ref && self.wing2Ref) {
			// Flapping wings animation for healer boss
			var wingFlap = Math.sin(LK.ticks * 0.15) * 0.2;
			self.wing1Ref.rotation = wingFlap;
			self.wing2Ref.rotation = -wingFlap;
		}
		if (player) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				self.x += dx / distance * self.speed;
				self.y += dy / distance * self.speed;
			}
			if (distance < 80 && LK.ticks - self.lastAttack > self.attackCooldown) {
				player.takeDamage(self.damage);
				self.lastAttack = LK.ticks;
				LK.effects.flashScreen(0xff0000, 200);
			}
			if (LK.ticks - self.lastSpecial > self.specialCooldown) {
				self.specialAttack();
				self.lastSpecial = LK.ticks;
			}
		}
	};
	self.specialAttack = function () {
		if (self.type === 1) {
			self.speed *= 2;
			tween(self, {
				speed: 0.8
			}, {
				duration: 2000
			});
		} else if (self.type === 2) {
			for (var i = 0; i < 3; i++) {
				var minion = new Zombie();
				minion.x = self.x + (Math.random() - 0.5) * 200;
				minion.y = self.y + (Math.random() - 0.5) * 200;
				minion.health = 25;
				zombies.push(minion);
				game.addChild(minion);
			}
		} else if (self.type === 3) {
			LK.effects.flashScreen(0x800080, 500);
			player.takeDamage(20);
		} else if (self.type === 4) {
			self.health += 25;
			self.health = Math.min(self.health, self.maxHealth);
			LK.effects.flashObject(self, 0x00ff00, 500);
		} else if (self.type === 5) {
			for (var i = 0; i < 8; i++) {
				var angle = i / 8 * Math.PI * 2;
				var shockwave = new Zombie();
				shockwave.x = self.x;
				shockwave.y = self.y;
				shockwave.speed = 3;
				shockwave.moveAngle = angle;
				shockwave.health = 1;
				shockwave.damage = 25;
				shockwave.update = function () {
					this.x += Math.cos(this.moveAngle) * this.speed;
					this.y += Math.sin(this.moveAngle) * this.speed;
					if (this.x < 0 || this.x > 2048 || this.y < 0 || this.y > 2732) {
						this.destroy();
						var index = zombies.indexOf(this);
						if (index > -1) zombies.splice(index, 1);
					}
				};
				zombies.push(shockwave);
				game.addChild(shockwave);
			}
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 150);
		return self.health <= 0;
	};
	return self;
});
var Bullet = Container.expand(function (isSuper) {
	var self = Container.call(this);
	var bulletAsset = isSuper ? 'superBullet' : 'bullet';
	var bulletGraphics = self.attachAsset(bulletAsset, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = isSuper ? 30 : 25;
	self.dx = 0;
	self.dy = 0;
	self.update = function () {
		self.x += self.dx * self.speed;
		self.y += self.dy * self.speed;
		if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
			self.destroy();
			var index = bullets.indexOf(self);
			if (index > -1) bullets.splice(index, 1);
		}
	};
	return self;
});
var HealthPickup = Container.expand(function () {
	var self = Container.call(this);
	var healthBase = self.attachAsset('healthPickup', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var crossH = self.attachAsset('healthCross', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var crossV = self.attachAsset('healthCrossV', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.healAmount = 30;
	self.collected = false;
	self.pulseDirection = 1;
	self.update = function () {
		// Gentle pulsing animation
		self.scaleX += 0.01 * self.pulseDirection;
		self.scaleY += 0.01 * self.pulseDirection;
		if (self.scaleX > 1.2) self.pulseDirection = -1;
		if (self.scaleX < 0.9) self.pulseDirection = 1;
		self.rotation += 0.02;
		if (player && !self.collected && self.intersects(player)) {
			self.collected = true;
			player.heal(self.healAmount);
			LK.effects.flashObject(player, 0x00ff00, 500);
			self.destroy();
			var index = healthPickups.indexOf(self);
			if (index > -1) healthPickups.splice(index, 1);
		}
	};
	return self;
});
var Key = Container.expand(function () {
	var self = Container.call(this);
	var keyGraphics = self.attachAsset('key', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.collected = false;
	self.update = function () {
		self.rotation += 0.05;
		if (player && !self.collected && self.intersects(player)) {
			self.collected = true;
			keys++;
			LK.getSound('keyCollect').play();
			LK.effects.flashObject(self, 0xffffff, 300);
			self.destroy();
		}
	};
	return self;
});
var MapDecoration = Container.expand(function (type) {
	var self = Container.call(this);
	if (type === 'rock') {
		var rock = self.attachAsset('rock', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.scaleX = 0.8 + Math.random() * 0.4;
		self.scaleY = 0.8 + Math.random() * 0.4;
		self.rotation = Math.random() * Math.PI * 2;
	} else if (type === 'tree') {
		var trunk = self.attachAsset('tree', {
			anchorX: 0.5,
			anchorY: 1
		});
		var crown = self.attachAsset('treeCrown', {
			anchorX: 0.5,
			anchorY: 0.8,
			y: -60
		});
		self.scaleX = 0.7 + Math.random() * 0.6;
		self.scaleY = 0.7 + Math.random() * 0.6;
	} else if (type === 'grass') {
		var grass = self.attachAsset('grass', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.scaleX = 0.5 + Math.random() * 0.8;
		self.scaleY = 0.5 + Math.random() * 0.8;
		self.rotation = Math.random() * Math.PI * 2;
		self.alpha = 0.6 + Math.random() * 0.4;
	}
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Create character design with multiple parts
	var playerBase = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var playerBody = self.attachAsset('playerBody', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -5
	});
	var playerHead = self.attachAsset('playerHead', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -25
	});
	self.health = 100;
	self.maxHealth = 100;
	self.speed = 5;
	self.lastShot = 0;
	self.shootCooldown = 15;
	self.weaponLevel = 1;
	self.velocityX = 0;
	self.velocityY = 0;
	self.friction = 0.85;
	self.smoothMove = function (moveX, moveY) {
		// Add acceleration instead of instant movement
		self.velocityX += moveX * 0.3;
		self.velocityY += moveY * 0.3;
		// Cap maximum velocity
		var maxVel = self.speed;
		if (Math.abs(self.velocityX) > maxVel) self.velocityX = self.velocityX > 0 ? maxVel : -maxVel;
		if (Math.abs(self.velocityY) > maxVel) self.velocityY = self.velocityY > 0 ? maxVel : -maxVel;
	};
	self.updateMovement = function () {
		// Apply velocity to position
		self.x += self.velocityX;
		self.y += self.velocityY;
		// Apply friction when not moving
		self.velocityX *= self.friction;
		self.velocityY *= self.friction;
		// Keep player in bounds
		self.x = Math.max(40, Math.min(2008, self.x));
		self.y = Math.max(40, Math.min(2692, self.y));
		// Rotate character slightly based on movement direction
		if (Math.abs(self.velocityX) > 0.1 || Math.abs(self.velocityY) > 0.1) {
			var targetRotation = Math.atan2(self.velocityY, self.velocityX) * 0.1;
			tween(playerBase, {
				rotation: targetRotation
			}, {
				duration: 200
			});
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			LK.showGameOver();
		}
		LK.effects.flashObject(self, 0xff0000, 300);
	};
	self.heal = function (amount) {
		self.health = Math.min(self.maxHealth, self.health + amount);
		// Visual healing feedback
		tween(self, {
			tint: 0x00ff00
		}, {
			duration: 300,
			onFinish: function onFinish() {
				tween(self, {
					tint: 0xffffff
				}, {
					duration: 200
				});
			}
		});
	};
	self.upgrade = function () {
		self.weaponLevel++;
		self.shootCooldown = Math.max(5, self.shootCooldown - 2);
		if (self.weaponLevel >= 5) {
			self.shootCooldown = 8;
		}
		// Visual upgrade feedback
		tween(self, {
			scaleX: 1.2,
			scaleY: 1.2
		}, {
			duration: 300,
			onFinish: function onFinish() {
				tween(self, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 200
				});
			}
		});
	};
	return self;
});
var Zombie = Container.expand(function () {
	var self = Container.call(this);
	// Create zombie with multiple body parts for better design
	var zombieBase = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var zombieBody = self.attachAsset('zombieBody', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -5
	});
	var zombieHead = self.attachAsset('zombieHead', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -25
	});
	var zombieArms = self.attachAsset('zombieArms', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -8
	});
	// Add some visual variety
	self.scaleX = 0.8 + Math.random() * 0.4;
	self.scaleY = 0.8 + Math.random() * 0.4;
	zombieHead.tint = Math.random() > 0.5 ? 0x9acd32 : 0x556b2f;
	self.wobbleOffset = Math.random() * Math.PI * 2;
	self.health = 50;
	self.speed = 1.5;
	self.damage = 10;
	self.lastAttack = 0;
	self.attackCooldown = 60;
	self.update = function () {
		// Add wobble animation while moving
		self.rotation = Math.sin(LK.ticks * 0.1 + self.wobbleOffset) * 0.1;
		zombieArms.rotation = Math.sin(LK.ticks * 0.15 + self.wobbleOffset) * 0.3;
		if (player) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				self.x += dx / distance * self.speed;
				self.y += dy / distance * self.speed;
			}
			if (distance < 50 && LK.ticks - self.lastAttack > self.attackCooldown) {
				player.takeDamage(self.damage);
				self.lastAttack = LK.ticks;
			}
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 100);
		return self.health <= 0;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2d1b1b
});
/**** 
* Game Code
****/ 
var player;
var zombies = [];
var bullets = [];
var healthPickups = [];
var bombs = [];
var boss = null;
var keys = 0;
var currentWave = 1;
var waveInProgress = false;
var zombiesSpawned = 0;
var zombiesToSpawn = 0;
var spawnTimer = 0;
var healthSpawnTimer = 0;
var moveButton, shootButton, joystickKnob;
var isDragging = false;
var isShootPressed = false;
var joystickRadius = 120;
var joystickCenterX = 200;
var joystickCenterY = 2500;
var currentMoveX = 0;
var currentMoveY = 0;
// UI Elements
var waveText = new Text2('Wave 1', {
	size: 80,
	fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
var healthText = new Text2('Health: 100', {
	size: 60,
	fill: 0xFF0000
});
healthText.anchor.set(0, 0);
healthText.x = 120;
healthText.y = 20;
LK.gui.topLeft.addChild(healthText);
var keysText = new Text2('Keys: 0', {
	size: 60,
	fill: 0xFFD700
});
keysText.anchor.set(1, 0);
LK.gui.topRight.addChild(keysText);
var instructionText = new Text2('Survive the zombie waves!\nDefeat bosses to get keys!', {
	size: 50,
	fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 0;
instructionText.y = -200;
LK.gui.center.addChild(instructionText);
// Initialize player
player = new Player();
player.x = 1024;
player.y = 1366;
game.addChild(player);
// Control buttons with enhanced design
moveButton = game.addChild(LK.getAsset('moveButton', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.6,
	scaleY: 1.6
}));
moveButton.x = joystickCenterX;
moveButton.y = joystickCenterY;
moveButton.alpha = 0.4;
// Add joystick knob
joystickKnob = game.addChild(LK.getAsset('joystickKnob', {
	anchorX: 0.5,
	anchorY: 0.5
}));
joystickKnob.x = joystickCenterX;
joystickKnob.y = joystickCenterY;
joystickKnob.alpha = 0.8;
shootButton = game.addChild(LK.getAsset('shootButton', {
	anchorX: 0.5,
	anchorY: 0.5
}));
shootButton.x = 1850;
shootButton.y = 2500;
shootButton.alpha = 0.6;
function startWave() {
	if (currentWave > 5) {
		LK.showYouWin();
		return;
	}
	waveInProgress = true;
	zombiesSpawned = 0;
	zombiesToSpawn = 5 + currentWave * 3;
	spawnTimer = 0;
	waveText.setText('Wave ' + currentWave);
	instructionText.setText('');
	// Spawn bomb for this wave
	spawnBombForWave(currentWave);
	if (currentWave > 1) {
		player.upgrade();
	}
}
function spawnZombie() {
	var zombie = new Zombie();
	var side = Math.floor(Math.random() * 4);
	switch (side) {
		case 0:
			// Top
			zombie.x = Math.random() * 2048;
			zombie.y = -30;
			break;
		case 1:
			// Right
			zombie.x = 2078;
			zombie.y = Math.random() * 2732;
			break;
		case 2:
			// Bottom
			zombie.x = Math.random() * 2048;
			zombie.y = 2762;
			break;
		case 3:
			// Left
			zombie.x = -30;
			zombie.y = Math.random() * 2732;
			break;
	}
	zombie.health = 50 + currentWave * 15;
	zombie.speed = 1.5 + currentWave * 0.4;
	// Make final wave zombies extra tough
	if (currentWave === 5) {
		zombie.health += 50;
		zombie.speed += 0.5;
		zombie.damage = 20; // Increased damage for final wave
	}
	zombies.push(zombie);
	game.addChild(zombie);
}
function spawnBoss() {
	boss = new Boss(currentWave);
	boss.x = 1024;
	boss.y = 200;
	game.addChild(boss);
}
function shootBullet() {
	if (LK.ticks - player.lastShot < player.shootCooldown) return;
	var isSuper = player.weaponLevel >= 5;
	var bullet = new Bullet(isSuper);
	bullet.x = player.x;
	bullet.y = player.y;
	var nearestEnemy = null;
	var minDistance = Infinity;
	for (var i = 0; i < zombies.length; i++) {
		var distance = Math.sqrt(Math.pow(zombies[i].x - player.x, 2) + Math.pow(zombies[i].y - player.y, 2));
		if (distance < minDistance) {
			minDistance = distance;
			nearestEnemy = zombies[i];
		}
	}
	if (boss) {
		var bossDistance = Math.sqrt(Math.pow(boss.x - player.x, 2) + Math.pow(boss.y - player.y, 2));
		if (bossDistance < minDistance) {
			nearestEnemy = boss;
		}
	}
	if (nearestEnemy) {
		var dx = nearestEnemy.x - bullet.x;
		var dy = nearestEnemy.y - bullet.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		bullet.dx = dx / distance;
		bullet.dy = dy / distance;
	} else {
		bullet.dx = 0;
		bullet.dy = -1;
	}
	bullets.push(bullet);
	game.addChild(bullet);
	player.lastShot = LK.ticks;
	LK.getSound('shoot').play();
}
// Touch controls with smooth analog movement
moveButton.down = function (x, y, obj) {
	isDragging = true;
	// Visual feedback - make joystick base slightly larger
	tween(moveButton, {
		scaleX: 1.8,
		scaleY: 1.8,
		alpha: 0.6
	}, {
		duration: 150
	});
};
shootButton.down = function (x, y, obj) {
	isShootPressed = true;
	// Visual feedback for shoot button
	tween(shootButton, {
		scaleX: 0.9,
		scaleY: 0.9,
		tint: 0xffaa00
	}, {
		duration: 100
	});
	shootBullet();
};
shootButton.up = function (x, y, obj) {
	isShootPressed = false;
	// Return shoot button to normal
	tween(shootButton, {
		scaleX: 1,
		scaleY: 1,
		tint: 0xffffff
	}, {
		duration: 150
	});
};
game.move = function (x, y, obj) {
	if (isDragging) {
		var dx = x - joystickCenterX;
		var dy = y - joystickCenterY;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Limit knob position within joystick radius
		if (distance > joystickRadius) {
			dx = dx / distance * joystickRadius;
			dy = dy / distance * joystickRadius;
			distance = joystickRadius;
		}
		// Update knob position smoothly
		joystickKnob.x = joystickCenterX + dx;
		joystickKnob.y = joystickCenterY + dy;
		// Calculate movement with smooth analog control
		var intensity = distance / joystickRadius;
		currentMoveX = dx / joystickRadius * player.speed * intensity;
		currentMoveY = dy / joystickRadius * player.speed * intensity;
		// Apply smooth movement to player
		if (player) {
			player.smoothMove(currentMoveX, currentMoveY);
		}
	}
};
game.up = function (x, y, obj) {
	if (isDragging) {
		isDragging = false;
		currentMoveX = 0;
		currentMoveY = 0;
		// Return joystick to center with smooth animation
		tween(joystickKnob, {
			x: joystickCenterX,
			y: joystickCenterY
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		tween(moveButton, {
			scaleX: 1.6,
			scaleY: 1.6,
			alpha: 0.4
		}, {
			duration: 200
		});
	}
	isShootPressed = false;
};
function spawnHealthPickup() {
	var health = new HealthPickup();
	health.x = 200 + Math.random() * 1648; // Keep away from edges
	health.y = 200 + Math.random() * 2332;
	healthPickups.push(health);
	game.addChild(health);
}
function spawnBombForWave(wave) {
	// Remove existing bomb if any
	for (var i = bombs.length - 1; i >= 0; i--) {
		bombs[i].destroy();
		bombs.splice(i, 1);
	}
	var bomb = new Bomb();
	// Position bomb at different locations based on wave
	switch (wave) {
		case 1:
			bomb.x = 400;
			bomb.y = 600;
			break;
		case 2:
			bomb.x = 1600;
			bomb.y = 1000;
			break;
		case 3:
			bomb.x = 800;
			bomb.y = 2000;
			break;
		case 4:
			bomb.x = 1400;
			bomb.y = 1600;
			break;
		case 5:
			bomb.x = 1024;
			bomb.y = 1000;
			break;
	}
	bombs.push(bomb);
	game.addChild(bomb);
}
function createMapDecorations() {
	// Add trees around the map
	for (var i = 0; i < 8; i++) {
		var tree = new MapDecoration('tree');
		tree.x = 100 + Math.random() * 1848;
		tree.y = 100 + Math.random() * 2532;
		game.addChild(tree);
	}
	// Add rocks scattered around
	for (var i = 0; i < 15; i++) {
		var rock = new MapDecoration('rock');
		rock.x = 100 + Math.random() * 1848;
		rock.y = 100 + Math.random() * 2532;
		game.addChild(rock);
	}
	// Add grass patches
	for (var i = 0; i < 25; i++) {
		var grass = new MapDecoration('grass');
		grass.x = Math.random() * 2048;
		grass.y = Math.random() * 2732;
		game.addChild(grass);
	}
}
// Create map decorations
createMapDecorations();
// Start first wave
startWave();
LK.playMusic('gameMusic');
game.update = function () {
	// Update UI
	healthText.setText('Health: ' + player.health);
	keysText.setText('Keys: ' + keys);
	// Update player movement
	if (player) {
		player.updateMovement();
	}
	// Spawn health pickups occasionally
	healthSpawnTimer++;
	if (healthSpawnTimer >= 1800 && healthPickups.length < 2) {
		// Every 30 seconds max 2 on map
		spawnHealthPickup();
		healthSpawnTimer = 0;
	}
	// Smooth continuous shooting when button held
	if (isShootPressed) {
		shootBullet();
	}
	// Spawn zombies during wave
	if (waveInProgress && zombiesSpawned < zombiesToSpawn) {
		spawnTimer++;
		if (spawnTimer >= 60) {
			spawnZombie();
			zombiesSpawned++;
			spawnTimer = 0;
		}
	}
	// Check if wave is complete
	if (waveInProgress && zombiesSpawned >= zombiesToSpawn && zombies.length === 0 && !boss) {
		spawnBoss();
	}
	// Bullet collision detection
	for (var i = bullets.length - 1; i >= 0; i--) {
		var bullet = bullets[i];
		var hit = false;
		// Check bomb collisions
		for (var k = bombs.length - 1; k >= 0; k--) {
			if (bullet.intersects(bombs[k])) {
				if (bombs[k].takeDamage(bullet.damage)) {
					// Bomb will handle its own destruction and explosion
				}
				bullet.destroy();
				bullets.splice(i, 1);
				hit = true;
				break;
			}
		}
		if (!hit) {
			// Check zombie collisions
			for (var j = zombies.length - 1; j >= 0; j--) {
				if (bullet.intersects(zombies[j])) {
					if (zombies[j].takeDamage(bullet.damage)) {
						LK.getSound('zombieDeath').play();
						LK.setScore(LK.getScore() + 10);
						zombies[j].destroy();
						zombies.splice(j, 1);
					}
					bullet.destroy();
					bullets.splice(i, 1);
					hit = true;
					break;
				}
			}
		}
		// Check boss collision
		if (!hit && boss && bullet.intersects(boss)) {
			if (boss.takeDamage(bullet.damage)) {
				LK.getSound('bossDefeat').play();
				LK.setScore(LK.getScore() + 100);
				// Drop key
				var key = new Key();
				key.x = boss.x;
				key.y = boss.y;
				game.addChild(key);
				boss.destroy();
				boss = null;
				waveInProgress = false;
				currentWave++;
				LK.setTimeout(function () {
					if (currentWave <= 5) {
						startWave();
					} else {
						instructionText.setText('Congratulations!\nYou survived all waves!');
						LK.setTimeout(function () {
							LK.showYouWin();
						}, 3000);
					}
				}, 2000);
			}
			bullet.destroy();
			bullets.splice(i, 1);
		}
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Bomb = Container.expand(function () {
	var self = Container.call(this);
	var bombBase = self.attachAsset('bomb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var fuse = self.attachAsset('bombFuse', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 0,
		y: -35
	});
	var spark = self.attachAsset('bombSpark', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 0,
		y: -40
	});
	self.health = 25;
	self.exploded = false;
	self.sparkOffset = 0;
	self.update = function () {
		// Animate the spark on the fuse
		self.sparkOffset += 0.15;
		spark.alpha = 0.8 + Math.sin(self.sparkOffset) * 0.2;
		spark.scaleX = 0.8 + Math.sin(self.sparkOffset * 2) * 0.3;
		spark.scaleY = 0.8 + Math.sin(self.sparkOffset * 2) * 0.3;
		// Gentle bobbing animation
		self.y += Math.sin(LK.ticks * 0.05) * 0.3;
	};
	self.explode = function () {
		if (self.exploded) return;
		self.exploded = true;
		// Create explosion effect
		LK.effects.flashScreen(0xff4500, 300);
		// Damage nearby enemies and player
		var explosionRadius = 150;
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance < explosionRadius) {
				if (zombie.takeDamage(75)) {
					LK.getSound('zombieDeath').play();
					LK.setScore(LK.getScore() + 10);
					zombie.destroy();
					zombies.splice(i, 1);
					i--;
				}
			}
		}
		// Check boss damage
		if (boss) {
			var bossDistance = Math.sqrt(Math.pow(boss.x - self.x, 2) + Math.pow(boss.y - self.y, 2));
			if (bossDistance < explosionRadius) {
				boss.takeDamage(100);
			}
		}
		// Check player damage
		if (player) {
			var playerDistance = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2));
			if (playerDistance < explosionRadius) {
				player.takeDamage(30);
			}
		}
		// Remove bomb
		self.destroy();
		var index = bombs.indexOf(self);
		if (index > -1) bombs.splice(index, 1);
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 100);
		if (self.health <= 0) {
			self.explode();
			return true;
		}
		return false;
	};
	return self;
});
var Boss = Container.expand(function (type) {
	var self = Container.call(this);
	var bossAsset = type === 5 ? 'finalBoss' : 'boss' + type;
	var bossGraphics = self.attachAsset(bossAsset, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add unique design elements for each boss
	if (type === 1) {
		// Speed boss with spikes
		var eyes1 = self.attachAsset('boss1Eyes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -15,
			y: -10
		});
		var eyes2 = self.attachAsset('boss1Eyes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 15,
			y: -10
		});
		var spike1 = self.attachAsset('boss1Spikes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: -35,
			rotation: 0
		});
		var spike2 = self.attachAsset('boss1Spikes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -25,
			y: 0,
			rotation: 1.57
		});
		var spike3 = self.attachAsset('boss1Spikes', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 25,
			y: 0,
			rotation: -1.57
		});
	} else if (type === 2) {
		// Summoner boss with horns and claws
		var horn = self.attachAsset('boss2Horn', {
			anchorX: 0.5,
			anchorY: 1,
			x: 0,
			y: -40
		});
		var claw1 = self.attachAsset('boss2Claws', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -35,
			y: 0
		});
		var claw2 = self.attachAsset('boss2Claws', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 35,
			y: 0
		});
	} else if (type === 3) {
		// Screamer boss with armor and gem
		var armor = self.attachAsset('boss3Armor', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: 0
		});
		var gem = self.attachAsset('boss3Gem', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: -20
		});
		self.gemRef = gem; // Store reference for pulsing animation
	} else if (type === 4) {
		// Healer boss with wings and crown
		var wing1 = self.attachAsset('boss4Wings', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: -50,
			y: 0
		});
		var wing2 = self.attachAsset('boss4Wings', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 50,
			y: 0
		});
		var crown = self.attachAsset('boss4Crown', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: -50
		});
		self.wing1Ref = wing1;
		self.wing2Ref = wing2;
	}
	self.type = type;
	self.health = 150 + type * 50;
	// Make final boss extra tough
	if (type === 5) {
		self.health = 500; // Much higher health for final boss
	}
	self.maxHealth = self.health;
	self.speed = 0.8 + type * 0.2;
	self.damage = 15 + type * 5;
	// Increase final boss damage
	if (type === 5) {
		self.damage = 40; // Much higher damage for final boss
	}
	self.lastAttack = 0;
	self.attackCooldown = 90 - type * 10;
	self.lastSpecial = 0;
	self.specialCooldown = 300;
	self.update = function () {
		// Boss-specific animations
		if (self.type === 3 && self.gemRef) {
			// Pulsing gem animation for screamer boss
			self.gemRef.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.3;
			self.gemRef.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.3;
		} else if (self.type === 4 && self.wing1Ref && self.wing2Ref) {
			// Flapping wings animation for healer boss
			var wingFlap = Math.sin(LK.ticks * 0.15) * 0.2;
			self.wing1Ref.rotation = wingFlap;
			self.wing2Ref.rotation = -wingFlap;
		}
		if (player) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				self.x += dx / distance * self.speed;
				self.y += dy / distance * self.speed;
			}
			if (distance < 80 && LK.ticks - self.lastAttack > self.attackCooldown) {
				player.takeDamage(self.damage);
				self.lastAttack = LK.ticks;
				LK.effects.flashScreen(0xff0000, 200);
			}
			if (LK.ticks - self.lastSpecial > self.specialCooldown) {
				self.specialAttack();
				self.lastSpecial = LK.ticks;
			}
		}
	};
	self.specialAttack = function () {
		if (self.type === 1) {
			self.speed *= 2;
			tween(self, {
				speed: 0.8
			}, {
				duration: 2000
			});
		} else if (self.type === 2) {
			for (var i = 0; i < 3; i++) {
				var minion = new Zombie();
				minion.x = self.x + (Math.random() - 0.5) * 200;
				minion.y = self.y + (Math.random() - 0.5) * 200;
				minion.health = 25;
				zombies.push(minion);
				game.addChild(minion);
			}
		} else if (self.type === 3) {
			LK.effects.flashScreen(0x800080, 500);
			player.takeDamage(20);
		} else if (self.type === 4) {
			self.health += 25;
			self.health = Math.min(self.health, self.maxHealth);
			LK.effects.flashObject(self, 0x00ff00, 500);
		} else if (self.type === 5) {
			for (var i = 0; i < 8; i++) {
				var angle = i / 8 * Math.PI * 2;
				var shockwave = new Zombie();
				shockwave.x = self.x;
				shockwave.y = self.y;
				shockwave.speed = 3;
				shockwave.moveAngle = angle;
				shockwave.health = 1;
				shockwave.damage = 25;
				shockwave.update = function () {
					this.x += Math.cos(this.moveAngle) * this.speed;
					this.y += Math.sin(this.moveAngle) * this.speed;
					if (this.x < 0 || this.x > 2048 || this.y < 0 || this.y > 2732) {
						this.destroy();
						var index = zombies.indexOf(this);
						if (index > -1) zombies.splice(index, 1);
					}
				};
				zombies.push(shockwave);
				game.addChild(shockwave);
			}
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 150);
		return self.health <= 0;
	};
	return self;
});
var Bullet = Container.expand(function (isSuper) {
	var self = Container.call(this);
	var bulletAsset = isSuper ? 'superBullet' : 'bullet';
	var bulletGraphics = self.attachAsset(bulletAsset, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = isSuper ? 30 : 25;
	self.dx = 0;
	self.dy = 0;
	self.update = function () {
		self.x += self.dx * self.speed;
		self.y += self.dy * self.speed;
		if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
			self.destroy();
			var index = bullets.indexOf(self);
			if (index > -1) bullets.splice(index, 1);
		}
	};
	return self;
});
var HealthPickup = Container.expand(function () {
	var self = Container.call(this);
	var healthBase = self.attachAsset('healthPickup', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var crossH = self.attachAsset('healthCross', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var crossV = self.attachAsset('healthCrossV', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.healAmount = 30;
	self.collected = false;
	self.pulseDirection = 1;
	self.update = function () {
		// Gentle pulsing animation
		self.scaleX += 0.01 * self.pulseDirection;
		self.scaleY += 0.01 * self.pulseDirection;
		if (self.scaleX > 1.2) self.pulseDirection = -1;
		if (self.scaleX < 0.9) self.pulseDirection = 1;
		self.rotation += 0.02;
		if (player && !self.collected && self.intersects(player)) {
			self.collected = true;
			player.heal(self.healAmount);
			LK.effects.flashObject(player, 0x00ff00, 500);
			self.destroy();
			var index = healthPickups.indexOf(self);
			if (index > -1) healthPickups.splice(index, 1);
		}
	};
	return self;
});
var Key = Container.expand(function () {
	var self = Container.call(this);
	var keyGraphics = self.attachAsset('key', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.collected = false;
	self.update = function () {
		self.rotation += 0.05;
		if (player && !self.collected && self.intersects(player)) {
			self.collected = true;
			keys++;
			LK.getSound('keyCollect').play();
			LK.effects.flashObject(self, 0xffffff, 300);
			self.destroy();
		}
	};
	return self;
});
var MapDecoration = Container.expand(function (type) {
	var self = Container.call(this);
	if (type === 'rock') {
		var rock = self.attachAsset('rock', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.scaleX = 0.8 + Math.random() * 0.4;
		self.scaleY = 0.8 + Math.random() * 0.4;
		self.rotation = Math.random() * Math.PI * 2;
	} else if (type === 'tree') {
		var trunk = self.attachAsset('tree', {
			anchorX: 0.5,
			anchorY: 1
		});
		var crown = self.attachAsset('treeCrown', {
			anchorX: 0.5,
			anchorY: 0.8,
			y: -60
		});
		self.scaleX = 0.7 + Math.random() * 0.6;
		self.scaleY = 0.7 + Math.random() * 0.6;
	} else if (type === 'grass') {
		var grass = self.attachAsset('grass', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.scaleX = 0.5 + Math.random() * 0.8;
		self.scaleY = 0.5 + Math.random() * 0.8;
		self.rotation = Math.random() * Math.PI * 2;
		self.alpha = 0.6 + Math.random() * 0.4;
	}
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Create character design with multiple parts
	var playerBase = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var playerBody = self.attachAsset('playerBody', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -5
	});
	var playerHead = self.attachAsset('playerHead', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -25
	});
	self.health = 100;
	self.maxHealth = 100;
	self.speed = 5;
	self.lastShot = 0;
	self.shootCooldown = 15;
	self.weaponLevel = 1;
	self.velocityX = 0;
	self.velocityY = 0;
	self.friction = 0.85;
	self.smoothMove = function (moveX, moveY) {
		// Add acceleration instead of instant movement
		self.velocityX += moveX * 0.3;
		self.velocityY += moveY * 0.3;
		// Cap maximum velocity
		var maxVel = self.speed;
		if (Math.abs(self.velocityX) > maxVel) self.velocityX = self.velocityX > 0 ? maxVel : -maxVel;
		if (Math.abs(self.velocityY) > maxVel) self.velocityY = self.velocityY > 0 ? maxVel : -maxVel;
	};
	self.updateMovement = function () {
		// Apply velocity to position
		self.x += self.velocityX;
		self.y += self.velocityY;
		// Apply friction when not moving
		self.velocityX *= self.friction;
		self.velocityY *= self.friction;
		// Keep player in bounds
		self.x = Math.max(40, Math.min(2008, self.x));
		self.y = Math.max(40, Math.min(2692, self.y));
		// Rotate character slightly based on movement direction
		if (Math.abs(self.velocityX) > 0.1 || Math.abs(self.velocityY) > 0.1) {
			var targetRotation = Math.atan2(self.velocityY, self.velocityX) * 0.1;
			tween(playerBase, {
				rotation: targetRotation
			}, {
				duration: 200
			});
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			LK.showGameOver();
		}
		LK.effects.flashObject(self, 0xff0000, 300);
	};
	self.heal = function (amount) {
		self.health = Math.min(self.maxHealth, self.health + amount);
		// Visual healing feedback
		tween(self, {
			tint: 0x00ff00
		}, {
			duration: 300,
			onFinish: function onFinish() {
				tween(self, {
					tint: 0xffffff
				}, {
					duration: 200
				});
			}
		});
	};
	self.upgrade = function () {
		self.weaponLevel++;
		self.shootCooldown = Math.max(5, self.shootCooldown - 2);
		if (self.weaponLevel >= 5) {
			self.shootCooldown = 8;
		}
		// Visual upgrade feedback
		tween(self, {
			scaleX: 1.2,
			scaleY: 1.2
		}, {
			duration: 300,
			onFinish: function onFinish() {
				tween(self, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 200
				});
			}
		});
	};
	return self;
});
var Zombie = Container.expand(function () {
	var self = Container.call(this);
	// Create zombie with multiple body parts for better design
	var zombieBase = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var zombieBody = self.attachAsset('zombieBody', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -5
	});
	var zombieHead = self.attachAsset('zombieHead', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -25
	});
	var zombieArms = self.attachAsset('zombieArms', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -8
	});
	// Add some visual variety
	self.scaleX = 0.8 + Math.random() * 0.4;
	self.scaleY = 0.8 + Math.random() * 0.4;
	zombieHead.tint = Math.random() > 0.5 ? 0x9acd32 : 0x556b2f;
	self.wobbleOffset = Math.random() * Math.PI * 2;
	self.health = 50;
	self.speed = 1.5;
	self.damage = 10;
	self.lastAttack = 0;
	self.attackCooldown = 60;
	self.update = function () {
		// Add wobble animation while moving
		self.rotation = Math.sin(LK.ticks * 0.1 + self.wobbleOffset) * 0.1;
		zombieArms.rotation = Math.sin(LK.ticks * 0.15 + self.wobbleOffset) * 0.3;
		if (player) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				self.x += dx / distance * self.speed;
				self.y += dy / distance * self.speed;
			}
			if (distance < 50 && LK.ticks - self.lastAttack > self.attackCooldown) {
				player.takeDamage(self.damage);
				self.lastAttack = LK.ticks;
			}
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 100);
		return self.health <= 0;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2d1b1b
});
/**** 
* Game Code
****/ 
var player;
var zombies = [];
var bullets = [];
var healthPickups = [];
var bombs = [];
var boss = null;
var keys = 0;
var currentWave = 1;
var waveInProgress = false;
var zombiesSpawned = 0;
var zombiesToSpawn = 0;
var spawnTimer = 0;
var healthSpawnTimer = 0;
var moveButton, shootButton, joystickKnob;
var isDragging = false;
var isShootPressed = false;
var joystickRadius = 120;
var joystickCenterX = 200;
var joystickCenterY = 2500;
var currentMoveX = 0;
var currentMoveY = 0;
// UI Elements
var waveText = new Text2('Wave 1', {
	size: 80,
	fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
var healthText = new Text2('Health: 100', {
	size: 60,
	fill: 0xFF0000
});
healthText.anchor.set(0, 0);
healthText.x = 120;
healthText.y = 20;
LK.gui.topLeft.addChild(healthText);
var keysText = new Text2('Keys: 0', {
	size: 60,
	fill: 0xFFD700
});
keysText.anchor.set(1, 0);
LK.gui.topRight.addChild(keysText);
var instructionText = new Text2('Survive the zombie waves!\nDefeat bosses to get keys!', {
	size: 50,
	fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 0;
instructionText.y = -200;
LK.gui.center.addChild(instructionText);
// Initialize player
player = new Player();
player.x = 1024;
player.y = 1366;
game.addChild(player);
// Control buttons with enhanced design
moveButton = game.addChild(LK.getAsset('moveButton', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.6,
	scaleY: 1.6
}));
moveButton.x = joystickCenterX;
moveButton.y = joystickCenterY;
moveButton.alpha = 0.4;
// Add joystick knob
joystickKnob = game.addChild(LK.getAsset('joystickKnob', {
	anchorX: 0.5,
	anchorY: 0.5
}));
joystickKnob.x = joystickCenterX;
joystickKnob.y = joystickCenterY;
joystickKnob.alpha = 0.8;
shootButton = game.addChild(LK.getAsset('shootButton', {
	anchorX: 0.5,
	anchorY: 0.5
}));
shootButton.x = 1850;
shootButton.y = 2500;
shootButton.alpha = 0.6;
function startWave() {
	if (currentWave > 5) {
		LK.showYouWin();
		return;
	}
	waveInProgress = true;
	zombiesSpawned = 0;
	zombiesToSpawn = 5 + currentWave * 3;
	spawnTimer = 0;
	waveText.setText('Wave ' + currentWave);
	instructionText.setText('');
	// Spawn bomb for this wave
	spawnBombForWave(currentWave);
	if (currentWave > 1) {
		player.upgrade();
	}
}
function spawnZombie() {
	var zombie = new Zombie();
	var side = Math.floor(Math.random() * 4);
	switch (side) {
		case 0:
			// Top
			zombie.x = Math.random() * 2048;
			zombie.y = -30;
			break;
		case 1:
			// Right
			zombie.x = 2078;
			zombie.y = Math.random() * 2732;
			break;
		case 2:
			// Bottom
			zombie.x = Math.random() * 2048;
			zombie.y = 2762;
			break;
		case 3:
			// Left
			zombie.x = -30;
			zombie.y = Math.random() * 2732;
			break;
	}
	zombie.health = 50 + currentWave * 15;
	zombie.speed = 1.5 + currentWave * 0.4;
	// Make final wave zombies extra tough
	if (currentWave === 5) {
		zombie.health += 50;
		zombie.speed += 0.5;
		zombie.damage = 20; // Increased damage for final wave
	}
	zombies.push(zombie);
	game.addChild(zombie);
}
function spawnBoss() {
	boss = new Boss(currentWave);
	boss.x = 1024;
	boss.y = 200;
	game.addChild(boss);
}
function shootBullet() {
	if (LK.ticks - player.lastShot < player.shootCooldown) return;
	var isSuper = player.weaponLevel >= 5;
	var bullet = new Bullet(isSuper);
	bullet.x = player.x;
	bullet.y = player.y;
	var nearestEnemy = null;
	var minDistance = Infinity;
	for (var i = 0; i < zombies.length; i++) {
		var distance = Math.sqrt(Math.pow(zombies[i].x - player.x, 2) + Math.pow(zombies[i].y - player.y, 2));
		if (distance < minDistance) {
			minDistance = distance;
			nearestEnemy = zombies[i];
		}
	}
	if (boss) {
		var bossDistance = Math.sqrt(Math.pow(boss.x - player.x, 2) + Math.pow(boss.y - player.y, 2));
		if (bossDistance < minDistance) {
			nearestEnemy = boss;
		}
	}
	if (nearestEnemy) {
		var dx = nearestEnemy.x - bullet.x;
		var dy = nearestEnemy.y - bullet.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		bullet.dx = dx / distance;
		bullet.dy = dy / distance;
	} else {
		bullet.dx = 0;
		bullet.dy = -1;
	}
	bullets.push(bullet);
	game.addChild(bullet);
	player.lastShot = LK.ticks;
	LK.getSound('shoot').play();
}
// Touch controls with smooth analog movement
moveButton.down = function (x, y, obj) {
	isDragging = true;
	// Visual feedback - make joystick base slightly larger
	tween(moveButton, {
		scaleX: 1.8,
		scaleY: 1.8,
		alpha: 0.6
	}, {
		duration: 150
	});
};
shootButton.down = function (x, y, obj) {
	isShootPressed = true;
	// Visual feedback for shoot button
	tween(shootButton, {
		scaleX: 0.9,
		scaleY: 0.9,
		tint: 0xffaa00
	}, {
		duration: 100
	});
	shootBullet();
};
shootButton.up = function (x, y, obj) {
	isShootPressed = false;
	// Return shoot button to normal
	tween(shootButton, {
		scaleX: 1,
		scaleY: 1,
		tint: 0xffffff
	}, {
		duration: 150
	});
};
game.move = function (x, y, obj) {
	if (isDragging) {
		var dx = x - joystickCenterX;
		var dy = y - joystickCenterY;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Limit knob position within joystick radius
		if (distance > joystickRadius) {
			dx = dx / distance * joystickRadius;
			dy = dy / distance * joystickRadius;
			distance = joystickRadius;
		}
		// Update knob position smoothly
		joystickKnob.x = joystickCenterX + dx;
		joystickKnob.y = joystickCenterY + dy;
		// Calculate movement with smooth analog control
		var intensity = distance / joystickRadius;
		currentMoveX = dx / joystickRadius * player.speed * intensity;
		currentMoveY = dy / joystickRadius * player.speed * intensity;
		// Apply smooth movement to player
		if (player) {
			player.smoothMove(currentMoveX, currentMoveY);
		}
	}
};
game.up = function (x, y, obj) {
	if (isDragging) {
		isDragging = false;
		currentMoveX = 0;
		currentMoveY = 0;
		// Return joystick to center with smooth animation
		tween(joystickKnob, {
			x: joystickCenterX,
			y: joystickCenterY
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		tween(moveButton, {
			scaleX: 1.6,
			scaleY: 1.6,
			alpha: 0.4
		}, {
			duration: 200
		});
	}
	isShootPressed = false;
};
function spawnHealthPickup() {
	var health = new HealthPickup();
	health.x = 200 + Math.random() * 1648; // Keep away from edges
	health.y = 200 + Math.random() * 2332;
	healthPickups.push(health);
	game.addChild(health);
}
function spawnBombForWave(wave) {
	// Remove existing bomb if any
	for (var i = bombs.length - 1; i >= 0; i--) {
		bombs[i].destroy();
		bombs.splice(i, 1);
	}
	var bomb = new Bomb();
	// Position bomb at different locations based on wave
	switch (wave) {
		case 1:
			bomb.x = 400;
			bomb.y = 600;
			break;
		case 2:
			bomb.x = 1600;
			bomb.y = 1000;
			break;
		case 3:
			bomb.x = 800;
			bomb.y = 2000;
			break;
		case 4:
			bomb.x = 1400;
			bomb.y = 1600;
			break;
		case 5:
			bomb.x = 1024;
			bomb.y = 1000;
			break;
	}
	bombs.push(bomb);
	game.addChild(bomb);
}
function createMapDecorations() {
	// Add trees around the map
	for (var i = 0; i < 8; i++) {
		var tree = new MapDecoration('tree');
		tree.x = 100 + Math.random() * 1848;
		tree.y = 100 + Math.random() * 2532;
		game.addChild(tree);
	}
	// Add rocks scattered around
	for (var i = 0; i < 15; i++) {
		var rock = new MapDecoration('rock');
		rock.x = 100 + Math.random() * 1848;
		rock.y = 100 + Math.random() * 2532;
		game.addChild(rock);
	}
	// Add grass patches
	for (var i = 0; i < 25; i++) {
		var grass = new MapDecoration('grass');
		grass.x = Math.random() * 2048;
		grass.y = Math.random() * 2732;
		game.addChild(grass);
	}
}
// Create map decorations
createMapDecorations();
// Start first wave
startWave();
LK.playMusic('gameMusic');
game.update = function () {
	// Update UI
	healthText.setText('Health: ' + player.health);
	keysText.setText('Keys: ' + keys);
	// Update player movement
	if (player) {
		player.updateMovement();
	}
	// Spawn health pickups occasionally
	healthSpawnTimer++;
	if (healthSpawnTimer >= 1800 && healthPickups.length < 2) {
		// Every 30 seconds max 2 on map
		spawnHealthPickup();
		healthSpawnTimer = 0;
	}
	// Smooth continuous shooting when button held
	if (isShootPressed) {
		shootBullet();
	}
	// Spawn zombies during wave
	if (waveInProgress && zombiesSpawned < zombiesToSpawn) {
		spawnTimer++;
		if (spawnTimer >= 60) {
			spawnZombie();
			zombiesSpawned++;
			spawnTimer = 0;
		}
	}
	// Check if wave is complete
	if (waveInProgress && zombiesSpawned >= zombiesToSpawn && zombies.length === 0 && !boss) {
		spawnBoss();
	}
	// Bullet collision detection
	for (var i = bullets.length - 1; i >= 0; i--) {
		var bullet = bullets[i];
		var hit = false;
		// Check bomb collisions
		for (var k = bombs.length - 1; k >= 0; k--) {
			if (bullet.intersects(bombs[k])) {
				if (bombs[k].takeDamage(bullet.damage)) {
					// Bomb will handle its own destruction and explosion
				}
				bullet.destroy();
				bullets.splice(i, 1);
				hit = true;
				break;
			}
		}
		if (!hit) {
			// Check zombie collisions
			for (var j = zombies.length - 1; j >= 0; j--) {
				if (bullet.intersects(zombies[j])) {
					if (zombies[j].takeDamage(bullet.damage)) {
						LK.getSound('zombieDeath').play();
						LK.setScore(LK.getScore() + 10);
						zombies[j].destroy();
						zombies.splice(j, 1);
					}
					bullet.destroy();
					bullets.splice(i, 1);
					hit = true;
					break;
				}
			}
		}
		// Check boss collision
		if (!hit && boss && bullet.intersects(boss)) {
			if (boss.takeDamage(bullet.damage)) {
				LK.getSound('bossDefeat').play();
				LK.setScore(LK.getScore() + 100);
				// Drop key
				var key = new Key();
				key.x = boss.x;
				key.y = boss.y;
				game.addChild(key);
				boss.destroy();
				boss = null;
				waveInProgress = false;
				currentWave++;
				LK.setTimeout(function () {
					if (currentWave <= 5) {
						startWave();
					} else {
						instructionText.setText('Congratulations!\nYou survived all waves!');
						LK.setTimeout(function () {
							LK.showYouWin();
						}, 3000);
					}
				}, 2000);
			}
			bullet.destroy();
			bullets.splice(i, 1);
		}
	}
};