/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Beam item class
var BeamItem = Container.expand(function () {
	var self = Container.call(this);
	var beamSprite = self.attachAsset('beamItem', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	beamSprite.width = 90;
	beamSprite.height = 90;
	beamSprite.alpha = 0.95;
	self.update = function () {
		self.y += 6;
	};
	return self;
});
// Enemy type 1: moves straight down
var Enemy1 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('enemy1', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 200;
	enemySprite.height = 200;
	self.speed = 2 + Math.random() * 1;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Enemy type 2: moves in sine wave
var Enemy2 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('enemy2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 160;
	enemySprite.height = 160;
	self.speed = 3.5 + Math.random() * 1.5;
	self.waveAmplitude = 120 + Math.random() * 80;
	self.waveSpeed = 0.012 + Math.random() * 0.005;
	self.baseX = 0;
	self.t = 0;
	self.update = function () {
		self.y += self.speed;
		self.t += self.waveSpeed;
		self.x = self.baseX + Math.sin(self.t * 6.28) * self.waveAmplitude;
	};
	return self;
});
// Strong Enemy3: needs 5 hits to die, moves straight down, larger and purple
var Enemy3 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('enemy3', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 260;
	enemySprite.height = 260;
	self.speed = 3 + Math.random() * 1;
	self.hp = 5;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Enemy4: new enemy type, moves diagonally, bounces off screen edges, explodes when near hero, needs 3 hits to die
var Enemy4 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('Enemy4', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 180;
	enemySprite.height = 180;
	self.speedX = (Math.random() < 0.5 ? 1 : -1) * (3.5 + Math.random() * 1.5);
	self.speedY = 3.5 + Math.random() * 1.5;
	self.exploded = false;
	self.hp = 3; // Needs 3 hits to die
	self.update = function () {
		// --- Enemy4 follows the hero ---
		// Only follow if hero exists and Enemy4 is not exploded
		if (typeof hero !== "undefined" && !self.exploded) {
			// Calculate direction vector to hero
			var dx = hero.x - self.x;
			var dy = hero.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// Set speed to always move at a fixed speed toward the hero
			var speed = 8; // Enemy4's following speed (slower movement)
			if (dist > 0) {
				self.speedX = dx / dist * speed;
				self.speedY = dy / dist * speed;
			}
		}
		self.x += self.speedX;
		self.y += self.speedY;
		// Bounce off left/right edges
		if (self.x - enemySprite.width / 2 <= 0 && self.speedX < 0 || self.x + enemySprite.width / 2 >= 2048 && self.speedX > 0) {
			self.speedX *= -1;
		}
		// --- Enemy4 explodes and deals 2 damage when near or colliding with hero ---
		if (typeof hero !== "undefined" && !self.exploded && (
		// Collides with hero
		self.intersects(hero) ||
		// Or is "near" hero (distance < 120px)
		Math.abs(self.x - hero.x) < 120 && Math.abs(self.y - hero.y) < 120)) {
			self.exploded = true;
			// Tiny flash/explosion effect on Enemy4 itself
			LK.effects.flashObject(self, 0xffffff, 120);
			// Only deal damage if not in godMode or shieldActive
			if (!godMode && !shieldActive) {
				LK.getSound('heroHit').play();
				LK.effects.flashScreen(0xff0000, 800);
				if (typeof heroHealth !== "undefined") {
					heroHealth -= 2;
					if (heroHealth < 0) heroHealth = 0;
					if (typeof updateHealthBar === "function") updateHealthBar();
					if (typeof updateDemoHealthSquares === "function") updateDemoHealthSquares();
					if (heroHealth <= 0) {
						LK.getSound('Death').play();
						LK.showGameOver();
						return;
					}
				}
			} else if (shieldActive) {
				LK.effects.flashObject(hero, 0x00ffff, 200);
			}
			// Play explosion animation (particles)
			var particleCount = 16;
			for (var pi = 0; pi < particleCount; pi++) {
				var part = LK.getAsset('Enemy4', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				part.x = self.x;
				part.y = self.y;
				part.width = 24 + Math.random() * 24;
				part.height = 24 + Math.random() * 24;
				part.alpha = 0.8 + Math.random() * 0.2;
				var angle = Math.PI * 2 * (pi / particleCount) + Math.random() * 0.2;
				var speed = 12 + Math.random() * 8;
				var vx = Math.cos(angle) * speed;
				var vy = Math.sin(angle) * speed;
				part.life = 10 + Math.floor(Math.random() * 10);
				part.update = function () {
					this.x += vx;
					this.y += vy;
					this.life--;
					this.alpha *= 0.88 + Math.random() * 0.06;
					if (this.life <= 0) {
						this.destroy();
					}
				};
				if (typeof game !== "undefined") game.addChild(part);
			}
			// Remove Enemy4 from game/enemies array on next update
			if (typeof self.destroy === "function") self.destroy();
			// Remove from enemies[] in main game.update (handled by main loop)
			return;
		}
		// Enemy4 now ignores proximity to hero and does not explode or interact when flying through the hero
	};
	return self;
});
// Enemy bullet class
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletSprite = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speedX = 0;
	self.speedY = 8;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
	};
	return self;
});
// Extraordinary EnemyX: spawns only once after 250 score, unique appearance and behavior
var EnemyX = Container.expand(function () {
	var self = Container.call(this);
	// Use dedicated enemyX asset
	var enemySprite = self.attachAsset('enemyX', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 600;
	enemySprite.height = 600;
	enemySprite.alpha = 0.98;
	self.speed = 4 + Math.random() * 2;
	// Set EnemyX health to 250 only in normal mode, otherwise 500 (boss mode)
	self.hp = typeof bossMode !== "undefined" && bossMode ? 500 : 250; // much higher HP (500 hits required)
	// --- EnemyX shooting logic ---
	self.shootTick = 0;
	self.beamCooldown = 0;
	self.update = function () {
		// Boss mode: randomly drop health potion, shield, or beam items from EnemyX (less frequently)
		if (typeof bossMode !== "undefined" && bossMode && Math.random() < 0.005) {
			// 1/3 chance for each item
			var dropType = Math.floor(Math.random() * 3);
			var item;
			if (dropType === 0) {
				item = new HealthPotion();
			} else if (dropType === 1) {
				item = new ShieldItem();
			} else {
				item = new BeamItem();
			}
			item.x = self.x + (Math.random() - 0.5) * 120;
			item.y = self.y + 120;
			if (typeof items !== "undefined" && typeof game !== "undefined") {
				items.push(item);
				game.addChild(item);
			}
		}
		// Only allow EnemyX to wander in the upper part of the screen (y between 0 and 500)
		if (typeof self.t === "undefined") self.t = Math.random() * 2;
		self.t += 0.012;
		// Sway left/right slowly
		self.x += Math.sin(self.t * 2.5) * 6;
		// Restrict vertical movement: only allow y to increase up to a certain limit, then bounce back up
		if (typeof self.directionY === "undefined") self.directionY = 1;
		// Set upper and lower bounds for wandering
		var upperY = 60 + enemySprite.height / 2;
		var lowerY = 420 + enemySprite.height / 2;
		// Move down or up depending on direction
		self.y += self.speed * self.directionY * 0.3; // even slower vertical movement
		// If reached lower bound, go up; if reached upper bound, go down
		if (self.y >= lowerY) {
			self.y = lowerY;
			self.directionY = -1;
		} else if (self.y <= upperY) {
			self.y = upperY;
			self.directionY = 1;
		}
		// --- Shooting less frequently ---
		self.shootTick = (self.shootTick || 0) + 1;
		self.beamCooldown = (self.beamCooldown || 0) - 1;
		// Shoot a bullet every 60-90 ticks (randomized, less frequent)
		if (self.shootTick >= 60 + Math.floor(Math.random() * 31)) {
			if (typeof game !== "undefined" && typeof hero !== "undefined") {
				// Shoot 3-way spread
				for (var i = -1; i <= 1; i++) {
					var bullet = new EnemyBullet();
					bullet.x = self.x + i * 60;
					bullet.y = self.y + 120;
					// Aim at hero, but with spread
					var dx = hero.x - bullet.x + i * 80;
					var dy = hero.y - bullet.y;
					var len = Math.sqrt(dx * dx + dy * dy);
					if (len > 0) {
						bullet.speedX = dx / len * 10;
						bullet.speedY = dy / len * 10;
					}
					enemyBullets.push(bullet);
					game.addChild(bullet);
					LK.getSound('enemyShoot').play();
				}
			}
			self.shootTick = 0;
		}
		// Sometimes shoot a beam down (every 360-540 ticks, much more rare, and only hit when visually active)
		if (self.beamCooldown <= 0 && Math.random() < 0.012) {
			if (typeof game !== "undefined") {
				// Visual: big vertical beam
				var beam = LK.getAsset('beamItem', {
					anchorX: 0.5,
					anchorY: 0,
					x: self.x,
					y: self.y + enemySprite.height / 2
				});
				beam.width = 120;
				beam.height = 2732 - (self.y + enemySprite.height / 2);
				beam.alpha = 0.38 + Math.random() * 0.12;
				game.addChild(beam);
				// Beam effect: damage hero if in column for 60 frames, but only on first 20 frames is it "active"
				beam.life = 60;
				beam.activeFrames = 20;
				beam.update = function () {
					this.life--;
					// Flicker effect
					this.alpha = 0.32 + Math.random() * 0.18;
					// Only hit hero if beam is visually active (first 20 frames)
					if (this.life > 60 - this.activeFrames) {
						if (typeof hero !== "undefined" && hero.y > this.y && hero.y < this.y + this.height) {
							if (Math.abs(hero.x - this.x) < this.width / 2 + hero.width / 2) {
								if (!godMode && !shieldActive && this.life === 60 - this.activeFrames + 1) {
									LK.getSound('heroHit').play();
									LK.effects.flashScreen(0xff0000, 800);
									heroHealth--;
									updateHealthBar();
									updateDemoHealthSquares && updateDemoHealthSquares();
									if (heroHealth <= 0) {
										LK.getSound('Death').play();
										LK.showGameOver();
										return;
									}
								} else if (!godMode && shieldActive && this.life === 60 - this.activeFrames + 1) {
									LK.effects.flashObject(hero, 0x00ffff, 200);
								}
							}
						}
					}
					if (this.life <= 0) {
						this.destroy();
					}
				};
				// Add to enemyBullets for update/removal
				enemyBullets.push(beam);
				// Play laser sound
				LK.getSound('laser').play();
				// Set cooldown for next beam (much more rare)
				self.beamCooldown = 540 + Math.floor(Math.random() * 180);
			}
		}
	};
	return self;
});
// EnemyZ: New boss type, appears as a large, fast, zig-zagging boss with high HP and double beam attack
var EnemyZ = Container.expand(function () {
	var self = Container.call(this);
	// Use enemyZ asset, large size
	var enemySprite = self.attachAsset('EnemyZ', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 520;
	enemySprite.height = 520;
	enemySprite.alpha = 0.99;
	self.speed = 4 + Math.random() * 1.5;
	self.hp = Math.round((typeof bossMode !== "undefined" && bossMode ? 500 : 250) * 8 / 5); // Set EnemyZ health to 8/5 of EnemyX health
	self.t = Math.random() * 2;
	self.zigzagAmplitude = 320 + Math.random() * 80;
	self.zigzagSpeed = 0.009 + Math.random() * 0.004;
	self.baseX = 2048 / 2;
	self.directionY = 1;
	self.shootTick = 0;
	self.beamCooldown = 0;
	self.update = function () {
		// Zig-zag movement, stays in upper half of screen
		self.t += self.zigzagSpeed;
		self.x = self.baseX + Math.sin(self.t * 2.5) * self.zigzagAmplitude;
		// Restrict vertical movement: only allow y to increase up to a certain limit, then bounce back up
		var upperY = 80 + enemySprite.height / 2;
		var lowerY = 600 + enemySprite.height / 2;
		self.y += self.speed * self.directionY * 0.3;
		if (self.y >= lowerY) {
			self.y = lowerY;
			self.directionY = -1;
		} else if (self.y <= upperY) {
			self.y = upperY;
			self.directionY = 1;
		}
		// --- Shooting logic: fires 5-way spread every 48-72 ticks ---
		self.shootTick = (self.shootTick || 0) + 1;
		self.beamCooldown = (self.beamCooldown || 0) - 1;
		if (self.shootTick >= 48 + Math.floor(Math.random() * 25)) {
			if (typeof game !== "undefined" && typeof hero !== "undefined") {
				// Shoot 5-way spread
				for (var i = -2; i <= 2; i++) {
					var bullet = new EnemyBullet();
					bullet.x = self.x + i * 60;
					bullet.y = self.y + 120;
					// Aim at hero, but with spread
					var dx = hero.x - bullet.x + i * 60;
					var dy = hero.y - bullet.y;
					var len = Math.sqrt(dx * dx + dy * dy);
					if (len > 0) {
						bullet.speedX = dx / len * 11;
						bullet.speedY = dy / len * 11;
					}
					enemyBullets.push(bullet);
					game.addChild(bullet);
					LK.getSound('enemyShoot').play();
				}
			}
			self.shootTick = 0;
		}
		// --- Double beam attack: two beams at once, more frequent than EnemyX ---
		if (self.beamCooldown <= 0 && Math.random() < 0.025) {
			if (typeof game !== "undefined") {
				// Visual: two vertical beams, one at self.x-100, one at self.x+100
				for (var bx = -100; bx <= 100; bx += 200) {
					var beam = LK.getAsset('beamItem', {
						anchorX: 0.5,
						anchorY: 0,
						x: self.x + bx,
						y: self.y + enemySprite.height / 2
					});
					beam.width = 100;
					beam.height = 2732 - (self.y + enemySprite.height / 2);
					beam.alpha = 0.42 + Math.random() * 0.10;
					game.addChild(beam);
					// Beam effect: damage hero if in column for 48 frames, only first 16 frames "active"
					beam.life = 48;
					beam.activeFrames = 16;
					beam.update = function () {
						this.life--;
						this.alpha = 0.32 + Math.random() * 0.18;
						if (this.life > 48 - this.activeFrames) {
							if (typeof hero !== "undefined" && hero.y > this.y && hero.y < this.y + this.height) {
								if (Math.abs(hero.x - this.x) < this.width / 2 + hero.width / 2) {
									if (!godMode && !shieldActive && this.life === 48 - this.activeFrames + 1) {
										LK.getSound('heroHit').play();
										LK.effects.flashScreen(0x3399ff, 800);
										heroHealth--;
										updateHealthBar();
										updateDemoHealthSquares && updateDemoHealthSquares();
										if (heroHealth <= 0) {
											LK.getSound('Death').play();
											LK.showGameOver();
											return;
										}
									} else if (!godMode && shieldActive && this.life === 48 - this.activeFrames + 1) {
										LK.effects.flashObject(hero, 0x00ffff, 200);
									}
								}
							}
						}
						if (this.life <= 0) {
							this.destroy();
						}
					};
					enemyBullets.push(beam);
					LK.getSound('laser').play();
				}
				// Set cooldown for next double beam (more frequent than EnemyX)
				self.beamCooldown = 300 + Math.floor(Math.random() * 90);
			}
		}
	};
	return self;
});
// Health potion class (separate asset)
var HealthPotion = Container.expand(function () {
	var self = Container.call(this);
	var potionSprite = self.attachAsset('healthPotion', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	potionSprite.width = 90;
	potionSprite.height = 90;
	potionSprite.alpha = 0.95;
	self.update = function () {
		self.y += 8;
	};
	return self;
});
// Hero class
var Hero = Container.expand(function () {
	var self = Container.call(this);
	var heroSprite = self.attachAsset('hero', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = heroSprite.width / 2;
	self.shootCooldown = 0;
	self.update = function () {
		if (self.shootCooldown > 0) self.shootCooldown--;
	};
	return self;
});
// Hero bullet class
var HeroBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletSprite = self.attachAsset('heroBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -16;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Shield item class
var ShieldItem = Container.expand(function () {
	var self = Container.call(this);
	var shieldSprite = self.attachAsset('shieldItem', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	shieldSprite.width = 90;
	shieldSprite.height = 90;
	shieldSprite.alpha = 0.95; // Make it much brighter/less transparent
	self.update = function () {
		self.y += 6;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x181818
});
/**** 
* Game Code
****/ 
// Add 6 healthbar assets to the screen (for demo/test, not for health UI)
var greenSquares = [];
// (defer adding to game until after background is added)
for (var i = 0; i < 6; i++) {
	var square = LK.getAsset('Healthbar', {
		anchorX: 0,
		anchorY: 1,
		x: 60 + i * 70,
		y: 2732 - 60,
		width: 60,
		height: 60,
		tint: 0x44ff44
	});
	greenSquares.push(square);
}
// Helper to update demo health squares to match heroHealth
function updateDemoHealthSquares() {
	for (var i = 0; i < greenSquares.length; i++) {
		if (i < heroHealth) {
			greenSquares[i].visible = true;
		} else {
			greenSquares[i].visible = false;
		}
	}
}
// separate asset for health potion
// Play menu music and stop background music when menu is shown
// --- MENU OVERLAY ---
// Add menu asset as background in menu, and background asset in game
var menuBgSprite = LK.getAsset('Menu', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
menuBgSprite.width = 2048;
menuBgSprite.height = 2732;
game.addChild(menuBgSprite);
var backgroundSprite = LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
// Scale background to fill the screen (2048x2732)
var bgOriginalWidth = backgroundSprite.width;
var bgOriginalHeight = backgroundSprite.height;
var scaleX = 2048 / bgOriginalWidth;
var scaleY = 2732 / bgOriginalHeight;
var scale = Math.max(scaleX, scaleY); // cover entire area
backgroundSprite.width = bgOriginalWidth * scale;
backgroundSprite.height = bgOriginalHeight * scale;
// Center if needed (in case aspect ratio doesn't match)
backgroundSprite.x = (2048 - backgroundSprite.width) / 2;
backgroundSprite.y = (2732 - backgroundSprite.height) / 2;
backgroundSprite.visible = false; // Only show in game, not in menu
game.addChild(backgroundSprite);
// Add green squares after background so they are in front
for (var i = 0; i < greenSquares.length; i++) {
	game.addChild(greenSquares[i]);
}
LK.stopMusic();
LK.playMusic('Menu');
var menuOverlay = new Container();
menuOverlay.zIndex = 10000; // ensure on top
// Title text
var titleTxt = new Text2("GALAXY DODGE SHOOTER", {
	size: 160,
	fill: "#fff",
	fontWeight: "bold"
});
titleTxt.anchor.set(0.5, 0);
titleTxt.x = 2048 / 2;
titleTxt.y = 220;
menuOverlay.addChild(titleTxt);
// Play button background
var playBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
playBtnBg.width = 600;
playBtnBg.height = 220;
playBtnBg.alpha = 0.7;
playBtnBg.x = 2048 / 2;
playBtnBg.y = 700;
menuOverlay.addChild(playBtnBg);
// Play button text
var playBtn = new Text2("PLAY", {
	size: 140,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
playBtn.anchor.set(0.5, 0.5);
playBtn.x = 2048 / 2;
playBtn.y = 700;
menuOverlay.addChild(playBtn);
// Add god mode and boss mode play buttons first, so their positions are available for music button placement
var godMode = false;
var bossMode = false;
var godPlayBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
godPlayBtnBg.width = 600;
godPlayBtnBg.height = 220;
godPlayBtnBg.alpha = 0.7;
// Place god mode button below the play button (with margin)
godPlayBtnBg.x = 2048 / 2;
godPlayBtnBg.y = 700 + 220 / 2 + 60 + godPlayBtnBg.height / 2; // below playBtnBg
menuOverlay.addChild(godPlayBtnBg);
var godPlayBtn = new Text2("GOD MODE", {
	size: 100,
	fill: 0xffd700,
	fontWeight: "bold"
});
godPlayBtn.anchor.set(0.5, 0.5);
godPlayBtn.x = 2048 / 2;
godPlayBtn.y = godPlayBtnBg.y;
menuOverlay.addChild(godPlayBtn);
var bossPlayBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
bossPlayBtnBg.width = 600;
bossPlayBtnBg.height = 220;
bossPlayBtnBg.alpha = 0.7;
bossPlayBtnBg.x = 2048 / 2;
bossPlayBtnBg.y = godPlayBtnBg.y + godPlayBtnBg.height / 2 + 60 + bossPlayBtnBg.height / 2;
menuOverlay.addChild(bossPlayBtnBg);
var bossPlayBtn = new Text2("BOSS MODE", {
	size: 100,
	fill: 0xff4444,
	fontWeight: "bold"
});
bossPlayBtn.anchor.set(0.5, 0.5);
bossPlayBtn.x = 2048 / 2;
bossPlayBtn.y = bossPlayBtnBg.y;
menuOverlay.addChild(bossPlayBtn);
// Add music toggle button to menu
var musicOn = true;
// Place music button below boss mode button (with margin)
var musicBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
musicBtnBg.width = 340;
musicBtnBg.height = 140;
musicBtnBg.alpha = 0.7;
musicBtnBg.x = 2048 / 2;
musicBtnBg.y = bossPlayBtnBg.y + bossPlayBtnBg.height / 2 + 60 + musicBtnBg.height / 2;
menuOverlay.addChild(musicBtnBg);
var musicBtn = new Text2("MUSIC: ON", {
	size: 80,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
musicBtn.anchor.set(0.5, 0.5);
musicBtn.x = 2048 / 2;
musicBtn.y = musicBtnBg.y;
menuOverlay.addChild(musicBtn);
// Add help button below music button
var helpBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
helpBtnBg.width = 340;
helpBtnBg.height = 140;
helpBtnBg.alpha = 0.7;
helpBtnBg.x = 2048 / 2;
helpBtnBg.y = musicBtnBg.y + musicBtnBg.height / 2 + 60 + helpBtnBg.height / 2;
menuOverlay.addChild(helpBtnBg);
var helpBtn = new Text2("HELP", {
	size: 80,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
helpBtn.anchor.set(0.5, 0.5);
helpBtn.x = 2048 / 2;
helpBtn.y = helpBtnBg.y;
menuOverlay.addChild(helpBtn);
// Add menu overlay to game
game.addChild(menuOverlay);
// --- HELP MENU POPUP ---
var helpMenuOverlay = null;
function showHelpMenu() {
	if (helpMenuOverlay && helpMenuOverlay.visible) return;
	if (helpMenuOverlay) {
		helpMenuOverlay.visible = true;
		return;
	}
	helpMenuOverlay = new Container();
	helpMenuOverlay.zIndex = 20000;
	// Help menu background using helpbackground asset
	var bg = LK.getAsset('Helpbackground', {
		anchorX: 0,
		anchorY: 0,
		x: 0,
		y: 0
	});
	bg.width = 2048;
	bg.height = 2732;
	bg.alpha = 1.0;
	helpMenuOverlay.addChild(bg);
	// Help title
	var helpTitle = new Text2("HELP", {
		size: 120,
		fill: "#fff",
		fontWeight: "bold"
	});
	helpTitle.anchor.set(0.5, 0);
	helpTitle.x = 2048 / 2;
	helpTitle.y = 320;
	helpMenuOverlay.addChild(helpTitle);
	// --- PAGE SYSTEM ---
	var helpPage = 0; // 0 = enemies, 1 = items
	// Enemy types info for help menu
	var enemyTypes = [{
		asset: 'enemy1',
		name: 'Enemy 1',
		desc: 'Standard enemy. Moves straight down. Easy to destroy.'
	}, {
		asset: 'enemy2',
		name: 'Enemy 2',
		desc: 'Sine-wave enemy. Moves in a wavy pattern. Harder to hit.'
	}, {
		asset: 'enemy3',
		name: 'Enemy 3',
		desc: 'Strong enemy. Takes 5 hits to destroy. Large and slow.'
	}, {
		asset: 'Enemy4',
		name: 'Enemy 4',
		desc: 'Diagonal bouncer. Moves diagonally, bounces off edges, and explodes when near the hero!'
	}, {
		asset: 'enemyX',
		name: 'Boss Enemy X',
		desc: 'Boss enemy. Appears after 250 score or in Boss Mode. Very tough!'
	}, {
		asset: 'EnemyZ',
		name: 'Boss Enemy Z',
		desc: 'Boss enemy. Zig-zags, shoots double beams, and is very fast!'
	}];
	// Item types info for help menu
	var itemTypes = [{
		asset: 'healthPotion',
		name: 'Health Potion',
		desc: 'Restores 1 health. Pick up to heal. If at max health, does nothing.'
	}, {
		asset: 'shieldItem',
		name: 'Shield',
		desc: 'Grants a shield for 6 seconds if at max health. Absorbs one hit from enemies or bullets.'
	}, {
		asset: 'beamItem',
		name: 'Beam Powerup',
		desc: 'Enables triple-shot for a short time. Fires 3 bullets in a spread.'
	}];
	// --- CONTAINER FOR PAGE CONTENT ---
	var pageContent = new Container();
	helpMenuOverlay.addChild(pageContent);
	// --- RENDER PAGE FUNCTION ---
	function renderHelpPage() {
		// Remove all children from pageContent
		while (pageContent.children.length > 0) {
			pageContent.removeChild(pageContent.children[0]);
		}
		// Title
		helpTitle.setText(helpPage === 0 ? "HELP" : "ITEMS");
		// Layout: vertical list, left-aligned for both image and text
		var startY = 500;
		var spacingY = 340;
		var leftMargin = 220;
		var imageTextGap = 40;
		var data = helpPage === 0 ? enemyTypes : itemTypes;
		for (var i = 0; i < data.length; i++) {
			var et = data[i];
			// Image
			var img = LK.getAsset(et.asset, {
				anchorX: 0,
				anchorY: 0,
				x: leftMargin,
				y: startY + i * spacingY,
				width: et.asset === 'enemyX' ? 180 : 120,
				height: et.asset === 'enemyX' ? 180 : 120
			});
			pageContent.addChild(img);
			// Name
			var nameTxt = new Text2(et.name, {
				size: 80,
				fill: "#fff",
				fontWeight: "bold"
			});
			nameTxt.anchor.set(0, 0);
			nameTxt.x = leftMargin + (et.asset === 'enemyX' ? 180 : 120) + imageTextGap;
			nameTxt.y = startY + i * spacingY + 10;
			pageContent.addChild(nameTxt);
			// Description
			var descTxt = new Text2(et.desc, {
				size: 60,
				fill: "#fff",
				align: "left"
			});
			descTxt.anchor.set(0, 0);
			descTxt.x = leftMargin + (et.asset === 'enemyX' ? 180 : 120) + imageTextGap;
			descTxt.y = startY + i * spacingY + 100;
			pageContent.addChild(descTxt);
		}
	}
	renderHelpPage();
	// --- PAGE NAVIGATION BUTTONS ---
	// Place under the last description text
	// Compute button Y based on number of entries in current help page
	var numEntries = helpPage === 0 ? enemyTypes.length : itemTypes.length;
	var lastDescY = 500 + (numEntries - 1) * 340 + 100 + 120; // 100 for desc offset, 120 for some margin
	// Close button (centered, first so it's under others visually)
	var closeBtnBg = LK.getAsset('Button', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	closeBtnBg.width = 340;
	closeBtnBg.height = 140;
	closeBtnBg.alpha = 0.7;
	closeBtnBg.x = 2048 / 2;
	closeBtnBg.y = lastDescY;
	helpMenuOverlay.addChild(closeBtnBg);
	var closeBtn = new Text2("CLOSE", {
		size: 80,
		fill: 0x00EAFF,
		fontWeight: "bold"
	});
	closeBtn.anchor.set(0.5, 0.5);
	closeBtn.x = 2048 / 2;
	closeBtn.y = lastDescY;
	helpMenuOverlay.addChild(closeBtn);
	// Items button (right)
	var nextBtnBg = LK.getAsset('Button', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	nextBtnBg.width = 340;
	nextBtnBg.height = 140;
	nextBtnBg.alpha = 0.7;
	nextBtnBg.x = 2048 / 2 + 400;
	nextBtnBg.y = lastDescY;
	helpMenuOverlay.addChild(nextBtnBg);
	var nextBtn = new Text2("ITEMS", {
		size: 60,
		fill: 0x00EAFF,
		fontWeight: "bold"
	});
	nextBtn.anchor.set(0.5, 0.5);
	nextBtn.x = nextBtnBg.x;
	nextBtn.y = nextBtnBg.y;
	helpMenuOverlay.addChild(nextBtn);
	// Enemies button (left)
	var prevBtnBg = LK.getAsset('Button', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	prevBtnBg.width = 340;
	prevBtnBg.height = 140;
	prevBtnBg.alpha = 0.7;
	prevBtnBg.x = 2048 / 2 - 400;
	prevBtnBg.y = lastDescY;
	helpMenuOverlay.addChild(prevBtnBg);
	var prevBtn = new Text2("ENEMIES", {
		size: 60,
		fill: 0x00EAFF,
		fontWeight: "bold"
	});
	prevBtn.anchor.set(0.5, 0.5);
	prevBtn.x = prevBtnBg.x;
	prevBtn.y = prevBtnBg.y;
	helpMenuOverlay.addChild(prevBtn);
	// Dismiss help menu on close button press, and handle page navigation
	helpMenuOverlay.down = function (x, y, obj) {
		// Close
		var dx = x - closeBtn.x;
		var dy = y - closeBtn.y;
		if (Math.abs(dx) <= closeBtnBg.width / 2 && Math.abs(dy) <= closeBtnBg.height / 2) {
			helpMenuOverlay.visible = false;
			return;
		}
		// Prev (ENEMIES)
		var pdx = x - prevBtn.x;
		var pdy = y - prevBtn.y;
		if (Math.abs(pdx) <= prevBtnBg.width / 2 && Math.abs(pdy) <= prevBtnBg.height / 2) {
			if (helpPage !== 0) {
				helpPage = 0;
				renderHelpPage();
			}
			return;
		}
		// Next (ITEMS)
		var ndx = x - nextBtn.x;
		var ndy = y - nextBtn.y;
		if (Math.abs(ndx) <= nextBtnBg.width / 2 && Math.abs(ndy) <= nextBtnBg.height / 2) {
			if (helpPage !== 1) {
				helpPage = 1;
				renderHelpPage();
			}
			return;
		}
	};
	game.addChild(helpMenuOverlay);
}
// Menu state
var menuActive = true;
// Play button interaction
menuOverlay.down = function (x, y, obj) {
	// Check if play button was pressed (normal mode)
	var dx = x - playBtn.x;
	var dy = y - playBtn.y;
	if (Math.abs(dx) <= playBtnBg.width / 2 && Math.abs(dy) <= playBtnBg.height / 2) {
		// Hide menu, start game in normal mode
		menuOverlay.visible = false;
		menuActive = false;
		godMode = false;
		if (typeof menuBgSprite !== "undefined") menuBgSprite.visible = false;
		if (typeof backgroundSprite !== "undefined") backgroundSprite.visible = true;
		LK.stopMusic();
		if (musicOn) {
			LK.playMusic('bgmusic');
		}
		return;
	}
	// Check if god mode play button was pressed
	var gdx = x - godPlayBtn.x;
	var gdy = y - godPlayBtn.y;
	if (Math.abs(gdx) <= godPlayBtnBg.width / 2 && Math.abs(gdy) <= godPlayBtnBg.height / 2) {
		// Hide menu, start game in god mode
		menuOverlay.visible = false;
		menuActive = false;
		godMode = true;
		if (typeof menuBgSprite !== "undefined") menuBgSprite.visible = false;
		if (typeof backgroundSprite !== "undefined") backgroundSprite.visible = true;
		LK.stopMusic();
		if (musicOn) {
			LK.playMusic('Godmode'); // godmode music while playing in godmode
		}
		return;
	}
	// Check if music button was pressed
	var mdx = x - musicBtn.x;
	var mdy = y - musicBtn.y;
	if (Math.abs(mdx) <= musicBtnBg.width / 2 && Math.abs(mdy) <= musicBtnBg.height / 2) {
		musicOn = !musicOn;
		if (musicOn) {
			musicBtn.setText("MUSIC: ON");
			LK.playMusic('Menu');
		} else {
			musicBtn.setText("MUSIC: OFF");
			LK.stopMusic();
		}
		return;
	}
	// Check if boss mode play button was pressed
	var bdx = x - bossPlayBtn.x;
	var bdy = y - bossPlayBtn.y;
	if (Math.abs(bdx) <= bossPlayBtnBg.width / 2 && Math.abs(bdy) <= bossPlayBtnBg.height / 2) {
		// Hide menu, start game in boss mode
		menuOverlay.visible = false;
		menuActive = false;
		godMode = false;
		bossMode = true;
		if (typeof menuBgSprite !== "undefined") menuBgSprite.visible = false;
		if (typeof backgroundSprite !== "undefined") backgroundSprite.visible = true;
		LK.stopMusic();
		if (musicOn) {
			LK.playMusic('Boss');
		}
		// Set up for boss mode: reset score, enemyXSpawned, etc.
		score = 0;
		scoreTxt.setText(score);
		enemyXSpawned = false;
		bossMusicPlayed = true; // already playing
		spawnTick = 0;
		return;
	}
	// Check if help button was pressed
	if (typeof helpBtn !== "undefined" && typeof helpBtnBg !== "undefined") {
		var hdx = x - helpBtn.x;
		var hdy = y - helpBtn.y;
		if (Math.abs(hdx) <= helpBtnBg.width / 2 && Math.abs(hdy) <= helpBtnBg.height / 2) {
			// Show help popup (custom help menu)
			showHelpMenu();
			return;
		}
	}
};
menuOverlay.move = function (x, y, obj) {};
menuOverlay.up = function (x, y, obj) {};
// Score display
var scoreTxt = new Text2('0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Health bar UI (horizontal, left bottom)
var maxHealth = 6;
var heroHealth = maxHealth;
var healthBarBg = LK.getAsset('enemy2', {
	anchorX: 0,
	// left edge
	anchorY: 1,
	// bottom edge
	tint: 0x222222
});
healthBarBg.width = 420;
healthBarBg.height = 60;
healthBarBg.alpha = 0.45;
// Place at left bottom, with margin (60px from left, 60px from bottom)
healthBarBg.x = 60;
healthBarBg.y = 2732 - 60;
LK.gui.bottomLeft.addChild(healthBarBg);
var healthBar = LK.getAsset('enemy1', {
	anchorX: 0,
	// left edge
	anchorY: 1,
	// bottom edge
	tint: 0xff4444
});
healthBar.width = 420;
healthBar.height = 60;
healthBar.alpha = 0.85;
healthBar.x = 60;
healthBar.y = 2732 - 60;
LK.gui.bottomLeft.addChild(healthBar);
// --- Health bar squares (vertical, left bottom) ---
var healthBarVSquares = [];
var squareSpacing = 12;
var squareSize = 60;
var baseX = 60;
var baseY = 2732 - 60;
for (var i = 0; i < maxHealth; i++) {
	var square = LK.getAsset('Healthbar', {
		anchorX: 0,
		anchorY: 1,
		x: baseX + i * (squareSize + squareSpacing),
		y: baseY,
		width: squareSize,
		height: squareSize,
		tint: 0x44ff44
	});
	LK.gui.bottomLeft.addChild(square);
	healthBarVSquares.push(square);
}
function updateHealthBar() {
	// Horizontal bar (left)
	healthBar.width = 420 * (heroHealth / maxHealth);
	if (heroHealth <= 2) {
		healthBar.tint = 0xff2222;
	} else if (heroHealth <= 4) {
		healthBar.tint = 0xffbb22;
	} else {
		healthBar.tint = 0x44ff44;
	}
	// Vertical bar (center) - show/hide squares and tint by health
	for (var i = 0; i < healthBarVSquares.length; i++) {
		if (i < heroHealth) {
			healthBarVSquares[i].visible = true;
			// Tint by health: green if >4, yellow if 3-4, red if 1-2
			if (heroHealth <= 2) {
				healthBarVSquares[i].tint = 0xff2222;
			} else if (heroHealth <= 4) {
				healthBarVSquares[i].tint = 0xffbb22;
			} else {
				healthBarVSquares[i].tint = 0x44ff44;
			}
			// Add a white border highlight if health is full
			healthBarVSquares[i].alpha = heroHealth === maxHealth ? 1.0 : 0.95;
		} else {
			healthBarVSquares[i].visible = false;
		}
	}
}
updateDemoHealthSquares && updateDemoHealthSquares();
updateHealthBar();
// Game variables
var hero = new Hero();
game.addChild(hero);
hero.x = 2048 / 2;
hero.y = 2732 - 350;
// Track if EnemyX has spawned
var enemyXSpawned = false;
var enemyZSpawned = false; // Track if EnemyZ is present in boss mode
// Track if EnemyX has been killed after 250 score (not in boss mode)
var enemyXKilledAfter250 = false;
// Ulti button UI and state
var ultiReady = true;
var ultiCooldown = 0;
var ultiCooldownMax = 1800; // 30 seconds at 60fps
// Create ulti button
var ultiBtn = new Text2("ULTI", {
	size: 120,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
ultiBtn.anchor.set(0.5, 0.5);
// Place in right corner, leaving margin for touch and not overlapping top menu
ultiBtn.x = 2048 - 180;
ultiBtn.y = 2732 - 180;
ultiBtn.bg = LK.getAsset('enemy2', {
	anchorX: 0.5,
	anchorY: 0.5,
	tint: 0x00eaff
});
ultiBtn.bg.width = 340;
ultiBtn.bg.height = 220;
ultiBtn.bg.alpha = 0.25;
ultiBtn.bg.x = ultiBtn.x;
ultiBtn.bg.y = ultiBtn.y;
game.addChild(ultiBtn.bg);
game.addChild(ultiBtn);
// Ulti button cooldown overlay
var ultiBtnOverlay = LK.getAsset('enemy2', {
	anchorX: 0.5,
	anchorY: 0.5,
	tint: 0x222222
});
ultiBtnOverlay.width = 340;
ultiBtnOverlay.height = 220;
ultiBtnOverlay.alpha = 0.55;
ultiBtnOverlay.x = ultiBtn.x;
ultiBtnOverlay.y = ultiBtn.y;
ultiBtnOverlay.visible = false;
game.addChild(ultiBtnOverlay);
// Laser Cannon state (no button UI)
var laserReady = true;
var laserCooldown = 0;
var laserCooldownMax = 720; // 12 seconds at 60fps
// Armor visual overlay for shield
var heroArmor = LK.getAsset('enemy2', {
	anchorX: 0.5,
	anchorY: 0.5,
	tint: 0x80eaff // light blue
});
heroArmor.width = hero.width * 1.35;
heroArmor.height = hero.height * 1.35;
heroArmor.alpha = 0.55;
heroArmor.visible = false;
game.addChild(heroArmor);
var heroBullets = [];
var enemies = [];
var enemyBullets = [];
var items = [];
var dragNode = null;
var lastHeroIntersecting = false;
var score = 0;
var spawnTick = 0;
var enemyShootTick = 0;
// Powerup state
var shieldActive = false;
var shieldTimer = 0;
var beamActive = false;
var beamTimer = 0;
// Helper: spawn item
function spawnItem() {
	var itemType = Math.random() < 0.5 ? "shield" : "beam";
	var item;
	if (itemType === "shield") {
		item = new ShieldItem();
	} else {
		item = new BeamItem();
	}
	item.x = 200 + Math.random() * (2048 - 400);
	item.y = -80;
	items.push(item);
	game.addChild(item);
}
// Helper: spawn enemy
function spawnEnemy() {
	// 10% Enemy4 (only if score >= 600), 20% Enemy3, 35% Enemy1, 35% Enemy2
	var rand = Math.random();
	var enemy;
	if (rand < 0.35) {
		enemy = new Enemy1();
		enemy.x = 200 + Math.random() * (2048 - 400);
		enemy.y = -80;
	} else if (rand < 0.7) {
		enemy = new Enemy2();
		enemy.baseX = 200 + Math.random() * (2048 - 400);
		enemy.x = enemy.baseX;
		enemy.y = -80;
		enemy.t = Math.random() * 2;
	} else if (rand < 0.9) {
		enemy = new Enemy3();
		enemy.x = 200 + Math.random() * (2048 - 400);
		enemy.y = -80;
	} else {
		// Only spawn Enemy4 if score >= 600
		if (score >= 600) {
			enemy = new Enemy4();
			enemy.x = 200 + Math.random() * (2048 - 400);
			enemy.y = -80;
		} else {
			// If not allowed, fallback to Enemy1
			enemy = new Enemy1();
			enemy.x = 200 + Math.random() * (2048 - 400);
			enemy.y = -80;
		}
	}
	enemies.push(enemy);
	game.addChild(enemy);
}
// Helper: spawn enemy bullet
function spawnEnemyBullet(enemy, targetX, targetY) {
	var bullet = new EnemyBullet();
	bullet.x = enemy.x;
	bullet.y = enemy.y + 60;
	// Aim at hero
	var dx = targetX - bullet.x;
	var dy = targetY - bullet.y;
	var len = Math.sqrt(dx * dx + dy * dy);
	if (len > 0) {
		bullet.speedX = dx / len * 18;
		bullet.speedY = dy / len * 18;
	}
	enemyBullets.push(bullet);
	game.addChild(bullet);
	LK.getSound('enemyShoot').play();
}
// Move handler for dragging hero
function handleMove(x, y, obj) {
	// Always follow mouse if not dragging and not in menu
	if (!dragNode && !(typeof menuActive !== "undefined" && menuActive)) {
		// Clamp hero inside screen
		var hw = hero.width / 2;
		var hh = hero.height / 2;
		var nx = Math.max(hw, Math.min(2048 - hw, x));
		var ny = Math.max(hh + 100, Math.min(2732 - hh, y));
		hero.x = nx;
		hero.y = ny;
		return;
	}
	if (dragNode) {
		// Clamp hero inside screen
		var hw = dragNode.width / 2;
		var hh = dragNode.height / 2;
		var nx = Math.max(hw, Math.min(2048 - hw, x));
		var ny = Math.max(hh + 100, Math.min(2732 - hh, y));
		dragNode.x = nx;
		dragNode.y = ny;
	}
}
// --- Make hero follow mouse automatically at game start (PC only) ---
if (typeof window !== "undefined" && window.addEventListener) {
	window.addEventListener("mousemove", function (evt) {
		// Only follow if not in menu and not dragging
		if (typeof menuActive !== "undefined" && menuActive) return;
		if (dragNode) return;
		// Get bounding rect of canvas
		var canvas = LK.getCanvas ? LK.getCanvas() : document.querySelector("canvas") || null;
		if (!canvas) return;
		var rect = canvas.getBoundingClientRect();
		// Convert mouse coordinates to game coordinates
		var scaleX = 2048 / rect.width;
		var scaleY = 2732 / rect.height;
		var x = (evt.clientX - rect.left) * scaleX;
		var y = (evt.clientY - rect.top) * scaleY;
		handleMove(x, y, {
			event: evt
		});
	});
}
// Touch down: start dragging hero
game.down = function (x, y, obj) {
	if (typeof menuActive !== "undefined" && menuActive) return;
	// PC: left mouse click triggers laser cannon if ready and not on menu
	if (obj && obj.event && obj.event.type === "mousedown" && obj.event.button === 0 && laserReady) {
		// Only fire if click is inside hero sprite (circle)
		var dx = x - hero.x;
		var dy = y - hero.y;
		if (dx * dx + dy * dy <= hero.radius * hero.radius) {
			// Activate laser
			laserReady = false;
			laserCooldown = laserCooldownMax;
			// Laser effect: fire a vertical laser column at hero.x
			var laserX = hero.x;
			// Visual effect: draw a vertical beam for a short time, and make it follow the hero
			var laserBeam = LK.getAsset('heroBullet', {
				anchorX: 0.5,
				anchorY: 1,
				x: laserX,
				y: hero.y - hero.height / 2
			});
			laserBeam.width = 80;
			laserBeam.height = hero.y - hero.height / 2; // from hero to top
			laserBeam.alpha = 0.45;
			game.addChild(laserBeam);
			// Store reference to active laser beam and set timer
			game.activeLaserBeam = laserBeam;
			game.activeLaserBeamTimer = 90; // 1.5 seconds at 60fps
			LK.getSound('laser').play();
			// Destroy all enemies and enemy bullets in the column
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (Math.abs(e.x - laserX) <= 80) {
					// Laser cannon does NOT affect EnemyX (boss)
					if (e instanceof EnemyX) {
						// Flash to show hit, but do not damage or destroy
						LK.effects.flashObject(e, 0xff0000, 120);
						continue;
					}
					LK.effects.flashObject(e, 0xffffff, 200);
					for (var pi = 0; pi < 12; pi++) {
						var part = LK.getAsset(e instanceof Enemy1 ? 'enemy1' : e instanceof Enemy2 ? 'enemy2' : 'enemy3', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = e.x;
						part.y = e.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 12) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					// 35% chance to drop a health potion if Enemy3
					if (e instanceof Enemy3 && Math.random() < 0.35) {
						var healthPotion = new HealthPotion();
						healthPotion.x = e.x;
						healthPotion.y = e.y;
						items.push(healthPotion);
						game.addChild(healthPotion);
					}
					e.destroy();
					enemies.splice(i, 1);
				}
			}
			for (var i = enemyBullets.length - 1; i >= 0; i--) {
				var b = enemyBullets[i];
				if (Math.abs(b.x - laserX) <= 80) {
					b.destroy();
					enemyBullets.splice(i, 1);
				}
			}
			return;
		}
	}
	dragNode = hero;
	handleMove(x, y, obj);
};
// Touch up: stop dragging
game.up = function (x, y, obj) {
	if (typeof menuActive !== "undefined" && menuActive) return;
	dragNode = null;
};
// Touch move: move hero
game.move = function (x, y, obj) {
	if (typeof menuActive !== "undefined" && menuActive) return;
	handleMove(x, y, obj);
	// Handle ulti button press (touch/click)
	if (ultiReady) {
		// Check if touch is inside ulti button area
		var dx = x - ultiBtn.x;
		var dy = y - ultiBtn.y;
		if (Math.abs(dx) <= ultiBtn.bg.width / 2 && Math.abs(dy) <= ultiBtn.bg.height / 2) {
			// Activate ulti
			ultiReady = false;
			ultiCooldown = ultiCooldownMax;
			ultiBtnOverlay.visible = true;
			// Play ulti sound
			LK.getSound('Ulti').play();
			// Ulti effect: clear all enemies and enemy bullets
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (e instanceof EnemyX) {
					// Ulti does 50 damage to EnemyX in both boss mode and normal mode
					e.hp -= 50;
					LK.effects.flashObject(e, 0xffffff, 400);
					if (e.hp <= 0) {
						// Play death animation for EnemyX
						var enemyToDestroy = e;
						for (var pi = 0; pi < 48; pi++) {
							var part = LK.getAsset('enemyX', {
								anchorX: 0.5,
								anchorY: 0.5
							});
							part.x = enemyToDestroy.x;
							part.y = enemyToDestroy.y;
							part.width = 48 + Math.random() * 48;
							part.height = 48 + Math.random() * 48;
							part.alpha = 0.8 + Math.random() * 0.2;
							var angle = Math.PI * 2 * (pi / 48) + Math.random() * 0.2;
							var speed = 24 + Math.random() * 16;
							var vx = Math.cos(angle) * speed;
							var vy = Math.sin(angle) * speed;
							part.life = 32 + Math.floor(Math.random() * 32);
							part.update = function () {
								this.x += vx;
								this.y += vy;
								this.life--;
								this.alpha *= 0.90 + Math.random() * 0.04;
								if (this.life <= 0) {
									this.destroy();
								}
							};
							game.addChild(part);
						}
						// Add score for killing EnemyX with ulti
						score += 1;
						scoreTxt.setText(score);
						// Drop 3 health potions when EnemyX is killed by ulti
						for (var hp = 0; hp < 3; hp++) {
							var healthPotion = new HealthPotion();
							healthPotion.x = enemyToDestroy.x - 60 + 60 * hp;
							healthPotion.y = enemyToDestroy.y;
							items.push(healthPotion);
							game.addChild(healthPotion);
						}
						enemyToDestroy.destroy();
						enemies.splice(i, 1);
					}
				} else {
					// Add score for killing normal enemies with ulti
					score += 1;
					scoreTxt.setText(score);
					enemies[i].destroy();
					enemies.splice(i, 1);
				}
			}
			for (var i = enemyBullets.length - 1; i >= 0; i--) {
				enemyBullets[i].destroy();
				enemyBullets.splice(i, 1);
			}
			LK.effects.flashScreen(0x00eaff, 600);
			return;
		}
	}
	// Handle laser cannon activation by clicking on the hero
	if (laserReady) {
		var dx = x - hero.x;
		var dy = y - hero.y;
		// Check if touch/click is inside hero sprite (circle)
		if (dx * dx + dy * dy <= hero.radius * hero.radius) {
			// Activate laser
			laserReady = false;
			laserCooldown = laserCooldownMax;
			// Laser effect: fire a vertical laser column at hero.x
			var laserX = hero.x;
			// Visual effect: draw a vertical beam for a short time, and make it follow the hero
			var laserBeam = LK.getAsset('heroBullet', {
				anchorX: 0.5,
				anchorY: 1,
				//{37}  // anchor at bottom
				x: laserX,
				y: hero.y - hero.height / 2
			});
			laserBeam.width = 80;
			laserBeam.height = hero.y - hero.height / 2; // from hero to top
			laserBeam.alpha = 0.45;
			game.addChild(laserBeam);
			// Store reference to active laser beam and set timer
			game.activeLaserBeam = laserBeam;
			game.activeLaserBeamTimer = 90; // 1.5 seconds at 60fps
			LK.getSound('laser').play();
			// Destroy all enemies and enemy bullets in the column
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (Math.abs(e.x - laserX) <= 80) {
					// Laser cannon does NOT affect EnemyX (boss)
					if (e instanceof EnemyX) {
						// Flash to show hit, but do not damage or destroy
						LK.effects.flashObject(e, 0xff0000, 120);
						continue;
					}
					// Play death animation for each
					LK.effects.flashObject(e, 0xffffff, 200);
					// Particle effect for each
					for (var pi = 0; pi < 12; pi++) {
						var part = LK.getAsset(e instanceof Enemy1 ? 'enemy1' : e instanceof Enemy2 ? 'enemy2' : 'enemy3', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = e.x;
						part.y = e.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 12) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					// 35% chance to drop a health potion if Enemy3
					if (e instanceof Enemy3 && Math.random() < 0.35) {
						var healthPotion = new HealthPotion();
						healthPotion.x = e.x;
						healthPotion.y = e.y;
						items.push(healthPotion);
						game.addChild(healthPotion);
					}
					e.destroy();
					enemies.splice(i, 1);
				}
			}
			for (var i = enemyBullets.length - 1; i >= 0; i--) {
				var b = enemyBullets[i];
				if (Math.abs(b.x - laserX) <= 80) {
					b.destroy();
					enemyBullets.splice(i, 1);
				}
			}
			return;
		}
	}
};
// Main game update
game.update = function () {
	if (typeof menuActive !== "undefined" && menuActive) {
		// Block all game logic while menu is active
		return;
	}
	// Update hero
	hero.update();
	// Laser beam follow logic
	if (game.activeLaserBeam) {
		// Move the beam to follow the hero's x and y, and always stretch from hero to top
		game.activeLaserBeam.x = hero.x;
		game.activeLaserBeam.y = hero.y - hero.height / 2;
		game.activeLaserBeam.height = hero.y - hero.height / 2;
		// Laser beam hits enemies it touches
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			// Check if enemy is within the laser beam's column (80px wide, same as beam)
			if (e.y + (e.height ? e.height / 2 : 60) >= 0 &&
			// enemy is not above top
			e.y - (e.height ? e.height / 2 : 60) <= hero.y - hero.height / 2 &&
			// enemy is not below beam bottom
			Math.abs(e.x - game.activeLaserBeam.x) <= game.activeLaserBeam.width / 2) {
				// Laser cannon does NOT affect EnemyX (boss)
				if (e instanceof EnemyX) {
					// Flash to show hit, but do not damage or destroy
					LK.effects.flashObject(e, 0xff0000, 120);
					continue;
				}
				// Play hit sound and flash
				LK.getSound('enemyHit').play();
				LK.effects.flashObject(e, 0xffffff, 200);
				// Score and handle Enemy3 HP
				score += 1;
				scoreTxt.setText(score);
				if (e instanceof Enemy3) {
					e.hp--;
					if (e.hp <= 0) {
						// Play death animation before destroying Enemy3
						var enemyToDestroy = e;
						for (var pi = 0; pi < 24; pi++) {
							var part = LK.getAsset('enemy3', {
								anchorX: 0.5,
								anchorY: 0.5
							});
							part.x = enemyToDestroy.x;
							part.y = enemyToDestroy.y;
							part.width = 32 + Math.random() * 32;
							part.height = 32 + Math.random() * 32;
							part.alpha = 0.8 + Math.random() * 0.2;
							var angle = Math.PI * 2 * (pi / 24) + Math.random() * 0.2;
							var speed = 16 + Math.random() * 12;
							var vx = Math.cos(angle) * speed;
							var vy = Math.sin(angle) * speed;
							part.life = 16 + Math.floor(Math.random() * 16);
							part.update = function () {
								this.x += vx;
								this.y += vy;
								this.life--;
								this.alpha *= 0.90 + Math.random() * 0.04;
								if (this.life <= 0) {
									this.destroy();
								}
							};
							game.addChild(part);
						}
						// 35% chance to drop a health potion when Enemy3 is killed
						if (Math.random() < 0.35) {
							var healthPotion = new HealthPotion();
							healthPotion.x = enemyToDestroy.x;
							healthPotion.y = enemyToDestroy.y;
							items.push(healthPotion);
							game.addChild(healthPotion);
						}
						enemyToDestroy.destroy();
						enemies.splice(i, 1);
					} else {
						// Flash for hit, but don't destroy
						LK.effects.flashObject(e, 0x8e24aa, 120);
					}
				} else {
					// Play death animation before destroying normal enemies
					var enemyToDestroy = e;
					for (var pi = 0; pi < 16; pi++) {
						var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : 'enemy2', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = enemyToDestroy.x;
						part.y = enemyToDestroy.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					enemyToDestroy.destroy();
					enemies.splice(i, 1);
				}
			}
		}
		// Decrement timer and destroy when done
		game.activeLaserBeamTimer--;
		if (game.activeLaserBeamTimer <= 0) {
			game.activeLaserBeam.destroy();
			game.activeLaserBeam = null;
		}
	}
	// Ulti cooldown logic
	if (godMode) {
		ultiReady = true;
		ultiCooldown = 0;
		ultiBtnOverlay.visible = false;
		ultiBtn.text = "ULTI";
	} else {
		if (!ultiReady) {
			ultiCooldown--;
			if (ultiCooldown <= 0) {
				ultiReady = true;
				ultiBtnOverlay.visible = false;
			} else {
				// Show overlay and update text to show seconds left
				ultiBtnOverlay.visible = true;
				ultiBtn.text = "ULTI\n" + Math.ceil(ultiCooldown / 60) + "s";
			}
		}
		if (ultiReady) {
			ultiBtn.text = "ULTI";
			ultiBtnOverlay.visible = false;
		}
	}
	// Update armor overlay position and visibility
	heroArmor.x = hero.x;
	heroArmor.y = hero.y;
	heroArmor.visible = shieldActive;
	// Laser cannon cooldown logic (no button UI)
	if (!laserReady) {
		laserCooldown--;
		if (laserCooldown <= 0) {
			laserReady = true;
		}
	}
	// Update shield/beam timers
	if (shieldActive) {
		shieldTimer--;
		if (shieldTimer <= 0) {
			shieldActive = false;
		}
	}
	if (beamActive) {
		beamTimer--;
		if (beamTimer <= 0) {
			beamActive = false;
		}
	}
	// Update items (powerups)
	for (var i = items.length - 1; i >= 0; i--) {
		var item = items[i];
		item.update();
		// Remove if off screen
		if (item.y > 2732 + 100) {
			item.destroy();
			items.splice(i, 1);
			continue;
		}
		// Pickup by hero
		if (item.intersects(hero)) {
			if (item instanceof HealthPotion) {
				// Health potion always gives 1 health (if not at max)
				if (heroHealth < maxHealth) {
					heroHealth = Math.min(maxHealth, heroHealth + 1);
					updateHealthBar();
					updateDemoHealthSquares && updateDemoHealthSquares();
					LK.effects.flashObject(hero, 0x44ff44, 400);
				}
			} else if (item instanceof ShieldItem) {
				// If already at max health, treat as shield
				if (heroHealth >= maxHealth) {
					shieldActive = true;
					shieldTimer = 360; // 6 seconds at 60fps
					LK.effects.flashObject(hero, 0x00ffff, 400);
				} else {
					// If not at max health, ignore shield pickup (health potions now handled separately)
				}
			} else if (item instanceof BeamItem) {
				beamActive = true;
				beamTimer = 180; // 3 seconds at 60fps
				LK.effects.flashObject(hero, 0xff00ff, 400);
			}
			item.destroy();
			items.splice(i, 1);
			continue;
		}
	}
	// Hero shooting (auto-fire)
	if (hero.shootCooldown <= 0) {
		if (beamActive) {
			// Beam: fire 3 bullets in spread
			for (var bdir = -1; bdir <= 1; bdir++) {
				var bullet = new HeroBullet();
				bullet.x = hero.x + bdir * 40;
				bullet.y = hero.y - hero.height / 2 - 20;
				bullet.spread = bdir * 0.18; // radians
				bullet.update = function (origUpdate, spread) {
					return function () {
						this.y += this.speed;
						this.x += Math.sin(spread) * 18;
					};
				}(bullet.update, bullet.spread);
				heroBullets.push(bullet);
				game.addChild(bullet);
			}
			hero.shootCooldown = 12;
			LK.getSound('laser').play();
		} else {
			var bullet = new HeroBullet();
			bullet.x = hero.x;
			bullet.y = hero.y - hero.height / 2 - 20;
			heroBullets.push(bullet);
			game.addChild(bullet);
			hero.shootCooldown = 20;
			LK.getSound('laser').play();
		}
	}
	// Update hero bullets
	for (var i = heroBullets.length - 1; i >= 0; i--) {
		var b = heroBullets[i];
		b.update();
		// Remove if off screen
		if (b.y < -60) {
			b.destroy();
			heroBullets.splice(i, 1);
			continue;
		}
		// Check collision with enemies
		for (var j = enemies.length - 1; j >= 0; j--) {
			var e = enemies[j];
			// In boss mode, if EnemyZ is killed, allow next boss to spawn
			if (typeof bossMode !== "undefined" && bossMode && e instanceof EnemyZ && e.hp <= 1 && b.intersects(e)) {
				enemyZSpawned = false;
				spawnTick = 0;
				bossNextToSpawn = "X"; // Always alternate to X after Z dies
			}
			if (b.intersects(e)) {
				// Enemy hit
				LK.getSound('enemyHit').play();
				score += 1;
				scoreTxt.setText(score);
				// Flash enemy
				LK.effects.flashObject(e, 0xffffff, 200);
				// Remove both or handle Enemy3/EnemyX/Enemy4/EnemyZ hp
				if (e instanceof Enemy3 || e instanceof EnemyX || e instanceof Enemy4 || e instanceof EnemyZ) {
					e.hp--;
					if (e.hp <= 0) {
						// Play death animation before destroying Enemy3/EnemyX/Enemy4/EnemyZ
						var enemyToDestroy = e;
						// --- Enemy4 explosion: NO damage to hero when destroyed by bullets, laser, or shield ---
						// (intentionally left blank, Enemy4 does not deal damage when destroyed by bullets, laser, or shield)
						// Particle animation for Enemy3/EnemyX/Enemy4/EnemyZ death (more particles, richer effect)
						var particleCount = e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 24 : e instanceof EnemyZ ? 48 : 16;
						var assetName = e instanceof EnemyX ? 'enemyX' : e instanceof Enemy3 ? 'enemy3' : e instanceof EnemyZ ? 'EnemyZ' : 'Enemy4';
						for (var pi = 0; pi < particleCount; pi++) {
							var part = LK.getAsset(assetName, {
								anchorX: 0.5,
								anchorY: 0.5
							});
							part.x = enemyToDestroy.x;
							part.y = enemyToDestroy.y;
							part.width = (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24) + Math.random() * (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24);
							part.height = (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24) + Math.random() * (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24);
							part.alpha = 0.8 + Math.random() * 0.2;
							var angle = Math.PI * 2 * (pi / particleCount) + Math.random() * 0.2;
							var speed = (e instanceof EnemyX ? 24 : e instanceof Enemy3 ? 16 : e instanceof EnemyZ ? 24 : 12) + Math.random() * (e instanceof EnemyX ? 16 : e instanceof Enemy3 ? 12 : e instanceof EnemyZ ? 16 : 8);
							var vx = Math.cos(angle) * speed;
							var vy = Math.sin(angle) * speed;
							part.life = (e instanceof EnemyX ? 32 : e instanceof Enemy3 ? 16 : e instanceof EnemyZ ? 32 : 10) + Math.floor(Math.random() * (e instanceof EnemyX ? 32 : e instanceof Enemy3 ? 16 : e instanceof EnemyZ ? 32 : 8));
							part.update = function () {
								this.x += vx;
								this.y += vy;
								this.life--;
								this.alpha *= 0.90 + Math.random() * 0.04;
								if (this.life <= 0) {
									this.destroy();
								}
							};
							game.addChild(part);
						}
						// 35% chance to drop a health potion when Enemy3 is killed (not for EnemyX/Enemy4/EnemyZ)
						if (e instanceof Enemy3 && Math.random() < 0.35) {
							var healthPotion = new HealthPotion();
							healthPotion.x = enemyToDestroy.x;
							healthPotion.y = enemyToDestroy.y;
							items.push(healthPotion);
							game.addChild(healthPotion);
						}
						enemyToDestroy.destroy();
						enemies.splice(j, 1);
						// If EnemyX was killed, drop 3 health potions and restart normal enemy spawning
						if (e instanceof EnemyX) {
							for (var hp = 0; hp < 3; hp++) {
								var healthPotion = new HealthPotion();
								// Spread potions horizontally a bit
								healthPotion.x = enemyToDestroy.x - 60 + 60 * hp;
								healthPotion.y = enemyToDestroy.y;
								items.push(healthPotion);
								game.addChild(healthPotion);
							}
							// --- In boss mode, alternate to EnemyZ after EnemyX dies
							if (typeof bossMode !== "undefined" && bossMode) {
								enemyXSpawned = false;
								enemyZSpawned = false; // Allow next boss to spawn (EnemyZ)
								spawnTick = 0;
								bossNextToSpawn = "Z"; // Always alternate to Z after X dies
								// Music continues
							} else {
								// Reset boss state and allow normal enemies to spawn again
								enemyXSpawned = false;
								bossMusicPlayed = false;
								// Stop boss music and play bgmusic when EnemyX is killed
								LK.stopMusic();
								LK.playMusic('bgmusic');
								// If score >= 250, mark EnemyX as killed so it never spawns again (not in boss mode)
								if (score >= 250 && !(typeof bossMode !== "undefined" && bossMode)) {
									enemyXKilledAfter250 = true;
								}
								// Reset spawnTick so normal enemies start coming again, but slowly
								spawnTick = 0;
								// Reset spawnIntervalNormal to its original value when resuming normal enemy spawns
								spawnIntervalNormal = 60;
								// Optionally, set a delay before next normal spawn (e.g. 60 frames)
								// spawnTick = -60;
							}
						}
						// If EnemyZ was killed, alternate to EnemyX after Z dies (boss mode)
						if (e instanceof EnemyZ && typeof bossMode !== "undefined" && bossMode) {
							enemyZSpawned = false;
							spawnTick = 0;
							bossNextToSpawn = "X"; // Always alternate to X after Z dies
						}
					} else {
						// Flash for hit, but don't destroy
						LK.effects.flashObject(e, 0x8e24aa, 120);
					}
					b.destroy();
					heroBullets.splice(i, 1);
					break;
				} else {
					b.destroy();
					heroBullets.splice(i, 1);
					// Play death animation before destroying normal enemies
					var enemyToDestroy = e;
					// Particle animation for normal enemy death (more particles, richer effect)
					for (var pi = 0; pi < 16; pi++) {
						var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : 'enemy2', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = enemyToDestroy.x;
						part.y = enemyToDestroy.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					enemyToDestroy.destroy();
					enemies.splice(j, 1);
					break;
				}
			}
		}
	}
	// Update enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var e = enemies[i];
		if (typeof bossMode !== "undefined" && bossMode && e instanceof EnemyZ && e.hp <= 0) {
			enemyZSpawned = false;
			spawnTick = 0;
			bossNextToSpawn = "X"; // Always alternate to X after Z dies
		}
		e.update();
		// Remove if off screen
		if (e.y > 2732 + 100) {
			e.destroy();
			enemies.splice(i, 1);
			continue;
		}
		// Enemy shoots randomly
		if (Math.random() < 0.008) {
			spawnEnemyBullet(e, hero.x, hero.y);
		}
		// Check collision with hero
		// Prevent hero from affecting or being affected by boss type enemies (EnemyX, EnemyZ)
		if (e instanceof EnemyX || e instanceof EnemyZ) {
			// Do nothing: hero does not affect or get hit by boss type enemies
			continue;
		}
		if (e.intersects(hero)) {
			if (godMode) {
				// In god mode, ignore all damage and just destroy enemy
				enemies[i].destroy();
				enemies.splice(i, 1);
				continue;
			}
			if (!shieldActive) {
				// Hero hit
				LK.getSound('heroHit').play();
				LK.effects.flashScreen(0xff0000, 800);
				heroHealth--;
				updateHealthBar();
				updateDemoHealthSquares && updateDemoHealthSquares();
				if (heroHealth <= 0) {
					LK.getSound('Death').play();
					LK.showGameOver();
					return;
				}
				enemies[i].destroy();
				enemies.splice(i, 1);
				continue;
			} else {
				// Shield absorbs hit, destroy enemy
				LK.effects.flashObject(hero, 0x00ffff, 200);
				// Play death animation before destroying enemy killed by shield
				var enemyToDestroy = e;
				// Particle animation for shield kill (more particles, richer effect)
				for (var pi = 0; pi < 16; pi++) {
					var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : enemyToDestroy instanceof Enemy2 ? 'enemy2' : 'enemy3', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					part.x = enemyToDestroy.x;
					part.y = enemyToDestroy.y;
					part.width = 20 + Math.random() * 20;
					part.height = 20 + Math.random() * 20;
					part.alpha = 0.7 + Math.random() * 0.3;
					var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2;
					var speed = 10 + Math.random() * 10;
					var vx = Math.cos(angle) * speed;
					var vy = Math.sin(angle) * speed;
					part.life = 10 + Math.floor(Math.random() * 10);
					part.update = function () {
						this.x += vx;
						this.y += vy;
						this.life--;
						this.alpha *= 0.88 + Math.random() * 0.06;
						if (this.life <= 0) {
							this.destroy();
						}
					};
					game.addChild(part);
				}
				enemyToDestroy.destroy();
				enemies.splice(i, 1);
				continue;
			}
		}
	}
	// Update enemy bullets
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var b = enemyBullets[i];
		if (typeof bossMode !== "undefined" && bossMode && b instanceof EnemyBullet) {
			// Check if this bullet killed EnemyZ (shouldn't happen, but for completeness)
			for (var j = enemies.length - 1; j >= 0; j--) {
				var e = enemies[j];
				if (e instanceof EnemyZ && e.hp <= 0) {
					enemyZSpawned = false;
					spawnTick = 0;
					bossNextToSpawn = "X"; // Always alternate to X after Z dies
				}
			}
		}
		b.update();
		// Remove if off screen
		if (b.y < -60 || b.y > 2732 + 60 || b.x < -60 || b.x > 2048 + 60) {
			b.destroy();
			enemyBullets.splice(i, 1);
			continue;
		}
		// Check collision with hero
		if (b.intersects(hero)) {
			if (godMode) {
				// In god mode, ignore all damage and just destroy bullet
				b.destroy();
				enemyBullets.splice(i, 1);
				continue;
			}
			if (!shieldActive) {
				LK.getSound('heroHit').play();
				LK.effects.flashScreen(0xff0000, 800);
				heroHealth--;
				updateHealthBar();
				updateDemoHealthSquares && updateDemoHealthSquares();
				if (heroHealth <= 0) {
					LK.getSound('Death').play();
					LK.showGameOver();
					return;
				}
				b.destroy();
				enemyBullets.splice(i, 1);
				continue;
			} else {
				// Shield absorbs bullet
				LK.effects.flashObject(hero, 0x00ffff, 120);
				b.destroy();
				enemyBullets.splice(i, 1);
				continue;
			}
		}
	}
	// --- ENEMY SPAWN RATE BOOST LOGIC ---
	if (typeof spawnRateBoostActive === "undefined") {
		var spawnRateBoostActive = false;
		var spawnRateBoostTimer = 0;
		var nextBoostScore = 50;
		var spawnIntervalNormal = 90;
		var spawnIntervalBoost = 60;
	}
	// Boss mode: alternate EnemyX and EnemyZ, never normal enemies or items
	if (typeof bossMode !== "undefined" && bossMode) {
		spawnTick++;
		// Track which boss to spawn next: "X" or "Z"
		if (typeof bossNextToSpawn === "undefined") bossNextToSpawn = "X";
		if (!enemyXSpawned && !enemyZSpawned && spawnTick >= 30) {
			var enemy;
			// Special case: at score 451, always spawn EnemyZ regardless of alternation
			if (score === 451) {
				enemy = new EnemyZ();
				enemy.x = 2048 / 2;
				enemy.y = -80;
				enemies.push(enemy);
				game.addChild(enemy);
				enemyZSpawned = true;
				bossNextToSpawn = "X"; // After Z, alternate to X
				spawnTick = 0;
			} else if (bossNextToSpawn === "X") {
				enemy = new EnemyX();
				enemy.x = 200 + Math.random() * (2048 - 400);
				enemy.y = -80;
				enemies.push(enemy);
				game.addChild(enemy);
				enemyXSpawned = true;
				// Do not alternate bossNextToSpawn here; alternate only on death
				spawnTick = 0;
			} else if (bossNextToSpawn === "Z") {
				enemy = new EnemyZ();
				enemy.x = 2048 / 2;
				enemy.y = -80;
				enemies.push(enemy);
				game.addChild(enemy);
				enemyZSpawned = true;
				// Do not alternate bossNextToSpawn here; alternate only on death
				spawnTick = 0;
			}
		}
		// Never spawn items or normal enemies in boss mode
	} else {
		// Check if we reached a new boost score (50, 150, 250, ...) and trigger boost
		if (score >= nextBoostScore && !spawnRateBoostActive) {
			spawnRateBoostActive = true;
			spawnRateBoostTimer = 180; // 3 seconds at 60fps
			// After 50, next is 150, then 250, 350, ...
			if (nextBoostScore === 50) {
				nextBoostScore = 150;
			} else {
				nextBoostScore += 100;
			}
		}
		// Handle boost timer
		if (spawnRateBoostActive) {
			spawnRateBoostTimer--;
			if (spawnRateBoostTimer <= 0) {
				spawnRateBoostActive = false;
			}
		}
		// Spawn enemies
		spawnTick++;
		// Use boosted or normal interval
		// Make spawn rate scale more slowly with score (easier): decrease by 2 per 20 score, not 4 per 10
		var spawnInterval = spawnRateBoostActive ? spawnIntervalBoost : Math.max(18, spawnIntervalNormal - Math.floor(score / 20) * 2); // Slower scaling for easier game
		if (score < 250) {
			if (spawnTick >= spawnInterval) {
				// Calculate how many enemies to spawn based on score (1 + 1 per 50 score)
				var numEnemies = 1 + Math.floor(score / 50);
				for (var i = 0; i < numEnemies; i++) {
					spawnEnemy();
				}
				// 1 in 8 chance to spawn an item
				if (Math.random() < 0.125) {
					spawnItem();
				}
				spawnTick = 0;
			}
		} else if (score >= 250) {
			// Stop current music and play boss music when score passes 250
			if (typeof bossMusicPlayed === "undefined") {
				var bossMusicPlayed = false;
			}
			if (!enemyXKilledAfter250) {
				// --- Ensure EnemyX spawns immediately after passing 250 score before any other enemies ---
				if (!enemyXSpawned) {
					// Only spawn EnemyX if not already present
					var enemy = new EnemyX();
					enemy.x = 200 + Math.random() * (2048 - 400);
					enemy.y = -80;
					enemies.push(enemy);
					game.addChild(enemy);
					enemyXSpawned = true;
					// Stop current music and play boss music when EnemyX spawns
					if (!bossMusicPlayed) {
						LK.stopMusic();
						LK.playMusic('Boss');
						bossMusicPlayed = true;
					}
					spawnTick = 0;
				}
				// Do NOT spawn any other enemies or items until EnemyX is killed
				else {
					// Wait until EnemyX is killed before resuming normal spawns
					// (do nothing here)
				}
			} else {
				// EnemyX has been killed after 250 score, resume normal enemy and item spawns
				spawnTick++;
				// After score reaches 600, start to increase enemy spawn speed slowly
				var postBossSpawnInterval = 60;
				if (score >= 600) {
					// Decrease interval by 1 every 60 score above 600, minimum 18
					postBossSpawnInterval = Math.max(18, 60 - Math.floor((score - 600) / 60));
				}
				// Always spawn exactly 1 enemy per postBossSpawnInterval ticks after EnemyX is killed post-250
				if (score < 800 && spawnTick >= postBossSpawnInterval) {
					spawnEnemy();
					// 1 in 8 chance to spawn an item
					if (Math.random() < 0.125) {
						spawnItem();
					}
					spawnTick = 0;
				} else if (score === 800 && !enemyZSpawned) {
					// Spawn EnemyZ at score 800
					var enemy = new EnemyZ();
					enemy.x = 2048 / 2;
					enemy.y = -80;
					enemies.push(enemy);
					game.addChild(enemy);
					enemyZSpawned = true;
					// Optionally play boss music if not already playing
					if (typeof bossMusicPlayed === "undefined" || !bossMusicPlayed) {
						LK.stopMusic();
						LK.playMusic('Boss');
						bossMusicPlayed = true;
					}
					spawnTick = 0;
				}
			}
			// In god mode, also allow enemies to spawn after EnemyX is killed, just like normal mode
			if (godMode && enemyXKilledAfter250) {
				spawnTick++;
				var postBossSpawnInterval = 60;
				if (score >= 600) {
					postBossSpawnInterval = Math.max(18, 60 - Math.floor((score - 600) / 60));
				}
				if (score < 800 && spawnTick >= postBossSpawnInterval) {
					spawnEnemy();
					if (Math.random() < 0.125) {
						spawnItem();
					}
					spawnTick = 0;
				}
			}
		}
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Beam item class
var BeamItem = Container.expand(function () {
	var self = Container.call(this);
	var beamSprite = self.attachAsset('beamItem', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	beamSprite.width = 90;
	beamSprite.height = 90;
	beamSprite.alpha = 0.95;
	self.update = function () {
		self.y += 6;
	};
	return self;
});
// Enemy type 1: moves straight down
var Enemy1 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('enemy1', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 200;
	enemySprite.height = 200;
	self.speed = 2 + Math.random() * 1;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Enemy type 2: moves in sine wave
var Enemy2 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('enemy2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 160;
	enemySprite.height = 160;
	self.speed = 3.5 + Math.random() * 1.5;
	self.waveAmplitude = 120 + Math.random() * 80;
	self.waveSpeed = 0.012 + Math.random() * 0.005;
	self.baseX = 0;
	self.t = 0;
	self.update = function () {
		self.y += self.speed;
		self.t += self.waveSpeed;
		self.x = self.baseX + Math.sin(self.t * 6.28) * self.waveAmplitude;
	};
	return self;
});
// Strong Enemy3: needs 5 hits to die, moves straight down, larger and purple
var Enemy3 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('enemy3', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 260;
	enemySprite.height = 260;
	self.speed = 3 + Math.random() * 1;
	self.hp = 5;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Enemy4: new enemy type, moves diagonally, bounces off screen edges, explodes when near hero, needs 3 hits to die
var Enemy4 = Container.expand(function () {
	var self = Container.call(this);
	var enemySprite = self.attachAsset('Enemy4', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 180;
	enemySprite.height = 180;
	self.speedX = (Math.random() < 0.5 ? 1 : -1) * (3.5 + Math.random() * 1.5);
	self.speedY = 3.5 + Math.random() * 1.5;
	self.exploded = false;
	self.hp = 3; // Needs 3 hits to die
	self.update = function () {
		// --- Enemy4 follows the hero ---
		// Only follow if hero exists and Enemy4 is not exploded
		if (typeof hero !== "undefined" && !self.exploded) {
			// Calculate direction vector to hero
			var dx = hero.x - self.x;
			var dy = hero.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// Set speed to always move at a fixed speed toward the hero
			var speed = 8; // Enemy4's following speed (slower movement)
			if (dist > 0) {
				self.speedX = dx / dist * speed;
				self.speedY = dy / dist * speed;
			}
		}
		self.x += self.speedX;
		self.y += self.speedY;
		// Bounce off left/right edges
		if (self.x - enemySprite.width / 2 <= 0 && self.speedX < 0 || self.x + enemySprite.width / 2 >= 2048 && self.speedX > 0) {
			self.speedX *= -1;
		}
		// --- Enemy4 explodes and deals 2 damage when near or colliding with hero ---
		if (typeof hero !== "undefined" && !self.exploded && (
		// Collides with hero
		self.intersects(hero) ||
		// Or is "near" hero (distance < 120px)
		Math.abs(self.x - hero.x) < 120 && Math.abs(self.y - hero.y) < 120)) {
			self.exploded = true;
			// Tiny flash/explosion effect on Enemy4 itself
			LK.effects.flashObject(self, 0xffffff, 120);
			// Only deal damage if not in godMode or shieldActive
			if (!godMode && !shieldActive) {
				LK.getSound('heroHit').play();
				LK.effects.flashScreen(0xff0000, 800);
				if (typeof heroHealth !== "undefined") {
					heroHealth -= 2;
					if (heroHealth < 0) heroHealth = 0;
					if (typeof updateHealthBar === "function") updateHealthBar();
					if (typeof updateDemoHealthSquares === "function") updateDemoHealthSquares();
					if (heroHealth <= 0) {
						LK.getSound('Death').play();
						LK.showGameOver();
						return;
					}
				}
			} else if (shieldActive) {
				LK.effects.flashObject(hero, 0x00ffff, 200);
			}
			// Play explosion animation (particles)
			var particleCount = 16;
			for (var pi = 0; pi < particleCount; pi++) {
				var part = LK.getAsset('Enemy4', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				part.x = self.x;
				part.y = self.y;
				part.width = 24 + Math.random() * 24;
				part.height = 24 + Math.random() * 24;
				part.alpha = 0.8 + Math.random() * 0.2;
				var angle = Math.PI * 2 * (pi / particleCount) + Math.random() * 0.2;
				var speed = 12 + Math.random() * 8;
				var vx = Math.cos(angle) * speed;
				var vy = Math.sin(angle) * speed;
				part.life = 10 + Math.floor(Math.random() * 10);
				part.update = function () {
					this.x += vx;
					this.y += vy;
					this.life--;
					this.alpha *= 0.88 + Math.random() * 0.06;
					if (this.life <= 0) {
						this.destroy();
					}
				};
				if (typeof game !== "undefined") game.addChild(part);
			}
			// Remove Enemy4 from game/enemies array on next update
			if (typeof self.destroy === "function") self.destroy();
			// Remove from enemies[] in main game.update (handled by main loop)
			return;
		}
		// Enemy4 now ignores proximity to hero and does not explode or interact when flying through the hero
	};
	return self;
});
// Enemy bullet class
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletSprite = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speedX = 0;
	self.speedY = 8;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
	};
	return self;
});
// Extraordinary EnemyX: spawns only once after 250 score, unique appearance and behavior
var EnemyX = Container.expand(function () {
	var self = Container.call(this);
	// Use dedicated enemyX asset
	var enemySprite = self.attachAsset('enemyX', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 600;
	enemySprite.height = 600;
	enemySprite.alpha = 0.98;
	self.speed = 4 + Math.random() * 2;
	// Set EnemyX health to 250 only in normal mode, otherwise 500 (boss mode)
	self.hp = typeof bossMode !== "undefined" && bossMode ? 500 : 250; // much higher HP (500 hits required)
	// --- EnemyX shooting logic ---
	self.shootTick = 0;
	self.beamCooldown = 0;
	self.update = function () {
		// Boss mode: randomly drop health potion, shield, or beam items from EnemyX (less frequently)
		if (typeof bossMode !== "undefined" && bossMode && Math.random() < 0.005) {
			// 1/3 chance for each item
			var dropType = Math.floor(Math.random() * 3);
			var item;
			if (dropType === 0) {
				item = new HealthPotion();
			} else if (dropType === 1) {
				item = new ShieldItem();
			} else {
				item = new BeamItem();
			}
			item.x = self.x + (Math.random() - 0.5) * 120;
			item.y = self.y + 120;
			if (typeof items !== "undefined" && typeof game !== "undefined") {
				items.push(item);
				game.addChild(item);
			}
		}
		// Only allow EnemyX to wander in the upper part of the screen (y between 0 and 500)
		if (typeof self.t === "undefined") self.t = Math.random() * 2;
		self.t += 0.012;
		// Sway left/right slowly
		self.x += Math.sin(self.t * 2.5) * 6;
		// Restrict vertical movement: only allow y to increase up to a certain limit, then bounce back up
		if (typeof self.directionY === "undefined") self.directionY = 1;
		// Set upper and lower bounds for wandering
		var upperY = 60 + enemySprite.height / 2;
		var lowerY = 420 + enemySprite.height / 2;
		// Move down or up depending on direction
		self.y += self.speed * self.directionY * 0.3; // even slower vertical movement
		// If reached lower bound, go up; if reached upper bound, go down
		if (self.y >= lowerY) {
			self.y = lowerY;
			self.directionY = -1;
		} else if (self.y <= upperY) {
			self.y = upperY;
			self.directionY = 1;
		}
		// --- Shooting less frequently ---
		self.shootTick = (self.shootTick || 0) + 1;
		self.beamCooldown = (self.beamCooldown || 0) - 1;
		// Shoot a bullet every 60-90 ticks (randomized, less frequent)
		if (self.shootTick >= 60 + Math.floor(Math.random() * 31)) {
			if (typeof game !== "undefined" && typeof hero !== "undefined") {
				// Shoot 3-way spread
				for (var i = -1; i <= 1; i++) {
					var bullet = new EnemyBullet();
					bullet.x = self.x + i * 60;
					bullet.y = self.y + 120;
					// Aim at hero, but with spread
					var dx = hero.x - bullet.x + i * 80;
					var dy = hero.y - bullet.y;
					var len = Math.sqrt(dx * dx + dy * dy);
					if (len > 0) {
						bullet.speedX = dx / len * 10;
						bullet.speedY = dy / len * 10;
					}
					enemyBullets.push(bullet);
					game.addChild(bullet);
					LK.getSound('enemyShoot').play();
				}
			}
			self.shootTick = 0;
		}
		// Sometimes shoot a beam down (every 360-540 ticks, much more rare, and only hit when visually active)
		if (self.beamCooldown <= 0 && Math.random() < 0.012) {
			if (typeof game !== "undefined") {
				// Visual: big vertical beam
				var beam = LK.getAsset('beamItem', {
					anchorX: 0.5,
					anchorY: 0,
					x: self.x,
					y: self.y + enemySprite.height / 2
				});
				beam.width = 120;
				beam.height = 2732 - (self.y + enemySprite.height / 2);
				beam.alpha = 0.38 + Math.random() * 0.12;
				game.addChild(beam);
				// Beam effect: damage hero if in column for 60 frames, but only on first 20 frames is it "active"
				beam.life = 60;
				beam.activeFrames = 20;
				beam.update = function () {
					this.life--;
					// Flicker effect
					this.alpha = 0.32 + Math.random() * 0.18;
					// Only hit hero if beam is visually active (first 20 frames)
					if (this.life > 60 - this.activeFrames) {
						if (typeof hero !== "undefined" && hero.y > this.y && hero.y < this.y + this.height) {
							if (Math.abs(hero.x - this.x) < this.width / 2 + hero.width / 2) {
								if (!godMode && !shieldActive && this.life === 60 - this.activeFrames + 1) {
									LK.getSound('heroHit').play();
									LK.effects.flashScreen(0xff0000, 800);
									heroHealth--;
									updateHealthBar();
									updateDemoHealthSquares && updateDemoHealthSquares();
									if (heroHealth <= 0) {
										LK.getSound('Death').play();
										LK.showGameOver();
										return;
									}
								} else if (!godMode && shieldActive && this.life === 60 - this.activeFrames + 1) {
									LK.effects.flashObject(hero, 0x00ffff, 200);
								}
							}
						}
					}
					if (this.life <= 0) {
						this.destroy();
					}
				};
				// Add to enemyBullets for update/removal
				enemyBullets.push(beam);
				// Play laser sound
				LK.getSound('laser').play();
				// Set cooldown for next beam (much more rare)
				self.beamCooldown = 540 + Math.floor(Math.random() * 180);
			}
		}
	};
	return self;
});
// EnemyZ: New boss type, appears as a large, fast, zig-zagging boss with high HP and double beam attack
var EnemyZ = Container.expand(function () {
	var self = Container.call(this);
	// Use enemyZ asset, large size
	var enemySprite = self.attachAsset('EnemyZ', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enemySprite.width = 520;
	enemySprite.height = 520;
	enemySprite.alpha = 0.99;
	self.speed = 4 + Math.random() * 1.5;
	self.hp = Math.round((typeof bossMode !== "undefined" && bossMode ? 500 : 250) * 8 / 5); // Set EnemyZ health to 8/5 of EnemyX health
	self.t = Math.random() * 2;
	self.zigzagAmplitude = 320 + Math.random() * 80;
	self.zigzagSpeed = 0.009 + Math.random() * 0.004;
	self.baseX = 2048 / 2;
	self.directionY = 1;
	self.shootTick = 0;
	self.beamCooldown = 0;
	self.update = function () {
		// Zig-zag movement, stays in upper half of screen
		self.t += self.zigzagSpeed;
		self.x = self.baseX + Math.sin(self.t * 2.5) * self.zigzagAmplitude;
		// Restrict vertical movement: only allow y to increase up to a certain limit, then bounce back up
		var upperY = 80 + enemySprite.height / 2;
		var lowerY = 600 + enemySprite.height / 2;
		self.y += self.speed * self.directionY * 0.3;
		if (self.y >= lowerY) {
			self.y = lowerY;
			self.directionY = -1;
		} else if (self.y <= upperY) {
			self.y = upperY;
			self.directionY = 1;
		}
		// --- Shooting logic: fires 5-way spread every 48-72 ticks ---
		self.shootTick = (self.shootTick || 0) + 1;
		self.beamCooldown = (self.beamCooldown || 0) - 1;
		if (self.shootTick >= 48 + Math.floor(Math.random() * 25)) {
			if (typeof game !== "undefined" && typeof hero !== "undefined") {
				// Shoot 5-way spread
				for (var i = -2; i <= 2; i++) {
					var bullet = new EnemyBullet();
					bullet.x = self.x + i * 60;
					bullet.y = self.y + 120;
					// Aim at hero, but with spread
					var dx = hero.x - bullet.x + i * 60;
					var dy = hero.y - bullet.y;
					var len = Math.sqrt(dx * dx + dy * dy);
					if (len > 0) {
						bullet.speedX = dx / len * 11;
						bullet.speedY = dy / len * 11;
					}
					enemyBullets.push(bullet);
					game.addChild(bullet);
					LK.getSound('enemyShoot').play();
				}
			}
			self.shootTick = 0;
		}
		// --- Double beam attack: two beams at once, more frequent than EnemyX ---
		if (self.beamCooldown <= 0 && Math.random() < 0.025) {
			if (typeof game !== "undefined") {
				// Visual: two vertical beams, one at self.x-100, one at self.x+100
				for (var bx = -100; bx <= 100; bx += 200) {
					var beam = LK.getAsset('beamItem', {
						anchorX: 0.5,
						anchorY: 0,
						x: self.x + bx,
						y: self.y + enemySprite.height / 2
					});
					beam.width = 100;
					beam.height = 2732 - (self.y + enemySprite.height / 2);
					beam.alpha = 0.42 + Math.random() * 0.10;
					game.addChild(beam);
					// Beam effect: damage hero if in column for 48 frames, only first 16 frames "active"
					beam.life = 48;
					beam.activeFrames = 16;
					beam.update = function () {
						this.life--;
						this.alpha = 0.32 + Math.random() * 0.18;
						if (this.life > 48 - this.activeFrames) {
							if (typeof hero !== "undefined" && hero.y > this.y && hero.y < this.y + this.height) {
								if (Math.abs(hero.x - this.x) < this.width / 2 + hero.width / 2) {
									if (!godMode && !shieldActive && this.life === 48 - this.activeFrames + 1) {
										LK.getSound('heroHit').play();
										LK.effects.flashScreen(0x3399ff, 800);
										heroHealth--;
										updateHealthBar();
										updateDemoHealthSquares && updateDemoHealthSquares();
										if (heroHealth <= 0) {
											LK.getSound('Death').play();
											LK.showGameOver();
											return;
										}
									} else if (!godMode && shieldActive && this.life === 48 - this.activeFrames + 1) {
										LK.effects.flashObject(hero, 0x00ffff, 200);
									}
								}
							}
						}
						if (this.life <= 0) {
							this.destroy();
						}
					};
					enemyBullets.push(beam);
					LK.getSound('laser').play();
				}
				// Set cooldown for next double beam (more frequent than EnemyX)
				self.beamCooldown = 300 + Math.floor(Math.random() * 90);
			}
		}
	};
	return self;
});
// Health potion class (separate asset)
var HealthPotion = Container.expand(function () {
	var self = Container.call(this);
	var potionSprite = self.attachAsset('healthPotion', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	potionSprite.width = 90;
	potionSprite.height = 90;
	potionSprite.alpha = 0.95;
	self.update = function () {
		self.y += 8;
	};
	return self;
});
// Hero class
var Hero = Container.expand(function () {
	var self = Container.call(this);
	var heroSprite = self.attachAsset('hero', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = heroSprite.width / 2;
	self.shootCooldown = 0;
	self.update = function () {
		if (self.shootCooldown > 0) self.shootCooldown--;
	};
	return self;
});
// Hero bullet class
var HeroBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletSprite = self.attachAsset('heroBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -16;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Shield item class
var ShieldItem = Container.expand(function () {
	var self = Container.call(this);
	var shieldSprite = self.attachAsset('shieldItem', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	shieldSprite.width = 90;
	shieldSprite.height = 90;
	shieldSprite.alpha = 0.95; // Make it much brighter/less transparent
	self.update = function () {
		self.y += 6;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x181818
});
/**** 
* Game Code
****/ 
// Add 6 healthbar assets to the screen (for demo/test, not for health UI)
var greenSquares = [];
// (defer adding to game until after background is added)
for (var i = 0; i < 6; i++) {
	var square = LK.getAsset('Healthbar', {
		anchorX: 0,
		anchorY: 1,
		x: 60 + i * 70,
		y: 2732 - 60,
		width: 60,
		height: 60,
		tint: 0x44ff44
	});
	greenSquares.push(square);
}
// Helper to update demo health squares to match heroHealth
function updateDemoHealthSquares() {
	for (var i = 0; i < greenSquares.length; i++) {
		if (i < heroHealth) {
			greenSquares[i].visible = true;
		} else {
			greenSquares[i].visible = false;
		}
	}
}
// separate asset for health potion
// Play menu music and stop background music when menu is shown
// --- MENU OVERLAY ---
// Add menu asset as background in menu, and background asset in game
var menuBgSprite = LK.getAsset('Menu', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
menuBgSprite.width = 2048;
menuBgSprite.height = 2732;
game.addChild(menuBgSprite);
var backgroundSprite = LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
// Scale background to fill the screen (2048x2732)
var bgOriginalWidth = backgroundSprite.width;
var bgOriginalHeight = backgroundSprite.height;
var scaleX = 2048 / bgOriginalWidth;
var scaleY = 2732 / bgOriginalHeight;
var scale = Math.max(scaleX, scaleY); // cover entire area
backgroundSprite.width = bgOriginalWidth * scale;
backgroundSprite.height = bgOriginalHeight * scale;
// Center if needed (in case aspect ratio doesn't match)
backgroundSprite.x = (2048 - backgroundSprite.width) / 2;
backgroundSprite.y = (2732 - backgroundSprite.height) / 2;
backgroundSprite.visible = false; // Only show in game, not in menu
game.addChild(backgroundSprite);
// Add green squares after background so they are in front
for (var i = 0; i < greenSquares.length; i++) {
	game.addChild(greenSquares[i]);
}
LK.stopMusic();
LK.playMusic('Menu');
var menuOverlay = new Container();
menuOverlay.zIndex = 10000; // ensure on top
// Title text
var titleTxt = new Text2("GALAXY DODGE SHOOTER", {
	size: 160,
	fill: "#fff",
	fontWeight: "bold"
});
titleTxt.anchor.set(0.5, 0);
titleTxt.x = 2048 / 2;
titleTxt.y = 220;
menuOverlay.addChild(titleTxt);
// Play button background
var playBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
playBtnBg.width = 600;
playBtnBg.height = 220;
playBtnBg.alpha = 0.7;
playBtnBg.x = 2048 / 2;
playBtnBg.y = 700;
menuOverlay.addChild(playBtnBg);
// Play button text
var playBtn = new Text2("PLAY", {
	size: 140,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
playBtn.anchor.set(0.5, 0.5);
playBtn.x = 2048 / 2;
playBtn.y = 700;
menuOverlay.addChild(playBtn);
// Add god mode and boss mode play buttons first, so their positions are available for music button placement
var godMode = false;
var bossMode = false;
var godPlayBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
godPlayBtnBg.width = 600;
godPlayBtnBg.height = 220;
godPlayBtnBg.alpha = 0.7;
// Place god mode button below the play button (with margin)
godPlayBtnBg.x = 2048 / 2;
godPlayBtnBg.y = 700 + 220 / 2 + 60 + godPlayBtnBg.height / 2; // below playBtnBg
menuOverlay.addChild(godPlayBtnBg);
var godPlayBtn = new Text2("GOD MODE", {
	size: 100,
	fill: 0xffd700,
	fontWeight: "bold"
});
godPlayBtn.anchor.set(0.5, 0.5);
godPlayBtn.x = 2048 / 2;
godPlayBtn.y = godPlayBtnBg.y;
menuOverlay.addChild(godPlayBtn);
var bossPlayBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
bossPlayBtnBg.width = 600;
bossPlayBtnBg.height = 220;
bossPlayBtnBg.alpha = 0.7;
bossPlayBtnBg.x = 2048 / 2;
bossPlayBtnBg.y = godPlayBtnBg.y + godPlayBtnBg.height / 2 + 60 + bossPlayBtnBg.height / 2;
menuOverlay.addChild(bossPlayBtnBg);
var bossPlayBtn = new Text2("BOSS MODE", {
	size: 100,
	fill: 0xff4444,
	fontWeight: "bold"
});
bossPlayBtn.anchor.set(0.5, 0.5);
bossPlayBtn.x = 2048 / 2;
bossPlayBtn.y = bossPlayBtnBg.y;
menuOverlay.addChild(bossPlayBtn);
// Add music toggle button to menu
var musicOn = true;
// Place music button below boss mode button (with margin)
var musicBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
musicBtnBg.width = 340;
musicBtnBg.height = 140;
musicBtnBg.alpha = 0.7;
musicBtnBg.x = 2048 / 2;
musicBtnBg.y = bossPlayBtnBg.y + bossPlayBtnBg.height / 2 + 60 + musicBtnBg.height / 2;
menuOverlay.addChild(musicBtnBg);
var musicBtn = new Text2("MUSIC: ON", {
	size: 80,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
musicBtn.anchor.set(0.5, 0.5);
musicBtn.x = 2048 / 2;
musicBtn.y = musicBtnBg.y;
menuOverlay.addChild(musicBtn);
// Add help button below music button
var helpBtnBg = LK.getAsset('Button', {
	anchorX: 0.5,
	anchorY: 0.5
});
helpBtnBg.width = 340;
helpBtnBg.height = 140;
helpBtnBg.alpha = 0.7;
helpBtnBg.x = 2048 / 2;
helpBtnBg.y = musicBtnBg.y + musicBtnBg.height / 2 + 60 + helpBtnBg.height / 2;
menuOverlay.addChild(helpBtnBg);
var helpBtn = new Text2("HELP", {
	size: 80,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
helpBtn.anchor.set(0.5, 0.5);
helpBtn.x = 2048 / 2;
helpBtn.y = helpBtnBg.y;
menuOverlay.addChild(helpBtn);
// Add menu overlay to game
game.addChild(menuOverlay);
// --- HELP MENU POPUP ---
var helpMenuOverlay = null;
function showHelpMenu() {
	if (helpMenuOverlay && helpMenuOverlay.visible) return;
	if (helpMenuOverlay) {
		helpMenuOverlay.visible = true;
		return;
	}
	helpMenuOverlay = new Container();
	helpMenuOverlay.zIndex = 20000;
	// Help menu background using helpbackground asset
	var bg = LK.getAsset('Helpbackground', {
		anchorX: 0,
		anchorY: 0,
		x: 0,
		y: 0
	});
	bg.width = 2048;
	bg.height = 2732;
	bg.alpha = 1.0;
	helpMenuOverlay.addChild(bg);
	// Help title
	var helpTitle = new Text2("HELP", {
		size: 120,
		fill: "#fff",
		fontWeight: "bold"
	});
	helpTitle.anchor.set(0.5, 0);
	helpTitle.x = 2048 / 2;
	helpTitle.y = 320;
	helpMenuOverlay.addChild(helpTitle);
	// --- PAGE SYSTEM ---
	var helpPage = 0; // 0 = enemies, 1 = items
	// Enemy types info for help menu
	var enemyTypes = [{
		asset: 'enemy1',
		name: 'Enemy 1',
		desc: 'Standard enemy. Moves straight down. Easy to destroy.'
	}, {
		asset: 'enemy2',
		name: 'Enemy 2',
		desc: 'Sine-wave enemy. Moves in a wavy pattern. Harder to hit.'
	}, {
		asset: 'enemy3',
		name: 'Enemy 3',
		desc: 'Strong enemy. Takes 5 hits to destroy. Large and slow.'
	}, {
		asset: 'Enemy4',
		name: 'Enemy 4',
		desc: 'Diagonal bouncer. Moves diagonally, bounces off edges, and explodes when near the hero!'
	}, {
		asset: 'enemyX',
		name: 'Boss Enemy X',
		desc: 'Boss enemy. Appears after 250 score or in Boss Mode. Very tough!'
	}, {
		asset: 'EnemyZ',
		name: 'Boss Enemy Z',
		desc: 'Boss enemy. Zig-zags, shoots double beams, and is very fast!'
	}];
	// Item types info for help menu
	var itemTypes = [{
		asset: 'healthPotion',
		name: 'Health Potion',
		desc: 'Restores 1 health. Pick up to heal. If at max health, does nothing.'
	}, {
		asset: 'shieldItem',
		name: 'Shield',
		desc: 'Grants a shield for 6 seconds if at max health. Absorbs one hit from enemies or bullets.'
	}, {
		asset: 'beamItem',
		name: 'Beam Powerup',
		desc: 'Enables triple-shot for a short time. Fires 3 bullets in a spread.'
	}];
	// --- CONTAINER FOR PAGE CONTENT ---
	var pageContent = new Container();
	helpMenuOverlay.addChild(pageContent);
	// --- RENDER PAGE FUNCTION ---
	function renderHelpPage() {
		// Remove all children from pageContent
		while (pageContent.children.length > 0) {
			pageContent.removeChild(pageContent.children[0]);
		}
		// Title
		helpTitle.setText(helpPage === 0 ? "HELP" : "ITEMS");
		// Layout: vertical list, left-aligned for both image and text
		var startY = 500;
		var spacingY = 340;
		var leftMargin = 220;
		var imageTextGap = 40;
		var data = helpPage === 0 ? enemyTypes : itemTypes;
		for (var i = 0; i < data.length; i++) {
			var et = data[i];
			// Image
			var img = LK.getAsset(et.asset, {
				anchorX: 0,
				anchorY: 0,
				x: leftMargin,
				y: startY + i * spacingY,
				width: et.asset === 'enemyX' ? 180 : 120,
				height: et.asset === 'enemyX' ? 180 : 120
			});
			pageContent.addChild(img);
			// Name
			var nameTxt = new Text2(et.name, {
				size: 80,
				fill: "#fff",
				fontWeight: "bold"
			});
			nameTxt.anchor.set(0, 0);
			nameTxt.x = leftMargin + (et.asset === 'enemyX' ? 180 : 120) + imageTextGap;
			nameTxt.y = startY + i * spacingY + 10;
			pageContent.addChild(nameTxt);
			// Description
			var descTxt = new Text2(et.desc, {
				size: 60,
				fill: "#fff",
				align: "left"
			});
			descTxt.anchor.set(0, 0);
			descTxt.x = leftMargin + (et.asset === 'enemyX' ? 180 : 120) + imageTextGap;
			descTxt.y = startY + i * spacingY + 100;
			pageContent.addChild(descTxt);
		}
	}
	renderHelpPage();
	// --- PAGE NAVIGATION BUTTONS ---
	// Place under the last description text
	// Compute button Y based on number of entries in current help page
	var numEntries = helpPage === 0 ? enemyTypes.length : itemTypes.length;
	var lastDescY = 500 + (numEntries - 1) * 340 + 100 + 120; // 100 for desc offset, 120 for some margin
	// Close button (centered, first so it's under others visually)
	var closeBtnBg = LK.getAsset('Button', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	closeBtnBg.width = 340;
	closeBtnBg.height = 140;
	closeBtnBg.alpha = 0.7;
	closeBtnBg.x = 2048 / 2;
	closeBtnBg.y = lastDescY;
	helpMenuOverlay.addChild(closeBtnBg);
	var closeBtn = new Text2("CLOSE", {
		size: 80,
		fill: 0x00EAFF,
		fontWeight: "bold"
	});
	closeBtn.anchor.set(0.5, 0.5);
	closeBtn.x = 2048 / 2;
	closeBtn.y = lastDescY;
	helpMenuOverlay.addChild(closeBtn);
	// Items button (right)
	var nextBtnBg = LK.getAsset('Button', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	nextBtnBg.width = 340;
	nextBtnBg.height = 140;
	nextBtnBg.alpha = 0.7;
	nextBtnBg.x = 2048 / 2 + 400;
	nextBtnBg.y = lastDescY;
	helpMenuOverlay.addChild(nextBtnBg);
	var nextBtn = new Text2("ITEMS", {
		size: 60,
		fill: 0x00EAFF,
		fontWeight: "bold"
	});
	nextBtn.anchor.set(0.5, 0.5);
	nextBtn.x = nextBtnBg.x;
	nextBtn.y = nextBtnBg.y;
	helpMenuOverlay.addChild(nextBtn);
	// Enemies button (left)
	var prevBtnBg = LK.getAsset('Button', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	prevBtnBg.width = 340;
	prevBtnBg.height = 140;
	prevBtnBg.alpha = 0.7;
	prevBtnBg.x = 2048 / 2 - 400;
	prevBtnBg.y = lastDescY;
	helpMenuOverlay.addChild(prevBtnBg);
	var prevBtn = new Text2("ENEMIES", {
		size: 60,
		fill: 0x00EAFF,
		fontWeight: "bold"
	});
	prevBtn.anchor.set(0.5, 0.5);
	prevBtn.x = prevBtnBg.x;
	prevBtn.y = prevBtnBg.y;
	helpMenuOverlay.addChild(prevBtn);
	// Dismiss help menu on close button press, and handle page navigation
	helpMenuOverlay.down = function (x, y, obj) {
		// Close
		var dx = x - closeBtn.x;
		var dy = y - closeBtn.y;
		if (Math.abs(dx) <= closeBtnBg.width / 2 && Math.abs(dy) <= closeBtnBg.height / 2) {
			helpMenuOverlay.visible = false;
			return;
		}
		// Prev (ENEMIES)
		var pdx = x - prevBtn.x;
		var pdy = y - prevBtn.y;
		if (Math.abs(pdx) <= prevBtnBg.width / 2 && Math.abs(pdy) <= prevBtnBg.height / 2) {
			if (helpPage !== 0) {
				helpPage = 0;
				renderHelpPage();
			}
			return;
		}
		// Next (ITEMS)
		var ndx = x - nextBtn.x;
		var ndy = y - nextBtn.y;
		if (Math.abs(ndx) <= nextBtnBg.width / 2 && Math.abs(ndy) <= nextBtnBg.height / 2) {
			if (helpPage !== 1) {
				helpPage = 1;
				renderHelpPage();
			}
			return;
		}
	};
	game.addChild(helpMenuOverlay);
}
// Menu state
var menuActive = true;
// Play button interaction
menuOverlay.down = function (x, y, obj) {
	// Check if play button was pressed (normal mode)
	var dx = x - playBtn.x;
	var dy = y - playBtn.y;
	if (Math.abs(dx) <= playBtnBg.width / 2 && Math.abs(dy) <= playBtnBg.height / 2) {
		// Hide menu, start game in normal mode
		menuOverlay.visible = false;
		menuActive = false;
		godMode = false;
		if (typeof menuBgSprite !== "undefined") menuBgSprite.visible = false;
		if (typeof backgroundSprite !== "undefined") backgroundSprite.visible = true;
		LK.stopMusic();
		if (musicOn) {
			LK.playMusic('bgmusic');
		}
		return;
	}
	// Check if god mode play button was pressed
	var gdx = x - godPlayBtn.x;
	var gdy = y - godPlayBtn.y;
	if (Math.abs(gdx) <= godPlayBtnBg.width / 2 && Math.abs(gdy) <= godPlayBtnBg.height / 2) {
		// Hide menu, start game in god mode
		menuOverlay.visible = false;
		menuActive = false;
		godMode = true;
		if (typeof menuBgSprite !== "undefined") menuBgSprite.visible = false;
		if (typeof backgroundSprite !== "undefined") backgroundSprite.visible = true;
		LK.stopMusic();
		if (musicOn) {
			LK.playMusic('Godmode'); // godmode music while playing in godmode
		}
		return;
	}
	// Check if music button was pressed
	var mdx = x - musicBtn.x;
	var mdy = y - musicBtn.y;
	if (Math.abs(mdx) <= musicBtnBg.width / 2 && Math.abs(mdy) <= musicBtnBg.height / 2) {
		musicOn = !musicOn;
		if (musicOn) {
			musicBtn.setText("MUSIC: ON");
			LK.playMusic('Menu');
		} else {
			musicBtn.setText("MUSIC: OFF");
			LK.stopMusic();
		}
		return;
	}
	// Check if boss mode play button was pressed
	var bdx = x - bossPlayBtn.x;
	var bdy = y - bossPlayBtn.y;
	if (Math.abs(bdx) <= bossPlayBtnBg.width / 2 && Math.abs(bdy) <= bossPlayBtnBg.height / 2) {
		// Hide menu, start game in boss mode
		menuOverlay.visible = false;
		menuActive = false;
		godMode = false;
		bossMode = true;
		if (typeof menuBgSprite !== "undefined") menuBgSprite.visible = false;
		if (typeof backgroundSprite !== "undefined") backgroundSprite.visible = true;
		LK.stopMusic();
		if (musicOn) {
			LK.playMusic('Boss');
		}
		// Set up for boss mode: reset score, enemyXSpawned, etc.
		score = 0;
		scoreTxt.setText(score);
		enemyXSpawned = false;
		bossMusicPlayed = true; // already playing
		spawnTick = 0;
		return;
	}
	// Check if help button was pressed
	if (typeof helpBtn !== "undefined" && typeof helpBtnBg !== "undefined") {
		var hdx = x - helpBtn.x;
		var hdy = y - helpBtn.y;
		if (Math.abs(hdx) <= helpBtnBg.width / 2 && Math.abs(hdy) <= helpBtnBg.height / 2) {
			// Show help popup (custom help menu)
			showHelpMenu();
			return;
		}
	}
};
menuOverlay.move = function (x, y, obj) {};
menuOverlay.up = function (x, y, obj) {};
// Score display
var scoreTxt = new Text2('0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Health bar UI (horizontal, left bottom)
var maxHealth = 6;
var heroHealth = maxHealth;
var healthBarBg = LK.getAsset('enemy2', {
	anchorX: 0,
	// left edge
	anchorY: 1,
	// bottom edge
	tint: 0x222222
});
healthBarBg.width = 420;
healthBarBg.height = 60;
healthBarBg.alpha = 0.45;
// Place at left bottom, with margin (60px from left, 60px from bottom)
healthBarBg.x = 60;
healthBarBg.y = 2732 - 60;
LK.gui.bottomLeft.addChild(healthBarBg);
var healthBar = LK.getAsset('enemy1', {
	anchorX: 0,
	// left edge
	anchorY: 1,
	// bottom edge
	tint: 0xff4444
});
healthBar.width = 420;
healthBar.height = 60;
healthBar.alpha = 0.85;
healthBar.x = 60;
healthBar.y = 2732 - 60;
LK.gui.bottomLeft.addChild(healthBar);
// --- Health bar squares (vertical, left bottom) ---
var healthBarVSquares = [];
var squareSpacing = 12;
var squareSize = 60;
var baseX = 60;
var baseY = 2732 - 60;
for (var i = 0; i < maxHealth; i++) {
	var square = LK.getAsset('Healthbar', {
		anchorX: 0,
		anchorY: 1,
		x: baseX + i * (squareSize + squareSpacing),
		y: baseY,
		width: squareSize,
		height: squareSize,
		tint: 0x44ff44
	});
	LK.gui.bottomLeft.addChild(square);
	healthBarVSquares.push(square);
}
function updateHealthBar() {
	// Horizontal bar (left)
	healthBar.width = 420 * (heroHealth / maxHealth);
	if (heroHealth <= 2) {
		healthBar.tint = 0xff2222;
	} else if (heroHealth <= 4) {
		healthBar.tint = 0xffbb22;
	} else {
		healthBar.tint = 0x44ff44;
	}
	// Vertical bar (center) - show/hide squares and tint by health
	for (var i = 0; i < healthBarVSquares.length; i++) {
		if (i < heroHealth) {
			healthBarVSquares[i].visible = true;
			// Tint by health: green if >4, yellow if 3-4, red if 1-2
			if (heroHealth <= 2) {
				healthBarVSquares[i].tint = 0xff2222;
			} else if (heroHealth <= 4) {
				healthBarVSquares[i].tint = 0xffbb22;
			} else {
				healthBarVSquares[i].tint = 0x44ff44;
			}
			// Add a white border highlight if health is full
			healthBarVSquares[i].alpha = heroHealth === maxHealth ? 1.0 : 0.95;
		} else {
			healthBarVSquares[i].visible = false;
		}
	}
}
updateDemoHealthSquares && updateDemoHealthSquares();
updateHealthBar();
// Game variables
var hero = new Hero();
game.addChild(hero);
hero.x = 2048 / 2;
hero.y = 2732 - 350;
// Track if EnemyX has spawned
var enemyXSpawned = false;
var enemyZSpawned = false; // Track if EnemyZ is present in boss mode
// Track if EnemyX has been killed after 250 score (not in boss mode)
var enemyXKilledAfter250 = false;
// Ulti button UI and state
var ultiReady = true;
var ultiCooldown = 0;
var ultiCooldownMax = 1800; // 30 seconds at 60fps
// Create ulti button
var ultiBtn = new Text2("ULTI", {
	size: 120,
	fill: 0x00EAFF,
	fontWeight: "bold"
});
ultiBtn.anchor.set(0.5, 0.5);
// Place in right corner, leaving margin for touch and not overlapping top menu
ultiBtn.x = 2048 - 180;
ultiBtn.y = 2732 - 180;
ultiBtn.bg = LK.getAsset('enemy2', {
	anchorX: 0.5,
	anchorY: 0.5,
	tint: 0x00eaff
});
ultiBtn.bg.width = 340;
ultiBtn.bg.height = 220;
ultiBtn.bg.alpha = 0.25;
ultiBtn.bg.x = ultiBtn.x;
ultiBtn.bg.y = ultiBtn.y;
game.addChild(ultiBtn.bg);
game.addChild(ultiBtn);
// Ulti button cooldown overlay
var ultiBtnOverlay = LK.getAsset('enemy2', {
	anchorX: 0.5,
	anchorY: 0.5,
	tint: 0x222222
});
ultiBtnOverlay.width = 340;
ultiBtnOverlay.height = 220;
ultiBtnOverlay.alpha = 0.55;
ultiBtnOverlay.x = ultiBtn.x;
ultiBtnOverlay.y = ultiBtn.y;
ultiBtnOverlay.visible = false;
game.addChild(ultiBtnOverlay);
// Laser Cannon state (no button UI)
var laserReady = true;
var laserCooldown = 0;
var laserCooldownMax = 720; // 12 seconds at 60fps
// Armor visual overlay for shield
var heroArmor = LK.getAsset('enemy2', {
	anchorX: 0.5,
	anchorY: 0.5,
	tint: 0x80eaff // light blue
});
heroArmor.width = hero.width * 1.35;
heroArmor.height = hero.height * 1.35;
heroArmor.alpha = 0.55;
heroArmor.visible = false;
game.addChild(heroArmor);
var heroBullets = [];
var enemies = [];
var enemyBullets = [];
var items = [];
var dragNode = null;
var lastHeroIntersecting = false;
var score = 0;
var spawnTick = 0;
var enemyShootTick = 0;
// Powerup state
var shieldActive = false;
var shieldTimer = 0;
var beamActive = false;
var beamTimer = 0;
// Helper: spawn item
function spawnItem() {
	var itemType = Math.random() < 0.5 ? "shield" : "beam";
	var item;
	if (itemType === "shield") {
		item = new ShieldItem();
	} else {
		item = new BeamItem();
	}
	item.x = 200 + Math.random() * (2048 - 400);
	item.y = -80;
	items.push(item);
	game.addChild(item);
}
// Helper: spawn enemy
function spawnEnemy() {
	// 10% Enemy4 (only if score >= 600), 20% Enemy3, 35% Enemy1, 35% Enemy2
	var rand = Math.random();
	var enemy;
	if (rand < 0.35) {
		enemy = new Enemy1();
		enemy.x = 200 + Math.random() * (2048 - 400);
		enemy.y = -80;
	} else if (rand < 0.7) {
		enemy = new Enemy2();
		enemy.baseX = 200 + Math.random() * (2048 - 400);
		enemy.x = enemy.baseX;
		enemy.y = -80;
		enemy.t = Math.random() * 2;
	} else if (rand < 0.9) {
		enemy = new Enemy3();
		enemy.x = 200 + Math.random() * (2048 - 400);
		enemy.y = -80;
	} else {
		// Only spawn Enemy4 if score >= 600
		if (score >= 600) {
			enemy = new Enemy4();
			enemy.x = 200 + Math.random() * (2048 - 400);
			enemy.y = -80;
		} else {
			// If not allowed, fallback to Enemy1
			enemy = new Enemy1();
			enemy.x = 200 + Math.random() * (2048 - 400);
			enemy.y = -80;
		}
	}
	enemies.push(enemy);
	game.addChild(enemy);
}
// Helper: spawn enemy bullet
function spawnEnemyBullet(enemy, targetX, targetY) {
	var bullet = new EnemyBullet();
	bullet.x = enemy.x;
	bullet.y = enemy.y + 60;
	// Aim at hero
	var dx = targetX - bullet.x;
	var dy = targetY - bullet.y;
	var len = Math.sqrt(dx * dx + dy * dy);
	if (len > 0) {
		bullet.speedX = dx / len * 18;
		bullet.speedY = dy / len * 18;
	}
	enemyBullets.push(bullet);
	game.addChild(bullet);
	LK.getSound('enemyShoot').play();
}
// Move handler for dragging hero
function handleMove(x, y, obj) {
	// Always follow mouse if not dragging and not in menu
	if (!dragNode && !(typeof menuActive !== "undefined" && menuActive)) {
		// Clamp hero inside screen
		var hw = hero.width / 2;
		var hh = hero.height / 2;
		var nx = Math.max(hw, Math.min(2048 - hw, x));
		var ny = Math.max(hh + 100, Math.min(2732 - hh, y));
		hero.x = nx;
		hero.y = ny;
		return;
	}
	if (dragNode) {
		// Clamp hero inside screen
		var hw = dragNode.width / 2;
		var hh = dragNode.height / 2;
		var nx = Math.max(hw, Math.min(2048 - hw, x));
		var ny = Math.max(hh + 100, Math.min(2732 - hh, y));
		dragNode.x = nx;
		dragNode.y = ny;
	}
}
// --- Make hero follow mouse automatically at game start (PC only) ---
if (typeof window !== "undefined" && window.addEventListener) {
	window.addEventListener("mousemove", function (evt) {
		// Only follow if not in menu and not dragging
		if (typeof menuActive !== "undefined" && menuActive) return;
		if (dragNode) return;
		// Get bounding rect of canvas
		var canvas = LK.getCanvas ? LK.getCanvas() : document.querySelector("canvas") || null;
		if (!canvas) return;
		var rect = canvas.getBoundingClientRect();
		// Convert mouse coordinates to game coordinates
		var scaleX = 2048 / rect.width;
		var scaleY = 2732 / rect.height;
		var x = (evt.clientX - rect.left) * scaleX;
		var y = (evt.clientY - rect.top) * scaleY;
		handleMove(x, y, {
			event: evt
		});
	});
}
// Touch down: start dragging hero
game.down = function (x, y, obj) {
	if (typeof menuActive !== "undefined" && menuActive) return;
	// PC: left mouse click triggers laser cannon if ready and not on menu
	if (obj && obj.event && obj.event.type === "mousedown" && obj.event.button === 0 && laserReady) {
		// Only fire if click is inside hero sprite (circle)
		var dx = x - hero.x;
		var dy = y - hero.y;
		if (dx * dx + dy * dy <= hero.radius * hero.radius) {
			// Activate laser
			laserReady = false;
			laserCooldown = laserCooldownMax;
			// Laser effect: fire a vertical laser column at hero.x
			var laserX = hero.x;
			// Visual effect: draw a vertical beam for a short time, and make it follow the hero
			var laserBeam = LK.getAsset('heroBullet', {
				anchorX: 0.5,
				anchorY: 1,
				x: laserX,
				y: hero.y - hero.height / 2
			});
			laserBeam.width = 80;
			laserBeam.height = hero.y - hero.height / 2; // from hero to top
			laserBeam.alpha = 0.45;
			game.addChild(laserBeam);
			// Store reference to active laser beam and set timer
			game.activeLaserBeam = laserBeam;
			game.activeLaserBeamTimer = 90; // 1.5 seconds at 60fps
			LK.getSound('laser').play();
			// Destroy all enemies and enemy bullets in the column
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (Math.abs(e.x - laserX) <= 80) {
					// Laser cannon does NOT affect EnemyX (boss)
					if (e instanceof EnemyX) {
						// Flash to show hit, but do not damage or destroy
						LK.effects.flashObject(e, 0xff0000, 120);
						continue;
					}
					LK.effects.flashObject(e, 0xffffff, 200);
					for (var pi = 0; pi < 12; pi++) {
						var part = LK.getAsset(e instanceof Enemy1 ? 'enemy1' : e instanceof Enemy2 ? 'enemy2' : 'enemy3', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = e.x;
						part.y = e.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 12) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					// 35% chance to drop a health potion if Enemy3
					if (e instanceof Enemy3 && Math.random() < 0.35) {
						var healthPotion = new HealthPotion();
						healthPotion.x = e.x;
						healthPotion.y = e.y;
						items.push(healthPotion);
						game.addChild(healthPotion);
					}
					e.destroy();
					enemies.splice(i, 1);
				}
			}
			for (var i = enemyBullets.length - 1; i >= 0; i--) {
				var b = enemyBullets[i];
				if (Math.abs(b.x - laserX) <= 80) {
					b.destroy();
					enemyBullets.splice(i, 1);
				}
			}
			return;
		}
	}
	dragNode = hero;
	handleMove(x, y, obj);
};
// Touch up: stop dragging
game.up = function (x, y, obj) {
	if (typeof menuActive !== "undefined" && menuActive) return;
	dragNode = null;
};
// Touch move: move hero
game.move = function (x, y, obj) {
	if (typeof menuActive !== "undefined" && menuActive) return;
	handleMove(x, y, obj);
	// Handle ulti button press (touch/click)
	if (ultiReady) {
		// Check if touch is inside ulti button area
		var dx = x - ultiBtn.x;
		var dy = y - ultiBtn.y;
		if (Math.abs(dx) <= ultiBtn.bg.width / 2 && Math.abs(dy) <= ultiBtn.bg.height / 2) {
			// Activate ulti
			ultiReady = false;
			ultiCooldown = ultiCooldownMax;
			ultiBtnOverlay.visible = true;
			// Play ulti sound
			LK.getSound('Ulti').play();
			// Ulti effect: clear all enemies and enemy bullets
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (e instanceof EnemyX) {
					// Ulti does 50 damage to EnemyX in both boss mode and normal mode
					e.hp -= 50;
					LK.effects.flashObject(e, 0xffffff, 400);
					if (e.hp <= 0) {
						// Play death animation for EnemyX
						var enemyToDestroy = e;
						for (var pi = 0; pi < 48; pi++) {
							var part = LK.getAsset('enemyX', {
								anchorX: 0.5,
								anchorY: 0.5
							});
							part.x = enemyToDestroy.x;
							part.y = enemyToDestroy.y;
							part.width = 48 + Math.random() * 48;
							part.height = 48 + Math.random() * 48;
							part.alpha = 0.8 + Math.random() * 0.2;
							var angle = Math.PI * 2 * (pi / 48) + Math.random() * 0.2;
							var speed = 24 + Math.random() * 16;
							var vx = Math.cos(angle) * speed;
							var vy = Math.sin(angle) * speed;
							part.life = 32 + Math.floor(Math.random() * 32);
							part.update = function () {
								this.x += vx;
								this.y += vy;
								this.life--;
								this.alpha *= 0.90 + Math.random() * 0.04;
								if (this.life <= 0) {
									this.destroy();
								}
							};
							game.addChild(part);
						}
						// Add score for killing EnemyX with ulti
						score += 1;
						scoreTxt.setText(score);
						// Drop 3 health potions when EnemyX is killed by ulti
						for (var hp = 0; hp < 3; hp++) {
							var healthPotion = new HealthPotion();
							healthPotion.x = enemyToDestroy.x - 60 + 60 * hp;
							healthPotion.y = enemyToDestroy.y;
							items.push(healthPotion);
							game.addChild(healthPotion);
						}
						enemyToDestroy.destroy();
						enemies.splice(i, 1);
					}
				} else {
					// Add score for killing normal enemies with ulti
					score += 1;
					scoreTxt.setText(score);
					enemies[i].destroy();
					enemies.splice(i, 1);
				}
			}
			for (var i = enemyBullets.length - 1; i >= 0; i--) {
				enemyBullets[i].destroy();
				enemyBullets.splice(i, 1);
			}
			LK.effects.flashScreen(0x00eaff, 600);
			return;
		}
	}
	// Handle laser cannon activation by clicking on the hero
	if (laserReady) {
		var dx = x - hero.x;
		var dy = y - hero.y;
		// Check if touch/click is inside hero sprite (circle)
		if (dx * dx + dy * dy <= hero.radius * hero.radius) {
			// Activate laser
			laserReady = false;
			laserCooldown = laserCooldownMax;
			// Laser effect: fire a vertical laser column at hero.x
			var laserX = hero.x;
			// Visual effect: draw a vertical beam for a short time, and make it follow the hero
			var laserBeam = LK.getAsset('heroBullet', {
				anchorX: 0.5,
				anchorY: 1,
				//{37}  // anchor at bottom
				x: laserX,
				y: hero.y - hero.height / 2
			});
			laserBeam.width = 80;
			laserBeam.height = hero.y - hero.height / 2; // from hero to top
			laserBeam.alpha = 0.45;
			game.addChild(laserBeam);
			// Store reference to active laser beam and set timer
			game.activeLaserBeam = laserBeam;
			game.activeLaserBeamTimer = 90; // 1.5 seconds at 60fps
			LK.getSound('laser').play();
			// Destroy all enemies and enemy bullets in the column
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (Math.abs(e.x - laserX) <= 80) {
					// Laser cannon does NOT affect EnemyX (boss)
					if (e instanceof EnemyX) {
						// Flash to show hit, but do not damage or destroy
						LK.effects.flashObject(e, 0xff0000, 120);
						continue;
					}
					// Play death animation for each
					LK.effects.flashObject(e, 0xffffff, 200);
					// Particle effect for each
					for (var pi = 0; pi < 12; pi++) {
						var part = LK.getAsset(e instanceof Enemy1 ? 'enemy1' : e instanceof Enemy2 ? 'enemy2' : 'enemy3', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = e.x;
						part.y = e.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 12) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					// 35% chance to drop a health potion if Enemy3
					if (e instanceof Enemy3 && Math.random() < 0.35) {
						var healthPotion = new HealthPotion();
						healthPotion.x = e.x;
						healthPotion.y = e.y;
						items.push(healthPotion);
						game.addChild(healthPotion);
					}
					e.destroy();
					enemies.splice(i, 1);
				}
			}
			for (var i = enemyBullets.length - 1; i >= 0; i--) {
				var b = enemyBullets[i];
				if (Math.abs(b.x - laserX) <= 80) {
					b.destroy();
					enemyBullets.splice(i, 1);
				}
			}
			return;
		}
	}
};
// Main game update
game.update = function () {
	if (typeof menuActive !== "undefined" && menuActive) {
		// Block all game logic while menu is active
		return;
	}
	// Update hero
	hero.update();
	// Laser beam follow logic
	if (game.activeLaserBeam) {
		// Move the beam to follow the hero's x and y, and always stretch from hero to top
		game.activeLaserBeam.x = hero.x;
		game.activeLaserBeam.y = hero.y - hero.height / 2;
		game.activeLaserBeam.height = hero.y - hero.height / 2;
		// Laser beam hits enemies it touches
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			// Check if enemy is within the laser beam's column (80px wide, same as beam)
			if (e.y + (e.height ? e.height / 2 : 60) >= 0 &&
			// enemy is not above top
			e.y - (e.height ? e.height / 2 : 60) <= hero.y - hero.height / 2 &&
			// enemy is not below beam bottom
			Math.abs(e.x - game.activeLaserBeam.x) <= game.activeLaserBeam.width / 2) {
				// Laser cannon does NOT affect EnemyX (boss)
				if (e instanceof EnemyX) {
					// Flash to show hit, but do not damage or destroy
					LK.effects.flashObject(e, 0xff0000, 120);
					continue;
				}
				// Play hit sound and flash
				LK.getSound('enemyHit').play();
				LK.effects.flashObject(e, 0xffffff, 200);
				// Score and handle Enemy3 HP
				score += 1;
				scoreTxt.setText(score);
				if (e instanceof Enemy3) {
					e.hp--;
					if (e.hp <= 0) {
						// Play death animation before destroying Enemy3
						var enemyToDestroy = e;
						for (var pi = 0; pi < 24; pi++) {
							var part = LK.getAsset('enemy3', {
								anchorX: 0.5,
								anchorY: 0.5
							});
							part.x = enemyToDestroy.x;
							part.y = enemyToDestroy.y;
							part.width = 32 + Math.random() * 32;
							part.height = 32 + Math.random() * 32;
							part.alpha = 0.8 + Math.random() * 0.2;
							var angle = Math.PI * 2 * (pi / 24) + Math.random() * 0.2;
							var speed = 16 + Math.random() * 12;
							var vx = Math.cos(angle) * speed;
							var vy = Math.sin(angle) * speed;
							part.life = 16 + Math.floor(Math.random() * 16);
							part.update = function () {
								this.x += vx;
								this.y += vy;
								this.life--;
								this.alpha *= 0.90 + Math.random() * 0.04;
								if (this.life <= 0) {
									this.destroy();
								}
							};
							game.addChild(part);
						}
						// 35% chance to drop a health potion when Enemy3 is killed
						if (Math.random() < 0.35) {
							var healthPotion = new HealthPotion();
							healthPotion.x = enemyToDestroy.x;
							healthPotion.y = enemyToDestroy.y;
							items.push(healthPotion);
							game.addChild(healthPotion);
						}
						enemyToDestroy.destroy();
						enemies.splice(i, 1);
					} else {
						// Flash for hit, but don't destroy
						LK.effects.flashObject(e, 0x8e24aa, 120);
					}
				} else {
					// Play death animation before destroying normal enemies
					var enemyToDestroy = e;
					for (var pi = 0; pi < 16; pi++) {
						var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : 'enemy2', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = enemyToDestroy.x;
						part.y = enemyToDestroy.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					enemyToDestroy.destroy();
					enemies.splice(i, 1);
				}
			}
		}
		// Decrement timer and destroy when done
		game.activeLaserBeamTimer--;
		if (game.activeLaserBeamTimer <= 0) {
			game.activeLaserBeam.destroy();
			game.activeLaserBeam = null;
		}
	}
	// Ulti cooldown logic
	if (godMode) {
		ultiReady = true;
		ultiCooldown = 0;
		ultiBtnOverlay.visible = false;
		ultiBtn.text = "ULTI";
	} else {
		if (!ultiReady) {
			ultiCooldown--;
			if (ultiCooldown <= 0) {
				ultiReady = true;
				ultiBtnOverlay.visible = false;
			} else {
				// Show overlay and update text to show seconds left
				ultiBtnOverlay.visible = true;
				ultiBtn.text = "ULTI\n" + Math.ceil(ultiCooldown / 60) + "s";
			}
		}
		if (ultiReady) {
			ultiBtn.text = "ULTI";
			ultiBtnOverlay.visible = false;
		}
	}
	// Update armor overlay position and visibility
	heroArmor.x = hero.x;
	heroArmor.y = hero.y;
	heroArmor.visible = shieldActive;
	// Laser cannon cooldown logic (no button UI)
	if (!laserReady) {
		laserCooldown--;
		if (laserCooldown <= 0) {
			laserReady = true;
		}
	}
	// Update shield/beam timers
	if (shieldActive) {
		shieldTimer--;
		if (shieldTimer <= 0) {
			shieldActive = false;
		}
	}
	if (beamActive) {
		beamTimer--;
		if (beamTimer <= 0) {
			beamActive = false;
		}
	}
	// Update items (powerups)
	for (var i = items.length - 1; i >= 0; i--) {
		var item = items[i];
		item.update();
		// Remove if off screen
		if (item.y > 2732 + 100) {
			item.destroy();
			items.splice(i, 1);
			continue;
		}
		// Pickup by hero
		if (item.intersects(hero)) {
			if (item instanceof HealthPotion) {
				// Health potion always gives 1 health (if not at max)
				if (heroHealth < maxHealth) {
					heroHealth = Math.min(maxHealth, heroHealth + 1);
					updateHealthBar();
					updateDemoHealthSquares && updateDemoHealthSquares();
					LK.effects.flashObject(hero, 0x44ff44, 400);
				}
			} else if (item instanceof ShieldItem) {
				// If already at max health, treat as shield
				if (heroHealth >= maxHealth) {
					shieldActive = true;
					shieldTimer = 360; // 6 seconds at 60fps
					LK.effects.flashObject(hero, 0x00ffff, 400);
				} else {
					// If not at max health, ignore shield pickup (health potions now handled separately)
				}
			} else if (item instanceof BeamItem) {
				beamActive = true;
				beamTimer = 180; // 3 seconds at 60fps
				LK.effects.flashObject(hero, 0xff00ff, 400);
			}
			item.destroy();
			items.splice(i, 1);
			continue;
		}
	}
	// Hero shooting (auto-fire)
	if (hero.shootCooldown <= 0) {
		if (beamActive) {
			// Beam: fire 3 bullets in spread
			for (var bdir = -1; bdir <= 1; bdir++) {
				var bullet = new HeroBullet();
				bullet.x = hero.x + bdir * 40;
				bullet.y = hero.y - hero.height / 2 - 20;
				bullet.spread = bdir * 0.18; // radians
				bullet.update = function (origUpdate, spread) {
					return function () {
						this.y += this.speed;
						this.x += Math.sin(spread) * 18;
					};
				}(bullet.update, bullet.spread);
				heroBullets.push(bullet);
				game.addChild(bullet);
			}
			hero.shootCooldown = 12;
			LK.getSound('laser').play();
		} else {
			var bullet = new HeroBullet();
			bullet.x = hero.x;
			bullet.y = hero.y - hero.height / 2 - 20;
			heroBullets.push(bullet);
			game.addChild(bullet);
			hero.shootCooldown = 20;
			LK.getSound('laser').play();
		}
	}
	// Update hero bullets
	for (var i = heroBullets.length - 1; i >= 0; i--) {
		var b = heroBullets[i];
		b.update();
		// Remove if off screen
		if (b.y < -60) {
			b.destroy();
			heroBullets.splice(i, 1);
			continue;
		}
		// Check collision with enemies
		for (var j = enemies.length - 1; j >= 0; j--) {
			var e = enemies[j];
			// In boss mode, if EnemyZ is killed, allow next boss to spawn
			if (typeof bossMode !== "undefined" && bossMode && e instanceof EnemyZ && e.hp <= 1 && b.intersects(e)) {
				enemyZSpawned = false;
				spawnTick = 0;
				bossNextToSpawn = "X"; // Always alternate to X after Z dies
			}
			if (b.intersects(e)) {
				// Enemy hit
				LK.getSound('enemyHit').play();
				score += 1;
				scoreTxt.setText(score);
				// Flash enemy
				LK.effects.flashObject(e, 0xffffff, 200);
				// Remove both or handle Enemy3/EnemyX/Enemy4/EnemyZ hp
				if (e instanceof Enemy3 || e instanceof EnemyX || e instanceof Enemy4 || e instanceof EnemyZ) {
					e.hp--;
					if (e.hp <= 0) {
						// Play death animation before destroying Enemy3/EnemyX/Enemy4/EnemyZ
						var enemyToDestroy = e;
						// --- Enemy4 explosion: NO damage to hero when destroyed by bullets, laser, or shield ---
						// (intentionally left blank, Enemy4 does not deal damage when destroyed by bullets, laser, or shield)
						// Particle animation for Enemy3/EnemyX/Enemy4/EnemyZ death (more particles, richer effect)
						var particleCount = e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 24 : e instanceof EnemyZ ? 48 : 16;
						var assetName = e instanceof EnemyX ? 'enemyX' : e instanceof Enemy3 ? 'enemy3' : e instanceof EnemyZ ? 'EnemyZ' : 'Enemy4';
						for (var pi = 0; pi < particleCount; pi++) {
							var part = LK.getAsset(assetName, {
								anchorX: 0.5,
								anchorY: 0.5
							});
							part.x = enemyToDestroy.x;
							part.y = enemyToDestroy.y;
							part.width = (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24) + Math.random() * (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24);
							part.height = (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24) + Math.random() * (e instanceof EnemyX ? 48 : e instanceof Enemy3 ? 32 : e instanceof EnemyZ ? 48 : 24);
							part.alpha = 0.8 + Math.random() * 0.2;
							var angle = Math.PI * 2 * (pi / particleCount) + Math.random() * 0.2;
							var speed = (e instanceof EnemyX ? 24 : e instanceof Enemy3 ? 16 : e instanceof EnemyZ ? 24 : 12) + Math.random() * (e instanceof EnemyX ? 16 : e instanceof Enemy3 ? 12 : e instanceof EnemyZ ? 16 : 8);
							var vx = Math.cos(angle) * speed;
							var vy = Math.sin(angle) * speed;
							part.life = (e instanceof EnemyX ? 32 : e instanceof Enemy3 ? 16 : e instanceof EnemyZ ? 32 : 10) + Math.floor(Math.random() * (e instanceof EnemyX ? 32 : e instanceof Enemy3 ? 16 : e instanceof EnemyZ ? 32 : 8));
							part.update = function () {
								this.x += vx;
								this.y += vy;
								this.life--;
								this.alpha *= 0.90 + Math.random() * 0.04;
								if (this.life <= 0) {
									this.destroy();
								}
							};
							game.addChild(part);
						}
						// 35% chance to drop a health potion when Enemy3 is killed (not for EnemyX/Enemy4/EnemyZ)
						if (e instanceof Enemy3 && Math.random() < 0.35) {
							var healthPotion = new HealthPotion();
							healthPotion.x = enemyToDestroy.x;
							healthPotion.y = enemyToDestroy.y;
							items.push(healthPotion);
							game.addChild(healthPotion);
						}
						enemyToDestroy.destroy();
						enemies.splice(j, 1);
						// If EnemyX was killed, drop 3 health potions and restart normal enemy spawning
						if (e instanceof EnemyX) {
							for (var hp = 0; hp < 3; hp++) {
								var healthPotion = new HealthPotion();
								// Spread potions horizontally a bit
								healthPotion.x = enemyToDestroy.x - 60 + 60 * hp;
								healthPotion.y = enemyToDestroy.y;
								items.push(healthPotion);
								game.addChild(healthPotion);
							}
							// --- In boss mode, alternate to EnemyZ after EnemyX dies
							if (typeof bossMode !== "undefined" && bossMode) {
								enemyXSpawned = false;
								enemyZSpawned = false; // Allow next boss to spawn (EnemyZ)
								spawnTick = 0;
								bossNextToSpawn = "Z"; // Always alternate to Z after X dies
								// Music continues
							} else {
								// Reset boss state and allow normal enemies to spawn again
								enemyXSpawned = false;
								bossMusicPlayed = false;
								// Stop boss music and play bgmusic when EnemyX is killed
								LK.stopMusic();
								LK.playMusic('bgmusic');
								// If score >= 250, mark EnemyX as killed so it never spawns again (not in boss mode)
								if (score >= 250 && !(typeof bossMode !== "undefined" && bossMode)) {
									enemyXKilledAfter250 = true;
								}
								// Reset spawnTick so normal enemies start coming again, but slowly
								spawnTick = 0;
								// Reset spawnIntervalNormal to its original value when resuming normal enemy spawns
								spawnIntervalNormal = 60;
								// Optionally, set a delay before next normal spawn (e.g. 60 frames)
								// spawnTick = -60;
							}
						}
						// If EnemyZ was killed, alternate to EnemyX after Z dies (boss mode)
						if (e instanceof EnemyZ && typeof bossMode !== "undefined" && bossMode) {
							enemyZSpawned = false;
							spawnTick = 0;
							bossNextToSpawn = "X"; // Always alternate to X after Z dies
						}
					} else {
						// Flash for hit, but don't destroy
						LK.effects.flashObject(e, 0x8e24aa, 120);
					}
					b.destroy();
					heroBullets.splice(i, 1);
					break;
				} else {
					b.destroy();
					heroBullets.splice(i, 1);
					// Play death animation before destroying normal enemies
					var enemyToDestroy = e;
					// Particle animation for normal enemy death (more particles, richer effect)
					for (var pi = 0; pi < 16; pi++) {
						var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : 'enemy2', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						part.x = enemyToDestroy.x;
						part.y = enemyToDestroy.y;
						part.width = 20 + Math.random() * 20;
						part.height = 20 + Math.random() * 20;
						part.alpha = 0.7 + Math.random() * 0.3;
						var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2;
						var speed = 10 + Math.random() * 10;
						var vx = Math.cos(angle) * speed;
						var vy = Math.sin(angle) * speed;
						part.life = 10 + Math.floor(Math.random() * 10);
						part.update = function () {
							this.x += vx;
							this.y += vy;
							this.life--;
							this.alpha *= 0.88 + Math.random() * 0.06;
							if (this.life <= 0) {
								this.destroy();
							}
						};
						game.addChild(part);
					}
					enemyToDestroy.destroy();
					enemies.splice(j, 1);
					break;
				}
			}
		}
	}
	// Update enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var e = enemies[i];
		if (typeof bossMode !== "undefined" && bossMode && e instanceof EnemyZ && e.hp <= 0) {
			enemyZSpawned = false;
			spawnTick = 0;
			bossNextToSpawn = "X"; // Always alternate to X after Z dies
		}
		e.update();
		// Remove if off screen
		if (e.y > 2732 + 100) {
			e.destroy();
			enemies.splice(i, 1);
			continue;
		}
		// Enemy shoots randomly
		if (Math.random() < 0.008) {
			spawnEnemyBullet(e, hero.x, hero.y);
		}
		// Check collision with hero
		// Prevent hero from affecting or being affected by boss type enemies (EnemyX, EnemyZ)
		if (e instanceof EnemyX || e instanceof EnemyZ) {
			// Do nothing: hero does not affect or get hit by boss type enemies
			continue;
		}
		if (e.intersects(hero)) {
			if (godMode) {
				// In god mode, ignore all damage and just destroy enemy
				enemies[i].destroy();
				enemies.splice(i, 1);
				continue;
			}
			if (!shieldActive) {
				// Hero hit
				LK.getSound('heroHit').play();
				LK.effects.flashScreen(0xff0000, 800);
				heroHealth--;
				updateHealthBar();
				updateDemoHealthSquares && updateDemoHealthSquares();
				if (heroHealth <= 0) {
					LK.getSound('Death').play();
					LK.showGameOver();
					return;
				}
				enemies[i].destroy();
				enemies.splice(i, 1);
				continue;
			} else {
				// Shield absorbs hit, destroy enemy
				LK.effects.flashObject(hero, 0x00ffff, 200);
				// Play death animation before destroying enemy killed by shield
				var enemyToDestroy = e;
				// Particle animation for shield kill (more particles, richer effect)
				for (var pi = 0; pi < 16; pi++) {
					var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : enemyToDestroy instanceof Enemy2 ? 'enemy2' : 'enemy3', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					part.x = enemyToDestroy.x;
					part.y = enemyToDestroy.y;
					part.width = 20 + Math.random() * 20;
					part.height = 20 + Math.random() * 20;
					part.alpha = 0.7 + Math.random() * 0.3;
					var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2;
					var speed = 10 + Math.random() * 10;
					var vx = Math.cos(angle) * speed;
					var vy = Math.sin(angle) * speed;
					part.life = 10 + Math.floor(Math.random() * 10);
					part.update = function () {
						this.x += vx;
						this.y += vy;
						this.life--;
						this.alpha *= 0.88 + Math.random() * 0.06;
						if (this.life <= 0) {
							this.destroy();
						}
					};
					game.addChild(part);
				}
				enemyToDestroy.destroy();
				enemies.splice(i, 1);
				continue;
			}
		}
	}
	// Update enemy bullets
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var b = enemyBullets[i];
		if (typeof bossMode !== "undefined" && bossMode && b instanceof EnemyBullet) {
			// Check if this bullet killed EnemyZ (shouldn't happen, but for completeness)
			for (var j = enemies.length - 1; j >= 0; j--) {
				var e = enemies[j];
				if (e instanceof EnemyZ && e.hp <= 0) {
					enemyZSpawned = false;
					spawnTick = 0;
					bossNextToSpawn = "X"; // Always alternate to X after Z dies
				}
			}
		}
		b.update();
		// Remove if off screen
		if (b.y < -60 || b.y > 2732 + 60 || b.x < -60 || b.x > 2048 + 60) {
			b.destroy();
			enemyBullets.splice(i, 1);
			continue;
		}
		// Check collision with hero
		if (b.intersects(hero)) {
			if (godMode) {
				// In god mode, ignore all damage and just destroy bullet
				b.destroy();
				enemyBullets.splice(i, 1);
				continue;
			}
			if (!shieldActive) {
				LK.getSound('heroHit').play();
				LK.effects.flashScreen(0xff0000, 800);
				heroHealth--;
				updateHealthBar();
				updateDemoHealthSquares && updateDemoHealthSquares();
				if (heroHealth <= 0) {
					LK.getSound('Death').play();
					LK.showGameOver();
					return;
				}
				b.destroy();
				enemyBullets.splice(i, 1);
				continue;
			} else {
				// Shield absorbs bullet
				LK.effects.flashObject(hero, 0x00ffff, 120);
				b.destroy();
				enemyBullets.splice(i, 1);
				continue;
			}
		}
	}
	// --- ENEMY SPAWN RATE BOOST LOGIC ---
	if (typeof spawnRateBoostActive === "undefined") {
		var spawnRateBoostActive = false;
		var spawnRateBoostTimer = 0;
		var nextBoostScore = 50;
		var spawnIntervalNormal = 90;
		var spawnIntervalBoost = 60;
	}
	// Boss mode: alternate EnemyX and EnemyZ, never normal enemies or items
	if (typeof bossMode !== "undefined" && bossMode) {
		spawnTick++;
		// Track which boss to spawn next: "X" or "Z"
		if (typeof bossNextToSpawn === "undefined") bossNextToSpawn = "X";
		if (!enemyXSpawned && !enemyZSpawned && spawnTick >= 30) {
			var enemy;
			// Special case: at score 451, always spawn EnemyZ regardless of alternation
			if (score === 451) {
				enemy = new EnemyZ();
				enemy.x = 2048 / 2;
				enemy.y = -80;
				enemies.push(enemy);
				game.addChild(enemy);
				enemyZSpawned = true;
				bossNextToSpawn = "X"; // After Z, alternate to X
				spawnTick = 0;
			} else if (bossNextToSpawn === "X") {
				enemy = new EnemyX();
				enemy.x = 200 + Math.random() * (2048 - 400);
				enemy.y = -80;
				enemies.push(enemy);
				game.addChild(enemy);
				enemyXSpawned = true;
				// Do not alternate bossNextToSpawn here; alternate only on death
				spawnTick = 0;
			} else if (bossNextToSpawn === "Z") {
				enemy = new EnemyZ();
				enemy.x = 2048 / 2;
				enemy.y = -80;
				enemies.push(enemy);
				game.addChild(enemy);
				enemyZSpawned = true;
				// Do not alternate bossNextToSpawn here; alternate only on death
				spawnTick = 0;
			}
		}
		// Never spawn items or normal enemies in boss mode
	} else {
		// Check if we reached a new boost score (50, 150, 250, ...) and trigger boost
		if (score >= nextBoostScore && !spawnRateBoostActive) {
			spawnRateBoostActive = true;
			spawnRateBoostTimer = 180; // 3 seconds at 60fps
			// After 50, next is 150, then 250, 350, ...
			if (nextBoostScore === 50) {
				nextBoostScore = 150;
			} else {
				nextBoostScore += 100;
			}
		}
		// Handle boost timer
		if (spawnRateBoostActive) {
			spawnRateBoostTimer--;
			if (spawnRateBoostTimer <= 0) {
				spawnRateBoostActive = false;
			}
		}
		// Spawn enemies
		spawnTick++;
		// Use boosted or normal interval
		// Make spawn rate scale more slowly with score (easier): decrease by 2 per 20 score, not 4 per 10
		var spawnInterval = spawnRateBoostActive ? spawnIntervalBoost : Math.max(18, spawnIntervalNormal - Math.floor(score / 20) * 2); // Slower scaling for easier game
		if (score < 250) {
			if (spawnTick >= spawnInterval) {
				// Calculate how many enemies to spawn based on score (1 + 1 per 50 score)
				var numEnemies = 1 + Math.floor(score / 50);
				for (var i = 0; i < numEnemies; i++) {
					spawnEnemy();
				}
				// 1 in 8 chance to spawn an item
				if (Math.random() < 0.125) {
					spawnItem();
				}
				spawnTick = 0;
			}
		} else if (score >= 250) {
			// Stop current music and play boss music when score passes 250
			if (typeof bossMusicPlayed === "undefined") {
				var bossMusicPlayed = false;
			}
			if (!enemyXKilledAfter250) {
				// --- Ensure EnemyX spawns immediately after passing 250 score before any other enemies ---
				if (!enemyXSpawned) {
					// Only spawn EnemyX if not already present
					var enemy = new EnemyX();
					enemy.x = 200 + Math.random() * (2048 - 400);
					enemy.y = -80;
					enemies.push(enemy);
					game.addChild(enemy);
					enemyXSpawned = true;
					// Stop current music and play boss music when EnemyX spawns
					if (!bossMusicPlayed) {
						LK.stopMusic();
						LK.playMusic('Boss');
						bossMusicPlayed = true;
					}
					spawnTick = 0;
				}
				// Do NOT spawn any other enemies or items until EnemyX is killed
				else {
					// Wait until EnemyX is killed before resuming normal spawns
					// (do nothing here)
				}
			} else {
				// EnemyX has been killed after 250 score, resume normal enemy and item spawns
				spawnTick++;
				// After score reaches 600, start to increase enemy spawn speed slowly
				var postBossSpawnInterval = 60;
				if (score >= 600) {
					// Decrease interval by 1 every 60 score above 600, minimum 18
					postBossSpawnInterval = Math.max(18, 60 - Math.floor((score - 600) / 60));
				}
				// Always spawn exactly 1 enemy per postBossSpawnInterval ticks after EnemyX is killed post-250
				if (score < 800 && spawnTick >= postBossSpawnInterval) {
					spawnEnemy();
					// 1 in 8 chance to spawn an item
					if (Math.random() < 0.125) {
						spawnItem();
					}
					spawnTick = 0;
				} else if (score === 800 && !enemyZSpawned) {
					// Spawn EnemyZ at score 800
					var enemy = new EnemyZ();
					enemy.x = 2048 / 2;
					enemy.y = -80;
					enemies.push(enemy);
					game.addChild(enemy);
					enemyZSpawned = true;
					// Optionally play boss music if not already playing
					if (typeof bossMusicPlayed === "undefined" || !bossMusicPlayed) {
						LK.stopMusic();
						LK.playMusic('Boss');
						bossMusicPlayed = true;
					}
					spawnTick = 0;
				}
			}
			// In god mode, also allow enemies to spawn after EnemyX is killed, just like normal mode
			if (godMode && enemyXKilledAfter250) {
				spawnTick++;
				var postBossSpawnInterval = 60;
				if (score >= 600) {
					postBossSpawnInterval = Math.max(18, 60 - Math.floor((score - 600) / 60));
				}
				if (score < 800 && spawnTick >= postBossSpawnInterval) {
					spawnEnemy();
					if (Math.random() < 0.125) {
						spawnItem();
					}
					spawnTick = 0;
				}
			}
		}
	}
};
:quality(85)/https://cdn.frvr.ai/682f435f61b5c3c923320c5d.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/683031e82b533c5fbe327bb7.png%3F3) 
 A red winged alien with exoskeleton. . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/683032652b533c5fbe327bbf.png%3F3) 
 A tiny green alien with spikes. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/683033262b533c5fbe327bd1.png%3F3) 
 A strong yellow-white alien with horns. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/683034aa2b533c5fbe327bf3.png%3F3) 
 A king yellow alien with black and white stripes and wings. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/6831e33c7278e11d362be436.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6831e3f11ec26e71a6939342.png%3F3) 
 Neboula background. In-Game asset. 2d. High contrast. No shadows. Cinematic deep
:quality(85)/https://cdn.frvr.ai/6832ea3a64a9e36b8aad3a02.png%3F3) 
 Pixel art style, spaceship lazer bullet. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6832f1f364a9e36b8aad3a39.png%3F3) 
 Pixel art 2d heart. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6832f50d64a9e36b8aad3a69.png%3F3) 
 Pixel art Spaceship. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6832f70664a9e36b8aad3abe.png%3F3) 
 Pixel art shield. In-Game asset. 2d. High contrast. No shadows. blue color. Simple design
:quality(85)/https://cdn.frvr.ai/6832f78864a9e36b8aad3ada.png%3F3) 
 Flying Space enemy. In-Game asset. 2d. High contrast. No shadows. Pixelart style.
:quality(85)/https://cdn.frvr.ai/6832f80d64a9e36b8aad3af7.png%3F3) 
 A yellow pixelart rectangle button.. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6832f8d864a9e36b8aad3b13.png%3F3) 
 a pixelart flying space enemy. Green color, scary smiley face. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6832f92f64a9e36b8aad3b1d.png%3F3) 
 Pixelart healt thing. Simple. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6832f96364a9e36b8aad3b2e.png%3F3) 
 Pixelart power up item. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6832fa1364a9e36b8aad3b55.png%3F3) 
 Pixelart spike ellipse enemy bullet. In-Game asset. 2d. High contrast. No shadows. No fire effect.