/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highscore: 0,
	weaponLevel: 1
});
/**** 
* Classes
****/ 
var Barrel = Container.expand(function (x, y) {
	var self = Container.call(this);
	var barrelGraphic = self.attachAsset('barrel', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.update = function () {
		for (var i = bullets.length - 1; i >= 0; i--) {
			if (bullets[i].intersects(self)) {
				bullets[i].destroy();
				bullets.splice(i, 1);
				self.explode();
				return true;
			}
		}
		return false;
	};
	self.explode = function () {
		// Check for zombies in explosion area
		LK.getSound('explode').play();
		zombies.forEach(function (zombie) {
			if (zombie.intersects(self)) {
				if (zombie.takeDamage(100)) {
					// Inflict damage to zombie and check if it dies
					zombies.splice(zombies.indexOf(zombie), 1); // Remove zombie from the array if it dies
					zombie.destroy(); // Destroy the zombie
				}
			}
		});
		var explosion = LK.getAsset('explosionEffect', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y
		});
		game.addChild(explosion);
		tween(explosion, {}, {
			duration: 500,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		self.destroy();
	};
	return self;
});
var Bomb = Container.expand(function (x, y) {
	var self = Container.call(this);
	var bombGraphic = self.attachAsset('smallBomb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.explode = function () {
		// Check for player in red area
		LK.getSound('explode').play();
		if (player.intersects(self)) {
			player.takeDamage(100); // Inflict damage to player
		}
		// Check for zombies in red area
		zombies.forEach(function (zombie) {
			if (zombie.intersects(self)) {
				if (zombie.takeDamage(100)) {
					// Inflict damage to zombie and check if it dies
					zombies.splice(zombies.indexOf(zombie), 1); // Remove zombie from the array if it dies
					zombie.destroy(); // Destroy the zombie
				}
			}
		});
		// Check for crates in red area
		obstacles.forEach(function (obstacle) {
			if (obstacle.type === 'crate' && obstacle.intersects(self)) {
				obstacle.destroy(); // Destroy the crate
				obstacles.splice(obstacles.indexOf(obstacle), 1); // Remove crate from the array
			}
		});
		// Add explosion effect
		var explosion = LK.getAsset('explosionEffect', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y
		});
		game.addChild(explosion);
		tween(explosion, {}, {
			duration: 500,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		self.destroy(); // Remove bomb after explosion
	};
	return self;
});
var Bullet = Container.expand(function (startX, startY, targetX, targetY, damage) {
	var self = Container.call(this);
	var bulletGraphic = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 15;
	self.damage = damage || 10;
	// Calculate direction vector
	var dx = targetX - startX;
	var dy = targetY - startY;
	var distance = Math.sqrt(dx * dx + dy * dy);
	self.vx = dx / distance * self.speed;
	self.vy = dy / distance * self.speed;
	self.x = startX;
	self.y = startY;
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		bulletGraphic.rotation = Math.atan2(self.vy, self.vx);
		// Check if bullet is out of bounds
		if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
			return true; // Remove bullet 
		}
		// Check proximity to barrels
		for (var i = 0; i < obstacles.length; i++) {
			if (obstacles[i] instanceof Barrel && Math.abs(self.x - obstacles[i].x) < 50 && Math.abs(self.y - obstacles[i].y) < 50) {
				return true; // Remove bullet
			}
		}
		// Check proximity to zombies
		for (var j = 0; j < zombies.length; j++) {
			if (Math.abs(self.x - zombies[j].x) < 50 && Math.abs(self.y - zombies[j].y) < 50) {
				return true; // Remove bullet
			}
		}
		return false;
	};
	return self;
});
var Missile = Container.expand(function (startX, startY, targetX, targetY, damage) {
	var self = Container.call(this);
	var missileGraphic = self.attachAsset('missile', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10;
	self.damage = damage || 20;
	var dx = targetX - startX;
	var dy = targetY - startY;
	var distance = Math.sqrt(dx * dx + dy * dy);
	self.vx = dx / distance * self.speed;
	self.vy = dy / distance * self.speed;
	self.x = startX;
	self.y = startY;
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		missileGraphic.rotation = Math.atan2(self.vy, self.vx);
		if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
			return true;
		}
		// Check for collision with zombies
		for (var j = 0; j < zombies.length; j++) {
			if (self.intersects(zombies[j])) {
				// Trigger explosion effect
				self.explode();
				return true; // Remove missile
			}
		}
		return false;
	};
	self.explode = function () {
		// Play explosion sound
		LK.getSound('explode').play();
		// Check for zombies in explosion area
		zombies.forEach(function (zombie) {
			if (zombie.intersects(self)) {
				if (zombie.takeDamage(self.damage)) {
					// Remove zombie if it dies
					zombies.splice(zombies.indexOf(zombie), 1);
					zombie.destroy();
				}
			}
		});
		// Add explosion effect
		var explosion = LK.getAsset('explosionEffect', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y
		});
		game.addChild(explosion);
		tween(explosion, {}, {
			duration: 500,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		// Destroy the missile after explosion
		self.destroy();
	};
	return self;
});
var Obstacle = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	var obstacleGraphic = self.attachAsset(type === 'stone' ? 'stone' : type === 'crate' ? 'crate' : 'bush', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = type; // Store the type of obstacle
	self.update = function () {
		// Check for bullet collision with crate
		if (self.type === 'crate') {
			for (var i = bullets.length - 1; i >= 0; i--) {
				if (bullets[i].intersects(self)) {
					// Display bullet effect at the point of impact
					var bulletEffect = LK.getAsset('bulleteffect', {
						anchorX: 0.5,
						anchorY: 0.5,
						x: bullets[i].x,
						y: bullets[i].y
					});
					game.addChild(bulletEffect);
					tween(bulletEffect, {}, {
						duration: 200,
						onFinish: function onFinish() {
							bulletEffect.destroy();
						}
					});
					bullets[i].destroy();
					bullets.splice(i, 1);
					// 50% chance to drop a pickup when crate is destroyed
					if (Math.random() < 0.5) {
						spawnPickup(self.x, self.y);
					}
					self.destroy();
					return true; // Remove crate
				}
			}
		}
		return false;
	};
	self.spawnPickup = spawnPickup; // Make spawnPickup accessible
	return self;
});
var Pickup = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	var pickupGraphic = self.attachAsset(type === 'health' ? 'healthPack' : 'ammoBox', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = type; // 'health' or 'ammo'
	self.x = x;
	self.y = y;
	self.lifespan = 10000; // milliseconds until pickup disappears
	self.creationTime = Date.now();
	self.update = function () {
		// Make pickup pulse
		var age = Date.now() - self.creationTime;
		var pulse = Math.sin(age / 200) * 0.2 + 1;
		self.scale.set(pulse, pulse);
		// Check if pickup should expire
		if (age > self.lifespan) {
			return true; // Remove pickup
		}
		return false;
	};
	self.collect = function (player) {
		LK.getSound('pickup').play();
		if (self.type === 'health') {
			player.heal(25);
		} else if (self.type === 'ammo') {
			player.ammo = player.maxAmmo;
		}
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerWalkingGraphic = self.attachAsset('player1', {
		// Walking animation
		anchorX: 0.5,
		anchorY: 0.5
	});
	var playerIdleGraphic = self.attachAsset('player', {
		// Idle animation
		anchorX: 0.5,
		anchorY: 0.5
	});
	playerIdleGraphic.visible = true; // Start with idle animation
	playerWalkingGraphic.visible = false; // Hide walking animation initially
	self.health = 100;
	self.maxHealth = 100;
	self.ammo = 30;
	self.maxAmmo = 30;
	self.reloadTime = 1000; // milliseconds
	self.isReloading = false;
	self.speed = 7;
	self.weaponLevel = storage.weaponLevel || 0.5; // Reduced initial weapon level
	self.bulletDamage = 10 * self.weaponLevel; // Adjusted bullet damage to prevent one-hit kills in wave 1 
	self.lastShotTime = 0;
	self.shootDelay = 300; // milliseconds between shots
	self.moveTowards = function (targetX, targetY) {
		var dx = targetX - self.x;
		var dy = targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Play walking sound if player is moving
		if (distance > 0) {
			LK.getSound('walk').play();
			if (!self.walkingTimeout) {
				self.walkingTimeout = LK.setTimeout(function () {
					playerWalkingGraphic.visible = true; // Show walking animation
					playerIdleGraphic.visible = false; // Hide idle animation
				}, 2000);
			}
		} else {
			playerWalkingGraphic.visible = false; // Hide walking animation
			playerIdleGraphic.visible = true; // Show idle animation
			if (self.walkingTimeout) {
				LK.clearTimeout(self.walkingTimeout);
				self.walkingTimeout = null;
			}
		}
		if (distance > self.speed) {
			self.x += dx / distance * self.speed;
			self.y += dy / distance * self.speed;
		} else {
			self.x = targetX;
			self.y = targetY;
		}
		// Keep player within bounds
		self.x = Math.max(50, Math.min(2048 - 50, self.x));
		self.y = Math.max(50, Math.min(2732 - 50, self.y));
	};
	self.shoot = function (targetX, targetY) {
		var currentTime = Date.now();
		if (!self.infiniteAmmo && self.ammo <= 0) {
			self.reload();
			return null;
		}
		if (self.isReloading) {
			return null;
		}
		if (currentTime - self.lastShotTime < self.shootDelay) {
			return null;
		}
		self.lastShotTime = currentTime;
		self.ammo--;
		LK.getSound('shoot').play();
		LK.getSound('shoot').play();
		// Switch to player2 appearance when shooting
		playerIdleGraphic.visible = false;
		playerWalkingGraphic.visible = false;
		var playerShootingGraphic = self.attachAsset('player2', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.addChild(playerShootingGraphic);
		// Revert back to idle or walking appearance after shooting
		LK.setTimeout(function () {
			playerShootingGraphic.destroy();
			if (self.vx !== 0 || self.vy !== 0) {
				playerWalkingGraphic.visible = true;
			} else {
				playerIdleGraphic.visible = true;
			}
		}, self.shootDelay);
		// 25% chance for a critical hit
		var criticalHit = Math.random() < 0.25;
		var damage = criticalHit ? self.bulletDamage * 2 : self.bulletDamage;
		var bullet = new Bullet(self.x, self.y, targetX, targetY, damage);
		// Removed critical effect display
		return bullet;
	};
	self.reload = function () {
		if (!self.isReloading && self.ammo < self.maxAmmo) {
			self.isReloading = true;
			LK.setTimeout(function () {
				self.ammo = self.maxAmmo;
				self.isReloading = false;
			}, self.reloadTime);
		}
	};
	self.takeDamage = function (damage) {
		if (self.children.some(function (child) {
			return child.name === 'shieldEffect';
		})) {
			// If shield is active, prevent damage
			return false;
		}
		LK.getSound('playerHit').play();
		LK.effects.flashObject(self, 0xff0000, 300);
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			return true; // player died
		}
		return false; // player still alive
	};
	self.heal = function (amount) {
		self.health = Math.min(self.maxHealth, self.health + amount);
	};
	self.upgradeWeapon = function () {
		self.weaponLevel++;
		self.bulletDamage = 10 * self.weaponLevel;
		storage.weaponLevel = self.weaponLevel;
	};
	self.activateMissileMode = function () {
		var originalShoot = self.shoot; // Store the original shoot function
		self.missileMode = true;
		self.shoot = function (targetX, targetY) {
			var currentTime = Date.now();
			if (!self.infiniteAmmo && self.ammo <= 0) {
				self.reload();
				return null;
			}
			if (self.isReloading) {
				return null;
			}
			if (currentTime - self.lastShotTime < self.shootDelay) {
				return null;
			}
			self.lastShotTime = currentTime;
			self.ammo--;
			LK.getSound('shoot').play();
			var missile = new Missile(self.x, self.y, targetX, targetY, self.bulletDamage);
			return missile;
		};
		LK.setTimeout(function () {
			self.missileMode = false;
			self.shoot = originalShoot;
		}, 20000); // Missile mode lasts for 20 seconds
	};
	self.activateShield = function () {
		// Logic to activate shield
		console.log("Shield activated for player!");
		var shieldGraphic = self.attachAsset('shieldEffect', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		shieldGraphic.alpha = 0.5; // Make the shield semi-transparent
		self.addChild(shieldGraphic);
		// Add shield effect next to health bar
		var shieldBar = LK.getAsset('shieldEffect', {
			anchorX: 0,
			anchorY: 0.5
		});
		LK.gui.bottomLeft.addChild(shieldBar);
		shieldBar.x = healthBar.x + healthBar.width + 10;
		shieldBar.y = healthBar.y;
		// Add shield countdown text next to shield effect
		var shieldCountdownText = new Text2('20', {
			size: 40,
			fill: 0xFFFFFF
		});
		shieldCountdownText.anchor.set(0, 0.5);
		LK.gui.bottomLeft.addChild(shieldCountdownText);
		shieldCountdownText.x = shieldBar.x + shieldBar.width + 10;
		shieldCountdownText.y = shieldBar.y;
		var countdown = 20;
		var countdownInterval = LK.setInterval(function () {
			countdown--;
			shieldCountdownText.setText(countdown.toString());
			if (countdown <= 0) {
				LK.clearInterval(countdownInterval);
				shieldBar.destroy();
				shieldCountdownText.destroy();
			}
		}, 1000);
		// Remove shield after 20 seconds
		LK.setTimeout(function () {
			shieldGraphic.destroy();
		}, 20000);
	};
	return self;
});
var ShieldChest = Container.expand(function (x, y) {
	var self = Container.call(this);
	var shieldChestGraphic = self.attachAsset('shieldchest', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.update = function () {
		// Make shield chest pulse
		var age = Date.now() - self.creationTime;
		var pulse = Math.sin(age / 200) * 0.2 + 1;
		self.scale.set(pulse, pulse);
		return false;
	};
	self.collect = function (player) {
		LK.getSound('pickup').play();
		// Display 'Shield Activated' text on screen
		var shieldText = new Text2('Shield Activated', {
			size: 150,
			fill: 0x000000
		});
		shieldText.anchor.set(0.5, 0.5);
		shieldText.x = 2048 / 2;
		shieldText.y = 2732 / 4; // Position higher on the screen
		game.addChild(shieldText);
		tween(shieldText, {
			alpha: 0
		}, {
			duration: 4000,
			onFinish: function onFinish() {
				shieldText.destroy();
			}
		});
		player.activateShield();
		// Display countdown timer for shield effect
		var shieldCountdownText = new Text2('20', {
			size: 60,
			fill: 0xFFFFFF
		});
		shieldCountdownText.anchor.set(1, 1);
		shieldCountdownText.x = 2048;
		shieldCountdownText.y = 2732;
		LK.gui.bottomRight.addChild(shieldCountdownText);
		// Display shield effect text in the bottom left corner
		var shieldEffectText = new Text2('Shield Active', {
			size: 60,
			fill: 0xFFFFFF
		});
		shieldEffectText.anchor.set(0, 1);
		shieldEffectText.x = 20;
		shieldEffectText.y = 2732;
		LK.gui.bottomLeft.addChild(shieldEffectText);
		var countdown = 20;
		var countdownInterval = LK.setInterval(function () {
			countdown--;
			shieldCountdownText.setText(countdown.toString());
			if (countdown <= 0) {
				LK.clearInterval(countdownInterval);
				shieldCountdownText.destroy();
				shieldEffectText.destroy(); // Remove shield effect text
			}
		}, 1000);
		self.destroy();
	};
	return self;
});
var Upgrader = Container.expand(function (x, y) {
	var self = Container.call(this);
	var upgraderGraphic = self.attachAsset('Upgrade', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.update = function () {
		// Make upgrader pulse
		var age = Date.now() - self.creationTime;
		var pulse = Math.sin(age / 200) * 0.2 + 1;
		self.scale.set(pulse, pulse);
		return false;
	};
	self.collect = function (player) {
		LK.getSound('pickup').play();
		// Display 'Rocket Upgrade' text on screen
		var rocketUpgradeText = new Text2('Rocket Upgrade', {
			size: 150,
			fill: 0x000000
		});
		rocketUpgradeText.anchor.set(0.5, 0.5);
		rocketUpgradeText.x = 2048 / 2;
		rocketUpgradeText.y = 2732 / 4; // Position higher on the screen
		game.addChild(rocketUpgradeText);
		tween(rocketUpgradeText, {
			alpha: 0
		}, {
			duration: 4000,
			onFinish: function onFinish() {
				rocketUpgradeText.destroy();
			}
		});
		player.activateMissileMode();
		self.destroy();
	};
	return self;
});
var Zombie = Container.expand(function (x, y, health, speed, damage) {
	var self = Container.call(this);
	var zombieGraphic = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add health bar background
	var healthBarBg = LK.getAsset('healthBarBg', {
		anchorX: 0.5,
		anchorY: 1.0,
		x: 0,
		y: -zombieGraphic.height / 2 - 10,
		scaleX: 0.5,
		// Reduce the width of the health bar background
		scaleY: 0.5 // Reduce the height of the health bar background
	});
	self.addChild(healthBarBg);
	// Add health bar
	var healthBar = LK.getAsset('healthBar', {
		anchorX: 0.5,
		anchorY: 1.0,
		x: 0,
		y: -zombieGraphic.height / 2 - 10,
		scaleX: 0.5,
		// Reduce the width of the health bar
		scaleY: 0.5 // Reduce the height of the health bar
	});
	self.addChild(healthBar);
	self.health = health || 30;
	self.maxHealth = self.health;
	self.speed = speed || 3; // Increased speed for regular zombies
	self.damage = damage || 10;
	self.attackCooldown = 1000; // milliseconds
	self.lastAttackTime = 0;
	self.x = x;
	self.y = y;
	self.moveTowards = function (targetX, targetY) {
		var dx = targetX - self.x;
		var dy = targetY - 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;
		}
	};
	self.attack = function (player) {
		var currentTime = Date.now();
		if (currentTime - self.lastAttackTime >= self.attackCooldown) {
			self.lastAttackTime = currentTime;
			return player.takeDamage(self.damage);
		}
		return false;
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		// Update health bar scale
		var healthPercentage = self.health / self.maxHealth;
		healthBar.scale.x = healthPercentage;
		// Flash zombie when hit
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombieHit').play();
		// Change color based on health percentage
		var healthPercentage = self.health / self.maxHealth;
		var green = Math.floor(204 * healthPercentage);
		zombieGraphic.tint = 0 << 16 | green << 8 | 0;
		if (self.health <= 0) {
			if (damage > player.bulletDamage) {
				// Check if it was a critical hit
				var criticalEffect = LK.getAsset('criticalEffect', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: self.x,
					y: self.y
				});
				game.addChild(criticalEffect);
				tween(criticalEffect, {}, {
					// Use tween to extend the duration
					duration: 500,
					// Extend duration to 500ms
					onFinish: function onFinish() {
						criticalEffect.destroy();
					}
				});
			}
			// 20% chance to trigger infinite ammo power-up
			if (Math.random() < 0.2) {
				player.infiniteAmmo = true;
				LK.setTimeout(function () {
					player.infiniteAmmo = false;
				}, 10000); // 10 seconds duration
			}
			// Remove health bar
			healthBar.destroy();
			healthBarBg.destroy();
			// Add dead zombie appearance
			var deadZombie = LK.getAsset('deathzombie', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: self.x,
				y: self.y
			});
			game.addChild(deadZombie);
			tween(deadZombie, {}, {
				duration: 2000,
				onFinish: function onFinish() {
					deadZombie.destroy();
				}
			});
			return true; // zombie died
		}
		return false; // zombie still alive
	};
	return self;
});
var SludgeZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var sludgeZombieGraphic = self.attachAsset('slimeZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 1.5; // Set speed for sludge zombies
	self.health = health || 40; // Set health for sludge zombies
	self.damage = damage || 10; // Set damage for sludge zombies
	// Override takeDamage to spawn new zombies upon death
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		var died = originalTakeDamage.call(self, damage);
		if (died) {
			for (var i = 0; i < 3; i++) {
				var newZombie = new Zombie(self.x + Math.random() * 50 - 25, self.y + Math.random() * 50 - 25, 20, 1, 5);
				zombies.push(newZombie);
				game.addChild(newZombie);
			}
		}
		return died;
	};
	return self;
});
var SlimeZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var slimeZombieGraphic = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 1.0; // Set speed for slime zombies
	self.health = health || 30; // Set health for slime zombies
	self.damage = damage || 5; // Set damage for slime zombies
	// Override takeDamage to spawn new zombies upon death
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		var died = originalTakeDamage.call(self, damage);
		if (died) {
			for (var i = 0; i < 3; i++) {
				var newZombie = new Zombie(self.x + Math.random() * 50 - 25, self.y + Math.random() * 50 - 25, 10, 0.5, 2);
				zombies.push(newZombie);
				game.addChild(newZombie);
			}
		}
		return died;
	};
	return self;
});
var SkeletonZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var skeletonZombieGraphic = self.attachAsset('skeletonZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 2.5; // Set speed for skeleton zombies
	self.health = health || 100; // Increase health for skeleton zombies to prevent one-hit kills
	self.damage = damage || 15; // Set damage for skeleton zombies
	return self;
});
var FastZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var fastZombieGraphic = self.attachAsset('fastZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 600; // Further increased speed for fast zombies
	return self;
});
var BossZombie = Zombie.expand(function (x, y, waveNumber) {
	var self = Zombie.call(this, x, y, bossHealth, bossSpeed, bossDamage);
	// Calculate boss stats based on wave number
	var bossHealth = Math.max(5000, 5000 + waveNumber * 500); // Ensure minimum health of 5000
	var bossSpeed = 12.0 + waveNumber * 1.5; // Significantly increase base speed and scaling factor for boss
	var bossDamage = 50 + waveNumber * 10;
	// Replace the zombie graphic with a boss graphic
	self.removeChild(self.getChildAt(0)); // Remove the zombie graphic
	var bossGraphic = self.attachAsset('bossZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.scoreValue = 100; // More points for killing a boss
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
function spawnSlimeZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var slimeZombie = new SlimeZombie(x, y, health, speed, damage);
	zombies.push(slimeZombie);
	game.addChild(slimeZombie);
}
function spawnSludgeZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var sludgeZombie = new SludgeZombie(x, y, health, speed, damage);
	zombies.push(sludgeZombie);
	game.addChild(sludgeZombie);
}
function spawnSkeletonZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var skeletonZombie = new SkeletonZombie(x, y, health, speed, damage);
	zombies.push(skeletonZombie);
	game.addChild(skeletonZombie);
}
function spawnFastZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var fastZombie = new FastZombie(x, y, health, speed, damage);
	zombies.push(fastZombie);
	game.addChild(fastZombie);
}
// Game state variables
var player;
var legendaryChest; // Define legendaryChest in the global scope
var obstacles = [];
var bullets = [];
var bulletHitZombies = {}; // Use a plain object to track which zombies have been hit by which bullets
var zombies = [];
var missiles = [];
var pickups = [];
var wave = 1;
var zombiesKilled = 0;
var score = 0;
var gameStartTime;
var waveStartTime;
var isWaveActive = false;
var targetPosition = {
	x: 0,
	y: 0
};
var isGameOver = false;
// UI elements
var scoreText;
var waveText;
var healthBar;
var healthBarBg;
var ammoBar;
var ammoBarBg;
var gameStatusText;
var maxScoreText; // Declare maxScoreText in the global scope
function initGame() {
	// Reset game state
	wave = 1;
	zombiesKilled = 0;
	score = 0;
	bullets = [];
	zombies = [];
	pickups = [];
	isWaveActive = false;
	isGameOver = false;
	gameStartTime = Date.now();
	// Set background
	var background = LK.getAsset('backgroundImage', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 / 2
	});
	game.addChild(background);
	background.zIndex = -1; // Ensure the background is rendered behind other elements
	// Play background music
	LK.playMusic('Ozone', {
		fade: {
			start: 0,
			end: 0.3,
			duration: 1000
		}
	});
	// Create player at center of screen
	player = new Player();
	player.infiniteAmmo = false; // Initialize infinite ammo property
	player.x = 2048 / 2;
	player.y = 2732 / 2;
	// Add max score display
	maxScoreText = new Text2('Max Score: ' + storage.highscore, {
		size: 40,
		fill: 0xFFFFFF
	});
	maxScoreText.anchor.set(0.5, 0);
	LK.gui.top.addChild(maxScoreText);
	maxScoreText.x = 0;
	maxScoreText.y = 80;
	if (player) {
		player.lastX = player.x; // Initialize lastX for tracking
		player.lastY = player.y; // Initialize lastY for tracking
	}
	game.addChild(player);
	// Add obstacles
	var obstacles = [];
	// Add barrels at random positions
	for (var i = 0; i < 5; i++) {
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		var barrel = new Barrel(randomX, randomY);
		obstacles.push(barrel);
		game.addChild(barrel);
	}
	// Create an object at the right corner of the screen
	var rightCornerObject = LK.getAsset('crate', {
		anchorX: 1.0,
		anchorY: 0.5,
		x: 2048,
		y: 1366
	});
	game.addChild(rightCornerObject);
	// Add an abandoned car to the top-right corner of the screen
	var abandonedCarTopRight = LK.getAsset('abandonedCar', {
		anchorX: 1.0,
		anchorY: 0.0,
		x: 2048,
		y: 0
	});
	game.addChild(abandonedCarTopRight);
	abandonedCarTopRight.zIndex = 1; // Ensure the car is rendered in front of the background
	// Add abandoned cars to their original positions
	for (var i = 0; i < 3; i++) {
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		var abandonedCar = LK.getAsset('abandonedCar', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: randomX,
			y: randomY
		});
		game.addChild(abandonedCar);
		abandonedCar.zIndex = 1; // Ensure the car is rendered in front of the background
	}
	// Add decorative elements to the corners
	obstacles.push(new Obstacle(150, 150, 'bush')); // Near top-left corner
	obstacles.push(new Obstacle(1898, 150, 'bush')); // Near top-right corner
	obstacles.push(new Obstacle(150, 2582, 'bush')); // Near bottom-left corner
	obstacles.push(new Obstacle(1898, 2582, 'bush')); // Near bottom-right corner
	obstacles.push(new Obstacle(150, 150, 'crate')); // Near top-left corner
	obstacles.push(new Obstacle(1898, 150, 'crate')); // Near top-right corner
	obstacles.push(new Obstacle(150, 2582, 'crate')); // Near bottom-left corner
	obstacles.push(new Obstacle(1898, 2582, 'crate')); // Near bottom-right corner
	obstacles.push(new Barrel(200, 200)); // Near top-left corner
	obstacles.push(new Barrel(1848, 200)); // Near top-right corner
	obstacles.push(new Barrel(200, 2432)); // Near bottom-left corner
	obstacles.push(new Barrel(1848, 2432)); // Near bottom-right corner
	// Add more bushes
	for (var i = 0; i < 50; i++) {
		// Increased from 20 to 50 for more bushes
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		obstacles.push(new Obstacle(randomX, randomY, 'bush'));
	}
	// Add small stone patterns
	for (var i = 0; i < 100; i++) {
		// Increased from 50 to 100 for more stones
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		obstacles.push(new Obstacle(randomX, randomY, 'stone'));
	}
	// Add more crate obstacles at random positions
	for (var i = 0; i < 10; i++) {
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		obstacles.push(new Obstacle(randomX, randomY, 'crate'));
	}
	obstacles.forEach(function (obstacle) {
		game.addChild(obstacle);
	});
	// Initialize UI
	createUI();
	// Start first wave
	startWave();
}
function createUI() {
	// Score text
	scoreText = new Text2('Score: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreText.anchor.set(0.5, 0);
	LK.gui.top.addChild(scoreText);
	scoreText.x = 0;
	scoreText.y = 20;
	// Wave text
	waveText = new Text2('Wave: 1', {
		size: 60,
		fill: 0xFFFFFF
	});
	waveText.anchor.set(0, 0);
	LK.gui.topLeft.addChild(waveText);
	waveText.x = 20;
	waveText.y = 20;
	// Game status text (wave start, game over, etc.)
	gameStatusText = new Text2('', {
		size: 100,
		fill: 0xFFFFFF
	});
	gameStatusText.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(gameStatusText);
	gameStatusText.alpha = 0;
	// Adjust gameStatusText position to be slightly below the wave text
	gameStatusText.y = waveText.y + 70;
	// Health bar background
	healthBarBg = LK.getAsset('healthBarBg', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(healthBarBg);
	healthBarBg.x = 20;
	healthBarBg.y = -50;
	// Health bar
	healthBar = LK.getAsset('healthBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(healthBar);
	healthBar.x = 20;
	healthBar.y = -50;
	// Ammo bar background
	ammoBarBg = LK.getAsset('ammoBarBg', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(ammoBarBg);
	ammoBarBg.x = 20;
	ammoBarBg.y = -100;
	// Ammo bar
	ammoBar = LK.getAsset('ammoBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(ammoBar);
	ammoBar.x = 20;
	ammoBar.y = -100;
	// Game status text (wave start, game over, etc.)
	gameStatusText = new Text2('', {
		size: 100,
		fill: 0xFFFFFF
	});
	gameStatusText.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(gameStatusText);
	gameStatusText.alpha = 0;
}
function updateUI() {
	// Update score
	scoreText.setText('Score: ' + score);
	// Update player name and score display
	player.getChildAt(0).text = 'Player ' + (Math.floor(Math.random() * 1000) + 1) + ' | Score: ' + score;
	// Update max score display
	maxScoreText.setText('Max Score: ' + storage.highscore);
	// Update wave
	waveText.setText('Wave: ' + wave);
	// Update health bar
	var healthPercent = player.health / player.maxHealth;
	healthBar.scale.x = healthPercent;
	// Update ammo bar
	var ammoPercent = player.ammo / player.maxAmmo;
	ammoBar.scale.x = ammoPercent;
	// Change ammo bar color when reloading
	if (player.isReloading) {
		ammoBar.tint = 0xff6600;
	} else {
		ammoBar.tint = 0xcc9900;
	}
}
function startWave() {
	waveStartTime = Date.now();
	isWaveActive = false;
	// Display countdown before wave starts
	var countdown = 7;
	gameStatusText.setText('Wave ' + wave + ' in ' + countdown);
	gameStatusText.alpha = 1;
	var countdownInterval = LK.setInterval(function () {
		countdown--;
		if (countdown > 0) {
			gameStatusText.setText('Wave ' + wave + ' in ' + countdown);
		} else {
			LK.clearInterval(countdownInterval);
			isWaveActive = true;
			gameStatusText.setText('WAVE ' + wave);
			tween(gameStatusText, {
				alpha: 0
			}, {
				duration: 1500,
				easing: tween.easeIn
			});
			LK.getSound('newWave').play();
			// Randomly spawn a ShieldChest or Upgrader
			if (Math.random() < 0.5) {
				var shieldChest = new ShieldChest(Math.random() * 2048, Math.random() * 2732);
				game.addChild(shieldChest);
				pickups.push(shieldChest);
			} else {
				var upgrader = new Upgrader(Math.random() * 2048, Math.random() * 2732);
				game.addChild(upgrader);
				pickups.push(upgrader);
			}
		}
	}, 1000);
	// Spawn zombies based on wave number
	var zombieCount = wave === 1 ? 10 : wave === 2 ? 3 : wave === 3 ? 4 : 5 + wave * 2; // Increased zombie count for wave 1
	var zombieHealth = wave === 1 ? 20 : wave === 2 ? 25 : wave === 3 ? 30 : 30 + wave * 5; // Reduced health for first three waves
	var zombieSpeed = wave === 1 ? 1.0 : wave === 2 ? 1.1 : wave === 3 ? 1.2 : 2 + wave * 0.1; // Reduced speed for first three waves
	var zombieDamage = wave === 1 ? 3 : wave === 2 ? 4 : wave === 3 ? 5 : 10 + wave * 2; // Reduced damage for first three waves
	// Schedule zombie spawns over time
	// Delay zombie spawning until countdown is complete
	var spawnInterval = LK.setInterval(function () {
		if (isWaveActive && zombies.length < zombieCount) {
			if (wave >= 3 && Math.random() < 0.3 + wave * 0.05) {
				// Increase chance to spawn a sludge zombie as waves progress
				spawnSludgeZombie(zombieHealth, zombieSpeed, zombieDamage);
			} else if (Math.random() < 0.2 - wave * 0.01) {
				// Decrease chance to spawn a skeleton zombie initially, but increase as waves progress
				spawnSkeletonZombie(zombieHealth, zombieSpeed, zombieDamage);
			} else if (Math.random() < 0.2) {
				// 20% chance to spawn a fast zombie
				spawnFastZombie(zombieHealth, zombieSpeed * 2, zombieDamage); // Double the speed for fast zombies
			} else {
				spawnZombie(zombieHealth, zombieSpeed, zombieDamage);
			}
		} else if (zombies.length >= zombieCount) {
			LK.clearInterval(spawnInterval);
		}
	}, 500);
	// Spawn a boss every 5 waves
	if (wave % 5 === 0) {
		LK.setTimeout(function () {
			spawnBossZombie();
		}, 5000);
	}
}
function spawnZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			// top
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			// right
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			// bottom
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			// left
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var zombie = new Zombie(x, y, health, speed, damage);
	zombies.push(zombie);
	game.addChild(zombie);
}
function spawnBossZombie() {
	// Spawn boss at a random edge
	var edge = Math.floor(Math.random() * 4);
	var x, y;
	switch (edge) {
		case 0:
			// top
			x = Math.random() * 2048;
			y = -150;
			break;
		case 1:
			// right
			x = 2048 + 150;
			y = Math.random() * 2732;
			break;
		case 2:
			// bottom
			x = Math.random() * 2048;
			y = 2732 + 150;
			break;
		case 3:
			// left
			x = -150;
			y = Math.random() * 2732;
			break;
	}
	var boss = new BossZombie(x, y, wave);
	zombies.push(boss);
	game.addChild(boss);
	// Play boss appear sound
	LK.getSound('bossAppear').play();
	// Show boss alert
	gameStatusText.setText('BOSS ZOMBIE APPEARED!');
	gameStatusText.alpha = 1;
	tween(gameStatusText, {
		alpha: 0
	}, {
		duration: 2000,
		easing: tween.easeIn
	});
}
function spawnPickup(x, y) {
	// 30% chance for health, 70% for ammo
	var type = Math.random() < 0.3 ? 'health' : 'ammo';
	var pickup = new Pickup(x, y, type);
	pickups.push(pickup);
	game.addChild(pickup);
}
function checkWaveCompletion() {
	if (isWaveActive && zombies.length === 0 && !isGameOver && zombiesKilled >= 3 + wave) {
		isWaveActive = false;
		// Display wave complete message
		gameStatusText.setText('WAVE ' + wave + ' COMPLETE!');
		gameStatusText.alpha = 1;
		// Give player a weapon upgrade every 3 waves
		if (wave % 3 === 0) {
			player.upgradeWeapon();
			// Show upgrade message
			LK.setTimeout(function () {
				gameStatusText.setText('WEAPON UPGRADED!');
			}, 2000);
		}
		// Spawn crates as objects after wave completion
		for (var i = 0; i < 5; i++) {
			var randomX = Math.random() * 2048;
			var randomY = Math.random() * 2732;
			var crate = new Obstacle(randomX, randomY, 'crate');
			obstacles.push(crate);
			game.addChild(crate);
		}
		// Spawn barrels at the end of each wave
		for (var i = 0; i < 3; i++) {
			var randomX = Math.random() * 2048;
			var randomY = Math.random() * 2732;
			var barrel = new Barrel(randomX, randomY);
			obstacles.push(barrel);
			game.addChild(barrel);
		}
		// Start next wave after a 5-second delay
		LK.setTimeout(function () {
			wave++;
			gameStatusText.alpha = 0;
			startWave();
		}, 5000);
	}
}
// Event handling
game.down = function (x, y) {
	if (isGameOver) {
		return;
	}
	targetPosition.x = x;
	targetPosition.y = y;
	// Player shoots at clicked position
	var bullet = player.shoot(x, y);
	if (bullet) {
		bullets.push(bullet);
		game.addChild(bullet);
	}
};
game.move = function (x, y) {
	targetPosition.x = x;
	targetPosition.y = y;
};
game.up = function () {
	// Not needed for this game
};
// Main game update loop
game.update = function () {
	if (isGameOver) {
		return;
	}
	// Check for player collision with obstacles
	obstacles.forEach(function (obstacle) {
		if (player.intersects(obstacle) && obstacle.type !== 'crate') {
			// Prevent player from moving through the obstacle, except crates
			player.x = player.lastX;
			player.y = player.lastY;
		}
	});
	// Update player movement
	if (player) {
		player.lastX = player.x; // Track lastX before moving
		player.lastY = player.y; // Track lastY before moving
		player.moveTowards(targetPosition.x, targetPosition.y);
		// Check if player is near the legendary chest
		if (!player.nearLegendaryChest && player.intersects(legendaryChest)) {
			player.nearLegendaryChest = true;
			player.legendaryChestTimer = Date.now();
		} else if (player.nearLegendaryChest && !player.intersects(legendaryChest)) {
			player.nearLegendaryChest = false;
			player.legendaryChestTimer = null;
		}
		// Open the legendary chest if the player stands next to it for 3 seconds
		if (player.nearLegendaryChest && Date.now() - player.legendaryChestTimer >= 3000) {
			// Logic to open the chest
			console.log("Legendary chest opened!");
			legendaryChest.destroy();
			legendaryChest = null; // Set legendaryChest to null after destroying it
			// Change appearance to legendary2
			var legendary2 = LK.getAsset('legendary2', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: 2048 / 2,
				y: 2732 / 2,
				visible: true // Make legendary2 visible
			});
			game.addChild(legendary2);
			// Randomly decide to spawn an upgrader or shield chest
			if (Math.random() < 0.5) {
				var upgrader = new Upgrader(2048 / 2, 2732 / 2);
				game.addChild(upgrader);
				pickups.push(upgrader);
			} else {
				var shieldChest = new ShieldChest(2048 / 2, 2732 / 2);
				game.addChild(shieldChest);
				pickups.push(shieldChest);
			}
			player.nearLegendaryChest = false;
			player.legendaryChestTimer = null;
		}
		// Regenerate health slowly if not at max health
		if (player.health < player.maxHealth) {
			player.health = Math.min(player.maxHealth, player.health + 0.05); // Regenerate 0.05 health per update
		}
	}
	// Update bullets
	for (var i = bullets.length - 1; i >= 0; i--) {
		var shouldRemove = bullets[i].update();
		if (shouldRemove) {
			bullets[i].destroy();
			bullets.splice(i, 1);
			continue;
		}
		// Check bullet collision with zombies
		for (var j = zombies.length - 1; j >= 0; j--) {
			if (bullets[i] && bullets[i].intersects(zombies[j])) {
				// Display bullet effect at the point of impact
				var bulletEffect = LK.getAsset('bulleteffect', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: bullets[i].x,
					y: bullets[i].y
				});
				game.addChild(bulletEffect);
				tween(bulletEffect, {}, {
					duration: 200,
					onFinish: function onFinish() {
						bulletEffect.destroy();
					}
				});
				// Check if this bullet has already hit this zombie
				if (!bulletHitZombies[bullets[i]]) {
					bulletHitZombies[bullets[i]] = [];
				}
				if (!bulletHitZombies[bullets[i]].includes(zombies[j])) {
					bulletHitZombies[bullets[i]].push(zombies[j]);
					var zombieDied = zombies[j].takeDamage(bullets[i].damage);
					// Remove bullet after hit
					bullets[i].destroy();
					bullets.splice(i, 1);
					if (zombieDied) {
						// Increase score and zombie kill counter
						var scoreToAdd = zombies[j] instanceof BossZombie ? 100 : 10;
						score += scoreToAdd;
						zombiesKilled++;
						// Chance to drop pickup
						if (Math.random() < 0.3) {
							spawnPickup(zombies[j].x, zombies[j].y);
						}
						// Remove zombie
						zombies[j].destroy();
						zombies.splice(j, 1);
					}
					break;
				}
			}
		}
	}
	// Update obstacles
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var shouldRemove = obstacles[i].update();
		if (shouldRemove) {
			obstacles[i].destroy();
			obstacles.splice(i, 1);
		}
	}
	// Update zombies
	for (var i = zombies.length - 1; i >= 0; i--) {
		// Move zombie towards player
		zombies[i].moveTowards(player.x, player.y);
		// Check if zombie reached player
		if (zombies[i].intersects(player)) {
			var playerDied = zombies[i].attack(player);
			if (playerDied) {
				handleGameOver();
			}
		}
	}
	for (var i = pickups.length - 1; i >= 0; i--) {
		var shouldRemove = pickups[i].update();
		if (shouldRemove) {
			pickups[i].destroy();
			pickups.splice(i, 1);
			continue;
		}
		// Check if player collects pickup
		if (player.intersects(pickups[i])) {
			pickups[i].collect(player);
			pickups[i].destroy();
			pickups.splice(i, 1);
		}
	}
	// Update UI
	updateUI();
	// Spawn bomb in red area every 10 seconds, only if wave is active
	if (isWaveActive && LK.ticks % 600 === 0) {
		var bombX = Math.random() * 2048;
		var bombY = Math.random() * 2732;
		var bomb = new Bomb(bombX, bombY);
		game.addChild(bomb);
		// Trigger explosion after 3 seconds
		LK.setTimeout(function () {
			bomb.explode();
		}, 3000);
	}
	// Check if wave is complete
	checkWaveCompletion();
	// Auto-reload when empty and not already reloading
	if (player.ammo === 0 && !player.isReloading) {
		player.reload();
	}
};
function handleGameOver() {
	isGameOver = true;
	// Fade out background music
	LK.playMusic('gameMusic', {
		fade: {
			start: 0.3,
			end: 0,
			duration: 1000
		}
	});
	// Update high score if needed
	if (score > storage.highscore) {
		storage.highscore = score;
	}
	// Show score in game over dialog
	LK.setScore(score);
	// Show game over screen after a short delay
	LK.setTimeout(function () {
		LK.showGameOver();
	}, 1000);
}
initGame(); // Start the game immediately /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highscore: 0,
	weaponLevel: 1
});
/**** 
* Classes
****/ 
var Barrel = Container.expand(function (x, y) {
	var self = Container.call(this);
	var barrelGraphic = self.attachAsset('barrel', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.update = function () {
		for (var i = bullets.length - 1; i >= 0; i--) {
			if (bullets[i].intersects(self)) {
				bullets[i].destroy();
				bullets.splice(i, 1);
				self.explode();
				return true;
			}
		}
		return false;
	};
	self.explode = function () {
		// Check for zombies in explosion area
		LK.getSound('explode').play();
		zombies.forEach(function (zombie) {
			if (zombie.intersects(self)) {
				if (zombie.takeDamage(100)) {
					// Inflict damage to zombie and check if it dies
					zombies.splice(zombies.indexOf(zombie), 1); // Remove zombie from the array if it dies
					zombie.destroy(); // Destroy the zombie
				}
			}
		});
		var explosion = LK.getAsset('explosionEffect', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y
		});
		game.addChild(explosion);
		tween(explosion, {}, {
			duration: 500,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		self.destroy();
	};
	return self;
});
var Bomb = Container.expand(function (x, y) {
	var self = Container.call(this);
	var bombGraphic = self.attachAsset('smallBomb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.explode = function () {
		// Check for player in red area
		LK.getSound('explode').play();
		if (player.intersects(self)) {
			player.takeDamage(100); // Inflict damage to player
		}
		// Check for zombies in red area
		zombies.forEach(function (zombie) {
			if (zombie.intersects(self)) {
				if (zombie.takeDamage(100)) {
					// Inflict damage to zombie and check if it dies
					zombies.splice(zombies.indexOf(zombie), 1); // Remove zombie from the array if it dies
					zombie.destroy(); // Destroy the zombie
				}
			}
		});
		// Check for crates in red area
		obstacles.forEach(function (obstacle) {
			if (obstacle.type === 'crate' && obstacle.intersects(self)) {
				obstacle.destroy(); // Destroy the crate
				obstacles.splice(obstacles.indexOf(obstacle), 1); // Remove crate from the array
			}
		});
		// Add explosion effect
		var explosion = LK.getAsset('explosionEffect', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y
		});
		game.addChild(explosion);
		tween(explosion, {}, {
			duration: 500,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		self.destroy(); // Remove bomb after explosion
	};
	return self;
});
var Bullet = Container.expand(function (startX, startY, targetX, targetY, damage) {
	var self = Container.call(this);
	var bulletGraphic = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 15;
	self.damage = damage || 10;
	// Calculate direction vector
	var dx = targetX - startX;
	var dy = targetY - startY;
	var distance = Math.sqrt(dx * dx + dy * dy);
	self.vx = dx / distance * self.speed;
	self.vy = dy / distance * self.speed;
	self.x = startX;
	self.y = startY;
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		bulletGraphic.rotation = Math.atan2(self.vy, self.vx);
		// Check if bullet is out of bounds
		if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
			return true; // Remove bullet 
		}
		// Check proximity to barrels
		for (var i = 0; i < obstacles.length; i++) {
			if (obstacles[i] instanceof Barrel && Math.abs(self.x - obstacles[i].x) < 50 && Math.abs(self.y - obstacles[i].y) < 50) {
				return true; // Remove bullet
			}
		}
		// Check proximity to zombies
		for (var j = 0; j < zombies.length; j++) {
			if (Math.abs(self.x - zombies[j].x) < 50 && Math.abs(self.y - zombies[j].y) < 50) {
				return true; // Remove bullet
			}
		}
		return false;
	};
	return self;
});
var Missile = Container.expand(function (startX, startY, targetX, targetY, damage) {
	var self = Container.call(this);
	var missileGraphic = self.attachAsset('missile', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10;
	self.damage = damage || 20;
	var dx = targetX - startX;
	var dy = targetY - startY;
	var distance = Math.sqrt(dx * dx + dy * dy);
	self.vx = dx / distance * self.speed;
	self.vy = dy / distance * self.speed;
	self.x = startX;
	self.y = startY;
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		missileGraphic.rotation = Math.atan2(self.vy, self.vx);
		if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
			return true;
		}
		// Check for collision with zombies
		for (var j = 0; j < zombies.length; j++) {
			if (self.intersects(zombies[j])) {
				// Trigger explosion effect
				self.explode();
				return true; // Remove missile
			}
		}
		return false;
	};
	self.explode = function () {
		// Play explosion sound
		LK.getSound('explode').play();
		// Check for zombies in explosion area
		zombies.forEach(function (zombie) {
			if (zombie.intersects(self)) {
				if (zombie.takeDamage(self.damage)) {
					// Remove zombie if it dies
					zombies.splice(zombies.indexOf(zombie), 1);
					zombie.destroy();
				}
			}
		});
		// Add explosion effect
		var explosion = LK.getAsset('explosionEffect', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y
		});
		game.addChild(explosion);
		tween(explosion, {}, {
			duration: 500,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		// Destroy the missile after explosion
		self.destroy();
	};
	return self;
});
var Obstacle = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	var obstacleGraphic = self.attachAsset(type === 'stone' ? 'stone' : type === 'crate' ? 'crate' : 'bush', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = type; // Store the type of obstacle
	self.update = function () {
		// Check for bullet collision with crate
		if (self.type === 'crate') {
			for (var i = bullets.length - 1; i >= 0; i--) {
				if (bullets[i].intersects(self)) {
					// Display bullet effect at the point of impact
					var bulletEffect = LK.getAsset('bulleteffect', {
						anchorX: 0.5,
						anchorY: 0.5,
						x: bullets[i].x,
						y: bullets[i].y
					});
					game.addChild(bulletEffect);
					tween(bulletEffect, {}, {
						duration: 200,
						onFinish: function onFinish() {
							bulletEffect.destroy();
						}
					});
					bullets[i].destroy();
					bullets.splice(i, 1);
					// 50% chance to drop a pickup when crate is destroyed
					if (Math.random() < 0.5) {
						spawnPickup(self.x, self.y);
					}
					self.destroy();
					return true; // Remove crate
				}
			}
		}
		return false;
	};
	self.spawnPickup = spawnPickup; // Make spawnPickup accessible
	return self;
});
var Pickup = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	var pickupGraphic = self.attachAsset(type === 'health' ? 'healthPack' : 'ammoBox', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = type; // 'health' or 'ammo'
	self.x = x;
	self.y = y;
	self.lifespan = 10000; // milliseconds until pickup disappears
	self.creationTime = Date.now();
	self.update = function () {
		// Make pickup pulse
		var age = Date.now() - self.creationTime;
		var pulse = Math.sin(age / 200) * 0.2 + 1;
		self.scale.set(pulse, pulse);
		// Check if pickup should expire
		if (age > self.lifespan) {
			return true; // Remove pickup
		}
		return false;
	};
	self.collect = function (player) {
		LK.getSound('pickup').play();
		if (self.type === 'health') {
			player.heal(25);
		} else if (self.type === 'ammo') {
			player.ammo = player.maxAmmo;
		}
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerWalkingGraphic = self.attachAsset('player1', {
		// Walking animation
		anchorX: 0.5,
		anchorY: 0.5
	});
	var playerIdleGraphic = self.attachAsset('player', {
		// Idle animation
		anchorX: 0.5,
		anchorY: 0.5
	});
	playerIdleGraphic.visible = true; // Start with idle animation
	playerWalkingGraphic.visible = false; // Hide walking animation initially
	self.health = 100;
	self.maxHealth = 100;
	self.ammo = 30;
	self.maxAmmo = 30;
	self.reloadTime = 1000; // milliseconds
	self.isReloading = false;
	self.speed = 7;
	self.weaponLevel = storage.weaponLevel || 0.5; // Reduced initial weapon level
	self.bulletDamage = 10 * self.weaponLevel; // Adjusted bullet damage to prevent one-hit kills in wave 1 
	self.lastShotTime = 0;
	self.shootDelay = 300; // milliseconds between shots
	self.moveTowards = function (targetX, targetY) {
		var dx = targetX - self.x;
		var dy = targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Play walking sound if player is moving
		if (distance > 0) {
			LK.getSound('walk').play();
			if (!self.walkingTimeout) {
				self.walkingTimeout = LK.setTimeout(function () {
					playerWalkingGraphic.visible = true; // Show walking animation
					playerIdleGraphic.visible = false; // Hide idle animation
				}, 2000);
			}
		} else {
			playerWalkingGraphic.visible = false; // Hide walking animation
			playerIdleGraphic.visible = true; // Show idle animation
			if (self.walkingTimeout) {
				LK.clearTimeout(self.walkingTimeout);
				self.walkingTimeout = null;
			}
		}
		if (distance > self.speed) {
			self.x += dx / distance * self.speed;
			self.y += dy / distance * self.speed;
		} else {
			self.x = targetX;
			self.y = targetY;
		}
		// Keep player within bounds
		self.x = Math.max(50, Math.min(2048 - 50, self.x));
		self.y = Math.max(50, Math.min(2732 - 50, self.y));
	};
	self.shoot = function (targetX, targetY) {
		var currentTime = Date.now();
		if (!self.infiniteAmmo && self.ammo <= 0) {
			self.reload();
			return null;
		}
		if (self.isReloading) {
			return null;
		}
		if (currentTime - self.lastShotTime < self.shootDelay) {
			return null;
		}
		self.lastShotTime = currentTime;
		self.ammo--;
		LK.getSound('shoot').play();
		LK.getSound('shoot').play();
		// Switch to player2 appearance when shooting
		playerIdleGraphic.visible = false;
		playerWalkingGraphic.visible = false;
		var playerShootingGraphic = self.attachAsset('player2', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.addChild(playerShootingGraphic);
		// Revert back to idle or walking appearance after shooting
		LK.setTimeout(function () {
			playerShootingGraphic.destroy();
			if (self.vx !== 0 || self.vy !== 0) {
				playerWalkingGraphic.visible = true;
			} else {
				playerIdleGraphic.visible = true;
			}
		}, self.shootDelay);
		// 25% chance for a critical hit
		var criticalHit = Math.random() < 0.25;
		var damage = criticalHit ? self.bulletDamage * 2 : self.bulletDamage;
		var bullet = new Bullet(self.x, self.y, targetX, targetY, damage);
		// Removed critical effect display
		return bullet;
	};
	self.reload = function () {
		if (!self.isReloading && self.ammo < self.maxAmmo) {
			self.isReloading = true;
			LK.setTimeout(function () {
				self.ammo = self.maxAmmo;
				self.isReloading = false;
			}, self.reloadTime);
		}
	};
	self.takeDamage = function (damage) {
		if (self.children.some(function (child) {
			return child.name === 'shieldEffect';
		})) {
			// If shield is active, prevent damage
			return false;
		}
		LK.getSound('playerHit').play();
		LK.effects.flashObject(self, 0xff0000, 300);
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			return true; // player died
		}
		return false; // player still alive
	};
	self.heal = function (amount) {
		self.health = Math.min(self.maxHealth, self.health + amount);
	};
	self.upgradeWeapon = function () {
		self.weaponLevel++;
		self.bulletDamage = 10 * self.weaponLevel;
		storage.weaponLevel = self.weaponLevel;
	};
	self.activateMissileMode = function () {
		var originalShoot = self.shoot; // Store the original shoot function
		self.missileMode = true;
		self.shoot = function (targetX, targetY) {
			var currentTime = Date.now();
			if (!self.infiniteAmmo && self.ammo <= 0) {
				self.reload();
				return null;
			}
			if (self.isReloading) {
				return null;
			}
			if (currentTime - self.lastShotTime < self.shootDelay) {
				return null;
			}
			self.lastShotTime = currentTime;
			self.ammo--;
			LK.getSound('shoot').play();
			var missile = new Missile(self.x, self.y, targetX, targetY, self.bulletDamage);
			return missile;
		};
		LK.setTimeout(function () {
			self.missileMode = false;
			self.shoot = originalShoot;
		}, 20000); // Missile mode lasts for 20 seconds
	};
	self.activateShield = function () {
		// Logic to activate shield
		console.log("Shield activated for player!");
		var shieldGraphic = self.attachAsset('shieldEffect', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		shieldGraphic.alpha = 0.5; // Make the shield semi-transparent
		self.addChild(shieldGraphic);
		// Add shield effect next to health bar
		var shieldBar = LK.getAsset('shieldEffect', {
			anchorX: 0,
			anchorY: 0.5
		});
		LK.gui.bottomLeft.addChild(shieldBar);
		shieldBar.x = healthBar.x + healthBar.width + 10;
		shieldBar.y = healthBar.y;
		// Add shield countdown text next to shield effect
		var shieldCountdownText = new Text2('20', {
			size: 40,
			fill: 0xFFFFFF
		});
		shieldCountdownText.anchor.set(0, 0.5);
		LK.gui.bottomLeft.addChild(shieldCountdownText);
		shieldCountdownText.x = shieldBar.x + shieldBar.width + 10;
		shieldCountdownText.y = shieldBar.y;
		var countdown = 20;
		var countdownInterval = LK.setInterval(function () {
			countdown--;
			shieldCountdownText.setText(countdown.toString());
			if (countdown <= 0) {
				LK.clearInterval(countdownInterval);
				shieldBar.destroy();
				shieldCountdownText.destroy();
			}
		}, 1000);
		// Remove shield after 20 seconds
		LK.setTimeout(function () {
			shieldGraphic.destroy();
		}, 20000);
	};
	return self;
});
var ShieldChest = Container.expand(function (x, y) {
	var self = Container.call(this);
	var shieldChestGraphic = self.attachAsset('shieldchest', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.update = function () {
		// Make shield chest pulse
		var age = Date.now() - self.creationTime;
		var pulse = Math.sin(age / 200) * 0.2 + 1;
		self.scale.set(pulse, pulse);
		return false;
	};
	self.collect = function (player) {
		LK.getSound('pickup').play();
		// Display 'Shield Activated' text on screen
		var shieldText = new Text2('Shield Activated', {
			size: 150,
			fill: 0x000000
		});
		shieldText.anchor.set(0.5, 0.5);
		shieldText.x = 2048 / 2;
		shieldText.y = 2732 / 4; // Position higher on the screen
		game.addChild(shieldText);
		tween(shieldText, {
			alpha: 0
		}, {
			duration: 4000,
			onFinish: function onFinish() {
				shieldText.destroy();
			}
		});
		player.activateShield();
		// Display countdown timer for shield effect
		var shieldCountdownText = new Text2('20', {
			size: 60,
			fill: 0xFFFFFF
		});
		shieldCountdownText.anchor.set(1, 1);
		shieldCountdownText.x = 2048;
		shieldCountdownText.y = 2732;
		LK.gui.bottomRight.addChild(shieldCountdownText);
		// Display shield effect text in the bottom left corner
		var shieldEffectText = new Text2('Shield Active', {
			size: 60,
			fill: 0xFFFFFF
		});
		shieldEffectText.anchor.set(0, 1);
		shieldEffectText.x = 20;
		shieldEffectText.y = 2732;
		LK.gui.bottomLeft.addChild(shieldEffectText);
		var countdown = 20;
		var countdownInterval = LK.setInterval(function () {
			countdown--;
			shieldCountdownText.setText(countdown.toString());
			if (countdown <= 0) {
				LK.clearInterval(countdownInterval);
				shieldCountdownText.destroy();
				shieldEffectText.destroy(); // Remove shield effect text
			}
		}, 1000);
		self.destroy();
	};
	return self;
});
var Upgrader = Container.expand(function (x, y) {
	var self = Container.call(this);
	var upgraderGraphic = self.attachAsset('Upgrade', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.update = function () {
		// Make upgrader pulse
		var age = Date.now() - self.creationTime;
		var pulse = Math.sin(age / 200) * 0.2 + 1;
		self.scale.set(pulse, pulse);
		return false;
	};
	self.collect = function (player) {
		LK.getSound('pickup').play();
		// Display 'Rocket Upgrade' text on screen
		var rocketUpgradeText = new Text2('Rocket Upgrade', {
			size: 150,
			fill: 0x000000
		});
		rocketUpgradeText.anchor.set(0.5, 0.5);
		rocketUpgradeText.x = 2048 / 2;
		rocketUpgradeText.y = 2732 / 4; // Position higher on the screen
		game.addChild(rocketUpgradeText);
		tween(rocketUpgradeText, {
			alpha: 0
		}, {
			duration: 4000,
			onFinish: function onFinish() {
				rocketUpgradeText.destroy();
			}
		});
		player.activateMissileMode();
		self.destroy();
	};
	return self;
});
var Zombie = Container.expand(function (x, y, health, speed, damage) {
	var self = Container.call(this);
	var zombieGraphic = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add health bar background
	var healthBarBg = LK.getAsset('healthBarBg', {
		anchorX: 0.5,
		anchorY: 1.0,
		x: 0,
		y: -zombieGraphic.height / 2 - 10,
		scaleX: 0.5,
		// Reduce the width of the health bar background
		scaleY: 0.5 // Reduce the height of the health bar background
	});
	self.addChild(healthBarBg);
	// Add health bar
	var healthBar = LK.getAsset('healthBar', {
		anchorX: 0.5,
		anchorY: 1.0,
		x: 0,
		y: -zombieGraphic.height / 2 - 10,
		scaleX: 0.5,
		// Reduce the width of the health bar
		scaleY: 0.5 // Reduce the height of the health bar
	});
	self.addChild(healthBar);
	self.health = health || 30;
	self.maxHealth = self.health;
	self.speed = speed || 3; // Increased speed for regular zombies
	self.damage = damage || 10;
	self.attackCooldown = 1000; // milliseconds
	self.lastAttackTime = 0;
	self.x = x;
	self.y = y;
	self.moveTowards = function (targetX, targetY) {
		var dx = targetX - self.x;
		var dy = targetY - 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;
		}
	};
	self.attack = function (player) {
		var currentTime = Date.now();
		if (currentTime - self.lastAttackTime >= self.attackCooldown) {
			self.lastAttackTime = currentTime;
			return player.takeDamage(self.damage);
		}
		return false;
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		// Update health bar scale
		var healthPercentage = self.health / self.maxHealth;
		healthBar.scale.x = healthPercentage;
		// Flash zombie when hit
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombieHit').play();
		// Change color based on health percentage
		var healthPercentage = self.health / self.maxHealth;
		var green = Math.floor(204 * healthPercentage);
		zombieGraphic.tint = 0 << 16 | green << 8 | 0;
		if (self.health <= 0) {
			if (damage > player.bulletDamage) {
				// Check if it was a critical hit
				var criticalEffect = LK.getAsset('criticalEffect', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: self.x,
					y: self.y
				});
				game.addChild(criticalEffect);
				tween(criticalEffect, {}, {
					// Use tween to extend the duration
					duration: 500,
					// Extend duration to 500ms
					onFinish: function onFinish() {
						criticalEffect.destroy();
					}
				});
			}
			// 20% chance to trigger infinite ammo power-up
			if (Math.random() < 0.2) {
				player.infiniteAmmo = true;
				LK.setTimeout(function () {
					player.infiniteAmmo = false;
				}, 10000); // 10 seconds duration
			}
			// Remove health bar
			healthBar.destroy();
			healthBarBg.destroy();
			// Add dead zombie appearance
			var deadZombie = LK.getAsset('deathzombie', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: self.x,
				y: self.y
			});
			game.addChild(deadZombie);
			tween(deadZombie, {}, {
				duration: 2000,
				onFinish: function onFinish() {
					deadZombie.destroy();
				}
			});
			return true; // zombie died
		}
		return false; // zombie still alive
	};
	return self;
});
var SludgeZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var sludgeZombieGraphic = self.attachAsset('slimeZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 1.5; // Set speed for sludge zombies
	self.health = health || 40; // Set health for sludge zombies
	self.damage = damage || 10; // Set damage for sludge zombies
	// Override takeDamage to spawn new zombies upon death
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		var died = originalTakeDamage.call(self, damage);
		if (died) {
			for (var i = 0; i < 3; i++) {
				var newZombie = new Zombie(self.x + Math.random() * 50 - 25, self.y + Math.random() * 50 - 25, 20, 1, 5);
				zombies.push(newZombie);
				game.addChild(newZombie);
			}
		}
		return died;
	};
	return self;
});
var SlimeZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var slimeZombieGraphic = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 1.0; // Set speed for slime zombies
	self.health = health || 30; // Set health for slime zombies
	self.damage = damage || 5; // Set damage for slime zombies
	// Override takeDamage to spawn new zombies upon death
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		var died = originalTakeDamage.call(self, damage);
		if (died) {
			for (var i = 0; i < 3; i++) {
				var newZombie = new Zombie(self.x + Math.random() * 50 - 25, self.y + Math.random() * 50 - 25, 10, 0.5, 2);
				zombies.push(newZombie);
				game.addChild(newZombie);
			}
		}
		return died;
	};
	return self;
});
var SkeletonZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var skeletonZombieGraphic = self.attachAsset('skeletonZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 2.5; // Set speed for skeleton zombies
	self.health = health || 100; // Increase health for skeleton zombies to prevent one-hit kills
	self.damage = damage || 15; // Set damage for skeleton zombies
	return self;
});
var FastZombie = Zombie.expand(function (x, y, health, speed, damage) {
	var self = Zombie.call(this, x, y, health, speed, damage);
	self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
	var fastZombieGraphic = self.attachAsset('fastZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = speed || 600; // Further increased speed for fast zombies
	return self;
});
var BossZombie = Zombie.expand(function (x, y, waveNumber) {
	var self = Zombie.call(this, x, y, bossHealth, bossSpeed, bossDamage);
	// Calculate boss stats based on wave number
	var bossHealth = Math.max(5000, 5000 + waveNumber * 500); // Ensure minimum health of 5000
	var bossSpeed = 12.0 + waveNumber * 1.5; // Significantly increase base speed and scaling factor for boss
	var bossDamage = 50 + waveNumber * 10;
	// Replace the zombie graphic with a boss graphic
	self.removeChild(self.getChildAt(0)); // Remove the zombie graphic
	var bossGraphic = self.attachAsset('bossZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.scoreValue = 100; // More points for killing a boss
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
function spawnSlimeZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var slimeZombie = new SlimeZombie(x, y, health, speed, damage);
	zombies.push(slimeZombie);
	game.addChild(slimeZombie);
}
function spawnSludgeZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var sludgeZombie = new SludgeZombie(x, y, health, speed, damage);
	zombies.push(sludgeZombie);
	game.addChild(sludgeZombie);
}
function spawnSkeletonZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var skeletonZombie = new SkeletonZombie(x, y, health, speed, damage);
	zombies.push(skeletonZombie);
	game.addChild(skeletonZombie);
}
function spawnFastZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var fastZombie = new FastZombie(x, y, health, speed, damage);
	zombies.push(fastZombie);
	game.addChild(fastZombie);
}
// Game state variables
var player;
var legendaryChest; // Define legendaryChest in the global scope
var obstacles = [];
var bullets = [];
var bulletHitZombies = {}; // Use a plain object to track which zombies have been hit by which bullets
var zombies = [];
var missiles = [];
var pickups = [];
var wave = 1;
var zombiesKilled = 0;
var score = 0;
var gameStartTime;
var waveStartTime;
var isWaveActive = false;
var targetPosition = {
	x: 0,
	y: 0
};
var isGameOver = false;
// UI elements
var scoreText;
var waveText;
var healthBar;
var healthBarBg;
var ammoBar;
var ammoBarBg;
var gameStatusText;
var maxScoreText; // Declare maxScoreText in the global scope
function initGame() {
	// Reset game state
	wave = 1;
	zombiesKilled = 0;
	score = 0;
	bullets = [];
	zombies = [];
	pickups = [];
	isWaveActive = false;
	isGameOver = false;
	gameStartTime = Date.now();
	// Set background
	var background = LK.getAsset('backgroundImage', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 / 2
	});
	game.addChild(background);
	background.zIndex = -1; // Ensure the background is rendered behind other elements
	// Play background music
	LK.playMusic('Ozone', {
		fade: {
			start: 0,
			end: 0.3,
			duration: 1000
		}
	});
	// Create player at center of screen
	player = new Player();
	player.infiniteAmmo = false; // Initialize infinite ammo property
	player.x = 2048 / 2;
	player.y = 2732 / 2;
	// Add max score display
	maxScoreText = new Text2('Max Score: ' + storage.highscore, {
		size: 40,
		fill: 0xFFFFFF
	});
	maxScoreText.anchor.set(0.5, 0);
	LK.gui.top.addChild(maxScoreText);
	maxScoreText.x = 0;
	maxScoreText.y = 80;
	if (player) {
		player.lastX = player.x; // Initialize lastX for tracking
		player.lastY = player.y; // Initialize lastY for tracking
	}
	game.addChild(player);
	// Add obstacles
	var obstacles = [];
	// Add barrels at random positions
	for (var i = 0; i < 5; i++) {
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		var barrel = new Barrel(randomX, randomY);
		obstacles.push(barrel);
		game.addChild(barrel);
	}
	// Create an object at the right corner of the screen
	var rightCornerObject = LK.getAsset('crate', {
		anchorX: 1.0,
		anchorY: 0.5,
		x: 2048,
		y: 1366
	});
	game.addChild(rightCornerObject);
	// Add an abandoned car to the top-right corner of the screen
	var abandonedCarTopRight = LK.getAsset('abandonedCar', {
		anchorX: 1.0,
		anchorY: 0.0,
		x: 2048,
		y: 0
	});
	game.addChild(abandonedCarTopRight);
	abandonedCarTopRight.zIndex = 1; // Ensure the car is rendered in front of the background
	// Add abandoned cars to their original positions
	for (var i = 0; i < 3; i++) {
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		var abandonedCar = LK.getAsset('abandonedCar', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: randomX,
			y: randomY
		});
		game.addChild(abandonedCar);
		abandonedCar.zIndex = 1; // Ensure the car is rendered in front of the background
	}
	// Add decorative elements to the corners
	obstacles.push(new Obstacle(150, 150, 'bush')); // Near top-left corner
	obstacles.push(new Obstacle(1898, 150, 'bush')); // Near top-right corner
	obstacles.push(new Obstacle(150, 2582, 'bush')); // Near bottom-left corner
	obstacles.push(new Obstacle(1898, 2582, 'bush')); // Near bottom-right corner
	obstacles.push(new Obstacle(150, 150, 'crate')); // Near top-left corner
	obstacles.push(new Obstacle(1898, 150, 'crate')); // Near top-right corner
	obstacles.push(new Obstacle(150, 2582, 'crate')); // Near bottom-left corner
	obstacles.push(new Obstacle(1898, 2582, 'crate')); // Near bottom-right corner
	obstacles.push(new Barrel(200, 200)); // Near top-left corner
	obstacles.push(new Barrel(1848, 200)); // Near top-right corner
	obstacles.push(new Barrel(200, 2432)); // Near bottom-left corner
	obstacles.push(new Barrel(1848, 2432)); // Near bottom-right corner
	// Add more bushes
	for (var i = 0; i < 50; i++) {
		// Increased from 20 to 50 for more bushes
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		obstacles.push(new Obstacle(randomX, randomY, 'bush'));
	}
	// Add small stone patterns
	for (var i = 0; i < 100; i++) {
		// Increased from 50 to 100 for more stones
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		obstacles.push(new Obstacle(randomX, randomY, 'stone'));
	}
	// Add more crate obstacles at random positions
	for (var i = 0; i < 10; i++) {
		var randomX = Math.random() * 2048;
		var randomY = Math.random() * 2732;
		obstacles.push(new Obstacle(randomX, randomY, 'crate'));
	}
	obstacles.forEach(function (obstacle) {
		game.addChild(obstacle);
	});
	// Initialize UI
	createUI();
	// Start first wave
	startWave();
}
function createUI() {
	// Score text
	scoreText = new Text2('Score: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreText.anchor.set(0.5, 0);
	LK.gui.top.addChild(scoreText);
	scoreText.x = 0;
	scoreText.y = 20;
	// Wave text
	waveText = new Text2('Wave: 1', {
		size: 60,
		fill: 0xFFFFFF
	});
	waveText.anchor.set(0, 0);
	LK.gui.topLeft.addChild(waveText);
	waveText.x = 20;
	waveText.y = 20;
	// Game status text (wave start, game over, etc.)
	gameStatusText = new Text2('', {
		size: 100,
		fill: 0xFFFFFF
	});
	gameStatusText.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(gameStatusText);
	gameStatusText.alpha = 0;
	// Adjust gameStatusText position to be slightly below the wave text
	gameStatusText.y = waveText.y + 70;
	// Health bar background
	healthBarBg = LK.getAsset('healthBarBg', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(healthBarBg);
	healthBarBg.x = 20;
	healthBarBg.y = -50;
	// Health bar
	healthBar = LK.getAsset('healthBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(healthBar);
	healthBar.x = 20;
	healthBar.y = -50;
	// Ammo bar background
	ammoBarBg = LK.getAsset('ammoBarBg', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(ammoBarBg);
	ammoBarBg.x = 20;
	ammoBarBg.y = -100;
	// Ammo bar
	ammoBar = LK.getAsset('ammoBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	LK.gui.bottomLeft.addChild(ammoBar);
	ammoBar.x = 20;
	ammoBar.y = -100;
	// Game status text (wave start, game over, etc.)
	gameStatusText = new Text2('', {
		size: 100,
		fill: 0xFFFFFF
	});
	gameStatusText.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(gameStatusText);
	gameStatusText.alpha = 0;
}
function updateUI() {
	// Update score
	scoreText.setText('Score: ' + score);
	// Update player name and score display
	player.getChildAt(0).text = 'Player ' + (Math.floor(Math.random() * 1000) + 1) + ' | Score: ' + score;
	// Update max score display
	maxScoreText.setText('Max Score: ' + storage.highscore);
	// Update wave
	waveText.setText('Wave: ' + wave);
	// Update health bar
	var healthPercent = player.health / player.maxHealth;
	healthBar.scale.x = healthPercent;
	// Update ammo bar
	var ammoPercent = player.ammo / player.maxAmmo;
	ammoBar.scale.x = ammoPercent;
	// Change ammo bar color when reloading
	if (player.isReloading) {
		ammoBar.tint = 0xff6600;
	} else {
		ammoBar.tint = 0xcc9900;
	}
}
function startWave() {
	waveStartTime = Date.now();
	isWaveActive = false;
	// Display countdown before wave starts
	var countdown = 7;
	gameStatusText.setText('Wave ' + wave + ' in ' + countdown);
	gameStatusText.alpha = 1;
	var countdownInterval = LK.setInterval(function () {
		countdown--;
		if (countdown > 0) {
			gameStatusText.setText('Wave ' + wave + ' in ' + countdown);
		} else {
			LK.clearInterval(countdownInterval);
			isWaveActive = true;
			gameStatusText.setText('WAVE ' + wave);
			tween(gameStatusText, {
				alpha: 0
			}, {
				duration: 1500,
				easing: tween.easeIn
			});
			LK.getSound('newWave').play();
			// Randomly spawn a ShieldChest or Upgrader
			if (Math.random() < 0.5) {
				var shieldChest = new ShieldChest(Math.random() * 2048, Math.random() * 2732);
				game.addChild(shieldChest);
				pickups.push(shieldChest);
			} else {
				var upgrader = new Upgrader(Math.random() * 2048, Math.random() * 2732);
				game.addChild(upgrader);
				pickups.push(upgrader);
			}
		}
	}, 1000);
	// Spawn zombies based on wave number
	var zombieCount = wave === 1 ? 10 : wave === 2 ? 3 : wave === 3 ? 4 : 5 + wave * 2; // Increased zombie count for wave 1
	var zombieHealth = wave === 1 ? 20 : wave === 2 ? 25 : wave === 3 ? 30 : 30 + wave * 5; // Reduced health for first three waves
	var zombieSpeed = wave === 1 ? 1.0 : wave === 2 ? 1.1 : wave === 3 ? 1.2 : 2 + wave * 0.1; // Reduced speed for first three waves
	var zombieDamage = wave === 1 ? 3 : wave === 2 ? 4 : wave === 3 ? 5 : 10 + wave * 2; // Reduced damage for first three waves
	// Schedule zombie spawns over time
	// Delay zombie spawning until countdown is complete
	var spawnInterval = LK.setInterval(function () {
		if (isWaveActive && zombies.length < zombieCount) {
			if (wave >= 3 && Math.random() < 0.3 + wave * 0.05) {
				// Increase chance to spawn a sludge zombie as waves progress
				spawnSludgeZombie(zombieHealth, zombieSpeed, zombieDamage);
			} else if (Math.random() < 0.2 - wave * 0.01) {
				// Decrease chance to spawn a skeleton zombie initially, but increase as waves progress
				spawnSkeletonZombie(zombieHealth, zombieSpeed, zombieDamage);
			} else if (Math.random() < 0.2) {
				// 20% chance to spawn a fast zombie
				spawnFastZombie(zombieHealth, zombieSpeed * 2, zombieDamage); // Double the speed for fast zombies
			} else {
				spawnZombie(zombieHealth, zombieSpeed, zombieDamage);
			}
		} else if (zombies.length >= zombieCount) {
			LK.clearInterval(spawnInterval);
		}
	}, 500);
	// Spawn a boss every 5 waves
	if (wave % 5 === 0) {
		LK.setTimeout(function () {
			spawnBossZombie();
		}, 5000);
	}
}
function spawnZombie(health, speed, damage) {
	var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
	var x, y;
	switch (edge) {
		case 0:
			// top
			x = Math.random() * 2048;
			y = -100;
			break;
		case 1:
			// right
			x = 2048 + 100;
			y = Math.random() * 2732;
			break;
		case 2:
			// bottom
			x = Math.random() * 2048;
			y = 2732 + 100;
			break;
		case 3:
			// left
			x = -100;
			y = Math.random() * 2732;
			break;
	}
	var zombie = new Zombie(x, y, health, speed, damage);
	zombies.push(zombie);
	game.addChild(zombie);
}
function spawnBossZombie() {
	// Spawn boss at a random edge
	var edge = Math.floor(Math.random() * 4);
	var x, y;
	switch (edge) {
		case 0:
			// top
			x = Math.random() * 2048;
			y = -150;
			break;
		case 1:
			// right
			x = 2048 + 150;
			y = Math.random() * 2732;
			break;
		case 2:
			// bottom
			x = Math.random() * 2048;
			y = 2732 + 150;
			break;
		case 3:
			// left
			x = -150;
			y = Math.random() * 2732;
			break;
	}
	var boss = new BossZombie(x, y, wave);
	zombies.push(boss);
	game.addChild(boss);
	// Play boss appear sound
	LK.getSound('bossAppear').play();
	// Show boss alert
	gameStatusText.setText('BOSS ZOMBIE APPEARED!');
	gameStatusText.alpha = 1;
	tween(gameStatusText, {
		alpha: 0
	}, {
		duration: 2000,
		easing: tween.easeIn
	});
}
function spawnPickup(x, y) {
	// 30% chance for health, 70% for ammo
	var type = Math.random() < 0.3 ? 'health' : 'ammo';
	var pickup = new Pickup(x, y, type);
	pickups.push(pickup);
	game.addChild(pickup);
}
function checkWaveCompletion() {
	if (isWaveActive && zombies.length === 0 && !isGameOver && zombiesKilled >= 3 + wave) {
		isWaveActive = false;
		// Display wave complete message
		gameStatusText.setText('WAVE ' + wave + ' COMPLETE!');
		gameStatusText.alpha = 1;
		// Give player a weapon upgrade every 3 waves
		if (wave % 3 === 0) {
			player.upgradeWeapon();
			// Show upgrade message
			LK.setTimeout(function () {
				gameStatusText.setText('WEAPON UPGRADED!');
			}, 2000);
		}
		// Spawn crates as objects after wave completion
		for (var i = 0; i < 5; i++) {
			var randomX = Math.random() * 2048;
			var randomY = Math.random() * 2732;
			var crate = new Obstacle(randomX, randomY, 'crate');
			obstacles.push(crate);
			game.addChild(crate);
		}
		// Spawn barrels at the end of each wave
		for (var i = 0; i < 3; i++) {
			var randomX = Math.random() * 2048;
			var randomY = Math.random() * 2732;
			var barrel = new Barrel(randomX, randomY);
			obstacles.push(barrel);
			game.addChild(barrel);
		}
		// Start next wave after a 5-second delay
		LK.setTimeout(function () {
			wave++;
			gameStatusText.alpha = 0;
			startWave();
		}, 5000);
	}
}
// Event handling
game.down = function (x, y) {
	if (isGameOver) {
		return;
	}
	targetPosition.x = x;
	targetPosition.y = y;
	// Player shoots at clicked position
	var bullet = player.shoot(x, y);
	if (bullet) {
		bullets.push(bullet);
		game.addChild(bullet);
	}
};
game.move = function (x, y) {
	targetPosition.x = x;
	targetPosition.y = y;
};
game.up = function () {
	// Not needed for this game
};
// Main game update loop
game.update = function () {
	if (isGameOver) {
		return;
	}
	// Check for player collision with obstacles
	obstacles.forEach(function (obstacle) {
		if (player.intersects(obstacle) && obstacle.type !== 'crate') {
			// Prevent player from moving through the obstacle, except crates
			player.x = player.lastX;
			player.y = player.lastY;
		}
	});
	// Update player movement
	if (player) {
		player.lastX = player.x; // Track lastX before moving
		player.lastY = player.y; // Track lastY before moving
		player.moveTowards(targetPosition.x, targetPosition.y);
		// Check if player is near the legendary chest
		if (!player.nearLegendaryChest && player.intersects(legendaryChest)) {
			player.nearLegendaryChest = true;
			player.legendaryChestTimer = Date.now();
		} else if (player.nearLegendaryChest && !player.intersects(legendaryChest)) {
			player.nearLegendaryChest = false;
			player.legendaryChestTimer = null;
		}
		// Open the legendary chest if the player stands next to it for 3 seconds
		if (player.nearLegendaryChest && Date.now() - player.legendaryChestTimer >= 3000) {
			// Logic to open the chest
			console.log("Legendary chest opened!");
			legendaryChest.destroy();
			legendaryChest = null; // Set legendaryChest to null after destroying it
			// Change appearance to legendary2
			var legendary2 = LK.getAsset('legendary2', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: 2048 / 2,
				y: 2732 / 2,
				visible: true // Make legendary2 visible
			});
			game.addChild(legendary2);
			// Randomly decide to spawn an upgrader or shield chest
			if (Math.random() < 0.5) {
				var upgrader = new Upgrader(2048 / 2, 2732 / 2);
				game.addChild(upgrader);
				pickups.push(upgrader);
			} else {
				var shieldChest = new ShieldChest(2048 / 2, 2732 / 2);
				game.addChild(shieldChest);
				pickups.push(shieldChest);
			}
			player.nearLegendaryChest = false;
			player.legendaryChestTimer = null;
		}
		// Regenerate health slowly if not at max health
		if (player.health < player.maxHealth) {
			player.health = Math.min(player.maxHealth, player.health + 0.05); // Regenerate 0.05 health per update
		}
	}
	// Update bullets
	for (var i = bullets.length - 1; i >= 0; i--) {
		var shouldRemove = bullets[i].update();
		if (shouldRemove) {
			bullets[i].destroy();
			bullets.splice(i, 1);
			continue;
		}
		// Check bullet collision with zombies
		for (var j = zombies.length - 1; j >= 0; j--) {
			if (bullets[i] && bullets[i].intersects(zombies[j])) {
				// Display bullet effect at the point of impact
				var bulletEffect = LK.getAsset('bulleteffect', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: bullets[i].x,
					y: bullets[i].y
				});
				game.addChild(bulletEffect);
				tween(bulletEffect, {}, {
					duration: 200,
					onFinish: function onFinish() {
						bulletEffect.destroy();
					}
				});
				// Check if this bullet has already hit this zombie
				if (!bulletHitZombies[bullets[i]]) {
					bulletHitZombies[bullets[i]] = [];
				}
				if (!bulletHitZombies[bullets[i]].includes(zombies[j])) {
					bulletHitZombies[bullets[i]].push(zombies[j]);
					var zombieDied = zombies[j].takeDamage(bullets[i].damage);
					// Remove bullet after hit
					bullets[i].destroy();
					bullets.splice(i, 1);
					if (zombieDied) {
						// Increase score and zombie kill counter
						var scoreToAdd = zombies[j] instanceof BossZombie ? 100 : 10;
						score += scoreToAdd;
						zombiesKilled++;
						// Chance to drop pickup
						if (Math.random() < 0.3) {
							spawnPickup(zombies[j].x, zombies[j].y);
						}
						// Remove zombie
						zombies[j].destroy();
						zombies.splice(j, 1);
					}
					break;
				}
			}
		}
	}
	// Update obstacles
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var shouldRemove = obstacles[i].update();
		if (shouldRemove) {
			obstacles[i].destroy();
			obstacles.splice(i, 1);
		}
	}
	// Update zombies
	for (var i = zombies.length - 1; i >= 0; i--) {
		// Move zombie towards player
		zombies[i].moveTowards(player.x, player.y);
		// Check if zombie reached player
		if (zombies[i].intersects(player)) {
			var playerDied = zombies[i].attack(player);
			if (playerDied) {
				handleGameOver();
			}
		}
	}
	for (var i = pickups.length - 1; i >= 0; i--) {
		var shouldRemove = pickups[i].update();
		if (shouldRemove) {
			pickups[i].destroy();
			pickups.splice(i, 1);
			continue;
		}
		// Check if player collects pickup
		if (player.intersects(pickups[i])) {
			pickups[i].collect(player);
			pickups[i].destroy();
			pickups.splice(i, 1);
		}
	}
	// Update UI
	updateUI();
	// Spawn bomb in red area every 10 seconds, only if wave is active
	if (isWaveActive && LK.ticks % 600 === 0) {
		var bombX = Math.random() * 2048;
		var bombY = Math.random() * 2732;
		var bomb = new Bomb(bombX, bombY);
		game.addChild(bomb);
		// Trigger explosion after 3 seconds
		LK.setTimeout(function () {
			bomb.explode();
		}, 3000);
	}
	// Check if wave is complete
	checkWaveCompletion();
	// Auto-reload when empty and not already reloading
	if (player.ammo === 0 && !player.isReloading) {
		player.reload();
	}
};
function handleGameOver() {
	isGameOver = true;
	// Fade out background music
	LK.playMusic('gameMusic', {
		fade: {
			start: 0.3,
			end: 0,
			duration: 1000
		}
	});
	// Update high score if needed
	if (score > storage.highscore) {
		storage.highscore = score;
	}
	// Show score in game over dialog
	LK.setScore(score);
	// Show game over screen after a short delay
	LK.setTimeout(function () {
		LK.showGameOver();
	}, 1000);
}
initGame(); // Start the game immediately