/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Alien
var Alien = Container.expand(function () {
	var self = Container.call(this);
	var alien = self.attachAsset('alien', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = alien.width;
	self.height = alien.height;
	self.speedX = 0;
	self.speedY = 0.8;
	self.shootCooldown = 0;
	self.row = 0;
	self.col = 0;
	self.alive = true;
	self.hp = 2; // Aliens require 2 hits to be defeated
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	// Flash when hit
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Alien2
var Alien2 = Container.expand(function () {
	var self = Container.call(this);
	var alien = self.attachAsset('alien2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = alien.width;
	self.height = alien.height;
	self.speedX = 0;
	self.speedY = 0.8;
	self.shootCooldown = 0;
	self.row = 0;
	self.col = 0;
	self.alive = true;
	self.hp = 4;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Alien3
var Alien3 = Container.expand(function () {
	var self = Container.call(this);
	var alien = self.attachAsset('alien3', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = alien.width;
	self.height = alien.height;
	self.speedX = 0;
	self.speedY = 0.8;
	self.shootCooldown = 0;
	self.row = 0;
	self.col = 0;
	self.alive = true;
	self.hp = 3;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Alien Bullet
var AlienBullet = Container.expand(function () {
	var self = Container.call(this);
	var bullet = self.attachAsset('alienBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = bullet.width;
	self.height = bullet.height;
	self.speedY = 14;
	self.update = function () {
		if (typeof self.speedX === "undefined") {
			self.speedX = 0;
		}
		self.x += self.speedX;
		self.y += self.speedY;
	};
	return self;
});
// Boss
var Boss = Container.expand(function () {
	var self = Container.call(this);
	var bossAsset = self.attachAsset('Boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = bossAsset.width;
	self.height = bossAsset.height;
	self.hp = 500;
	self.speedX = 4;
	self.speedY = 0.7;
	self.alive = true;
	self.shootCooldown = 60;
	self.update = function () {
		// Move horizontally, bounce off edges
		self.x += self.speedX;
		if (self.x - self.width / 2 <= 0 && self.speedX < 0) {
			self.x = self.width / 2;
			self.speedX = -self.speedX;
		}
		if (self.x + self.width / 2 >= GAME_WIDTH && self.speedX > 0) {
			self.x = GAME_WIDTH - self.width / 2;
			self.speedX = -self.speedX;
		}
		// Boss does NOT move down in y direction anymore
		// --- Boss special events for HP thresholds ---
		// Boss event state: 0 = idle, 1 = right fired, waiting for left, 2 = left fired, waiting for right
		if (typeof self._bossEventState === "undefined") {
			self._bossEventState = 0;
			self._bossEventTimer = 0;
		}
		// HP > 300: original 5-bullet events
		if (self.hp > 300) {
			if (self._bossEventState === 0 && (!self.shootCooldown || self.shootCooldown <= 0)) {
				// Fire 5 bullets to the right at different angles
				var spread = Math.PI / 3; // 60 degrees total
				var baseAngle = Math.PI / 2 - spread / 2; // Start at 60deg
				for (var i = 0; i < 5; i++) {
					var angle = baseAngle + spread / 4 * i;
					var b = new AlienBullet();
					b.x = self.x + self.width * 0.35;
					b.y = self.y + self.height / 2 - 10;
					b.speedY = Math.sin(angle) * 16;
					b.speedX = Math.cos(angle) * 16;
					alienBullets.push(b);
					if (typeof game !== "undefined") {
						if (isInMenu) {
							game.addChild(b);
						} else {
							gameContainer.addChild(b);
						}
					}
				}
				LK.getSound('alienShoot').play();
				self._bossEventState = 1;
				self._bossEventTimer = 30; // 0.5s at 60fps
				self.shootCooldown = 60; // Prevent normal shooting for a bit
			} else if (self._bossEventState === 1) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					// Fire 5 bullets to the left at different angles
					var spread = Math.PI / 3; // 60 degrees total
					var baseAngle = Math.PI / 2 - spread / 2; // Start at 60deg
					for (var i = 0; i < 5; i++) {
						var angle = baseAngle + spread / 4 * i;
						var b = new AlienBullet();
						b.x = self.x - self.width * 0.35;
						b.y = self.y + self.height / 2 - 10;
						b.speedY = Math.sin(angle) * 16;
						b.speedX = -Math.cos(angle) * 16;
						alienBullets.push(b);
						if (typeof game !== "undefined") {
							game.addChild(b);
						}
					}
					LK.getSound('alienShoot').play();
					self._bossEventState = 2;
					self._bossEventTimer = 30; // 0.5s
					self.shootCooldown = 60;
				}
			} else if (self._bossEventState === 2) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					self._bossEventState = 0;
				}
			}
		}
		// Switch to bossmusic2 when HP drops to 300 or below
		if (typeof self._bossMusic2Played === "undefined") {
			self._bossMusic2Played = false;
		}
		if (typeof self._rage300Played === "undefined") {
			self._rage300Played = false;
		}
		if (typeof self._rage100Played === "undefined") {
			self._rage100Played = false;
		}
		if (!self._bossMusic2Played && self.hp <= 300) {
			LK.playMusic('bossmusic2');
			self._bossMusic2Played = true;
		}
		if (!self._rage300Played && self.hp <= 300) {
			LK.getSound('rage').play();
			self._rage300Played = true;
		}
		if (!self._rage100Played && self.hp <= 100) {
			LK.getSound('rage').play();
			self._rage100Played = true;
		}
		// HP between 300 and 100: 7-bullet events, alternate right/left every 0.5s
		else if (self.hp <= 300 && self.hp > 100) {
			if (self._bossEventState === 0 && (!self.shootCooldown || self.shootCooldown <= 0)) {
				// Fire 7 bullets to the right at different angles
				var spread = Math.PI * 2 / 3; // 120 degrees total
				var baseAngle = Math.PI / 2 - spread / 2; // Centered at down
				for (var i = 0; i < 7; i++) {
					var angle = baseAngle + spread / 6 * i;
					var b = new AlienBullet();
					b.x = self.x + self.width * 0.35;
					b.y = self.y + self.height / 2 - 10;
					b.speedY = Math.sin(angle) * 16;
					b.speedX = Math.cos(angle) * 16;
					alienBullets.push(b);
					if (typeof game !== "undefined") {
						game.addChild(b);
					}
				}
				LK.getSound('alienShoot').play();
				self._bossEventState = 1;
				self._bossEventTimer = 30; // 0.5s
				self.shootCooldown = 60;
			} else if (self._bossEventState === 1) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					// Fire 7 bullets to the left at different angles
					var spread = Math.PI * 2 / 3; // 120 degrees total
					var baseAngle = Math.PI / 2 - spread / 2;
					for (var i = 0; i < 7; i++) {
						var angle = baseAngle + spread / 6 * i;
						var b = new AlienBullet();
						b.x = self.x - self.width * 0.35;
						b.y = self.y + self.height / 2 - 10;
						b.speedY = Math.sin(angle) * 16;
						b.speedX = -Math.cos(angle) * 16;
						alienBullets.push(b);
						if (typeof game !== "undefined") {
							game.addChild(b);
						}
					}
					LK.getSound('alienShoot').play();
					self._bossEventState = 2;
					self._bossEventTimer = 30; // 0.5s
					self.shootCooldown = 60;
				}
			} else if (self._bossEventState === 2) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					self._bossEventState = 0;
				}
			}
		}
		// HP between 100 and 0: 9-bullet events, alternate right/left every 0.5s
		else if (self.hp <= 100 && self.hp > 0) {
			if (self._bossEventState === 0 && (!self.shootCooldown || self.shootCooldown <= 0)) {
				// Fire 9 bullets to the right at different angles
				var spread = Math.PI * 5 / 6; // 150 degrees total
				var baseAngle = Math.PI / 2 - spread / 2; // Centered at down
				for (var i = 0; i < 9; i++) {
					var angle = baseAngle + spread / 8 * i;
					var b = new AlienBullet();
					b.x = self.x + self.width * 0.35;
					b.y = self.y + self.height / 2 - 10;
					b.speedY = Math.sin(angle) * 16;
					b.speedX = Math.cos(angle) * 16;
					alienBullets.push(b);
					if (typeof game !== "undefined") {
						game.addChild(b);
					}
				}
				LK.getSound('alienShoot').play();
				self._bossEventState = 1;
				self._bossEventTimer = 30; // 0.5s
				self.shootCooldown = 60;
			} else if (self._bossEventState === 1) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					// Fire 9 bullets to the left at different angles
					var spread = Math.PI * 5 / 6; // 150 degrees total
					var baseAngle = Math.PI / 2 - spread / 2;
					for (var i = 0; i < 9; i++) {
						var angle = baseAngle + spread / 8 * i;
						var b = new AlienBullet();
						b.x = self.x - self.width * 0.35;
						b.y = self.y + self.height / 2 - 10;
						b.speedY = Math.sin(angle) * 16;
						b.speedX = -Math.cos(angle) * 16;
						alienBullets.push(b);
						if (typeof game !== "undefined") {
							game.addChild(b);
						}
					}
					LK.getSound('alienShoot').play();
					self._bossEventState = 2;
					self._bossEventTimer = 30; // 0.5s
					self.shootCooldown = 60;
				}
			} else if (self._bossEventState === 2) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					self._bossEventState = 0;
				}
			}
		} else {
			// Reset event state if HP drops below threshold or is above 300 or below/equal 0
			self._bossEventState = 0;
			self._bossEventTimer = 0;
		}
		// Shoot cooldown
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	// Flash when hit
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Coin
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var c = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = c.width;
	self.height = c.height;
	self.speedY = 12;
	self.update = function () {
		self.y += self.speedY;
	};
	return self;
});
// Hero Bullet
var HeroBullet = Container.expand(function () {
	var self = Container.call(this);
	var bullet = self.attachAsset('heroBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = bullet.width;
	self.height = bullet.height;
	self.speedY = -22;
	self.update = function () {
		if (typeof self.speedX === "undefined") {
			self.speedX = 0;
		}
		self.x += self.speedX;
		self.y += self.speedY;
	};
	return self;
});
// Hero Ship
var HeroShip = Container.expand(function () {
	var self = Container.call(this);
	var ship = self.attachAsset('heroShip', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = ship.width;
	self.height = ship.height;
	self.lives = 1;
	self.fireCooldown = 0;
	self.powerLevel = 1;
	self.invincible = false;
	self.invincibleTimer = 0;
	// Flash when hit
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 80,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 120
				});
			}
		});
	};
	// Power up
	self.upgrade = function () {
		if (self.powerLevel < 3) {
			self.powerLevel += 1;
			LK.effects.flashObject(self, 0xaa66ff, 400);
		}
	};
	// Invincibility after hit
	self.setInvincible = function (duration) {
		self.invincible = true;
		self.invincibleTimer = duration;
		tween(self, {
			alpha: 0.5
		}, {
			duration: 100
		});
	};
	// Called every tick
	self.update = function () {
		if (self.invincible) {
			self.invincibleTimer -= 1;
			if (self.invincibleTimer <= 0) {
				self.invincible = false;
				self.alpha = 1;
			}
		}
		if (self.fireCooldown > 0) {
			self.fireCooldown -= 1;
		}
	};
	return self;
});
// Powerup
var Powerup = Container.expand(function () {
	var self = Container.call(this);
	var p = self.attachAsset('powerup', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = p.width;
	self.height = p.height;
	self.speedY = 15;
	self.update = function () {
		self.y += self.speedY;
	};
	return self;
});
// Star for starfield background
var Star = Container.expand(function () {
	var self = Container.call(this);
	var star = self.attachAsset('star', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = star.width;
	self.height = star.height;
	self.speedY = 2; // Slow downward movement
	self.update = function () {
		self.y += self.speedY;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Game area
// Hero ship: blue box
// Alien: green ellipse
// Hero bullet: yellow box
// Alien bullet: red box
// Power-up: purple ellipse
// Sound effects
// Music
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Menu state
var isInMenu = true;
var isInInstructions = false;
var menuContainer = new Container();
var instructionsContainer = new Container();
var gameContainer = new Container();
// Starfield variables
var stars = [];
var starSpawnTimer = 0;
// Spawn a star at random position
function spawnStar() {
	var star = new Star();
	star.x = Math.random() * GAME_WIDTH;
	star.y = -star.height;
	// Vary speed slightly for visual effect
	star.speedY = 1 + Math.random() * 2;
	stars.push(star);
	if (isInMenu) {
		menuContainer.addChild(star);
	} else if (isInInstructions) {
		instructionsContainer.addChild(star);
	} else {
		gameContainer.addChild(star);
	}
}
// Update starfield
function updateStarfield() {
	// Spawn new stars periodically
	starSpawnTimer += 1;
	var spawnRate;
	if (isInMenu || isInInstructions) {
		spawnRate = 15; // Spawn every 15 frames (4 times per second at 60fps)
	} else {
		spawnRate = 60; // Much slower spawning during gameplay (1 per second at 60fps)
	}
	if (starSpawnTimer >= spawnRate) {
		spawnStar();
		starSpawnTimer = 0;
	}
	// Update existing stars
	for (var i = stars.length - 1; i >= 0; i--) {
		var star = stars[i];
		star.update();
		// Remove stars that have moved off screen
		if (star.y > GAME_HEIGHT + star.height) {
			star.destroy();
			stars.splice(i, 1);
		}
	}
}
// Clear all stars
function clearStarfield() {
	for (var i = stars.length - 1; i >= 0; i--) {
		stars[i].destroy();
	}
	stars = [];
	starSpawnTimer = 0;
}
// Create main menu
function createMainMenu() {
	// Play menu music
	LK.playMusic('menumusic');
	// Set solid black background for menu
	game.setBackgroundColor(0x000000);
	// Menu title
	var titleText = new Text2("SPACE WARDENS", {
		size: 180,
		fill: 0xFFFFFF,
		align: "center"
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = GAME_WIDTH / 2;
	titleText.y = GAME_HEIGHT / 3;
	menuContainer.addChild(titleText);
	// Start Game button
	var startBtn = new Text2("START GAME", {
		size: 120,
		fill: 0x00FF00,
		align: "center"
	});
	startBtn.anchor.set(0.5, 0.5);
	startBtn.x = GAME_WIDTH / 2;
	startBtn.y = GAME_HEIGHT / 2;
	startBtn.interactive = true;
	startBtn.buttonMode = true;
	startBtn.down = function (x, y, obj) {
		LK.getSound('menuclick').play();
		startGame();
	};
	menuContainer.addChild(startBtn);
	// Instructions button
	var instructionsBtn = new Text2("INSTRUCTIONS", {
		size: 120,
		fill: 0x0099FF,
		align: "center"
	});
	instructionsBtn.anchor.set(0.5, 0.5);
	instructionsBtn.x = GAME_WIDTH / 2;
	instructionsBtn.y = GAME_HEIGHT / 2 + 200;
	instructionsBtn.interactive = true;
	instructionsBtn.buttonMode = true;
	instructionsBtn.down = function (x, y, obj) {
		LK.getSound('menuclick').play();
		showInstructions();
	};
	menuContainer.addChild(instructionsBtn);
	game.addChild(menuContainer);
	// Spawn initial stars
	for (var i = 0; i < 20; i++) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		menuContainer.addChild(star);
	}
}
// Show instructions
function showInstructions() {
	// Play menu music
	LK.playMusic('menumusic');
	isInMenu = false;
	isInInstructions = true;
	// Remove menu container
	if (menuContainer.parent) {
		menuContainer.parent.removeChild(menuContainer);
	}
	// Clear instructions container
	while (instructionsContainer.children.length > 0) {
		instructionsContainer.removeChild(instructionsContainer.children[0]);
	}
	// Set solid black background for instructions
	game.setBackgroundColor(0x000000);
	// Instructions title
	var titleText = new Text2("INSTRUCTIONS", {
		size: 150,
		fill: 0xFFFF99,
		align: "center"
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = GAME_WIDTH / 2;
	titleText.y = GAME_HEIGHT / 4;
	instructionsContainer.addChild(titleText);
	// Instructions content
	var instructionsText = new Text2("HOW TO PLAY:\n\nDrag your ship to move\nCollect power-ups to upgrade your ship\nCollect coins for extra score\nDefeat all aliens to win a wave\nDefeat Lohar to win game!", {
		size: 80,
		fill: 0xFFFF99,
		align: "center"
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = GAME_WIDTH / 2;
	instructionsText.y = GAME_HEIGHT / 2;
	instructionsContainer.addChild(instructionsText);
	// Back button
	var backBtn = new Text2("BACK TO MENU", {
		size: 100,
		fill: 0xFF6600,
		align: "center"
	});
	backBtn.anchor.set(0.5, 0.5);
	backBtn.x = GAME_WIDTH / 2;
	backBtn.y = GAME_HEIGHT * 3 / 4;
	backBtn.interactive = true;
	backBtn.buttonMode = true;
	backBtn.down = function (x, y, obj) {
		LK.getSound('menuclick').play();
		returnToMenu();
	};
	instructionsContainer.addChild(backBtn);
	// Add instructions container to game
	game.addChild(instructionsContainer);
	// Transfer existing stars from menu to instructions container
	for (var i = 0; i < stars.length; i++) {
		var star = stars[i];
		if (star.parent) {
			star.parent.removeChild(star);
		}
		instructionsContainer.addChild(star);
	}
	// Only spawn additional stars if we have fewer than 20
	while (stars.length < 20) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		instructionsContainer.addChild(star);
	}
}
// Return to main menu from instructions
function returnToMenu() {
	// Play menu music
	LK.playMusic('menumusic');
	isInMenu = true;
	isInInstructions = false;
	// Remove instructions container
	if (instructionsContainer.parent) {
		instructionsContainer.parent.removeChild(instructionsContainer);
	}
	// Add menu container back
	game.addChild(menuContainer);
	// Transfer existing stars from instructions to menu container
	for (var i = 0; i < stars.length; i++) {
		var star = stars[i];
		if (star.parent) {
			star.parent.removeChild(star);
		}
		menuContainer.addChild(star);
	}
	// Only spawn additional stars if we have fewer than 20
	while (stars.length < 20) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		menuContainer.addChild(star);
	}
}
// Start the game
function startGame() {
	isInMenu = false;
	// Remove menu container
	if (menuContainer.parent) {
		menuContainer.parent.removeChild(menuContainer);
	}
	// Add game container
	game.addChild(gameContainer);
	// Play music
	LK.playMusic('bgmusic');
	// Clear starfield when starting game
	clearStarfield();
	// Spawn much fewer initial stars for gameplay (only 5 instead of 20)
	for (var i = 0; i < 5; i++) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		gameContainer.addChild(star);
	}
	// Initialize game elements
	initializeGame();
}
// Initialize game elements
function initializeGame() {
	// Move hero to game container
	if (hero.parent) {
		hero.parent.removeChild(hero);
	}
	gameContainer.addChild(hero);
	// Move remaining buttons to game container (buttons removed)
	// Start first wave
	spawnWave(wave);
	heroDead = false;
	// Initial score
	scoreTxt.setText(score);
}
// Score
var score = 0;
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Wave
var wave = 1;
var waveTxt = new Text2('Wave 1', {
	size: 70,
	fill: 0xAAFFFF
});
waveTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(waveTxt);
waveTxt.y = 120;
// Hero (created but not added to display until game starts)
var hero = new HeroShip();
hero.x = GAME_WIDTH / 2;
hero.y = GAME_HEIGHT - 220;
// Bullets, aliens, powerups, coins
var heroBullets = [];
var alienBullets = [];
var aliens = [];
var powerups = [];
var coins = [];
// Dragging
var dragNode = null;
// Track if hero is dead (prevents shooting after death)
var heroDead = false;
// Alien formation
function spawnWave(waveNum) {
	// Remove old aliens
	for (var i = aliens.length - 1; i >= 0; i--) {
		aliens[i].destroy();
		aliens.splice(i, 1);
	}
	if (waveNum === 10) {
		// Play boss music at start of wave 10
		LK.playMusic('bossmusic');
		// Only spawn the boss for wave 10
		var boss = new Boss();
		boss.x = GAME_WIDTH / 2;
		boss.y = 320;
		aliens.push(boss);
		if (isInMenu) {
			game.addChild(boss);
		} else {
			gameContainer.addChild(boss);
		}
		waveTxt.setText('Wave ' + waveNum);
		// Reset wave timer and alien zone flag for new wave
		game._waveStartTime = Date.now();
		game._alienReachedHeroZone = false;
		// Track boss spawn time for bonus
		game._bossSpawnTime = Date.now();
		game._bossBonusGiven = false;
		return;
	}
	// Formation: rows, cols, spacing
	var rows, cols;
	if (waveNum === 2) {
		// Reduce total aliens at wave 2, but keep it more than wave 1 (wave 1 default: rows=3, cols=6 = 18)
		// Let's use rows=4, cols=6 = 24 aliens (wave 1: 18, wave 2: 24, wave 3: 35)
		rows = 4;
		cols = 6;
	} else if (waveNum === 3) {
		// Reduce total aliens at wave 3, but more than wave 2 (wave 2 default: rows=4, cols=8 = 32)
		// Let's use rows=5, cols=7 = 35 aliens (wave 2 would be 32, wave 3 default would be 5,10=50)
		rows = 5;
		cols = 7;
	} else if (waveNum === 4) {
		rows = 3;
		cols = 5;
	} else if (waveNum === 5) {
		// More than wave 4, but less than default for wave 5 (default would be rows=6, cols=10)
		rows = 4;
		cols = 7;
	} else if (waveNum === 6) {
		// Slightly more than wave 5
		rows = 5;
		cols = 8;
	} else if (waveNum === 7) {
		// Reduce a little bit more from wave 6
		rows = 3;
		cols = 7;
	} else if (waveNum === 8) {
		// Decrease total alien number in wave 8 a little bit (but still more than wave 7)
		rows = 4;
		cols = 6;
	} else if (waveNum === 9) {
		// Reduce total alien number a little bit compared to wave 8
		rows = 3;
		cols = 8;
	} else {
		rows = Math.min(2 + waveNum, 6);
		cols = Math.min(4 + waveNum * 2, 10);
	}
	var spacingX = 160;
	var spacingY = 140;
	var startX = (GAME_WIDTH - (cols - 1) * spacingX) / 2;
	var startY = 220 + (waveNum - 1) * 30;
	for (var r = 0; r < rows; r++) {
		for (var c = 0; c < cols; c++) {
			var alien;
			if (waveNum === 4 || waveNum === 5) {
				alien = new Alien2();
			} else if (waveNum === 6) {
				// 70% Alien2, 30% Alien
				if (Math.random() < 0.7) {
					alien = new Alien2();
				} else {
					alien = new Alien();
				}
			} else if (waveNum === 7) {
				// 30% Alien3, 70% Alien
				if (Math.random() < 0.3) {
					alien = new Alien3();
				} else {
					alien = new Alien();
				}
			} else if (waveNum === 8) {
				// 50% Alien2, 50% Alien3
				if (Math.random() < 0.5) {
					alien = new Alien2();
				} else {
					alien = new Alien3();
				}
			} else if (waveNum === 9) {
				// All Alien3 for wave 9
				alien = new Alien3();
			} else {
				alien = new Alien();
			}
			alien.x = startX + c * spacingX;
			alien.y = startY + r * spacingY;
			alien.row = r;
			alien.col = c;
			alien.speedX = Math.sin((r * cols + c + waveNum) * 0.7) * 1.5 + (Math.random() - 0.5) * 0.5;
			alien.speedY = 0.7 + 0.1 * waveNum + (Math.random() - 0.5) * 0.2;
			alien.shootCooldown = 60 + Math.floor(Math.random() * 60);
			aliens.push(alien);
			if (isInMenu) {
				game.addChild(alien);
			} else {
				gameContainer.addChild(alien);
			}
		}
	}
	waveTxt.setText('Wave ' + waveNum);
	// Reset wave timer and alien zone flag for new wave
	game._waveStartTime = Date.now();
	game._alienReachedHeroZone = false;
}
// Powerup spawn
function maybeSpawnPowerup(x, y) {
	if (Math.random() < 0.03) {
		var p = new Powerup();
		p.x = x;
		p.y = y;
		powerups.push(p);
		game.addChild(p);
	}
}
// Coin spawn (lower probability than powerup)
function maybeSpawnCoin(x, y) {
	// Powerup is 0.03, so coin should be less, but increase coin drop rate (e.g. 0.02)
	if (Math.random() < 0.02) {
		var c = new Coin();
		c.x = x;
		c.y = y;
		coins.push(c);
		game.addChild(c);
	}
}
// Fire hero bullets
function fireHeroBullets() {
	if (heroDead) {
		return;
	}
	if (hero.fireCooldown > 0) {
		return;
	}
	var b;
	if (hero.powerLevel === 1) {
		b = new HeroBullet();
		b.x = hero.x;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		gameContainer.addChild(b);
	} else if (hero.powerLevel === 2) {
		b = new HeroBullet();
		b.x = hero.x - 38;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
		b = new HeroBullet();
		b.x = hero.x + 38;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
	} else if (hero.powerLevel === 3) {
		// 3 straight bullets
		b = new HeroBullet();
		b.x = hero.x - 60;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
		b = new HeroBullet();
		b.x = hero.x;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
		b = new HeroBullet();
		b.x = hero.x + 60;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
	}
	hero.fireCooldown = 12;
	LK.getSound('shoot').play();
}
// Fire alien bullet
function fireAlienBullet(alien) {
	// If Alien3, fire triple bullets at different angles
	if (alien instanceof Alien3) {
		// Center bullet (straight down)
		var b0 = new AlienBullet();
		b0.x = alien.x;
		b0.y = alien.y + alien.height / 2 + 10;
		b0.speedY = 14;
		b0.speedX = 0;
		alienBullets.push(b0);
		game.addChild(b0);
		// Left bullet (angle -20deg)
		var b1 = new AlienBullet();
		b1.x = alien.x;
		b1.y = alien.y + alien.height / 2 + 10;
		var angle1 = Math.PI / 2 - Math.PI / 9; // 70deg
		b1.speedY = Math.sin(angle1) * 14;
		b1.speedX = Math.cos(angle1) * 14;
		alienBullets.push(b1);
		game.addChild(b1);
		// Right bullet (angle +20deg)
		var b2 = new AlienBullet();
		b2.x = alien.x;
		b2.y = alien.y + alien.height / 2 + 10;
		var angle2 = Math.PI / 2 + Math.PI / 9; // 110deg
		b2.speedY = Math.sin(angle2) * 14;
		b2.speedX = Math.cos(angle2) * 14;
		alienBullets.push(b2);
		game.addChild(b2);
		LK.getSound('alienShoot').play();
	} else {
		// Default: single bullet straight down
		var b = new AlienBullet();
		b.x = alien.x;
		b.y = alien.y + alien.height / 2 + 10;
		alienBullets.push(b);
		game.addChild(b);
		LK.getSound('alienShoot').play();
	}
}
// Move handler (drag hero)
function handleMove(x, y, obj) {
	if (dragNode) {
		// Clamp to game area, avoid top 100px (menu)
		var nx = Math.max(hero.width / 2, Math.min(GAME_WIDTH - hero.width / 2, x));
		var ny = Math.max(GAME_HEIGHT - 600, Math.min(GAME_HEIGHT - hero.height / 2, y));
		dragNode.x = nx;
		dragNode.y = ny;
	}
}
game.move = handleMove;
game.down = function (x, y, obj) {
	// Only drag if touch is on hero
	var local = hero.toLocal(game.toGlobal({
		x: x,
		y: y
	}));
	if (local.x > -hero.width / 2 && local.x < hero.width / 2 && local.y > -hero.height / 2 && local.y < hero.height / 2) {
		dragNode = hero;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Tap to shoot
game.tap = function (x, y, obj) {
	fireHeroBullets();
};
// Main update
game.update = function () {
	// Hide score and wave indicator in menu and instructions
	if (isInMenu || isInInstructions) {
		scoreTxt.visible = false;
		waveTxt.visible = false;
		updateStarfield();
		return;
	} else {
		// Show score and wave indicator during gameplay
		scoreTxt.visible = true;
		waveTxt.visible = true;
		updateStarfield(); // Update starfield during gameplay too
	}
	// Hero update
	hero.update();
	// Fire hero bullets automatically if holding
	if (dragNode === hero && LK.ticks % 6 === 0) {
		fireHeroBullets();
	}
	// Update hero bullets
	for (var i = heroBullets.length - 1; i >= 0; i--) {
		var b = heroBullets[i];
		b.update();
		// Off screen
		if (b.y < -b.height) {
			b.destroy();
			heroBullets.splice(i, 1);
			continue;
		}
		// Hit alien
		for (var j = aliens.length - 1; j >= 0; j--) {
			var a = aliens[j];
			if (a.alive && b.intersects(a)) {
				a.flash();
				a.hp -= 1;
				b.destroy();
				heroBullets.splice(i, 1);
				if (a.hp <= 0) {
					a.alive = false;
					a.destroy();
					aliens.splice(j, 1);
					if (a instanceof Boss) {
						score += 5000;
						// Award additional 7500 score if boss is defeated within 45 seconds after wave 10 starts
						if (typeof game._bossSpawnTime !== "undefined" && typeof game._bossBonusGiven !== "undefined" && !game._bossBonusGiven && Date.now() - game._bossSpawnTime <= 45000) {
							score += 7500;
							game._bossBonusGiven = true;
							// Optionally, you can show a popup or effect here if desired
						}
					} else if (a instanceof Alien3) {
						score += Math.floor(100 * 1.2 * 2);
					} else if (a instanceof Alien2) {
						score += Math.floor(100 * 1.2);
					} else {
						score += 100;
					}
					scoreTxt.setText(score);
					maybeSpawnPowerup(a.x, a.y);
					maybeSpawnCoin(a.x, a.y);
					// If this is the boss, play bossexplosion sounds in sequence
					if (a instanceof Boss) {
						LK.getSound('bossexplosion').play();
						LK.setTimeout(function () {
							LK.getSound('bossexplosion2').play();
						}, 300);
						LK.setTimeout(function () {
							LK.getSound('bossexplosion3').play();
						}, 600);
						LK.setTimeout(function () {
							LK.getSound('bossexplosion4').play();
						}, 900);
					} else {
						LK.getSound('alienexplosion').play();
					}
				}
				break;
			}
		}
	}
	// Update alien bullets
	for (var i = alienBullets.length - 1; i >= 0; i--) {
		var b = alienBullets[i];
		b.update();
		if (b.y > GAME_HEIGHT + b.height) {
			b.destroy();
			alienBullets.splice(i, 1);
			continue;
		}
		// Hit hero
		if (!hero.invincible && b.intersects(hero)) {
			hero.flash();
			hero.setInvincible(60);
			b.destroy();
			alienBullets.splice(i, 1);
			// Explosion effect at hero ship position
			LK.effects.flashObject(hero, 0xffe066, 700);
			LK.effects.flashScreen(0xff0000, 400);
			// Play explosion sound when hero ship dies
			var explosionSound = LK.getSound('explosion');
			explosionSound.play();
			// Remove hero ship from game immediately
			if (hero.parent) {
				hero.parent.removeChild(hero);
			}
			// Mark hero as dead to prevent further shooting
			heroDead = true;
			// Wait for explosion sound to finish before game over
			LK.setTimeout(function () {
				LK.showGameOver();
			}, Math.max(100, Math.floor((explosionSound.duration || 1) * 1000)));
			return;
		}
	}
	// Update aliens
	for (var i = aliens.length - 1; i >= 0; i--) {
		var a = aliens[i];
		a.update();
		// Game over if alien touches hero ship
		if (a.alive && !hero.invincible && a.intersects(hero)) {
			hero.flash();
			// Explosion effect at hero ship position
			LK.effects.flashObject(hero, 0xffe066, 700);
			LK.effects.flashScreen(0xff0000, 800);
			// Play explosion sound when hero ship dies
			var explosionSound = LK.getSound('explosion');
			explosionSound.play();
			// Remove hero ship from game immediately
			if (hero.parent) {
				hero.parent.removeChild(hero);
			}
			// Mark hero as dead to prevent further shooting
			heroDead = true;
			// Wait for explosion sound to finish before game over
			LK.setTimeout(function () {
				LK.showGameOver();
			}, Math.max(100, Math.floor((explosionSound.duration || 1) * 1000)));
			return;
		}
		// Fire bullet
		// Reduce firing frequency: lower probability and increase cooldown
		if (a.shootCooldown <= 0) {
			if (a instanceof Alien3) {
				// Alien3: much lower probability and higher cooldown
				if (Math.random() < 0.002 + 0.0005 * wave) {
					fireAlienBullet(a);
					a.shootCooldown = 220 + Math.floor(Math.random() * 100);
				}
			} else {
				if (Math.random() < 0.006 + 0.001 * wave) {
					fireAlienBullet(a);
					a.shootCooldown = 120 + Math.floor(Math.random() * 80);
				}
			}
		}
		// Off screen (bottom) or reached hero moving zone
		if (a.y > GAME_HEIGHT - 600) {
			// If any alien reaches hero moving zone, set flag to disable bonus for this wave
			game._alienReachedHeroZone = true;
		}
		if (a.y > GAME_HEIGHT - 200) {
			LK.effects.flashScreen(0xff0000, 800);
			LK.showGameOver();
			return;
		}
		// Bounce alien off left/right borders
		if (a.x - a.width / 2 <= 0 && a.speedX < 0) {
			a.x = a.width / 2;
			a.speedX = -a.speedX;
		}
		if (a.x + a.width / 2 >= GAME_WIDTH && a.speedX > 0) {
			a.x = GAME_WIDTH - a.width / 2;
			a.speedX = -a.speedX;
		}
		// Remove alien if it goes off screen at the top
		if (a.y < -a.height) {
			a.destroy();
			aliens.splice(i, 1);
			continue;
		}
	}
	// Update powerups
	for (var i = powerups.length - 1; i >= 0; i--) {
		var p = powerups[i];
		p.update();
		if (p.y > GAME_HEIGHT + p.height) {
			p.destroy();
			powerups.splice(i, 1);
			continue;
		}
		// Collect
		if (p.intersects(hero)) {
			if (hero.powerLevel < 3) {
				hero.upgrade();
			} else {
				// Already at max power, give bonus score instead
				score += 1000;
				scoreTxt.setText(score);
			}
			// Play powerup sound when collecting a powerup
			LK.getSound('powerup').play();
			p.destroy();
			powerups.splice(i, 1);
		}
	}
	// Update coins
	for (var i = coins.length - 1; i >= 0; i--) {
		var c = coins[i];
		c.update();
		if (c.y > GAME_HEIGHT + c.height) {
			c.destroy();
			coins.splice(i, 1);
			continue;
		}
		// Collect coin
		if (c.intersects(hero)) {
			score += 500; // Give additional score for collecting coin
			scoreTxt.setText(score);
			LK.getSound('coinsound').play();
			c.destroy();
			coins.splice(i, 1);
			// Optionally play a sound here if desired
		}
	}
	// --- Wave bonus logic variables ---
	if (typeof game._waveStartTime === "undefined") {
		game._waveStartTime = Date.now();
	}
	if (typeof game._alienReachedHeroZone === "undefined") {
		game._alienReachedHeroZone = false;
	}
	// Next wave
	if (aliens.length === 0 && !game._wavePopupActive) {
		// Calculate and award wave finish bonus if no alien reached hero zone
		var bonusScore = 0;
		var waveFinishTime = Date.now();
		if (!game._alienReachedHeroZone) {
			// Bonus: 5000 - 1000 * (seconds taken, min 0), min 1000, max 5000
			var elapsedSec = Math.floor((waveFinishTime - game._waveStartTime) / 1000);
			bonusScore = Math.max(1000, 5000 - 1000 * elapsedSec);
			score += bonusScore;
			scoreTxt.setText(score);
		}
		game._wavePopupActive = true;
		// Create popup
		if (!game._wavePopup) {
			game._wavePopup = new Text2("Congratulations\nGet ready for the next wave", {
				size: 120,
				fill: 0xFFFF99,
				align: "center"
			});
			game._wavePopup.anchor.set(0.5, 0.5);
		}
		if (wave >= 10) {
			game._wavePopup.setText("Congratulations!\nYou completed all 10 waves!" + (bonusScore > 0 ? "\nWave Bonus: +" + bonusScore : ""));
		} else {
			if (bonusScore > 0) {
				game._wavePopup.setText("Congratulations\nGet ready for the next wave\nWave Bonus: +" + bonusScore);
			} else if (game._alienReachedHeroZone) {
				game._wavePopup.setText("Congratulations\nGet ready for the next wave\n(No bonus: Aliens reached your zone!)");
			} else {
				game._wavePopup.setText("Congratulations\nGet ready for the next wave");
			}
		}
		game._wavePopup.x = GAME_WIDTH / 2;
		game._wavePopup.y = GAME_HEIGHT / 2;
		if (!game._wavePopup.parent) {
			game.addChild(game._wavePopup);
		}
		// Play wavepass sound
		LK.getSound('wavepass').play();
		// Hold for 2 seconds, then start next wave or finish
		LK.setTimeout(function () {
			if (game._wavePopup && game._wavePopup.parent) {
				game._wavePopup.parent.removeChild(game._wavePopup);
			}
			if (wave >= 10) {
				LK.showYouWin();
			} else {
				wave += 1;
				spawnWave(wave);
				// Reset wave timer and alien zone flag
				game._waveStartTime = Date.now();
				game._alienReachedHeroZone = false;
				game._wavePopupActive = false;
			}
		}, 2000);
	}
};
// --- Create buttons (not added to display until game starts) ---
// Start with main menu
createMainMenu(); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Alien
var Alien = Container.expand(function () {
	var self = Container.call(this);
	var alien = self.attachAsset('alien', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = alien.width;
	self.height = alien.height;
	self.speedX = 0;
	self.speedY = 0.8;
	self.shootCooldown = 0;
	self.row = 0;
	self.col = 0;
	self.alive = true;
	self.hp = 2; // Aliens require 2 hits to be defeated
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	// Flash when hit
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Alien2
var Alien2 = Container.expand(function () {
	var self = Container.call(this);
	var alien = self.attachAsset('alien2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = alien.width;
	self.height = alien.height;
	self.speedX = 0;
	self.speedY = 0.8;
	self.shootCooldown = 0;
	self.row = 0;
	self.col = 0;
	self.alive = true;
	self.hp = 4;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Alien3
var Alien3 = Container.expand(function () {
	var self = Container.call(this);
	var alien = self.attachAsset('alien3', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = alien.width;
	self.height = alien.height;
	self.speedX = 0;
	self.speedY = 0.8;
	self.shootCooldown = 0;
	self.row = 0;
	self.col = 0;
	self.alive = true;
	self.hp = 3;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Alien Bullet
var AlienBullet = Container.expand(function () {
	var self = Container.call(this);
	var bullet = self.attachAsset('alienBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = bullet.width;
	self.height = bullet.height;
	self.speedY = 14;
	self.update = function () {
		if (typeof self.speedX === "undefined") {
			self.speedX = 0;
		}
		self.x += self.speedX;
		self.y += self.speedY;
	};
	return self;
});
// Boss
var Boss = Container.expand(function () {
	var self = Container.call(this);
	var bossAsset = self.attachAsset('Boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = bossAsset.width;
	self.height = bossAsset.height;
	self.hp = 500;
	self.speedX = 4;
	self.speedY = 0.7;
	self.alive = true;
	self.shootCooldown = 60;
	self.update = function () {
		// Move horizontally, bounce off edges
		self.x += self.speedX;
		if (self.x - self.width / 2 <= 0 && self.speedX < 0) {
			self.x = self.width / 2;
			self.speedX = -self.speedX;
		}
		if (self.x + self.width / 2 >= GAME_WIDTH && self.speedX > 0) {
			self.x = GAME_WIDTH - self.width / 2;
			self.speedX = -self.speedX;
		}
		// Boss does NOT move down in y direction anymore
		// --- Boss special events for HP thresholds ---
		// Boss event state: 0 = idle, 1 = right fired, waiting for left, 2 = left fired, waiting for right
		if (typeof self._bossEventState === "undefined") {
			self._bossEventState = 0;
			self._bossEventTimer = 0;
		}
		// HP > 300: original 5-bullet events
		if (self.hp > 300) {
			if (self._bossEventState === 0 && (!self.shootCooldown || self.shootCooldown <= 0)) {
				// Fire 5 bullets to the right at different angles
				var spread = Math.PI / 3; // 60 degrees total
				var baseAngle = Math.PI / 2 - spread / 2; // Start at 60deg
				for (var i = 0; i < 5; i++) {
					var angle = baseAngle + spread / 4 * i;
					var b = new AlienBullet();
					b.x = self.x + self.width * 0.35;
					b.y = self.y + self.height / 2 - 10;
					b.speedY = Math.sin(angle) * 16;
					b.speedX = Math.cos(angle) * 16;
					alienBullets.push(b);
					if (typeof game !== "undefined") {
						if (isInMenu) {
							game.addChild(b);
						} else {
							gameContainer.addChild(b);
						}
					}
				}
				LK.getSound('alienShoot').play();
				self._bossEventState = 1;
				self._bossEventTimer = 30; // 0.5s at 60fps
				self.shootCooldown = 60; // Prevent normal shooting for a bit
			} else if (self._bossEventState === 1) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					// Fire 5 bullets to the left at different angles
					var spread = Math.PI / 3; // 60 degrees total
					var baseAngle = Math.PI / 2 - spread / 2; // Start at 60deg
					for (var i = 0; i < 5; i++) {
						var angle = baseAngle + spread / 4 * i;
						var b = new AlienBullet();
						b.x = self.x - self.width * 0.35;
						b.y = self.y + self.height / 2 - 10;
						b.speedY = Math.sin(angle) * 16;
						b.speedX = -Math.cos(angle) * 16;
						alienBullets.push(b);
						if (typeof game !== "undefined") {
							game.addChild(b);
						}
					}
					LK.getSound('alienShoot').play();
					self._bossEventState = 2;
					self._bossEventTimer = 30; // 0.5s
					self.shootCooldown = 60;
				}
			} else if (self._bossEventState === 2) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					self._bossEventState = 0;
				}
			}
		}
		// Switch to bossmusic2 when HP drops to 300 or below
		if (typeof self._bossMusic2Played === "undefined") {
			self._bossMusic2Played = false;
		}
		if (typeof self._rage300Played === "undefined") {
			self._rage300Played = false;
		}
		if (typeof self._rage100Played === "undefined") {
			self._rage100Played = false;
		}
		if (!self._bossMusic2Played && self.hp <= 300) {
			LK.playMusic('bossmusic2');
			self._bossMusic2Played = true;
		}
		if (!self._rage300Played && self.hp <= 300) {
			LK.getSound('rage').play();
			self._rage300Played = true;
		}
		if (!self._rage100Played && self.hp <= 100) {
			LK.getSound('rage').play();
			self._rage100Played = true;
		}
		// HP between 300 and 100: 7-bullet events, alternate right/left every 0.5s
		else if (self.hp <= 300 && self.hp > 100) {
			if (self._bossEventState === 0 && (!self.shootCooldown || self.shootCooldown <= 0)) {
				// Fire 7 bullets to the right at different angles
				var spread = Math.PI * 2 / 3; // 120 degrees total
				var baseAngle = Math.PI / 2 - spread / 2; // Centered at down
				for (var i = 0; i < 7; i++) {
					var angle = baseAngle + spread / 6 * i;
					var b = new AlienBullet();
					b.x = self.x + self.width * 0.35;
					b.y = self.y + self.height / 2 - 10;
					b.speedY = Math.sin(angle) * 16;
					b.speedX = Math.cos(angle) * 16;
					alienBullets.push(b);
					if (typeof game !== "undefined") {
						game.addChild(b);
					}
				}
				LK.getSound('alienShoot').play();
				self._bossEventState = 1;
				self._bossEventTimer = 30; // 0.5s
				self.shootCooldown = 60;
			} else if (self._bossEventState === 1) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					// Fire 7 bullets to the left at different angles
					var spread = Math.PI * 2 / 3; // 120 degrees total
					var baseAngle = Math.PI / 2 - spread / 2;
					for (var i = 0; i < 7; i++) {
						var angle = baseAngle + spread / 6 * i;
						var b = new AlienBullet();
						b.x = self.x - self.width * 0.35;
						b.y = self.y + self.height / 2 - 10;
						b.speedY = Math.sin(angle) * 16;
						b.speedX = -Math.cos(angle) * 16;
						alienBullets.push(b);
						if (typeof game !== "undefined") {
							game.addChild(b);
						}
					}
					LK.getSound('alienShoot').play();
					self._bossEventState = 2;
					self._bossEventTimer = 30; // 0.5s
					self.shootCooldown = 60;
				}
			} else if (self._bossEventState === 2) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					self._bossEventState = 0;
				}
			}
		}
		// HP between 100 and 0: 9-bullet events, alternate right/left every 0.5s
		else if (self.hp <= 100 && self.hp > 0) {
			if (self._bossEventState === 0 && (!self.shootCooldown || self.shootCooldown <= 0)) {
				// Fire 9 bullets to the right at different angles
				var spread = Math.PI * 5 / 6; // 150 degrees total
				var baseAngle = Math.PI / 2 - spread / 2; // Centered at down
				for (var i = 0; i < 9; i++) {
					var angle = baseAngle + spread / 8 * i;
					var b = new AlienBullet();
					b.x = self.x + self.width * 0.35;
					b.y = self.y + self.height / 2 - 10;
					b.speedY = Math.sin(angle) * 16;
					b.speedX = Math.cos(angle) * 16;
					alienBullets.push(b);
					if (typeof game !== "undefined") {
						game.addChild(b);
					}
				}
				LK.getSound('alienShoot').play();
				self._bossEventState = 1;
				self._bossEventTimer = 30; // 0.5s
				self.shootCooldown = 60;
			} else if (self._bossEventState === 1) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					// Fire 9 bullets to the left at different angles
					var spread = Math.PI * 5 / 6; // 150 degrees total
					var baseAngle = Math.PI / 2 - spread / 2;
					for (var i = 0; i < 9; i++) {
						var angle = baseAngle + spread / 8 * i;
						var b = new AlienBullet();
						b.x = self.x - self.width * 0.35;
						b.y = self.y + self.height / 2 - 10;
						b.speedY = Math.sin(angle) * 16;
						b.speedX = -Math.cos(angle) * 16;
						alienBullets.push(b);
						if (typeof game !== "undefined") {
							game.addChild(b);
						}
					}
					LK.getSound('alienShoot').play();
					self._bossEventState = 2;
					self._bossEventTimer = 30; // 0.5s
					self.shootCooldown = 60;
				}
			} else if (self._bossEventState === 2) {
				self._bossEventTimer -= 1;
				if (self._bossEventTimer <= 0) {
					self._bossEventState = 0;
				}
			}
		} else {
			// Reset event state if HP drops below threshold or is above 300 or below/equal 0
			self._bossEventState = 0;
			self._bossEventTimer = 0;
		}
		// Shoot cooldown
		if (self.shootCooldown > 0) {
			self.shootCooldown -= 1;
		}
	};
	// Flash when hit
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 60,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	};
	return self;
});
// Coin
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var c = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = c.width;
	self.height = c.height;
	self.speedY = 12;
	self.update = function () {
		self.y += self.speedY;
	};
	return self;
});
// Hero Bullet
var HeroBullet = Container.expand(function () {
	var self = Container.call(this);
	var bullet = self.attachAsset('heroBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = bullet.width;
	self.height = bullet.height;
	self.speedY = -22;
	self.update = function () {
		if (typeof self.speedX === "undefined") {
			self.speedX = 0;
		}
		self.x += self.speedX;
		self.y += self.speedY;
	};
	return self;
});
// Hero Ship
var HeroShip = Container.expand(function () {
	var self = Container.call(this);
	var ship = self.attachAsset('heroShip', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = ship.width;
	self.height = ship.height;
	self.lives = 1;
	self.fireCooldown = 0;
	self.powerLevel = 1;
	self.invincible = false;
	self.invincibleTimer = 0;
	// Flash when hit
	self.flash = function () {
		tween(self, {
			alpha: 0.3
		}, {
			duration: 80,
			onFinish: function onFinish() {
				tween(self, {
					alpha: 1
				}, {
					duration: 120
				});
			}
		});
	};
	// Power up
	self.upgrade = function () {
		if (self.powerLevel < 3) {
			self.powerLevel += 1;
			LK.effects.flashObject(self, 0xaa66ff, 400);
		}
	};
	// Invincibility after hit
	self.setInvincible = function (duration) {
		self.invincible = true;
		self.invincibleTimer = duration;
		tween(self, {
			alpha: 0.5
		}, {
			duration: 100
		});
	};
	// Called every tick
	self.update = function () {
		if (self.invincible) {
			self.invincibleTimer -= 1;
			if (self.invincibleTimer <= 0) {
				self.invincible = false;
				self.alpha = 1;
			}
		}
		if (self.fireCooldown > 0) {
			self.fireCooldown -= 1;
		}
	};
	return self;
});
// Powerup
var Powerup = Container.expand(function () {
	var self = Container.call(this);
	var p = self.attachAsset('powerup', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = p.width;
	self.height = p.height;
	self.speedY = 15;
	self.update = function () {
		self.y += self.speedY;
	};
	return self;
});
// Star for starfield background
var Star = Container.expand(function () {
	var self = Container.call(this);
	var star = self.attachAsset('star', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = star.width;
	self.height = star.height;
	self.speedY = 2; // Slow downward movement
	self.update = function () {
		self.y += self.speedY;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Game area
// Hero ship: blue box
// Alien: green ellipse
// Hero bullet: yellow box
// Alien bullet: red box
// Power-up: purple ellipse
// Sound effects
// Music
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Menu state
var isInMenu = true;
var isInInstructions = false;
var menuContainer = new Container();
var instructionsContainer = new Container();
var gameContainer = new Container();
// Starfield variables
var stars = [];
var starSpawnTimer = 0;
// Spawn a star at random position
function spawnStar() {
	var star = new Star();
	star.x = Math.random() * GAME_WIDTH;
	star.y = -star.height;
	// Vary speed slightly for visual effect
	star.speedY = 1 + Math.random() * 2;
	stars.push(star);
	if (isInMenu) {
		menuContainer.addChild(star);
	} else if (isInInstructions) {
		instructionsContainer.addChild(star);
	} else {
		gameContainer.addChild(star);
	}
}
// Update starfield
function updateStarfield() {
	// Spawn new stars periodically
	starSpawnTimer += 1;
	var spawnRate;
	if (isInMenu || isInInstructions) {
		spawnRate = 15; // Spawn every 15 frames (4 times per second at 60fps)
	} else {
		spawnRate = 60; // Much slower spawning during gameplay (1 per second at 60fps)
	}
	if (starSpawnTimer >= spawnRate) {
		spawnStar();
		starSpawnTimer = 0;
	}
	// Update existing stars
	for (var i = stars.length - 1; i >= 0; i--) {
		var star = stars[i];
		star.update();
		// Remove stars that have moved off screen
		if (star.y > GAME_HEIGHT + star.height) {
			star.destroy();
			stars.splice(i, 1);
		}
	}
}
// Clear all stars
function clearStarfield() {
	for (var i = stars.length - 1; i >= 0; i--) {
		stars[i].destroy();
	}
	stars = [];
	starSpawnTimer = 0;
}
// Create main menu
function createMainMenu() {
	// Play menu music
	LK.playMusic('menumusic');
	// Set solid black background for menu
	game.setBackgroundColor(0x000000);
	// Menu title
	var titleText = new Text2("SPACE WARDENS", {
		size: 180,
		fill: 0xFFFFFF,
		align: "center"
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = GAME_WIDTH / 2;
	titleText.y = GAME_HEIGHT / 3;
	menuContainer.addChild(titleText);
	// Start Game button
	var startBtn = new Text2("START GAME", {
		size: 120,
		fill: 0x00FF00,
		align: "center"
	});
	startBtn.anchor.set(0.5, 0.5);
	startBtn.x = GAME_WIDTH / 2;
	startBtn.y = GAME_HEIGHT / 2;
	startBtn.interactive = true;
	startBtn.buttonMode = true;
	startBtn.down = function (x, y, obj) {
		LK.getSound('menuclick').play();
		startGame();
	};
	menuContainer.addChild(startBtn);
	// Instructions button
	var instructionsBtn = new Text2("INSTRUCTIONS", {
		size: 120,
		fill: 0x0099FF,
		align: "center"
	});
	instructionsBtn.anchor.set(0.5, 0.5);
	instructionsBtn.x = GAME_WIDTH / 2;
	instructionsBtn.y = GAME_HEIGHT / 2 + 200;
	instructionsBtn.interactive = true;
	instructionsBtn.buttonMode = true;
	instructionsBtn.down = function (x, y, obj) {
		LK.getSound('menuclick').play();
		showInstructions();
	};
	menuContainer.addChild(instructionsBtn);
	game.addChild(menuContainer);
	// Spawn initial stars
	for (var i = 0; i < 20; i++) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		menuContainer.addChild(star);
	}
}
// Show instructions
function showInstructions() {
	// Play menu music
	LK.playMusic('menumusic');
	isInMenu = false;
	isInInstructions = true;
	// Remove menu container
	if (menuContainer.parent) {
		menuContainer.parent.removeChild(menuContainer);
	}
	// Clear instructions container
	while (instructionsContainer.children.length > 0) {
		instructionsContainer.removeChild(instructionsContainer.children[0]);
	}
	// Set solid black background for instructions
	game.setBackgroundColor(0x000000);
	// Instructions title
	var titleText = new Text2("INSTRUCTIONS", {
		size: 150,
		fill: 0xFFFF99,
		align: "center"
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = GAME_WIDTH / 2;
	titleText.y = GAME_HEIGHT / 4;
	instructionsContainer.addChild(titleText);
	// Instructions content
	var instructionsText = new Text2("HOW TO PLAY:\n\nDrag your ship to move\nCollect power-ups to upgrade your ship\nCollect coins for extra score\nDefeat all aliens to win a wave\nDefeat Lohar to win game!", {
		size: 80,
		fill: 0xFFFF99,
		align: "center"
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = GAME_WIDTH / 2;
	instructionsText.y = GAME_HEIGHT / 2;
	instructionsContainer.addChild(instructionsText);
	// Back button
	var backBtn = new Text2("BACK TO MENU", {
		size: 100,
		fill: 0xFF6600,
		align: "center"
	});
	backBtn.anchor.set(0.5, 0.5);
	backBtn.x = GAME_WIDTH / 2;
	backBtn.y = GAME_HEIGHT * 3 / 4;
	backBtn.interactive = true;
	backBtn.buttonMode = true;
	backBtn.down = function (x, y, obj) {
		LK.getSound('menuclick').play();
		returnToMenu();
	};
	instructionsContainer.addChild(backBtn);
	// Add instructions container to game
	game.addChild(instructionsContainer);
	// Transfer existing stars from menu to instructions container
	for (var i = 0; i < stars.length; i++) {
		var star = stars[i];
		if (star.parent) {
			star.parent.removeChild(star);
		}
		instructionsContainer.addChild(star);
	}
	// Only spawn additional stars if we have fewer than 20
	while (stars.length < 20) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		instructionsContainer.addChild(star);
	}
}
// Return to main menu from instructions
function returnToMenu() {
	// Play menu music
	LK.playMusic('menumusic');
	isInMenu = true;
	isInInstructions = false;
	// Remove instructions container
	if (instructionsContainer.parent) {
		instructionsContainer.parent.removeChild(instructionsContainer);
	}
	// Add menu container back
	game.addChild(menuContainer);
	// Transfer existing stars from instructions to menu container
	for (var i = 0; i < stars.length; i++) {
		var star = stars[i];
		if (star.parent) {
			star.parent.removeChild(star);
		}
		menuContainer.addChild(star);
	}
	// Only spawn additional stars if we have fewer than 20
	while (stars.length < 20) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		menuContainer.addChild(star);
	}
}
// Start the game
function startGame() {
	isInMenu = false;
	// Remove menu container
	if (menuContainer.parent) {
		menuContainer.parent.removeChild(menuContainer);
	}
	// Add game container
	game.addChild(gameContainer);
	// Play music
	LK.playMusic('bgmusic');
	// Clear starfield when starting game
	clearStarfield();
	// Spawn much fewer initial stars for gameplay (only 5 instead of 20)
	for (var i = 0; i < 5; i++) {
		var star = new Star();
		star.x = Math.random() * GAME_WIDTH;
		star.y = Math.random() * GAME_HEIGHT;
		star.speedY = 1 + Math.random() * 2;
		stars.push(star);
		gameContainer.addChild(star);
	}
	// Initialize game elements
	initializeGame();
}
// Initialize game elements
function initializeGame() {
	// Move hero to game container
	if (hero.parent) {
		hero.parent.removeChild(hero);
	}
	gameContainer.addChild(hero);
	// Move remaining buttons to game container (buttons removed)
	// Start first wave
	spawnWave(wave);
	heroDead = false;
	// Initial score
	scoreTxt.setText(score);
}
// Score
var score = 0;
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Wave
var wave = 1;
var waveTxt = new Text2('Wave 1', {
	size: 70,
	fill: 0xAAFFFF
});
waveTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(waveTxt);
waveTxt.y = 120;
// Hero (created but not added to display until game starts)
var hero = new HeroShip();
hero.x = GAME_WIDTH / 2;
hero.y = GAME_HEIGHT - 220;
// Bullets, aliens, powerups, coins
var heroBullets = [];
var alienBullets = [];
var aliens = [];
var powerups = [];
var coins = [];
// Dragging
var dragNode = null;
// Track if hero is dead (prevents shooting after death)
var heroDead = false;
// Alien formation
function spawnWave(waveNum) {
	// Remove old aliens
	for (var i = aliens.length - 1; i >= 0; i--) {
		aliens[i].destroy();
		aliens.splice(i, 1);
	}
	if (waveNum === 10) {
		// Play boss music at start of wave 10
		LK.playMusic('bossmusic');
		// Only spawn the boss for wave 10
		var boss = new Boss();
		boss.x = GAME_WIDTH / 2;
		boss.y = 320;
		aliens.push(boss);
		if (isInMenu) {
			game.addChild(boss);
		} else {
			gameContainer.addChild(boss);
		}
		waveTxt.setText('Wave ' + waveNum);
		// Reset wave timer and alien zone flag for new wave
		game._waveStartTime = Date.now();
		game._alienReachedHeroZone = false;
		// Track boss spawn time for bonus
		game._bossSpawnTime = Date.now();
		game._bossBonusGiven = false;
		return;
	}
	// Formation: rows, cols, spacing
	var rows, cols;
	if (waveNum === 2) {
		// Reduce total aliens at wave 2, but keep it more than wave 1 (wave 1 default: rows=3, cols=6 = 18)
		// Let's use rows=4, cols=6 = 24 aliens (wave 1: 18, wave 2: 24, wave 3: 35)
		rows = 4;
		cols = 6;
	} else if (waveNum === 3) {
		// Reduce total aliens at wave 3, but more than wave 2 (wave 2 default: rows=4, cols=8 = 32)
		// Let's use rows=5, cols=7 = 35 aliens (wave 2 would be 32, wave 3 default would be 5,10=50)
		rows = 5;
		cols = 7;
	} else if (waveNum === 4) {
		rows = 3;
		cols = 5;
	} else if (waveNum === 5) {
		// More than wave 4, but less than default for wave 5 (default would be rows=6, cols=10)
		rows = 4;
		cols = 7;
	} else if (waveNum === 6) {
		// Slightly more than wave 5
		rows = 5;
		cols = 8;
	} else if (waveNum === 7) {
		// Reduce a little bit more from wave 6
		rows = 3;
		cols = 7;
	} else if (waveNum === 8) {
		// Decrease total alien number in wave 8 a little bit (but still more than wave 7)
		rows = 4;
		cols = 6;
	} else if (waveNum === 9) {
		// Reduce total alien number a little bit compared to wave 8
		rows = 3;
		cols = 8;
	} else {
		rows = Math.min(2 + waveNum, 6);
		cols = Math.min(4 + waveNum * 2, 10);
	}
	var spacingX = 160;
	var spacingY = 140;
	var startX = (GAME_WIDTH - (cols - 1) * spacingX) / 2;
	var startY = 220 + (waveNum - 1) * 30;
	for (var r = 0; r < rows; r++) {
		for (var c = 0; c < cols; c++) {
			var alien;
			if (waveNum === 4 || waveNum === 5) {
				alien = new Alien2();
			} else if (waveNum === 6) {
				// 70% Alien2, 30% Alien
				if (Math.random() < 0.7) {
					alien = new Alien2();
				} else {
					alien = new Alien();
				}
			} else if (waveNum === 7) {
				// 30% Alien3, 70% Alien
				if (Math.random() < 0.3) {
					alien = new Alien3();
				} else {
					alien = new Alien();
				}
			} else if (waveNum === 8) {
				// 50% Alien2, 50% Alien3
				if (Math.random() < 0.5) {
					alien = new Alien2();
				} else {
					alien = new Alien3();
				}
			} else if (waveNum === 9) {
				// All Alien3 for wave 9
				alien = new Alien3();
			} else {
				alien = new Alien();
			}
			alien.x = startX + c * spacingX;
			alien.y = startY + r * spacingY;
			alien.row = r;
			alien.col = c;
			alien.speedX = Math.sin((r * cols + c + waveNum) * 0.7) * 1.5 + (Math.random() - 0.5) * 0.5;
			alien.speedY = 0.7 + 0.1 * waveNum + (Math.random() - 0.5) * 0.2;
			alien.shootCooldown = 60 + Math.floor(Math.random() * 60);
			aliens.push(alien);
			if (isInMenu) {
				game.addChild(alien);
			} else {
				gameContainer.addChild(alien);
			}
		}
	}
	waveTxt.setText('Wave ' + waveNum);
	// Reset wave timer and alien zone flag for new wave
	game._waveStartTime = Date.now();
	game._alienReachedHeroZone = false;
}
// Powerup spawn
function maybeSpawnPowerup(x, y) {
	if (Math.random() < 0.03) {
		var p = new Powerup();
		p.x = x;
		p.y = y;
		powerups.push(p);
		game.addChild(p);
	}
}
// Coin spawn (lower probability than powerup)
function maybeSpawnCoin(x, y) {
	// Powerup is 0.03, so coin should be less, but increase coin drop rate (e.g. 0.02)
	if (Math.random() < 0.02) {
		var c = new Coin();
		c.x = x;
		c.y = y;
		coins.push(c);
		game.addChild(c);
	}
}
// Fire hero bullets
function fireHeroBullets() {
	if (heroDead) {
		return;
	}
	if (hero.fireCooldown > 0) {
		return;
	}
	var b;
	if (hero.powerLevel === 1) {
		b = new HeroBullet();
		b.x = hero.x;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		gameContainer.addChild(b);
	} else if (hero.powerLevel === 2) {
		b = new HeroBullet();
		b.x = hero.x - 38;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
		b = new HeroBullet();
		b.x = hero.x + 38;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
	} else if (hero.powerLevel === 3) {
		// 3 straight bullets
		b = new HeroBullet();
		b.x = hero.x - 60;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
		b = new HeroBullet();
		b.x = hero.x;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
		b = new HeroBullet();
		b.x = hero.x + 60;
		b.y = hero.y - hero.height / 2 + 30;
		heroBullets.push(b);
		game.addChild(b);
	}
	hero.fireCooldown = 12;
	LK.getSound('shoot').play();
}
// Fire alien bullet
function fireAlienBullet(alien) {
	// If Alien3, fire triple bullets at different angles
	if (alien instanceof Alien3) {
		// Center bullet (straight down)
		var b0 = new AlienBullet();
		b0.x = alien.x;
		b0.y = alien.y + alien.height / 2 + 10;
		b0.speedY = 14;
		b0.speedX = 0;
		alienBullets.push(b0);
		game.addChild(b0);
		// Left bullet (angle -20deg)
		var b1 = new AlienBullet();
		b1.x = alien.x;
		b1.y = alien.y + alien.height / 2 + 10;
		var angle1 = Math.PI / 2 - Math.PI / 9; // 70deg
		b1.speedY = Math.sin(angle1) * 14;
		b1.speedX = Math.cos(angle1) * 14;
		alienBullets.push(b1);
		game.addChild(b1);
		// Right bullet (angle +20deg)
		var b2 = new AlienBullet();
		b2.x = alien.x;
		b2.y = alien.y + alien.height / 2 + 10;
		var angle2 = Math.PI / 2 + Math.PI / 9; // 110deg
		b2.speedY = Math.sin(angle2) * 14;
		b2.speedX = Math.cos(angle2) * 14;
		alienBullets.push(b2);
		game.addChild(b2);
		LK.getSound('alienShoot').play();
	} else {
		// Default: single bullet straight down
		var b = new AlienBullet();
		b.x = alien.x;
		b.y = alien.y + alien.height / 2 + 10;
		alienBullets.push(b);
		game.addChild(b);
		LK.getSound('alienShoot').play();
	}
}
// Move handler (drag hero)
function handleMove(x, y, obj) {
	if (dragNode) {
		// Clamp to game area, avoid top 100px (menu)
		var nx = Math.max(hero.width / 2, Math.min(GAME_WIDTH - hero.width / 2, x));
		var ny = Math.max(GAME_HEIGHT - 600, Math.min(GAME_HEIGHT - hero.height / 2, y));
		dragNode.x = nx;
		dragNode.y = ny;
	}
}
game.move = handleMove;
game.down = function (x, y, obj) {
	// Only drag if touch is on hero
	var local = hero.toLocal(game.toGlobal({
		x: x,
		y: y
	}));
	if (local.x > -hero.width / 2 && local.x < hero.width / 2 && local.y > -hero.height / 2 && local.y < hero.height / 2) {
		dragNode = hero;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Tap to shoot
game.tap = function (x, y, obj) {
	fireHeroBullets();
};
// Main update
game.update = function () {
	// Hide score and wave indicator in menu and instructions
	if (isInMenu || isInInstructions) {
		scoreTxt.visible = false;
		waveTxt.visible = false;
		updateStarfield();
		return;
	} else {
		// Show score and wave indicator during gameplay
		scoreTxt.visible = true;
		waveTxt.visible = true;
		updateStarfield(); // Update starfield during gameplay too
	}
	// Hero update
	hero.update();
	// Fire hero bullets automatically if holding
	if (dragNode === hero && LK.ticks % 6 === 0) {
		fireHeroBullets();
	}
	// Update hero bullets
	for (var i = heroBullets.length - 1; i >= 0; i--) {
		var b = heroBullets[i];
		b.update();
		// Off screen
		if (b.y < -b.height) {
			b.destroy();
			heroBullets.splice(i, 1);
			continue;
		}
		// Hit alien
		for (var j = aliens.length - 1; j >= 0; j--) {
			var a = aliens[j];
			if (a.alive && b.intersects(a)) {
				a.flash();
				a.hp -= 1;
				b.destroy();
				heroBullets.splice(i, 1);
				if (a.hp <= 0) {
					a.alive = false;
					a.destroy();
					aliens.splice(j, 1);
					if (a instanceof Boss) {
						score += 5000;
						// Award additional 7500 score if boss is defeated within 45 seconds after wave 10 starts
						if (typeof game._bossSpawnTime !== "undefined" && typeof game._bossBonusGiven !== "undefined" && !game._bossBonusGiven && Date.now() - game._bossSpawnTime <= 45000) {
							score += 7500;
							game._bossBonusGiven = true;
							// Optionally, you can show a popup or effect here if desired
						}
					} else if (a instanceof Alien3) {
						score += Math.floor(100 * 1.2 * 2);
					} else if (a instanceof Alien2) {
						score += Math.floor(100 * 1.2);
					} else {
						score += 100;
					}
					scoreTxt.setText(score);
					maybeSpawnPowerup(a.x, a.y);
					maybeSpawnCoin(a.x, a.y);
					// If this is the boss, play bossexplosion sounds in sequence
					if (a instanceof Boss) {
						LK.getSound('bossexplosion').play();
						LK.setTimeout(function () {
							LK.getSound('bossexplosion2').play();
						}, 300);
						LK.setTimeout(function () {
							LK.getSound('bossexplosion3').play();
						}, 600);
						LK.setTimeout(function () {
							LK.getSound('bossexplosion4').play();
						}, 900);
					} else {
						LK.getSound('alienexplosion').play();
					}
				}
				break;
			}
		}
	}
	// Update alien bullets
	for (var i = alienBullets.length - 1; i >= 0; i--) {
		var b = alienBullets[i];
		b.update();
		if (b.y > GAME_HEIGHT + b.height) {
			b.destroy();
			alienBullets.splice(i, 1);
			continue;
		}
		// Hit hero
		if (!hero.invincible && b.intersects(hero)) {
			hero.flash();
			hero.setInvincible(60);
			b.destroy();
			alienBullets.splice(i, 1);
			// Explosion effect at hero ship position
			LK.effects.flashObject(hero, 0xffe066, 700);
			LK.effects.flashScreen(0xff0000, 400);
			// Play explosion sound when hero ship dies
			var explosionSound = LK.getSound('explosion');
			explosionSound.play();
			// Remove hero ship from game immediately
			if (hero.parent) {
				hero.parent.removeChild(hero);
			}
			// Mark hero as dead to prevent further shooting
			heroDead = true;
			// Wait for explosion sound to finish before game over
			LK.setTimeout(function () {
				LK.showGameOver();
			}, Math.max(100, Math.floor((explosionSound.duration || 1) * 1000)));
			return;
		}
	}
	// Update aliens
	for (var i = aliens.length - 1; i >= 0; i--) {
		var a = aliens[i];
		a.update();
		// Game over if alien touches hero ship
		if (a.alive && !hero.invincible && a.intersects(hero)) {
			hero.flash();
			// Explosion effect at hero ship position
			LK.effects.flashObject(hero, 0xffe066, 700);
			LK.effects.flashScreen(0xff0000, 800);
			// Play explosion sound when hero ship dies
			var explosionSound = LK.getSound('explosion');
			explosionSound.play();
			// Remove hero ship from game immediately
			if (hero.parent) {
				hero.parent.removeChild(hero);
			}
			// Mark hero as dead to prevent further shooting
			heroDead = true;
			// Wait for explosion sound to finish before game over
			LK.setTimeout(function () {
				LK.showGameOver();
			}, Math.max(100, Math.floor((explosionSound.duration || 1) * 1000)));
			return;
		}
		// Fire bullet
		// Reduce firing frequency: lower probability and increase cooldown
		if (a.shootCooldown <= 0) {
			if (a instanceof Alien3) {
				// Alien3: much lower probability and higher cooldown
				if (Math.random() < 0.002 + 0.0005 * wave) {
					fireAlienBullet(a);
					a.shootCooldown = 220 + Math.floor(Math.random() * 100);
				}
			} else {
				if (Math.random() < 0.006 + 0.001 * wave) {
					fireAlienBullet(a);
					a.shootCooldown = 120 + Math.floor(Math.random() * 80);
				}
			}
		}
		// Off screen (bottom) or reached hero moving zone
		if (a.y > GAME_HEIGHT - 600) {
			// If any alien reaches hero moving zone, set flag to disable bonus for this wave
			game._alienReachedHeroZone = true;
		}
		if (a.y > GAME_HEIGHT - 200) {
			LK.effects.flashScreen(0xff0000, 800);
			LK.showGameOver();
			return;
		}
		// Bounce alien off left/right borders
		if (a.x - a.width / 2 <= 0 && a.speedX < 0) {
			a.x = a.width / 2;
			a.speedX = -a.speedX;
		}
		if (a.x + a.width / 2 >= GAME_WIDTH && a.speedX > 0) {
			a.x = GAME_WIDTH - a.width / 2;
			a.speedX = -a.speedX;
		}
		// Remove alien if it goes off screen at the top
		if (a.y < -a.height) {
			a.destroy();
			aliens.splice(i, 1);
			continue;
		}
	}
	// Update powerups
	for (var i = powerups.length - 1; i >= 0; i--) {
		var p = powerups[i];
		p.update();
		if (p.y > GAME_HEIGHT + p.height) {
			p.destroy();
			powerups.splice(i, 1);
			continue;
		}
		// Collect
		if (p.intersects(hero)) {
			if (hero.powerLevel < 3) {
				hero.upgrade();
			} else {
				// Already at max power, give bonus score instead
				score += 1000;
				scoreTxt.setText(score);
			}
			// Play powerup sound when collecting a powerup
			LK.getSound('powerup').play();
			p.destroy();
			powerups.splice(i, 1);
		}
	}
	// Update coins
	for (var i = coins.length - 1; i >= 0; i--) {
		var c = coins[i];
		c.update();
		if (c.y > GAME_HEIGHT + c.height) {
			c.destroy();
			coins.splice(i, 1);
			continue;
		}
		// Collect coin
		if (c.intersects(hero)) {
			score += 500; // Give additional score for collecting coin
			scoreTxt.setText(score);
			LK.getSound('coinsound').play();
			c.destroy();
			coins.splice(i, 1);
			// Optionally play a sound here if desired
		}
	}
	// --- Wave bonus logic variables ---
	if (typeof game._waveStartTime === "undefined") {
		game._waveStartTime = Date.now();
	}
	if (typeof game._alienReachedHeroZone === "undefined") {
		game._alienReachedHeroZone = false;
	}
	// Next wave
	if (aliens.length === 0 && !game._wavePopupActive) {
		// Calculate and award wave finish bonus if no alien reached hero zone
		var bonusScore = 0;
		var waveFinishTime = Date.now();
		if (!game._alienReachedHeroZone) {
			// Bonus: 5000 - 1000 * (seconds taken, min 0), min 1000, max 5000
			var elapsedSec = Math.floor((waveFinishTime - game._waveStartTime) / 1000);
			bonusScore = Math.max(1000, 5000 - 1000 * elapsedSec);
			score += bonusScore;
			scoreTxt.setText(score);
		}
		game._wavePopupActive = true;
		// Create popup
		if (!game._wavePopup) {
			game._wavePopup = new Text2("Congratulations\nGet ready for the next wave", {
				size: 120,
				fill: 0xFFFF99,
				align: "center"
			});
			game._wavePopup.anchor.set(0.5, 0.5);
		}
		if (wave >= 10) {
			game._wavePopup.setText("Congratulations!\nYou completed all 10 waves!" + (bonusScore > 0 ? "\nWave Bonus: +" + bonusScore : ""));
		} else {
			if (bonusScore > 0) {
				game._wavePopup.setText("Congratulations\nGet ready for the next wave\nWave Bonus: +" + bonusScore);
			} else if (game._alienReachedHeroZone) {
				game._wavePopup.setText("Congratulations\nGet ready for the next wave\n(No bonus: Aliens reached your zone!)");
			} else {
				game._wavePopup.setText("Congratulations\nGet ready for the next wave");
			}
		}
		game._wavePopup.x = GAME_WIDTH / 2;
		game._wavePopup.y = GAME_HEIGHT / 2;
		if (!game._wavePopup.parent) {
			game.addChild(game._wavePopup);
		}
		// Play wavepass sound
		LK.getSound('wavepass').play();
		// Hold for 2 seconds, then start next wave or finish
		LK.setTimeout(function () {
			if (game._wavePopup && game._wavePopup.parent) {
				game._wavePopup.parent.removeChild(game._wavePopup);
			}
			if (wave >= 10) {
				LK.showYouWin();
			} else {
				wave += 1;
				spawnWave(wave);
				// Reset wave timer and alien zone flag
				game._waveStartTime = Date.now();
				game._alienReachedHeroZone = false;
				game._wavePopupActive = false;
			}
		}, 2000);
	}
};
// --- Create buttons (not added to display until game starts) ---
// Start with main menu
createMainMenu();
 Space ship with guns. In-Game asset. 2d. High contrast. No shadows
 A green alien ship. In-Game asset. 2d. High contrast. No shadows
 A navy blue alien ship. In-Game asset. 2d. High contrast. No shadows
 A dark purple alien ship. In-Game asset. 2d. High contrast. No shadows
 A coin having saturn logo. In-Game asset. 2d. High contrast. No shadows
 A power-up logo for spaceships. In-Game asset. 2d. High contrast. No shadows
 Giant bordeux ostentatious alien ship with ostentatious giant guns. Looking straightly down In-Game asset. 2d. High contrast. No shadows
 red dot. In-Game asset. 2d. High contrast. No shadows
 light yellow dot. In-Game asset. 2d. High contrast. No shadows
bgmusic
Music
explosion
Sound effect
alienexplosion
Sound effect
powerup
Sound effect
wavepass
Sound effect
coinsound
Sound effect
shoot
Sound effect
alienShoot
Sound effect
bossmusic
Music
bossmusic2
Music
bossexplosion
Sound effect
bossexplosion2
Sound effect
bossexplosion3
Sound effect
bossexplosion4
Sound effect
bosswin
Sound effect
rage
Sound effect
menumusic
Music
menuclick
Sound effect