/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highscoresData: "[]"
});
/**** 
* Classes
****/ 
// Air Enemy Class (Snake Segment - Simplified for MVP)
var AirEnemy = Container.expand(function (startX, startY) {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('airEnemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = startX;
	self.y = startY;
	self.speedX = 4 + Math.random() * 2; // Horizontal speed
	self.amplitudeY = 100 + Math.random() * 100; // Vertical movement range
	self.frequencyY = 0.01 + Math.random() * 0.01; // Vertical movement speed
	self.fireRate = 150; // Ticks between shots
	self.fireCooldown = Math.random() * self.fireRate;
	self.update = function () {
		// Basic horizontal and sinusoidal vertical movement
		self.x -= self.speedX;
		self.y = startY + Math.sin(LK.ticks * self.frequencyY + startX) * self.amplitudeY; // Use startX for phase offset
		// Firing logic
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			// Fire a single bullet straight left
			var bulletSpeed = 8;
			fireEnemyBullet(self.x, self.y, -bulletSpeed, 0); // vx = -speed, vy = 0
		}
		// Boundary check (simple respawn logic)
		if (self.x < -enemyGraphics.width) {
			self.x = 2048 + enemyGraphics.width; // Respawn on the right
			startY = Math.random() * (2732 - 400) + 200; // Random Y position
		}
	};
	return self;
});
// Boss Class (Basic structure for future)
var Boss = Container.expand(function () {
	var self = Container.call(this);
	var bossGraphics = self.attachAsset('boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = 2048 - 300; // Position on the right
	self.y = 2732 / 2; // Center vertically
	self.fireRate = 180; // Ticks between laser bursts
	self.fireCooldown = 0;
	self.health = 100; // Example health
	self.update = function () {
		// Add movement logic if needed
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			fireBossLasers(self.x, self.y);
		}
	};
	return self;
});
// Boss Laser Class (Basic structure for future)
var BossLaser = Container.expand(function (startX, startY, vx, vy) {
	var self = Container.call(this);
	var laserGraphics = self.attachAsset('bossLaser', {
		anchorX: 0.5,
		anchorY: 0.5 // Anchor center
	});
	self.x = startX;
	self.y = startY;
	self.vx = vx;
	self.vy = vy;
	// Set rotation based on velocity direction
	self.rotation = Math.atan2(vy, vx) + Math.PI / 2; // Point laser in direction of travel (+90deg adjustment needed depending on asset orientation)
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
	};
	return self;
});
// Bottom Mountain Obstacle Class
var BottomMountain = Container.expand(function () {
	var self = Container.call(this);
	var mountainGraphics = self.attachAsset('bottommountain', {
		anchorX: 0.5,
		anchorY: 0.75 // Anchor base at terrain edge
	});
	self.speed = 5; // Should match terrain speed
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// DiagonalEnemy Class for Level 2
var DiagonalEnemy = Container.expand(function (xPos, yPos) {
	var self = Container.call(this);
	var graphics = self.attachAsset('diagonalEnemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	graphics.rotation = Math.PI / 4;
	self.x = xPos;
	self.y = yPos;
	self.speed = terrainSpeed + 1; // Slightly faster than terrain
	self.health = 4;
	self.fireRate = 160;
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	self.update = function () {
		if (self.isDestroyed) return;
		self.x -= self.speed;
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			var bulletSpeed = 7;
			fireEnemyBullet(self.x, self.y, bulletSpeed, 0, 'enemyBulletBlue'); // Right
			fireEnemyBullet(self.x, self.y, -bulletSpeed, 0, 'enemyBulletBlue'); // Left
			fireEnemyBullet(self.x, self.y, 0, bulletSpeed, 'enemyBulletBlue'); // Down
			fireEnemyBullet(self.x, self.y, 0, -bulletSpeed, 'enemyBulletBlue'); // Up
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			var index = diagonalEnemies.indexOf(self);
			if (index > -1) {
				diagonalEnemies.splice(index, 1);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
// Enemy Bullet Class
var EnemyBullet = Container.expand(function (startX, startY, vx, vy, assetId) {
	var self = Container.call(this);
	// Added assetId
	var bulletGraphics = self.attachAsset(assetId || 'enemyBullet', {
		// Use assetId or default
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = startX;
	self.y = startY;
	self.vx = vx; // Horizontal velocity
	self.vy = vy; // Vertical velocity
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
	};
	return self;
});
// Ground Enemy Class
var GroundEnemy = Container.expand(function (isTop) {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset(isTop ? 'groundEnemytop' : 'groundEnemybottom', {
		anchorX: 0.5,
		anchorY: isTop ? 0 : 1 // Anchor base at terrain edge
	});
	self.isTop = isTop;
	self.speed = 5; // Should match terrain speed
	self.fireRate = 120; // Ticks between firing sequences (2 seconds)
	self.fireCooldown = Math.random() * self.fireRate; // Random initial delay
	self.shotsInBurst = 3;
	self.burstDelay = 10; // Ticks between shots in a burst
	self.update = function () {
		self.x -= self.speed;
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0; // Reset cooldown
			// Fire burst
			for (var i = 0; i < self.shotsInBurst; i++) {
				LK.setTimeout(function () {
					// Check if enemy still exists before firing
					if (!self.destroyed) {
						var bulletSpeed = 8;
						// Calculate direction logic is now in fireEnemyBullet, but still need to pass initial values
						var vx = -bulletSpeed * 0.707; // Default direction if player not available
						var vy = self.isTop ? bulletSpeed * 0.707 : -bulletSpeed * 0.707; // Default direction
						fireEnemyBullet(self.x, self.y, vx, vy);
					}
				}, i * self.burstDelay);
			}
		}
	};
	return self;
});
// Player Bullet Class
var PlayerBullet = Container.expand(function (startX, startY) {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('playerBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = startX;
	self.y = startY;
	self.speed = 20; // Moves to the right
	self.update = function () {
		self.x += self.speed;
	};
	return self;
});
var SerpentEnemyShip = Container.expand(function (formation, relX, relY) {
	var self = Container.call(this);
	var graphics = self.attachAsset('serpentEnemyShip', {
		// Or 'airEnemy' if using that asset ID directly
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.parentFormation = formation;
	self.x = relX; // Relative X to formation anchor
	self.y = relY; // Relative Y to formation anchor
	self.health = 2;
	self.fireRate = 140; // Slightly slower than some other enemies
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	// update() is not strictly needed here if all positioning is handled by parentFormation setting self.x/y
	// However, firing logic will be here.
	self.updateShipLogic = function () {
		if (self.isDestroyed || !self.parentFormation || self.parentFormation.isDestroyed) {
			if (!self.isDestroyed) self.destroy();
			return;
		}
		// Firing logic
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate && player && !player.isDead) {
			self.fireCooldown = 0;
			// Calculate global position for bullet spawn
			var globalPos = self.parentFormation.toGlobal(self.position);
			var gamePos = game.toLocal(globalPos);
			var bulletSpeed = 7;
			// Basic targeting or straight shot
			var vx = -bulletSpeed;
			var vy = 0;
			if (player && !player.isDead) {
				var dx = player.x - gamePos.x;
				var dy = player.y - gamePos.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 0) {
					vx = dx / dist * bulletSpeed;
					vy = dy / dist * bulletSpeed;
				}
			}
			fireEnemyBullet(gamePos.x, gamePos.y, vx, vy, 'enemyBulletBlue');
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			if (self.parentFormation) {
				self.parentFormation.shipDestroyed(self);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
var SerpentFormation = Container.expand(function () {
	var self = Container.call(this);
	self.ships = [];
	self.stage = 0; // 0: approach, 1: retreat, 2: pass, 3: offscreen/done
	self.anchorX = 2048 + 400; // Initial X off-screen right
	self.anchorY = 2732 / 2 + (Math.random() * 600 - 300); // Initial Y with some variance
	self.x = self.anchorX;
	self.y = self.anchorY;
	self.targetAnchorX = 0;
	self.targetAnchorY = 0;
	self.movementSpeed = 6;
	self.retreatDirection = Math.random() < 0.5 ? 1 : -1; // 1 for bottom-right, -1 for top-right
	var APPROACH_TARGET_X = 1024;
	var RETREAT_DELTA_X = 500;
	var RETREAT_DELTA_Y = 700;
	var PASS_TARGET_X = -600; // Further off-screen left
	var SERPENT_SHIP_OFFSETS = [{
		x: 0,
		y: 0
	}, {
		x: -70,
		y: 35
	}, {
		x: -140,
		y: -35
	}, {
		x: -210,
		y: 70
	}, {
		x: -280,
		y: -70
	}, {
		x: -350,
		y: 105
	}, {
		x: -420,
		y: -105
	}];
	self.initializeShips = function () {
		for (var i = 0; i < 7; i++) {
			var offset = SERPENT_SHIP_OFFSETS[i];
			var ship = new SerpentEnemyShip(self, offset.x, offset.y);
			self.addChild(ship); // Add ship as child of the formation container
			self.ships.push(ship);
		}
	};
	self.setMovementStage = function (newStage) {
		self.stage = newStage;
		switch (self.stage) {
			case 0:
				// Approach
				self.targetAnchorX = APPROACH_TARGET_X;
				self.targetAnchorY = self.anchorY; // Maintain initial Y for approach
				break;
			case 1:
				// Diagonal Retreat
				self.targetAnchorX = self.anchorX + RETREAT_DELTA_X;
				self.targetAnchorY = self.anchorY + self.retreatDirection * RETREAT_DELTA_Y;
				break;
			case 2:
				// Forward Pass
				self.targetAnchorX = PASS_TARGET_X;
				// self.targetAnchorY remains from retreat or can be adjusted
				break;
			case 3:
				// Done
				// No target, just indicates it's finished its path
				break;
		}
	};
	self.update = function () {
		if (self.stage === 3) return; // Done moving
		var dx = self.targetAnchorX - self.x;
		var dy = self.targetAnchorY - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist < self.movementSpeed * 1.5) {
			// Reached target for current stage
			self.x = self.targetAnchorX;
			self.y = self.targetAnchorY;
			self.anchorX = self.x; // Update internal anchor tracking
			self.anchorY = self.y;
			self.setMovementStage(self.stage + 1);
		} else {
			self.x += dx / dist * self.movementSpeed;
			self.y += dy / dist * self.movementSpeed;
			self.anchorX = self.x;
			self.anchorY = self.y;
		}
		// Update individual ships' logic (like firing)
		for (var i = self.ships.length - 1; i >= 0; i--) {
			var ship = self.ships[i];
			if (ship.isDestroyed) {
				// Ship already removed itself from parent (self) and called shipDestroyed
			} else {
				ship.updateShipLogic();
			}
		}
		if (self.stage === 3 && self.x < PASS_TARGET_X + SERPENT_SHIP_OFFSETS[SERPENT_SHIP_OFFSETS.length - 1].x - 200) {
			// Check if fully off-screen
			// Handled by isDone check in main game loop
		}
	};
	self.shipDestroyed = function (ship) {
		var index = self.ships.indexOf(ship);
		if (index > -1) {
			self.ships.splice(index, 1);
		}
		// If the formation itself is a container, the ship's destroy method handles removing from parent.
	};
	self.isDone = function () {
		// Formation is done if all ships are destroyed OR if it has completed its path and is off-screen
		if (self.ships.length === 0) return true;
		// Check based on the leader (first ship offset) being sufficiently off-screen
		var leaderGlobalX = self.x + SERPENT_SHIP_OFFSETS[0].x;
		if (self.stage === 3 && leaderGlobalX < PASS_TARGET_X + SERPENT_SHIP_OFFSETS[0].x - 100) {
			// Check leader's x pos
			return true;
		}
		return false;
	};
	// Initialize
	self.initializeShips();
	self.setMovementStage(0); // Start with approaching stage
	return self;
});
// SmallTerrain Class for Level 2 Area 4
var SmallTerrain = Container.expand(function (isTop, initialX) {
	var self = Container.call(this);
	var graphics = self.attachAsset('smallTerrain', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = initialX;
	self.y = isTop ? 400 + 50 : 2732 - 400 - 50; // 400px from edges, centered on terrain height
	self.isTop = isTop;
	self.speed = terrainSpeed;
	self.tank = null; // Will hold the tank on this terrain
	self.isDestroyed = false;
	self.update = function () {
		if (self.isDestroyed) return;
		self.x -= self.speed;
	};
	self.addTank = function () {
		if (!self.tank && !self.isDestroyed) {
			self.tank = new Tank(self.isTop, self.x, self); // Pass terrain reference
			game.addChild(self.tank);
			tanks.push(self.tank);
		}
	};
	self.destroy = function () {
		if (self.tank && !self.tank.isDestroyed) {
			self.tank.destroy();
		}
		self.isDestroyed = true;
		Container.prototype.destroy.call(self);
	};
	return self;
});
// Tank Class for Level 2
var Tank = Container.expand(function (isTop, initialX, terrain) {
	var self = Container.call(this);
	var terrainHeight = terrain ? 100 : 200; // Use 100 for small terrains, 200 for regular
	var graphics = self.attachAsset('tank', {
		anchorX: 0.5,
		anchorY: isTop ? 0 : 1
	});
	self.x = initialX;
	self.y = terrain ? isTop ? 400 + 50 : 2732 - 400 - 50 : isTop ? terrainHeight : 2732 - terrainHeight;
	self.isTop = isTop;
	self.speed = terrainSpeed;
	self.health = 6; // Tanks are sturdy
	self.fireRate = 170;
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	self.parentTerrain = terrain; // Reference to terrain for area4 tanks
	self.horizontalSpeed = 3; // Speed for left-right movement on small terrains
	self.movingRight = Math.random() < 0.5; // Random initial direction
	self.update = function () {
		if (self.isDestroyed) return;
		if (self.parentTerrain) {
			// Area4 tank: move horizontally on small terrain
			var terrainLeft = self.parentTerrain.x - 150; // Half width of small terrain
			var terrainRight = self.parentTerrain.x + 150;
			if (self.movingRight) {
				self.x += self.horizontalSpeed;
				if (self.x >= terrainRight) {
					self.movingRight = false;
				}
			} else {
				self.x -= self.horizontalSpeed;
				if (self.x <= terrainLeft) {
					self.movingRight = true;
				}
			}
			// Move with terrain
			self.x -= self.speed;
		} else {
			// Regular area2 tank: just move with terrain
			self.x -= self.speed;
		}
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			var bulletSpeed = 8;
			var vx = -bulletSpeed * 0.707; // Aim slightly forward
			var vyDirection = self.isTop ? bulletSpeed * 0.707 : -bulletSpeed * 0.707;
			fireEnemyBullet(self.x, self.y, vx, vyDirection, 'enemyBulletBlue');
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			var index = tanks.indexOf(self);
			if (index > -1) {
				tanks.splice(index, 1);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
// Terrain Segment Class
var TerrainSegment = Container.expand(function (isTop) {
	var self = Container.call(this);
	var terrainGraphics = self.attachAsset('terrain', {
		anchorX: 0,
		anchorY: isTop ? 0 : 1 // Anchor at top for top terrain, bottom for bottom terrain
	});
	self.isTop = isTop;
	self.speed = 5; // Horizontal scroll speed
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// Top Mountain Obstacle Class
var TopMountain = Container.expand(function () {
	var self = Container.call(this);
	var mountainGraphics = self.attachAsset('topmountain', {
		anchorX: 0.5,
		anchorY: 0.3 // Anchor base at terrain edge
	});
	self.speed = 5; // Should match terrain speed
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// Player UFO Class
var UFO = Container.expand(function () {
	var self = Container.call(this);
	var ufoGraphics = self.attachAsset('ufo', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10; // Movement speed multiplier, adjust as needed
	self.isDead = false;
	self.invincibleUntil = 0;
	// Keep UFO within game boundaries
	self.clampPosition = function () {
		var halfWidth = ufoGraphics.width / 2;
		var halfHeight = ufoGraphics.height / 2;
		if (self.x < halfWidth) {
			self.x = halfWidth;
		}
		if (self.x > 2048 - halfWidth) {
			self.x = 2048 - halfWidth;
		}
		if (self.y < halfHeight + 100) {
			self.y = halfHeight + 100;
		} // Avoid top-left menu area
		if (self.y > 2732 - halfHeight) {
			self.y = 2732 - halfHeight;
		}
		// Adjust based on terrain phase (Level 1 Phase 0 or if it's Level 2 which also has terrain)
		if (gamePhase === 0 || currentLevel === 2) {
			// Find the current terrain height at the UFO's x position (simplified)
			var terrainHeight = 200; // Assuming constant terrain height for now
			if (self.y < terrainHeight + halfHeight) {
				self.y = terrainHeight + halfHeight;
			}
			if (self.y > 2732 - terrainHeight - halfHeight) {
				self.y = 2732 - terrainHeight - halfHeight;
			}
		}
	};
	return self;
});
// VerticalWall Class for Level 2
var VerticalWall = Container.expand(function (xPos) {
	var self = Container.call(this);
	var wallGraphicAsset = LK.getAsset('verticalWall', {});
	var graphics = self.attachAsset('verticalWall', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = wallGraphicAsset.width; // Store actual width for calculations
	self.height = wallGraphicAsset.height; // Store actual height
	self.x = xPos;
	self.y = 2732 / 2;
	self.speed = terrainSpeed;
	self.turrets = [];
	self.activeTurrets = 4;
	self.isDestroyed = false;
	// Wall graphics anchor is 0.5, 0.5.
	// Turrets are positioned on the front-facing side of the wall.
	// Spread 4 turrets along the height.
	var turretPositions = [-0.35 * self.height, -0.15 * self.height, 0.15 * self.height, 0.35 * self.height]; // Relative Y from center
	for (var i = 0; i < 4; i++) {
		// Turrets are on the "front" (left edge for player) of the wall
		var turret = new WallTurret(self, -0.4, turretPositions[i]); // relX as factor of half-width, relY absolute
		self.turrets.push(turret);
		game.addChild(turret);
	}
	self.update = function () {
		if (self.isDestroyed) return;
		self.x -= self.speed;
	};
	self.turretDestroyed = function (turret) {
		if (self.isDestroyed) return;
		self.activeTurrets--;
		if (self.activeTurrets <= 0) {
			self.isDestroyed = true;
			LK.getSound('bossExplosion').play();
			var wallIndex = verticalWalls.indexOf(self);
			if (wallIndex > -1) {
				verticalWalls.splice(wallIndex, 1);
			}
			// Ensure remaining turrets are cleaned up if any edge case
			self.turrets.forEach(function (t) {
				if (t && !t.isDestroyed) t.destroy();
			});
			self.destroy();
		}
	};
	return self;
});
// WallTurret Class for Level 2
var WallTurret = Container.expand(function (wall, relX, relY) {
	var self = Container.call(this);
	var graphics = self.attachAsset('wallTurret', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.parentWall = wall;
	self.relX = relX;
	self.relY = relY;
	self.health = 2; // Turrets are a bit tougher
	self.fireRate = 130; // Initial and current fire rate
	self.minFireRate = 60; // Minimum fire rate (e.g., 60 ticks = 1 shot per second)
	self.fireRateReductionAmount = 15; // Amount to reduce fireRate by each time
	self.shotsFiredCount = 0; // Counter for total shots fired by this turret
	self.shotsPerRateReduction = 3; // Reduce fire rate every this many shots
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	self.update = function () {
		if (self.isDestroyed || !self.parentWall || self.parentWall.isDestroyed) {
			if (!self.isDestroyed) self.destroy(); // Self-cleanup if parent is gone
			return;
		}
		// Update position relative to the moving wall
		self.x = self.parentWall.x + self.relX * (self.parentWall.width / 2); // relX is factor of half-width
		self.y = self.parentWall.y + self.relY;
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			fireEnemyBullet(self.x, self.y, -9, 0, 'enemyBulletBlue'); // Shoots blue bullets left
			self.shotsFiredCount++;
			// Check if it's time to reduce the fire rate
			if (self.shotsFiredCount > 0 && self.shotsFiredCount % self.shotsPerRateReduction === 0) {
				if (self.fireRate > self.minFireRate) {
					self.fireRate = Math.max(self.fireRate - self.fireRateReductionAmount, self.minFireRate);
					// The fire cooldown will naturally be shorter for the next cycle due to the reduced self.fireRate
				}
			}
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			if (self.parentWall && !self.parentWall.isDestroyed) {
				self.parentWall.turretDestroyed(self);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x101030 // Dark space blue background
});
/**** 
* Game Code
****/ 
// Reusing airEnemy asset for serpent ship
// Placeholder for Level 2 music
// Deep Sky Blue
// Forest Green
// Dark Orange
// Grey turret
// Brownish wall
// Level 2 Assets
// Game State
/**** 
* Assets
* Assets are automatically created and loaded either dynamically during gameplay
* or via static code analysis based on their usage in the code.
****/ 
// Initialize assets used in this game. Scale them according to what is needed for the game.
// Player UFO
// Ground/Ceiling
// Mountain Obstacle (simplified)
// Ground Enemy
// Enemy Bullet
// Air Enemy (Placeholder shape)
// Boss
// Boss Laser Beam
// Minimalistic tween library which should be used for animations over time
// LK.init.image('mountain', {width:150, height:250, id:'6819884bc4a0c8bae9e84ae0'}) // Removed - Replaced by top/bottom mountains
var isGameStarted = false; // Flag to track if game has started
var showingHighscores = false; // Flag to track if highscore screen is shown
var gamePhase = 0; // 0: Terrain, 1: Space, 2: Boss
var phaseStartTime = LK.ticks;
var phaseDuration = 3600; // 1 minute (60 seconds * 60 fps = 3600 ticks)
var terrainSpeed = 5;
var scoreIncrementTimer = 0;
var highscoreBackground = null;
var highscoreTexts = []; // Original, may become vestigial or be fully removed depending on final showHighscore structure
var elementsShownByShowHighscore = []; // New global array for showHighscore's element management
// Game Objects
var player = null;
var terrainSegmentsTop = [];
var terrainSegmentsBottom = [];
var mountains = [];
var groundEnemies = [];
var enemyBullets = [];
var airEnemies = []; // Simple air enemies for MVP phase 2
var boss = null;
var bossLasers = [];
var playerBullets = []; // Array for player bullets
// Player Control
var dragNode = null;
var playerFireRate = 15; // Ticks between shots (4 shots per second)
var playerFireCooldown = 0;
// Level 2 State and Constants
var currentLevel = 1;
var level2Progress = 0; // In pixels, for current level 2 progression
var level2Started = false;
var lastWallSpawnProgress = 0;
var lastDiagonalEnemySpawnProgress = 0;
var lastTankSpawnProgress = 0;
var verticalWalls = [];
var diagonalEnemies = [];
var tanks = [];
// enemyBulletsBlue will use the existing enemyBullets array
var PIXELS_PER_MILE = 250; // Adjusted for gameplay feel
var LEVEL2_AREA1_END_MILES = 500;
var LEVEL2_AREA2_DURATION_MILES = 500; // Duration of Area 2
var WALL_SPAWN_INTERVAL_MILES = 50;
var DIAGONAL_ENEMY_SPAWN_INTERVAL_MILES = 50;
var TANK_SPAWN_INTERVAL_MILES = 10;
// Level 2 Area 3: Serpent Formations
var serpentFormations = [];
var MAX_SERPENT_FORMATIONS = 2; // Max 1-2 active at once
var lastSerpentSpawnProgress = 0; // Tracks level2Progress for serpent spawning
var SERPENT_SPAWN_INTERVAL_MILES = 100; // Spawn a new serpent formation every 100 miles in Area 3
var LEVEL2_AREA3_DURATION_MILES = 700; // Duration of Area 3
var LEVEL2_AREA4_DURATION_MILES = 500; // Duration of Area 4
var SMALL_TERRAIN_SPAWN_INTERVAL_MILES = 80; // Spawn interval for small terrains in area4
var lastSmallTerrainSpawnProgress = 0; // Tracks spawning of small terrains
var smallTerrains = []; // Array to track small terrain pieces
// Player Lives
var MAX_PLAYER_LIVES = 5;
var playerLives = MAX_PLAYER_LIVES;
var livesTxt;
// Score Display
var scoreTxt = new Text2('0', {
	size: 100,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt); // Position score at top center
// Helper function to create terrain segments
function createTerrainSegment(isTop, xPos) {
	var segment = new TerrainSegment(isTop);
	segment.x = xPos;
	segment.y = isTop ? 0 : 2732;
	segment.speed = terrainSpeed;
	game.addChild(segment);
	if (isTop) {
		terrainSegmentsTop.push(segment);
	} else {
		terrainSegmentsBottom.push(segment);
	}
	return segment;
}
// Helper function to spawn mountains on terrain
function spawnMountain(terrainSegment) {
	var mountain;
	if (terrainSegment.isTop) {
		mountain = new TopMountain();
	} else {
		mountain = new BottomMountain();
	}
	// Position relative to the terrain segment
	// Ensure we use the actual height of the terrain graphic for positioning
	var terrainGraphic = terrainSegment.children[0]; // Assuming the graphic is the first child
	mountain.x = terrainSegment.x + Math.random() * terrainGraphic.width;
	// Position based on whether it's a top or bottom mountain
	mountain.y = terrainSegment.isTop ? terrainGraphic.height : 2732 - terrainGraphic.height;
	mountain.speed = terrainSpeed;
	game.addChild(mountain);
	mountains.push(mountain);
}
// Helper function to spawn ground enemies on terrain
function spawnGroundEnemy(terrainSegment) {
	var enemy = new GroundEnemy(terrainSegment.isTop);
	// Position relative to the terrain segment
	// Ensure we use the actual height of the terrain graphic for positioning
	var terrainGraphic = terrainSegment.children[0]; // Assuming the graphic is the first child
	enemy.x = terrainSegment.x + Math.random() * terrainGraphic.width;
	enemy.y = terrainSegment.isTop ? terrainGraphic.height : 2732 - terrainGraphic.height;
	enemy.speed = terrainSpeed;
	game.addChild(enemy);
	groundEnemies.push(enemy);
}
// Helper function to fire enemy bullets
function fireEnemyBullet(x, y, vx, vy, assetId) {
	// Added assetId parameter
	// If player exists and is not dead, target the player instead of using fixed direction
	if (player && !player.isDead) {
		// Calculate direction vector to player
		var dx = player.x - x;
		var dy = player.y - y;
		// Normalize the vector
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Use the bullet speed provided (or calculate from vx and vy if assetId is for styling only)
		// For simplicity, let's assume the passed vx,vy define the base speed.
		var baseSpeed = Math.sqrt(vx * vx + vy * vy);
		if (distance > 0 && baseSpeed > 0) {
			// Ensure distance and baseSpeed are valid
			vx = dx / distance * baseSpeed;
			vy = dy / distance * baseSpeed;
		}
		// If player is not available or too close, use original vx, vy
	}
	var bullet = new EnemyBullet(x, y, vx, vy, assetId); // Pass assetId to constructor
	game.addChild(bullet);
	enemyBullets.push(bullet);
	LK.getSound('enemyShoot').play();
}
// Helper function to spawn air enemies (simple version)
function spawnAirEnemy() {
	var startY = Math.random() * (2732 - 400) + 200; // Avoid edges
	var enemy = new AirEnemy(2048 + 100, startY); // Start off-screen right
	game.addChild(enemy);
	airEnemies.push(enemy);
}
// Helper function to fire boss lasers
function fireBossLasers(x, y) {
	var directions = 5;
	var laserSpeed = 12;
	var verticalSpread = 4; // Max vertical speed component
	for (var i = 0; i < directions; i++) {
		// Calculate vertical velocity component for spread
		// Example: i=0 -> -4, i=1 -> -2, i=2 -> 0, i=3 -> 2, i=4 -> 4
		var vy = -verticalSpread + verticalSpread * 2 / (directions - 1) * i;
		// Keep horizontal speed constant (moving left)
		var vx = -laserSpeed;
		var laser = new BossLaser(x, y, vx, vy);
		game.addChild(laser);
		bossLasers.push(laser);
	}
	// Add sound effect for laser fire (consider adding one e.g., LK.getSound('bossShoot').play(); if asset exists)
}
// Initialize Game Elements
function initGame() {
	// Reset state
	LK.setScore(0);
	scoreTxt.setText('0');
	// Hide score during intro
	scoreTxt.visible = !isGameStarted;
	// Initialize Lives
	playerLives = MAX_PLAYER_LIVES;
	if (!livesTxt) {
		// Create only if it doesn't exist (for game restarts)
		livesTxt = new Text2("Lives: x" + playerLives, {
			size: 80,
			// Slightly smaller than score
			fill: 0xFFFFFF
		});
		livesTxt.anchor.set(1, 0); // Anchor top-right
		LK.gui.topRight.addChild(livesTxt);
	} else {
		livesTxt.setText("Lives: x" + playerLives);
	}
	gamePhase = 0;
	phaseStartTime = LK.ticks;
	dragNode = null;
	playerBullets = []; // Clear player bullets
	playerFireCooldown = 0; // Reset fire cooldown
	// Clear existing elements from previous game (if any)
	// Note: LK engine handles full reset on GameOver/YouWin, but manual cleanup might be needed if restarting mid-game (not typical)
	// Let's assume full reset is handled by LK.
	// Create Player
	player = new UFO();
	player.x = 300;
	player.y = 2732 / 2;
	player.isDead = false;
	player.invincibleUntil = 0;
	player.alpha = 1; // Ensure player is visible
	game.addChild(player);
	// Create initial terrain
	var terrainWidth = LK.getAsset('terrain', {}).width; // Get width from asset
	for (var i = 0; i < Math.ceil(2048 / terrainWidth) + 1; i++) {
		createTerrainSegment(true, i * terrainWidth);
		createTerrainSegment(false, i * terrainWidth);
	}
	// Start Phase 1 Music
	LK.playMusic('phase1Music');
}
function initLevel2() {
	if (level2Started) return;
	level2Started = true;
	currentLevel = 2; // Explicitly set, though might be set at transition point too
	level2Progress = 0; // Reset progress for Level 2
	console.log("Initializing Level 2");
	LK.playMusic('level2Music'); // Play Level 2 music
	// Clean up any remaining Level 1 specific elements like air enemies
	airEnemies.forEach(function (ae) {
		if (ae && !ae.destroyed) ae.destroy();
	});
	airEnemies = [];
	// Boss should already be gone
	if (boss && !boss.destroyed) boss.destroy();
	boss = null;
	bossLasers.forEach(function (l) {
		if (l && !l.destroyed) l.destroy();
	});
	bossLasers = [];
	// Reset spawn progress markers for Level 2 elements
	lastWallSpawnProgress = 0;
	lastDiagonalEnemySpawnProgress = 0;
	lastTankSpawnProgress = 0;
	// Ensure terrain continues if it was cleared (e.g., after boss fight if phases stopped it)
	// The main terrain update loop should be modified to run during currentLevel === 2
	var terrainWidth = LK.getAsset('terrain', {}).width;
	var screenWidth = 2048;
	var numSegmentsNeeded = Math.ceil(screenWidth / terrainWidth) + 1;
	if (terrainSegmentsTop.length < numSegmentsNeeded) {
		for (var i = terrainSegmentsTop.length; i < numSegmentsNeeded; i++) {
			var xPos = i * terrainWidth;
			// Find max X of existing segments to append correctly
			if (terrainSegmentsTop.length > 0) {
				xPos = terrainSegmentsTop.reduce(function (max, s) {
					return s.x > max ? s.x : max;
				}, 0) + terrainWidth;
			}
			createTerrainSegment(true, xPos);
		}
	}
	if (terrainSegmentsBottom.length < numSegmentsNeeded) {
		for (var i = terrainSegmentsBottom.length; i < numSegmentsNeeded; i++) {
			var xPos = i * terrainWidth;
			if (terrainSegmentsBottom.length > 0) {
				xPos = terrainSegmentsBottom.reduce(function (max, s) {
					return s.x > max ? s.x : max;
				}, 0) + terrainWidth;
			}
			createTerrainSegment(false, xPos);
		}
	}
	// Announce Level 2 Start (Optional visual cue)
	var level2Text = new Text2("LEVEL 2", {
		size: 150,
		fill: 0xFFFF00
	});
	level2Text.anchor.set(0.5, 0.5);
	level2Text.x = 2048 / 2;
	level2Text.y = 2732 / 3;
	game.addChild(level2Text);
	LK.setTimeout(function () {
		if (level2Text && !level2Text.destroyed) level2Text.destroy();
	}, 3000); // Display for 3 seconds
	// gamePhase variable might be set to a new value (e.g., 3) if other systems rely on it.
	// For now, currentLevel = 2 will gate Level 2 logic.
	gamePhase = 3; // Indicate a new phase distinct from level 1's 0, 1, 2.
}
// Helper function already moved above
// Helper function to save highscore
function saveHighscore() {
	// Removed score argument, will use LK.getScore() internally
	var currentScore = LK.getScore();
	var currentPlayerId = LK.profile && LK.profile.id ? LK.profile.id : "guest";
	var currentPlayerName = LK.profile && LK.profile.name ? LK.profile.name : "FRVR Player";
	var highscores = [];
	try {
		if (storage && storage.available && storage.highscoresData) {
			var parsedData = JSON.parse(storage.highscoresData);
			if (Array.isArray(parsedData)) {
				highscores = parsedData;
			}
		}
	} catch (e) {
		console.log("Error parsing existing highscoresData, resetting: " + e.message);
		highscores = [];
	}
	// Add current score
	highscores.push({
		id: currentPlayerId,
		name: currentPlayerName,
		score: currentScore,
		date: Date.now() // Store timestamp for sorting or display
	});
	// Sort by score (descending), then by date (newest first for tie-breaking)
	highscores.sort(function (a, b) {
		if (b.score === a.score) {
			return b.date - a.date;
		}
		return b.score - a.score;
	});
	// Limit to a reasonable number of stored highscores, e.g., top 50
	var MAX_STORED_HIGHSCORES = 50;
	if (highscores.length > MAX_STORED_HIGHSCORES) {
		highscores = highscores.slice(0, MAX_STORED_HIGHSCORES);
	}
	// Save back to storage
	try {
		if (storage && storage.available) {
			storage.highscoresData = JSON.stringify(highscores);
		}
	} catch (e) {
		console.log("Error stringifying or saving highscoresData: " + e.message);
	}
	// Update the player's personal best score, stored separately for quick access
	// This key is used by createScoreBackground for "Your Best" display
	if (currentPlayerId !== "guest") {
		var personalBestKey = 'player_' + currentPlayerId;
		var currentPersonalBest = 0;
		try {
			if (storage && storage.available && storage[personalBestKey]) {
				currentPersonalBest = parseInt(storage[personalBestKey], 10) || 0;
			}
		} catch (parseError) {
			console.log("Error parsing personal best for key " + personalBestKey + ": " + parseError.message);
			currentPersonalBest = 0;
		}
		if (currentScore > currentPersonalBest) {
			if (storage && storage.available) {
				try {
					storage[personalBestKey] = currentScore.toString();
				} catch (saveError) {
					console.log("Error saving personal best for key " + personalBestKey + ": " + saveError.message);
				}
			}
		}
	}
}
// The createScoreBackground function is now defined earlier in the code
// This duplicate definition has been moved earlier in the code
// Helper function to handle player death
function handlePlayerDeath() {
	if (!player || player.isDead) {
		return;
	}
	// Event Handlers
	player.isDead = true;
	player.alpha = 0; // Make player invisible during death processing
	LK.getSound('playerExplosion').play();
	// Optional: Flash the player before making them fully invisible, or flash screen
	// LK.effects.flashObject(player, 0xFF0000, 500);
	LK.effects.flashScreen(0xFF0000, 200); // Short screen flash
	playerLives--;
	if (livesTxt) {
		livesTxt.setText("Lives: x" + playerLives);
	}
	LK.setTimeout(function () {
		if (playerLives > 0) {
			respawnPlayer();
		} else {
			// Save highscore before showing Game Over
			saveHighscore(); //{6o} // Argument removed
			// Create background for scores before showing game over
			createScoreBackground();
			LK.showGameOver();
		}
	}, 1000); // 1 second delay for effects and sound
}
// Helper function to create score background when game is won or lost
function createScoreBackground() {
	var createdTextElements = [];
	// Store reference to background for later access
	if (highscoreBackground) {
		highscoreBackground.destroy();
	}
	// Get current player information
	var currentPlayerId = LK.profile && LK.profile.id ? LK.profile.id : "guest";
	var currentPlayerName = LK.profile && LK.profile.name ? LK.profile.name : "FRVR Player";
	var currentScore = LK.getScore();
	// Get highscores from storage
	var highscores = [];
	try {
		if (storage && storage.available && storage.highscoresData) {
			highscores = JSON.parse(storage.highscoresData);
		}
	} catch (e) {
		console.log("Error parsing highscores:", e);
		highscores = [];
	}
	// Check if the current score is already in the list (for game over after saving score)
	var scoreExists = false;
	for (var i = 0; i < highscores.length; i++) {
		if (highscores[i].id === currentPlayerId && highscores[i].score === currentScore && Date.now() - highscores[i].date < 60000) {
			// Added in last minute
			scoreExists = true;
			highscores[i].isCurrent = true; // Mark as current game's score
			break;
		}
	}
	// Add the current score to the highscores immediately if not already there
	if (!scoreExists) {
		highscores.push({
			id: currentPlayerId,
			name: currentPlayerName,
			score: currentScore,
			date: Date.now(),
			isCurrent: true // Mark as current game's score
		});
	}
	// Sort highscores by date (most recent first)
	highscores.sort(function (a, b) {
		return b.date - a.date; // Most recent date first
	});
	var personalBest = 0;
	// Check if player has a personal best stored
	if (currentPlayerId !== "guest") {
		var personalKey = "player_" + currentPlayerId;
		try {
			if (storage && storage.available && storage[personalKey]) {
				personalBest = parseInt(storage[personalKey], 10) || 0;
			}
			// Also check from cloud storage
			if (storage && storage.available) {
				storage.load('player_score_' + currentPlayerId, function (savedScore) {
					if (savedScore) {
						var cloudScore = parseInt(savedScore, 10) || 0;
						if (cloudScore > personalBest) {
							personalBest = cloudScore;
							storage[personalKey] = personalBest.toString();
						}
					}
				});
			}
		} catch (e) {
			console.log("Error retrieving personal best:", e);
		}
	}
	// Create background
	highscoreBackground = game.addChild(LK.getAsset('Background2', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 / 2,
		scaleX: 20.48,
		scaleY: 27.32,
		alpha: 0.9
	}));
	// Create title
	var titleText = new Text2("GAME RESULTS", {
		size: 120,
		fill: 0xFFFFFF
	});
	titleText.anchor.set(0.5, 0);
	titleText.x = 2048 / 2;
	titleText.y = 200;
	game.addChild(titleText);
	createdTextElements.push(titleText);
	// Current score
	var currentScoreText = new Text2("Your Score: " + currentScore, {
		size: 100,
		fill: 0x00FF00
	});
	currentScoreText.anchor.set(0.5, 0);
	currentScoreText.x = 2048 / 2;
	currentScoreText.y = 350;
	game.addChild(currentScoreText);
	createdTextElements.push(currentScoreText);
	// Show personal best if it exists
	if (personalBest > 0 && personalBest !== currentScore) {
		var personalBestText = new Text2("Your Best: " + personalBest, {
			size: 80,
			fill: 0xFFD700
		});
		personalBestText.anchor.set(0.5, 0);
		personalBestText.x = 2048 / 2;
		personalBestText.y = 470;
		game.addChild(personalBestText);
		createdTextElements.push(personalBestText);
		// Show new record indicator
		if (currentScore > personalBest) {
			var newRecordText = new Text2("NEW RECORD!", {
				size: 80,
				fill: 0xFF00FF
			});
			newRecordText.anchor.set(0.5, 0);
			newRecordText.x = 2048 / 2;
			newRecordText.y = 560;
			game.addChild(newRecordText);
			createdTextElements.push(newRecordText);
		}
	}
	// Display up to 20 highscores instead of 10
	var maxToShow = Math.min(highscores.length, 20);
	if (maxToShow > 0) {
		// Display title for scores
		var titleScoreText = new Text2("Recent Player Scores", {
			size: 90,
			fill: 0xFFD700
		});
		titleScoreText.anchor.set(0.5, 0);
		titleScoreText.x = 2048 / 2;
		titleScoreText.y = 700;
		game.addChild(titleScoreText);
		createdTextElements.push(titleScoreText);
		// Adjust spacing based on number of scores
		var spacing = maxToShow > 10 ? 90 : maxToShow > 5 ? 120 : 150;
		var fontSize = maxToShow > 10 ? 60 : maxToShow > 5 ? 70 : 80;
		// Display player scores
		for (var i = 0; i < maxToShow; i++) {
			var entry = highscores[i];
			var isCurrentPlayer = entry.id === currentPlayerId;
			var isCurrentScore = entry.isCurrent === true;
			// Format score with comma separators
			var formattedScore = entry.score.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
			// Get player name, using ID if name is missing
			var playerName = entry.name || "Player " + entry.id.substring(0, 5);
			var scoreEntry = new Text2(i + 1 + ". " + playerName + ": " + formattedScore, {
				size: fontSize,
				fill: isCurrentScore ? "#FF00FF" : isCurrentPlayer ? "#00FF00" : "#FFFFFF" // Magenta for current score, green for other scores by current player
			});
			// If more than 10 entries, create two columns
			if (maxToShow > 10 && i >= 10) {
				// Second column (for entries 11-20)
				scoreEntry.anchor.set(0, 0); // Left align for second column
				scoreEntry.x = 2048 * 0.25; // Position at 1/4 of screen width
				scoreEntry.y = 800 + (i - 10) * spacing;
			} else if (maxToShow > 10) {
				// First column (for entries 1-10)
				scoreEntry.anchor.set(1, 0); // Right align for first column
				scoreEntry.x = 2048 * 0.75; // Position at 3/4 of screen width
				scoreEntry.y = 800 + i * spacing;
			} else {
				// Single column layout (for 10 or fewer entries)
				scoreEntry.anchor.set(0.5, 0);
				scoreEntry.x = 2048 / 2;
				scoreEntry.y = 800 + i * spacing;
			}
			game.addChild(scoreEntry);
			createdTextElements.push(scoreEntry);
		}
	} else {
		// No scores message
		var noScoresText = new Text2("No scores yet!", {
			size: 80,
			fill: 0xFFFFFF
		});
		noScoresText.anchor.set(0.5, 0);
		noScoresText.x = 2048 / 2;
		noScoresText.y = 800;
		game.addChild(noScoresText);
		createdTextElements.push(noScoresText);
	}
	return createdTextElements;
}
// The createScoreBackground function has been moved earlier in the code
// Helper function to respawn player at checkpoint
function respawnPlayer() {
	if (!player) {
		return;
	}
	player.x = 300;
	player.y = 2732 / 2;
	player.clampPosition();
	player.alpha = 1; // Make player visible again
	player.isDead = false;
	player.invincibleUntil = LK.ticks + 120; // 2 seconds of invincibility
	// Clear active threats
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		if (enemyBullets[i] && !enemyBullets[i].destroyed) {
			enemyBullets[i].destroy();
		}
	}
	enemyBullets = [];
	if (gamePhase === 2) {
		// Boss phase
		for (var i = bossLasers.length - 1; i >= 0; i--) {
			if (bossLasers[i] && !bossLasers[i].destroyed) {
				bossLasers[i].destroy();
			}
		}
		bossLasers = [];
	}
	// Player is reset, other game elements (enemies, boss health) remain.
}
// Create intro screen elements
var backgroundAsset = LK.getAsset('Background0', {});
var scaleX = 2048 / backgroundAsset.width;
var scaleY = 2732 / backgroundAsset.height;
var background = game.addChild(LK.getAsset('Background0', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2,
	scaleX: scaleX,
	scaleY: scaleY
}));
// Play intro music
LK.playMusic('Intromusic1');
var startButton = game.addChild(LK.getAsset('Startgamebutton', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2 + 700,
	scaleX: 1.5,
	scaleY: 1.5
}));
var highscoreButton = game.addChild(LK.getAsset('Highscorebutton', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2 + 1050,
	scaleX: 1.5,
	scaleY: 1.5
}));
function startGame() {
	// Remove intro elements
	background.destroy();
	startButton.destroy();
	highscoreButton.destroy();
	// Set game as started
	isGameStarted = true;
	// Show score
	scoreTxt.visible = true;
	// Initialize the game
	initGame();
}
function showHighscore() {
	if (showingHighscores) {
		// If currently showing, hide everything
		if (highscoreBackground) {
			// highscoreBackground is global, set by createScoreBackground
			highscoreBackground.destroy();
			highscoreBackground = null;
		}
		elementsShownByShowHighscore.forEach(function (el) {
			if (el && !el.destroyed) {
				el.destroy();
			}
		});
		elementsShownByShowHighscore = [];
		showingHighscores = false;
		return;
	}
	// Not showing, so display the highscore screen
	showingHighscores = true;
	// Clear any residual elements from a previous display, just in case
	if (highscoreBackground && !highscoreBackground.destroyed) {
		highscoreBackground.destroy();
		highscoreBackground = null;
	}
	elementsShownByShowHighscore.forEach(function (el) {
		if (el && !el.destroyed) {
			el.destroy();
		}
	});
	elementsShownByShowHighscore = [];
	// Call createScoreBackground to generate the main content.
	// This function sets the global 'highscoreBackground' and returns an array of its text elements.
	var textsFromCreateScoreBg = createScoreBackground();
	elementsShownByShowHighscore = elementsShownByShowHighscore.concat(textsFromCreateScoreBg);
	// Add "TAP ANYWHERE TO RETURN" text, specific to this highscore view
	var backText = new Text2("TAP ANYWHERE TO RETURN", {
		size: 70,
		fill: 0xFFFFFF //{dT} // Kept original fill and size
	});
	backText.anchor.set(0.5, 0);
	backText.x = 2048 / 2;
	backText.y = 2200; // Adjusted Y to be a bit lower if needed, or use original from createScoreBackground if it had one
	game.addChild(backText);
	elementsShownByShowHighscore.push(backText); // Add to our list for cleanup
	// Fallback to LK.showLeaderboard if our custom screen is up for too long
	if (typeof LK.showLeaderboard === 'function') {
		LK.setTimeout(function () {
			if (showingHighscores) {
				// Check if our screen is still active
				showingHighscores = false; // Toggle off state
				if (highscoreBackground && !highscoreBackground.destroyed) {
					highscoreBackground.destroy();
					highscoreBackground = null;
				}
				elementsShownByShowHighscore.forEach(function (el) {
					if (el && !el.destroyed) {
						el.destroy();
					}
				});
				elementsShownByShowHighscore = [];
				LK.showLeaderboard(); // Show the engine's leaderboard
			}
		}, 5000); // 5 second timeout
	}
}
// Add interactive behavior to buttons
startButton.interactive = true;
startButton.buttonMode = true;
startButton.down = function () {
	startGame();
};
highscoreButton.interactive = true;
highscoreButton.buttonMode = true;
highscoreButton.down = function () {
	showHighscore();
};
game.down = function (x, y, obj) {
	// Handle tapping on highscore screen to return to intro
	if (showingHighscores) {
		showHighscore(); // This will toggle off the highscore display
		return;
	}
	// Only process player dragging if game has started
	if (isGameStarted && player) {
		// Check if touch is on the player UFO
		var localPos = player.toLocal(game.toGlobal({
			x: x,
			y: y
		})); // Convert game coords to player's local coords
		// Use a slightly larger hit area for easier dragging
		var hitWidth = player.width * 1.5;
		var hitHeight = player.height * 1.5;
		if (Math.abs(localPos.x) < hitWidth / 2 && Math.abs(localPos.y) < hitHeight / 2) {
			dragNode = player;
			// Instantly move player to touch position for responsive feel
			var gamePos = game.toLocal(obj.global); // Use obj.global for precise position
			player.x = gamePos.x;
			player.y = gamePos.y;
			player.clampPosition();
		} else {
			dragNode = null;
		}
	}
};
game.move = function (x, y, obj) {
	if (dragNode) {
		var gamePos = game.toLocal(obj.global); // Convert event global position to game coordinates
		dragNode.x = gamePos.x;
		dragNode.y = gamePos.y;
		// Clamp player position within bounds immediately after move
		if (dragNode === player) {
			player.clampPosition();
		}
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Game Update Logic
game.update = function () {
	// If game hasn't started yet or player is gone, don't process game logic
	if (!isGameStarted || !player || player.destroyed) {
		// Check if we need to initialize level 2 due to a reload/restart mid-level 2
		// This is an edge case, main L2 init is after boss defeat.
		// if (currentLevel === 2 && !level2Started && isGameStarted && player) { initLevel2(); }
		// Make sure score is hidden during intro
		scoreTxt.visible = false;
		return; // Game not started or player fully gone, nothing to do.
	}
	// Make sure score is visible during gameplay
	scoreTxt.visible = true;
	// Initialize Level 2 if conditions are met (transitioned from Level 1)
	if (currentLevel === 2 && !level2Started && isGameStarted && player && !player.isDead) {
		initLevel2();
	}
	// If player is dead, stop their specific logic & wait for respawn/game over timeout
	// Other game elements (enemies, bullets) might still update.
	// Player input and collisions will be gated by player.isDead or invincibility.
	// Player invincibility blinking
	if (player && !player.isDead && LK.ticks < player.invincibleUntil) {
		player.alpha = LK.ticks % 20 < 10 ? 0.5 : 1; // Blink
	} else if (player && !player.isDead && player.alpha !== 1) {
		player.alpha = 1; // Ensure alpha is reset
	}
	// --- Global Updates ---
	// Player Shooting
	playerFireCooldown++;
	if (!player.isDead && dragNode === player && playerFireCooldown >= playerFireRate) {
		// Only shoot while dragging/controlling and alive
		playerFireCooldown = 0;
		var bullet = new PlayerBullet(player.x + player.width / 2, player.y);
		game.addChild(bullet);
		playerBullets.push(bullet);
		LK.getSound('playerShoot').play();
	}
	// Score increases over time
	scoreIncrementTimer++;
	if (scoreIncrementTimer >= 60) {
		// Add 10 points every second
		scoreIncrementTimer = 0;
		LK.setScore(LK.getScore() + 10);
		scoreTxt.setText(LK.getScore());
	}
	// Increment distance scrolled (used by Level 2)
	if (player && !player.isDead) {
		// Only scroll if player is active and game is running
		// gameDistanceScrolled += terrainSpeed; // This was for overall game, level2Progress is specific
		if (currentLevel === 2 && level2Started) {
			level2Progress += terrainSpeed;
		}
	}
	// --- Phase Management ---
	var elapsedTicks = LK.ticks - phaseStartTime;
	if (gamePhase === 0 && elapsedTicks >= phaseDuration) {
		// Transition to Phase 1 (Space)
		gamePhase = 1;
		phaseStartTime = LK.ticks; // Reset timer for next phase if needed
		console.log("Transitioning to Phase 1: Space");
		// Clean up terrain-specific elements
		terrainSegmentsTop.forEach(function (s) {
			return s.destroy();
		});
		terrainSegmentsBottom.forEach(function (s) {
			return s.destroy();
		});
		mountains.forEach(function (m) {
			return m.destroy();
		});
		groundEnemies.forEach(function (ge) {
			return ge.destroy();
		});
		terrainSegmentsTop = [];
		terrainSegmentsBottom = [];
		mountains = [];
		groundEnemies = [];
		// Spawn initial air enemies
		for (var i = 0; i < 5; i++) {
			// Start with 5 air enemies
			spawnAirEnemy();
		}
		LK.playMusic('phase2Music'); // Switch music
	} else if (gamePhase === 1 && elapsedTicks >= phaseDuration * 1.5) {
		// Example: Boss after 1.5x phase duration
		// Transition to Phase 2 (Boss)
		if (!boss) {
			// Ensure boss only spawns once
			gamePhase = 2;
			phaseStartTime = LK.ticks;
			console.log("Transitioning to Phase 2: Boss");
			// Clean up air enemies
			airEnemies.forEach(function (ae) {
				return ae.destroy();
			});
			airEnemies = [];
			// Spawn Boss
			boss = new Boss();
			game.addChild(boss);
			LK.playMusic('bossMusic'); // Boss music
		}
	}
	// --- Terrain Logic (Active in Level 1 Phase 0 and Level 2 except Area 4) ---
	var isArea4 = currentLevel === 2 && level2Progress >= LEVEL2_AREA3_END_PX;
	if ((gamePhase === 0 || currentLevel === 2) && !isArea4) {
		// Update and manage terrain segments
		var terrainWidth = LK.getAsset('terrain', {}).width;
		for (var i = terrainSegmentsTop.length - 1; i >= 0; i--) {
			var segment = terrainSegmentsTop[i];
			if (segment.x < -terrainWidth) {
				// Reposition segment to the right
				var maxX = 0;
				terrainSegmentsTop.forEach(function (s) {
					if (s.x > maxX) {
						maxX = s.x;
					}
				});
				segment.x = maxX + terrainWidth;
				// Always spawn an enemy on the reused segment
				spawnGroundEnemy(segment);
				// Additionally, 50% chance for a mountain
				if (Math.random() < 0.5) {
					spawnMountain(segment);
				}
			}
		}
		// Repeat for bottom terrain
		for (var i = terrainSegmentsBottom.length - 1; i >= 0; i--) {
			var segment = terrainSegmentsBottom[i];
			if (segment.x < -terrainWidth) {
				var maxX = 0;
				terrainSegmentsBottom.forEach(function (s) {
					if (s.x > maxX) {
						maxX = s.x;
					}
				});
				segment.x = maxX + terrainWidth;
				// Always spawn an enemy on the reused segment
				spawnGroundEnemy(segment);
				// Additionally, 50% chance for a mountain
				if (Math.random() < 0.5) {
					spawnMountain(segment);
				}
			}
		}
		// Update mountains & check collision
		for (var i = mountains.length - 1; i >= 0; i--) {
			var mountain = mountains[i];
			if (mountain.x < -mountain.width) {
				mountain.destroy();
				mountains.splice(i, 1);
			} else {
				if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(mountain)) {
					handlePlayerDeath();
					return; // Stop update processing
				}
			}
		}
		// Update ground enemies & check collision
		for (var i = groundEnemies.length - 1; i >= 0; i--) {
			var enemy = groundEnemies[i];
			if (enemy.x < -enemy.width) {
				enemy.destroy();
				groundEnemies.splice(i, 1);
			} else {
				// Collision check: Player vs Ground Enemy
				if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(enemy)) {
					LK.getSound('enemyExplosion').play(); //{3L} // Enemy explodes
					enemy.destroy(); // Destroy enemy on collision too
					groundEnemies.splice(i, 1);
					handlePlayerDeath();
					return;
				}
			}
		}
		// Re-clamp player position based on potentially moving terrain (simple clamp for now)
		player.clampPosition();
	}
	// --- Phase 1/2: Air Enemy Logic ---
	if (gamePhase === 1) {
		// Add more air enemies periodically?
		if (LK.ticks % 180 === 0 && airEnemies.length < 10) {
			// Spawn if less than 10, every 3 seconds
			spawnAirEnemy();
		}
		// Update air enemies & check collision
		for (var i = airEnemies.length - 1; i >= 0; i--) {
			var enemy = airEnemies[i];
			// Air enemies handle their own off-screen logic (respawn) in their update
			// Collision check: Player vs Air Enemy
			if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(enemy)) {
				LK.getSound('enemyExplosion').play(); //{41} // Enemy explodes
				enemy.destroy(); // Destroy enemy on collision
				airEnemies.splice(i, 1);
				// LK.setScore(LK.getScore() + 50); // Score for destroying enemy - player died, maybe no score for this? Or keep it. Let's keep for now.
				// scoreTxt.setText(LK.getScore());
				handlePlayerDeath();
				return;
			}
		}
	}
	// --- Phase 3: Boss Logic ---
	if (gamePhase === 2 && boss) {
		// Check collision: Player vs Boss
		if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(boss)) {
			// Don't destroy boss on collision
			handlePlayerDeath();
			return;
		}
		// Update boss lasers & check collision
		for (var i = bossLasers.length - 1; i >= 0; i--) {
			var laser = bossLasers[i];
			// Check if laser is off-screen
			if (laser.x < -laser.width || laser.x > 2048 + laser.width || laser.y < -laser.height || laser.y > 2732 + laser.height) {
				laser.destroy();
				bossLasers.splice(i, 1);
			} else {
				// Collision check: Player vs Boss Laser
				if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(laser)) {
					laser.destroy(); // Destroy laser
					bossLasers.splice(i, 1);
					handlePlayerDeath();
					return;
				}
			}
		}
		// Note: Boss defeat condition is now handled within the player bullet collision check loop.
	}
	// --- Update Enemy Bullets & Check Collision (All Phases) ---
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var bullet = enemyBullets[i];
		// Check if bullet is off-screen
		if (bullet.y < -bullet.height || bullet.y > 2732 + bullet.height) {
			bullet.destroy();
			enemyBullets.splice(i, 1);
		} else {
			// Collision check: Player vs Enemy Bullet
			if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(bullet)) {
				bullet.destroy(); // Destroy bullet
				enemyBullets.splice(i, 1);
				handlePlayerDeath(); // This function now handles the delay and sound
				return; // Stop update processing
			}
		}
	}
	// The saveHighscore function has been moved before handlePlayerDeath to fix the undefined error
	// --- Update Player Bullets & Check Collision ---
	for (var i = playerBullets.length - 1; i >= 0; i--) {
		var bullet = playerBullets[i];
		// Check if bullet is off-screen (right side)
		if (bullet.x > 2048 + bullet.width) {
			bullet.destroy();
			playerBullets.splice(i, 1);
			continue; // Skip collision checks if off-screen
		}
		// Collision Check: Player Bullet vs Ground Enemy (Phase 0)
		if (gamePhase === 0) {
			for (var j = groundEnemies.length - 1; j >= 0; j--) {
				var enemy = groundEnemies[j];
				if (bullet.intersects(enemy)) {
					LK.getSound('enemyExplosion').play();
					LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white
					enemy.destroy();
					groundEnemies.splice(j, 1);
					bullet.destroy();
					playerBullets.splice(i, 1);
					LK.setScore(LK.getScore() + 100); // Score for destroying ground enemy
					scoreTxt.setText(LK.getScore());
					break; // Bullet can only hit one enemy
				}
			}
			if (!bullet.exists) {
				continue;
			} // Check if bullet was destroyed in previous loop
		}
		// Collision Check: Player Bullet vs Air Enemy (Phase 1)
		if (gamePhase === 1) {
			for (var j = airEnemies.length - 1; j >= 0; j--) {
				var enemy = airEnemies[j];
				if (bullet.intersects(enemy)) {
					LK.getSound('enemyExplosion').play();
					LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white
					enemy.destroy();
					airEnemies.splice(j, 1);
					bullet.destroy();
					playerBullets.splice(i, 1);
					LK.setScore(LK.getScore() + 150); // Score for destroying air enemy
					scoreTxt.setText(LK.getScore());
					break; // Bullet can only hit one enemy
				}
			}
			if (!bullet.exists) {
				continue;
			} // Check if bullet was destroyed in previous loop
		}
		// Collision Check: Player Bullet vs Boss (Phase 2)
		if (gamePhase === 2 && boss) {
			if (bullet.intersects(boss)) {
				LK.getSound('enemyExplosion').play(); // Use enemy explosion for hit sound
				LK.effects.flashObject(boss, 0xFFFFFF, 100); // Flash boss white
				bullet.destroy();
				playerBullets.splice(i, 1);
				boss.health -= 1; // Decrease boss health
				LK.setScore(LK.getScore() + 10); // Small score for hitting boss
				scoreTxt.setText(LK.getScore());
				// Boss defeat check is now inside the bullet loop
				if (boss.health <= 0) {
					LK.getSound('bossExplosion').play(); // Play boss explosion sound
					boss.destroy();
					boss = null;
					// Cleanup remaining lasers
					bossLasers.forEach(function (l) {
						return l.destroy();
					});
					bossLasers = [];
					LK.setScore(LK.getScore() + 5000); // Big score bonus
					scoreTxt.setText(LK.getScore());
					// Save highscore as a milestone for defeating the boss
					saveHighscore(); //{be} // Argument removed
					// Transition to Level 2
					currentLevel = 2;
					level2Started = false; // Flag to trigger initLevel2() once at the start of next update cycle
					// Note: Removed createScoreBackground(); call here as game transitions to Level 2
					LK.setScore(LK.getScore() + 5000); // Bonus for defeating boss (applied again, consider if this is intended or consolidate)
					scoreTxt.setText(LK.getScore());
					// saveHighscore(LK.getScore()); // Score is already saved above, this might be redundant unless intended for separate tracking
					// Clear boss specific elements
					if (boss && !boss.destroyed) boss.destroy();
					boss = null;
					bossLasers.forEach(function (l) {
						if (l && !l.destroyed) l.destroy();
					});
					bossLasers = [];
					console.log("Boss defeated! Preparing Level 2.");
					// initLevel2() will be called in the next game.update() loop at the top
					return; // Stop update processing this frame to allow initLevel2 to run cleanly
				}
				break; // Bullet is destroyed after hitting boss
			}
		}
		// --- Level 2 Logic ---
		if (currentLevel === 2 && level2Started) {
			var LEVEL2_AREA1_END_PX = LEVEL2_AREA1_END_MILES * PIXELS_PER_MILE;
			var LEVEL2_AREA2_END_PX = (LEVEL2_AREA1_END_MILES + LEVEL2_AREA2_DURATION_MILES) * PIXELS_PER_MILE;
			var LEVEL2_AREA3_END_PX = (LEVEL2_AREA1_END_MILES + LEVEL2_AREA2_DURATION_MILES + LEVEL2_AREA3_DURATION_MILES) * PIXELS_PER_MILE;
			var LEVEL2_FINAL_END_PX = (LEVEL2_AREA1_END_MILES + LEVEL2_AREA2_DURATION_MILES + LEVEL2_AREA3_DURATION_MILES + LEVEL2_AREA4_DURATION_MILES) * PIXELS_PER_MILE;
			// --- Level 2, Area 1 (Vertical Walls) ---
			if (level2Progress < LEVEL2_AREA1_END_PX) {
				if (level2Progress > lastWallSpawnProgress + WALL_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastWallSpawnProgress = level2Progress;
					var wall = new VerticalWall(2048 + 200); // Spawn off-screen right
					game.addChild(wall);
					verticalWalls.push(wall);
				}
			}
			// --- Level 2, Area 2 (Diagonal Enemies, Tanks) ---
			else if (level2Progress < LEVEL2_AREA2_END_PX) {
				// Clear any remaining walls from Area 1 when transitioning
				if (verticalWalls.length > 0 && level2Progress >= LEVEL2_AREA1_END_PX && level2Progress < LEVEL2_AREA1_END_PX + terrainSpeed * 2) {
					verticalWalls.forEach(function (w) {
						if (w && !w.isDestroyed) {
							w.turrets.forEach(function (t) {
								if (t && !t.isDestroyed) t.destroy();
							});
							w.destroy();
						}
					});
					verticalWalls = [];
				}
				if (level2Progress > lastDiagonalEnemySpawnProgress + DIAGONAL_ENEMY_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastDiagonalEnemySpawnProgress = level2Progress;
					var diagEnemy = new DiagonalEnemy(2048 + 150, 2732 / 2);
					game.addChild(diagEnemy);
					diagonalEnemies.push(diagEnemy);
				}
				if (level2Progress > lastTankSpawnProgress + TANK_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastTankSpawnProgress = level2Progress;
					var tankTop = new Tank(true, 2048 + 100);
					var tankBottom = new Tank(false, 2048 + 100);
					game.addChild(tankTop);
					game.addChild(tankBottom);
					tanks.push(tankTop);
					tanks.push(tankBottom);
				}
			}
			// --- Level 2, Area 3 (Serpent Formations) ---
			else if (level2Progress < LEVEL2_FINAL_END_PX) {
				// Clear any remaining Diagonal Enemies and Tanks from Area 2
				if ((diagonalEnemies.length > 0 || tanks.length > 0) && level2Progress >= LEVEL2_AREA2_END_PX && level2Progress < LEVEL2_AREA2_END_PX + terrainSpeed * 2) {
					diagonalEnemies.forEach(function (de) {
						if (de && !de.isDestroyed) de.destroy();
					});
					diagonalEnemies = [];
					tanks.forEach(function (t) {
						if (t && !t.isDestroyed) t.destroy();
					});
					tanks = [];
				}
				// Spawn Serpent Formations
				if (serpentFormations.length < MAX_SERPENT_FORMATIONS && level2Progress > lastSerpentSpawnProgress + SERPENT_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastSerpentSpawnProgress = level2Progress;
					var newSerpent = new SerpentFormation();
					game.addChild(newSerpent); // The formation is a Container
					serpentFormations.push(newSerpent);
				}
			}
			// --- Level 2, Area 4 (Small Terrains with Moving Tanks) ---
			else if (level2Progress < LEVEL2_FINAL_END_PX + LEVEL2_AREA4_DURATION_MILES * PIXELS_PER_MILE) {
				// Clear serpent formations from Area 3 when transitioning to Area 4
				if (serpentFormations.length > 0 && level2Progress >= LEVEL2_FINAL_END_PX && level2Progress < LEVEL2_FINAL_END_PX + terrainSpeed * 2) {
					serpentFormations.forEach(function (sf) {
						if (sf && !sf.isDestroyed()) sf.destroy();
					});
					serpentFormations = [];
					// Clear main terrain since area4 has no ground
					terrainSegmentsTop.forEach(function (s) {
						return s.destroy();
					});
					terrainSegmentsBottom.forEach(function (s) {
						return s.destroy();
					});
					terrainSegmentsTop = [];
					terrainSegmentsBottom = [];
				}
				// Spawn Small Terrains with tanks
				if (level2Progress > lastSmallTerrainSpawnProgress + SMALL_TERRAIN_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastSmallTerrainSpawnProgress = level2Progress;
					var topTerrain = new SmallTerrain(true, 2048 + 200);
					var bottomTerrain = new SmallTerrain(false, 2048 + 200);
					game.addChild(topTerrain);
					game.addChild(bottomTerrain);
					smallTerrains.push(topTerrain);
					smallTerrains.push(bottomTerrain);
					// Add tanks to the terrains
					topTerrain.addTank();
					bottomTerrain.addTank();
				}
			}
			// --- Level 2 Completed ---
			else {
				if (player && !player.isDead) {
					// Ensure win condition only if player alive
					console.log("Level 2 Complete!");
					// Clean up any remaining serpent formations
					serpentFormations.forEach(function (sf) {
						if (sf && !sf.isDestroyed()) sf.destroy();
					});
					serpentFormations = [];
					saveHighscore(); //{bI} // Argument removed
					createScoreBackground();
					LK.setTimeout(function () {
						LK.showYouWin(); // Game ends after Level 2 (Area 3)
					}, 500);
					player.isDead = true; // Prevent further actions
					return;
				}
			}
			// Update and Collision for Level 2 Elements
			// Vertical Walls (and their turrets)
			for (var i = verticalWalls.length - 1; i >= 0; i--) {
				var wall = verticalWalls[i];
				if (wall.isDestroyed) {
					// Already handled by wall itself
					// verticalWalls.splice(i, 1); // Wall removes itself from array
					continue;
				}
				if (wall.x < -wall.width) {
					// Off-screen left
					wall.turrets.forEach(function (t) {
						if (t && !t.isDestroyed) t.destroy();
					});
					wall.destroy();
					verticalWalls.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(wall)) {
					handlePlayerDeath();
					return;
				}
			}
			// Turrets are updated via their own class or Wall. Bullets handled by main enemyBullets loop.
			// Diagonal Enemies
			for (var i = diagonalEnemies.length - 1; i >= 0; i--) {
				var diagEnemy = diagonalEnemies[i];
				if (diagEnemy.isDestroyed) {
					// diagonalEnemies.splice(i, 1); // Enemy removes itself
					continue;
				}
				if (diagEnemy.x < -diagEnemy.width) {
					diagEnemy.destroy();
					diagonalEnemies.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(diagEnemy)) {
					diagEnemy.takeDamage();
					handlePlayerDeath();
					return;
				}
			}
			// Tanks
			for (var i = tanks.length - 1; i >= 0; i--) {
				var tank = tanks[i];
				if (tank.isDestroyed) {
					// tanks.splice(i, 1); // Enemy removes itself
					continue;
				}
				if (tank.x < -tank.width) {
					tank.destroy();
					tanks.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(tank)) {
					tank.takeDamage();
					handlePlayerDeath();
					return;
				}
			}
			// Small Terrains (Area 4)
			for (var i = smallTerrains.length - 1; i >= 0; i--) {
				var smallTerrain = smallTerrains[i];
				if (smallTerrain.isDestroyed) {
					continue;
				}
				if (smallTerrain.x < -smallTerrain.width) {
					smallTerrain.destroy();
					smallTerrains.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(smallTerrain)) {
					handlePlayerDeath();
					return;
				}
			}
			// Update Serpent Formations (Area 3 specific, but update loop runs for all formations)
			for (var i = serpentFormations.length - 1; i >= 0; i--) {
				var serpent = serpentFormations[i];
				// serpent.update(); // Already called because it's a child of game
				if (serpent.isDone()) {
					serpent.destroy();
					serpentFormations.splice(i, 1);
				} else {
					// Player collision with individual serpent ships
					if (!player.isDead && LK.ticks > player.invincibleUntil) {
						for (var j = serpent.ships.length - 1; j >= 0; j--) {
							var ship = serpent.ships[j];
							if (!ship.isDestroyed) {
								// Need to get global position of the ship for intersection check
								var shipGlobalPos = serpent.toGlobal(ship.position);
								var shipGameAreaRect = new Rectangle(shipGlobalPos.x - ship.width / 2, shipGlobalPos.y - ship.height / 2, ship.width, ship.height);
								// Create a temporary object for player bounds for intersects method if player itself isn't a simple rectangle
								var playerBounds = new Rectangle(player.x - player.width / 2, player.y - player.height / 2, player.width, player.height);
								// AABB intersection check
								if (playerBounds.x < shipGameAreaRect.x + shipGameAreaRect.width && playerBounds.x + playerBounds.width > shipGameAreaRect.x && playerBounds.y < shipGameAreaRect.y + shipGameAreaRect.height && playerBounds.y + playerBounds.height > shipGameAreaRect.y) {
									ship.takeDamage(); // Serpent ship takes damage
									handlePlayerDeath(); // Player also dies
									return; // Stop further processing this frame
								}
							}
						}
					}
				}
			}
		} // End if (currentLevel === 2 && level2Started)
		// --- Update Player Bullets & Check Collision --- (Continued with Level 2 targets)
		// (This section is appended to the existing playerBullets loop, before the final closing brace of the loop)
		// The existing player bullet loop needs to be modified to include these checks.
		// This block should be inserted *inside* the `for (var i = playerBullets.length - 1; i >= 0; i--)` loop for player bullets,
		// after existing collision checks or as part of a conditional block for `currentLevel === 2`.
		// Existing player bullet loop:
		// for (var i = playerBullets.length - 1; i >= 0; i--) {
		//   var bullet = playerBullets[i];
		//   ...
		//   if (gamePhase === 2 && boss) { ... } // Existing boss collision
		//   // ADD LEVEL 2 COLLISION LOGIC HERE:
		if (currentLevel === 2 && bullet.exists) {
			// Check bullet.exists in case prior collision destroyed it
			// Vs WallTurrets (part of VerticalWalls)
			for (var k = verticalWalls.length - 1; k >= 0; k--) {
				var wall = verticalWalls[k];
				if (wall.isDestroyed) continue;
				for (var l = wall.turrets.length - 1; l >= 0; l--) {
					var turret = wall.turrets[l];
					if (turret.isDestroyed) continue;
					if (bullet.intersects(turret)) {
						if (turret.takeDamage()) {
							// true if destroyed
							LK.setScore(LK.getScore() + 75);
							scoreTxt.setText(LK.getScore());
						}
						bullet.destroy();
						playerBullets.splice(i, 1);
						break;
					}
				}
				if (!bullet.exists) break;
			}
			if (!bullet.exists) continue; // To next player bullet if this one was destroyed
			// Vs DiagonalEnemies
			for (var k = diagonalEnemies.length - 1; k >= 0; k--) {
				var diagEnemy = diagonalEnemies[k];
				if (diagEnemy.isDestroyed) continue;
				if (bullet.intersects(diagEnemy)) {
					if (diagEnemy.takeDamage()) {
						LK.setScore(LK.getScore() + 250);
						scoreTxt.setText(LK.getScore());
					}
					bullet.destroy();
					playerBullets.splice(i, 1);
					break;
				}
			}
			if (!bullet.exists) continue;
			// Vs Tanks
			for (var k = tanks.length - 1; k >= 0; k--) {
				var tank = tanks[k];
				if (tank.isDestroyed) continue;
				if (bullet.intersects(tank)) {
					if (tank.takeDamage()) {
						LK.setScore(LK.getScore() + 175);
						scoreTxt.setText(LK.getScore());
					}
					bullet.destroy();
					playerBullets.splice(i, 1);
					break;
				}
			}
			if (!bullet.exists) continue;
			// Vs SerpentEnemyShips (within SerpentFormations)
			if (bullet.exists) {
				// Check again in case previous collision destroyed it
				for (var k = serpentFormations.length - 1; k >= 0; k--) {
					var formation = serpentFormations[k];
					if (formation.isDestroyed()) continue;
					for (var l = formation.ships.length - 1; l >= 0; l--) {
						var serpentShip = formation.ships[l];
						if (serpentShip.isDestroyed) continue;
						// Get global position of the serpent ship for accurate intersection
						var shipGlobalPos = formation.toGlobal(serpentShip.position);
						// Create a temporary rectangle for the serpent ship in game coordinates
						// Assuming serpentShip.width and serpentShip.height are available (from its graphic)
						var serpentShipGameRect = new Rectangle(shipGlobalPos.x - serpentShip.width / 2, shipGlobalPos.y - serpentShip.height / 2, serpentShip.width, serpentShip.height);
						// Create a temporary rectangle for the bullet
						var bulletRect = new Rectangle(bullet.x - bullet.width / 2, bullet.y - bullet.height / 2, bullet.width, bullet.height);
						// Manual AABB intersection check
						if (bulletRect.x < serpentShipGameRect.x + serpentShipGameRect.width && bulletRect.x + bulletRect.width > serpentShipGameRect.x && bulletRect.y < serpentShipGameRect.y + serpentShipGameRect.height && bulletRect.y + bulletRect.height > serpentShipGameRect.y) {
							if (serpentShip.takeDamage()) {
								// true if destroyed
								LK.setScore(LK.getScore() + 200); // Score for serpent ship
								scoreTxt.setText(LK.getScore());
							}
							bullet.destroy();
							playerBullets.splice(i, 1);
							break; // Bullet hits one serpent ship
						}
					}
					if (!bullet.exists) break; // If bullet was destroyed, move to next player bullet
				}
			}
			if (!bullet.exists) continue; // To next player bullet
		}
		// } // End of playerBullets loop (this closing brace is illustrative, don't add a new one)
	} // End of playerBullets loop
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highscoresData: "[]"
});
/**** 
* Classes
****/ 
// Air Enemy Class (Snake Segment - Simplified for MVP)
var AirEnemy = Container.expand(function (startX, startY) {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('airEnemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = startX;
	self.y = startY;
	self.speedX = 4 + Math.random() * 2; // Horizontal speed
	self.amplitudeY = 100 + Math.random() * 100; // Vertical movement range
	self.frequencyY = 0.01 + Math.random() * 0.01; // Vertical movement speed
	self.fireRate = 150; // Ticks between shots
	self.fireCooldown = Math.random() * self.fireRate;
	self.update = function () {
		// Basic horizontal and sinusoidal vertical movement
		self.x -= self.speedX;
		self.y = startY + Math.sin(LK.ticks * self.frequencyY + startX) * self.amplitudeY; // Use startX for phase offset
		// Firing logic
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			// Fire a single bullet straight left
			var bulletSpeed = 8;
			fireEnemyBullet(self.x, self.y, -bulletSpeed, 0); // vx = -speed, vy = 0
		}
		// Boundary check (simple respawn logic)
		if (self.x < -enemyGraphics.width) {
			self.x = 2048 + enemyGraphics.width; // Respawn on the right
			startY = Math.random() * (2732 - 400) + 200; // Random Y position
		}
	};
	return self;
});
// Boss Class (Basic structure for future)
var Boss = Container.expand(function () {
	var self = Container.call(this);
	var bossGraphics = self.attachAsset('boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = 2048 - 300; // Position on the right
	self.y = 2732 / 2; // Center vertically
	self.fireRate = 180; // Ticks between laser bursts
	self.fireCooldown = 0;
	self.health = 100; // Example health
	self.update = function () {
		// Add movement logic if needed
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			fireBossLasers(self.x, self.y);
		}
	};
	return self;
});
// Boss Laser Class (Basic structure for future)
var BossLaser = Container.expand(function (startX, startY, vx, vy) {
	var self = Container.call(this);
	var laserGraphics = self.attachAsset('bossLaser', {
		anchorX: 0.5,
		anchorY: 0.5 // Anchor center
	});
	self.x = startX;
	self.y = startY;
	self.vx = vx;
	self.vy = vy;
	// Set rotation based on velocity direction
	self.rotation = Math.atan2(vy, vx) + Math.PI / 2; // Point laser in direction of travel (+90deg adjustment needed depending on asset orientation)
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
	};
	return self;
});
// Bottom Mountain Obstacle Class
var BottomMountain = Container.expand(function () {
	var self = Container.call(this);
	var mountainGraphics = self.attachAsset('bottommountain', {
		anchorX: 0.5,
		anchorY: 0.75 // Anchor base at terrain edge
	});
	self.speed = 5; // Should match terrain speed
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// DiagonalEnemy Class for Level 2
var DiagonalEnemy = Container.expand(function (xPos, yPos) {
	var self = Container.call(this);
	var graphics = self.attachAsset('diagonalEnemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	graphics.rotation = Math.PI / 4;
	self.x = xPos;
	self.y = yPos;
	self.speed = terrainSpeed + 1; // Slightly faster than terrain
	self.health = 4;
	self.fireRate = 160;
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	self.update = function () {
		if (self.isDestroyed) return;
		self.x -= self.speed;
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			var bulletSpeed = 7;
			fireEnemyBullet(self.x, self.y, bulletSpeed, 0, 'enemyBulletBlue'); // Right
			fireEnemyBullet(self.x, self.y, -bulletSpeed, 0, 'enemyBulletBlue'); // Left
			fireEnemyBullet(self.x, self.y, 0, bulletSpeed, 'enemyBulletBlue'); // Down
			fireEnemyBullet(self.x, self.y, 0, -bulletSpeed, 'enemyBulletBlue'); // Up
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			var index = diagonalEnemies.indexOf(self);
			if (index > -1) {
				diagonalEnemies.splice(index, 1);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
// Enemy Bullet Class
var EnemyBullet = Container.expand(function (startX, startY, vx, vy, assetId) {
	var self = Container.call(this);
	// Added assetId
	var bulletGraphics = self.attachAsset(assetId || 'enemyBullet', {
		// Use assetId or default
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = startX;
	self.y = startY;
	self.vx = vx; // Horizontal velocity
	self.vy = vy; // Vertical velocity
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
	};
	return self;
});
// Ground Enemy Class
var GroundEnemy = Container.expand(function (isTop) {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset(isTop ? 'groundEnemytop' : 'groundEnemybottom', {
		anchorX: 0.5,
		anchorY: isTop ? 0 : 1 // Anchor base at terrain edge
	});
	self.isTop = isTop;
	self.speed = 5; // Should match terrain speed
	self.fireRate = 120; // Ticks between firing sequences (2 seconds)
	self.fireCooldown = Math.random() * self.fireRate; // Random initial delay
	self.shotsInBurst = 3;
	self.burstDelay = 10; // Ticks between shots in a burst
	self.update = function () {
		self.x -= self.speed;
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0; // Reset cooldown
			// Fire burst
			for (var i = 0; i < self.shotsInBurst; i++) {
				LK.setTimeout(function () {
					// Check if enemy still exists before firing
					if (!self.destroyed) {
						var bulletSpeed = 8;
						// Calculate direction logic is now in fireEnemyBullet, but still need to pass initial values
						var vx = -bulletSpeed * 0.707; // Default direction if player not available
						var vy = self.isTop ? bulletSpeed * 0.707 : -bulletSpeed * 0.707; // Default direction
						fireEnemyBullet(self.x, self.y, vx, vy);
					}
				}, i * self.burstDelay);
			}
		}
	};
	return self;
});
// Player Bullet Class
var PlayerBullet = Container.expand(function (startX, startY) {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('playerBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = startX;
	self.y = startY;
	self.speed = 20; // Moves to the right
	self.update = function () {
		self.x += self.speed;
	};
	return self;
});
var SerpentEnemyShip = Container.expand(function (formation, relX, relY) {
	var self = Container.call(this);
	var graphics = self.attachAsset('serpentEnemyShip', {
		// Or 'airEnemy' if using that asset ID directly
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.parentFormation = formation;
	self.x = relX; // Relative X to formation anchor
	self.y = relY; // Relative Y to formation anchor
	self.health = 2;
	self.fireRate = 140; // Slightly slower than some other enemies
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	// update() is not strictly needed here if all positioning is handled by parentFormation setting self.x/y
	// However, firing logic will be here.
	self.updateShipLogic = function () {
		if (self.isDestroyed || !self.parentFormation || self.parentFormation.isDestroyed) {
			if (!self.isDestroyed) self.destroy();
			return;
		}
		// Firing logic
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate && player && !player.isDead) {
			self.fireCooldown = 0;
			// Calculate global position for bullet spawn
			var globalPos = self.parentFormation.toGlobal(self.position);
			var gamePos = game.toLocal(globalPos);
			var bulletSpeed = 7;
			// Basic targeting or straight shot
			var vx = -bulletSpeed;
			var vy = 0;
			if (player && !player.isDead) {
				var dx = player.x - gamePos.x;
				var dy = player.y - gamePos.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 0) {
					vx = dx / dist * bulletSpeed;
					vy = dy / dist * bulletSpeed;
				}
			}
			fireEnemyBullet(gamePos.x, gamePos.y, vx, vy, 'enemyBulletBlue');
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			if (self.parentFormation) {
				self.parentFormation.shipDestroyed(self);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
var SerpentFormation = Container.expand(function () {
	var self = Container.call(this);
	self.ships = [];
	self.stage = 0; // 0: approach, 1: retreat, 2: pass, 3: offscreen/done
	self.anchorX = 2048 + 400; // Initial X off-screen right
	self.anchorY = 2732 / 2 + (Math.random() * 600 - 300); // Initial Y with some variance
	self.x = self.anchorX;
	self.y = self.anchorY;
	self.targetAnchorX = 0;
	self.targetAnchorY = 0;
	self.movementSpeed = 6;
	self.retreatDirection = Math.random() < 0.5 ? 1 : -1; // 1 for bottom-right, -1 for top-right
	var APPROACH_TARGET_X = 1024;
	var RETREAT_DELTA_X = 500;
	var RETREAT_DELTA_Y = 700;
	var PASS_TARGET_X = -600; // Further off-screen left
	var SERPENT_SHIP_OFFSETS = [{
		x: 0,
		y: 0
	}, {
		x: -70,
		y: 35
	}, {
		x: -140,
		y: -35
	}, {
		x: -210,
		y: 70
	}, {
		x: -280,
		y: -70
	}, {
		x: -350,
		y: 105
	}, {
		x: -420,
		y: -105
	}];
	self.initializeShips = function () {
		for (var i = 0; i < 7; i++) {
			var offset = SERPENT_SHIP_OFFSETS[i];
			var ship = new SerpentEnemyShip(self, offset.x, offset.y);
			self.addChild(ship); // Add ship as child of the formation container
			self.ships.push(ship);
		}
	};
	self.setMovementStage = function (newStage) {
		self.stage = newStage;
		switch (self.stage) {
			case 0:
				// Approach
				self.targetAnchorX = APPROACH_TARGET_X;
				self.targetAnchorY = self.anchorY; // Maintain initial Y for approach
				break;
			case 1:
				// Diagonal Retreat
				self.targetAnchorX = self.anchorX + RETREAT_DELTA_X;
				self.targetAnchorY = self.anchorY + self.retreatDirection * RETREAT_DELTA_Y;
				break;
			case 2:
				// Forward Pass
				self.targetAnchorX = PASS_TARGET_X;
				// self.targetAnchorY remains from retreat or can be adjusted
				break;
			case 3:
				// Done
				// No target, just indicates it's finished its path
				break;
		}
	};
	self.update = function () {
		if (self.stage === 3) return; // Done moving
		var dx = self.targetAnchorX - self.x;
		var dy = self.targetAnchorY - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist < self.movementSpeed * 1.5) {
			// Reached target for current stage
			self.x = self.targetAnchorX;
			self.y = self.targetAnchorY;
			self.anchorX = self.x; // Update internal anchor tracking
			self.anchorY = self.y;
			self.setMovementStage(self.stage + 1);
		} else {
			self.x += dx / dist * self.movementSpeed;
			self.y += dy / dist * self.movementSpeed;
			self.anchorX = self.x;
			self.anchorY = self.y;
		}
		// Update individual ships' logic (like firing)
		for (var i = self.ships.length - 1; i >= 0; i--) {
			var ship = self.ships[i];
			if (ship.isDestroyed) {
				// Ship already removed itself from parent (self) and called shipDestroyed
			} else {
				ship.updateShipLogic();
			}
		}
		if (self.stage === 3 && self.x < PASS_TARGET_X + SERPENT_SHIP_OFFSETS[SERPENT_SHIP_OFFSETS.length - 1].x - 200) {
			// Check if fully off-screen
			// Handled by isDone check in main game loop
		}
	};
	self.shipDestroyed = function (ship) {
		var index = self.ships.indexOf(ship);
		if (index > -1) {
			self.ships.splice(index, 1);
		}
		// If the formation itself is a container, the ship's destroy method handles removing from parent.
	};
	self.isDone = function () {
		// Formation is done if all ships are destroyed OR if it has completed its path and is off-screen
		if (self.ships.length === 0) return true;
		// Check based on the leader (first ship offset) being sufficiently off-screen
		var leaderGlobalX = self.x + SERPENT_SHIP_OFFSETS[0].x;
		if (self.stage === 3 && leaderGlobalX < PASS_TARGET_X + SERPENT_SHIP_OFFSETS[0].x - 100) {
			// Check leader's x pos
			return true;
		}
		return false;
	};
	// Initialize
	self.initializeShips();
	self.setMovementStage(0); // Start with approaching stage
	return self;
});
// SmallTerrain Class for Level 2 Area 4
var SmallTerrain = Container.expand(function (isTop, initialX) {
	var self = Container.call(this);
	var graphics = self.attachAsset('smallTerrain', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = initialX;
	self.y = isTop ? 400 + 50 : 2732 - 400 - 50; // 400px from edges, centered on terrain height
	self.isTop = isTop;
	self.speed = terrainSpeed;
	self.tank = null; // Will hold the tank on this terrain
	self.isDestroyed = false;
	self.update = function () {
		if (self.isDestroyed) return;
		self.x -= self.speed;
	};
	self.addTank = function () {
		if (!self.tank && !self.isDestroyed) {
			self.tank = new Tank(self.isTop, self.x, self); // Pass terrain reference
			game.addChild(self.tank);
			tanks.push(self.tank);
		}
	};
	self.destroy = function () {
		if (self.tank && !self.tank.isDestroyed) {
			self.tank.destroy();
		}
		self.isDestroyed = true;
		Container.prototype.destroy.call(self);
	};
	return self;
});
// Tank Class for Level 2
var Tank = Container.expand(function (isTop, initialX, terrain) {
	var self = Container.call(this);
	var terrainHeight = terrain ? 100 : 200; // Use 100 for small terrains, 200 for regular
	var graphics = self.attachAsset('tank', {
		anchorX: 0.5,
		anchorY: isTop ? 0 : 1
	});
	self.x = initialX;
	self.y = terrain ? isTop ? 400 + 50 : 2732 - 400 - 50 : isTop ? terrainHeight : 2732 - terrainHeight;
	self.isTop = isTop;
	self.speed = terrainSpeed;
	self.health = 6; // Tanks are sturdy
	self.fireRate = 170;
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	self.parentTerrain = terrain; // Reference to terrain for area4 tanks
	self.horizontalSpeed = 3; // Speed for left-right movement on small terrains
	self.movingRight = Math.random() < 0.5; // Random initial direction
	self.update = function () {
		if (self.isDestroyed) return;
		if (self.parentTerrain) {
			// Area4 tank: move horizontally on small terrain
			var terrainLeft = self.parentTerrain.x - 150; // Half width of small terrain
			var terrainRight = self.parentTerrain.x + 150;
			if (self.movingRight) {
				self.x += self.horizontalSpeed;
				if (self.x >= terrainRight) {
					self.movingRight = false;
				}
			} else {
				self.x -= self.horizontalSpeed;
				if (self.x <= terrainLeft) {
					self.movingRight = true;
				}
			}
			// Move with terrain
			self.x -= self.speed;
		} else {
			// Regular area2 tank: just move with terrain
			self.x -= self.speed;
		}
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			var bulletSpeed = 8;
			var vx = -bulletSpeed * 0.707; // Aim slightly forward
			var vyDirection = self.isTop ? bulletSpeed * 0.707 : -bulletSpeed * 0.707;
			fireEnemyBullet(self.x, self.y, vx, vyDirection, 'enemyBulletBlue');
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			var index = tanks.indexOf(self);
			if (index > -1) {
				tanks.splice(index, 1);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
// Terrain Segment Class
var TerrainSegment = Container.expand(function (isTop) {
	var self = Container.call(this);
	var terrainGraphics = self.attachAsset('terrain', {
		anchorX: 0,
		anchorY: isTop ? 0 : 1 // Anchor at top for top terrain, bottom for bottom terrain
	});
	self.isTop = isTop;
	self.speed = 5; // Horizontal scroll speed
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// Top Mountain Obstacle Class
var TopMountain = Container.expand(function () {
	var self = Container.call(this);
	var mountainGraphics = self.attachAsset('topmountain', {
		anchorX: 0.5,
		anchorY: 0.3 // Anchor base at terrain edge
	});
	self.speed = 5; // Should match terrain speed
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
// Player UFO Class
var UFO = Container.expand(function () {
	var self = Container.call(this);
	var ufoGraphics = self.attachAsset('ufo', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10; // Movement speed multiplier, adjust as needed
	self.isDead = false;
	self.invincibleUntil = 0;
	// Keep UFO within game boundaries
	self.clampPosition = function () {
		var halfWidth = ufoGraphics.width / 2;
		var halfHeight = ufoGraphics.height / 2;
		if (self.x < halfWidth) {
			self.x = halfWidth;
		}
		if (self.x > 2048 - halfWidth) {
			self.x = 2048 - halfWidth;
		}
		if (self.y < halfHeight + 100) {
			self.y = halfHeight + 100;
		} // Avoid top-left menu area
		if (self.y > 2732 - halfHeight) {
			self.y = 2732 - halfHeight;
		}
		// Adjust based on terrain phase (Level 1 Phase 0 or if it's Level 2 which also has terrain)
		if (gamePhase === 0 || currentLevel === 2) {
			// Find the current terrain height at the UFO's x position (simplified)
			var terrainHeight = 200; // Assuming constant terrain height for now
			if (self.y < terrainHeight + halfHeight) {
				self.y = terrainHeight + halfHeight;
			}
			if (self.y > 2732 - terrainHeight - halfHeight) {
				self.y = 2732 - terrainHeight - halfHeight;
			}
		}
	};
	return self;
});
// VerticalWall Class for Level 2
var VerticalWall = Container.expand(function (xPos) {
	var self = Container.call(this);
	var wallGraphicAsset = LK.getAsset('verticalWall', {});
	var graphics = self.attachAsset('verticalWall', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = wallGraphicAsset.width; // Store actual width for calculations
	self.height = wallGraphicAsset.height; // Store actual height
	self.x = xPos;
	self.y = 2732 / 2;
	self.speed = terrainSpeed;
	self.turrets = [];
	self.activeTurrets = 4;
	self.isDestroyed = false;
	// Wall graphics anchor is 0.5, 0.5.
	// Turrets are positioned on the front-facing side of the wall.
	// Spread 4 turrets along the height.
	var turretPositions = [-0.35 * self.height, -0.15 * self.height, 0.15 * self.height, 0.35 * self.height]; // Relative Y from center
	for (var i = 0; i < 4; i++) {
		// Turrets are on the "front" (left edge for player) of the wall
		var turret = new WallTurret(self, -0.4, turretPositions[i]); // relX as factor of half-width, relY absolute
		self.turrets.push(turret);
		game.addChild(turret);
	}
	self.update = function () {
		if (self.isDestroyed) return;
		self.x -= self.speed;
	};
	self.turretDestroyed = function (turret) {
		if (self.isDestroyed) return;
		self.activeTurrets--;
		if (self.activeTurrets <= 0) {
			self.isDestroyed = true;
			LK.getSound('bossExplosion').play();
			var wallIndex = verticalWalls.indexOf(self);
			if (wallIndex > -1) {
				verticalWalls.splice(wallIndex, 1);
			}
			// Ensure remaining turrets are cleaned up if any edge case
			self.turrets.forEach(function (t) {
				if (t && !t.isDestroyed) t.destroy();
			});
			self.destroy();
		}
	};
	return self;
});
// WallTurret Class for Level 2
var WallTurret = Container.expand(function (wall, relX, relY) {
	var self = Container.call(this);
	var graphics = self.attachAsset('wallTurret', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.parentWall = wall;
	self.relX = relX;
	self.relY = relY;
	self.health = 2; // Turrets are a bit tougher
	self.fireRate = 130; // Initial and current fire rate
	self.minFireRate = 60; // Minimum fire rate (e.g., 60 ticks = 1 shot per second)
	self.fireRateReductionAmount = 15; // Amount to reduce fireRate by each time
	self.shotsFiredCount = 0; // Counter for total shots fired by this turret
	self.shotsPerRateReduction = 3; // Reduce fire rate every this many shots
	self.fireCooldown = Math.random() * self.fireRate;
	self.isDestroyed = false;
	self.update = function () {
		if (self.isDestroyed || !self.parentWall || self.parentWall.isDestroyed) {
			if (!self.isDestroyed) self.destroy(); // Self-cleanup if parent is gone
			return;
		}
		// Update position relative to the moving wall
		self.x = self.parentWall.x + self.relX * (self.parentWall.width / 2); // relX is factor of half-width
		self.y = self.parentWall.y + self.relY;
		self.fireCooldown++;
		if (self.fireCooldown >= self.fireRate) {
			self.fireCooldown = 0;
			fireEnemyBullet(self.x, self.y, -9, 0, 'enemyBulletBlue'); // Shoots blue bullets left
			self.shotsFiredCount++;
			// Check if it's time to reduce the fire rate
			if (self.shotsFiredCount > 0 && self.shotsFiredCount % self.shotsPerRateReduction === 0) {
				if (self.fireRate > self.minFireRate) {
					self.fireRate = Math.max(self.fireRate - self.fireRateReductionAmount, self.minFireRate);
					// The fire cooldown will naturally be shorter for the next cycle due to the reduced self.fireRate
				}
			}
		}
	};
	self.takeDamage = function () {
		if (self.isDestroyed) return false;
		self.health--;
		LK.effects.flashObject(self, 0xFFFFFF, 100);
		if (self.health <= 0) {
			self.isDestroyed = true;
			LK.getSound('enemyExplosion').play();
			if (self.parentWall && !self.parentWall.isDestroyed) {
				self.parentWall.turretDestroyed(self);
			}
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x101030 // Dark space blue background
});
/**** 
* Game Code
****/ 
// Reusing airEnemy asset for serpent ship
// Placeholder for Level 2 music
// Deep Sky Blue
// Forest Green
// Dark Orange
// Grey turret
// Brownish wall
// Level 2 Assets
// Game State
/**** 
* Assets
* Assets are automatically created and loaded either dynamically during gameplay
* or via static code analysis based on their usage in the code.
****/ 
// Initialize assets used in this game. Scale them according to what is needed for the game.
// Player UFO
// Ground/Ceiling
// Mountain Obstacle (simplified)
// Ground Enemy
// Enemy Bullet
// Air Enemy (Placeholder shape)
// Boss
// Boss Laser Beam
// Minimalistic tween library which should be used for animations over time
// LK.init.image('mountain', {width:150, height:250, id:'6819884bc4a0c8bae9e84ae0'}) // Removed - Replaced by top/bottom mountains
var isGameStarted = false; // Flag to track if game has started
var showingHighscores = false; // Flag to track if highscore screen is shown
var gamePhase = 0; // 0: Terrain, 1: Space, 2: Boss
var phaseStartTime = LK.ticks;
var phaseDuration = 3600; // 1 minute (60 seconds * 60 fps = 3600 ticks)
var terrainSpeed = 5;
var scoreIncrementTimer = 0;
var highscoreBackground = null;
var highscoreTexts = []; // Original, may become vestigial or be fully removed depending on final showHighscore structure
var elementsShownByShowHighscore = []; // New global array for showHighscore's element management
// Game Objects
var player = null;
var terrainSegmentsTop = [];
var terrainSegmentsBottom = [];
var mountains = [];
var groundEnemies = [];
var enemyBullets = [];
var airEnemies = []; // Simple air enemies for MVP phase 2
var boss = null;
var bossLasers = [];
var playerBullets = []; // Array for player bullets
// Player Control
var dragNode = null;
var playerFireRate = 15; // Ticks between shots (4 shots per second)
var playerFireCooldown = 0;
// Level 2 State and Constants
var currentLevel = 1;
var level2Progress = 0; // In pixels, for current level 2 progression
var level2Started = false;
var lastWallSpawnProgress = 0;
var lastDiagonalEnemySpawnProgress = 0;
var lastTankSpawnProgress = 0;
var verticalWalls = [];
var diagonalEnemies = [];
var tanks = [];
// enemyBulletsBlue will use the existing enemyBullets array
var PIXELS_PER_MILE = 250; // Adjusted for gameplay feel
var LEVEL2_AREA1_END_MILES = 500;
var LEVEL2_AREA2_DURATION_MILES = 500; // Duration of Area 2
var WALL_SPAWN_INTERVAL_MILES = 50;
var DIAGONAL_ENEMY_SPAWN_INTERVAL_MILES = 50;
var TANK_SPAWN_INTERVAL_MILES = 10;
// Level 2 Area 3: Serpent Formations
var serpentFormations = [];
var MAX_SERPENT_FORMATIONS = 2; // Max 1-2 active at once
var lastSerpentSpawnProgress = 0; // Tracks level2Progress for serpent spawning
var SERPENT_SPAWN_INTERVAL_MILES = 100; // Spawn a new serpent formation every 100 miles in Area 3
var LEVEL2_AREA3_DURATION_MILES = 700; // Duration of Area 3
var LEVEL2_AREA4_DURATION_MILES = 500; // Duration of Area 4
var SMALL_TERRAIN_SPAWN_INTERVAL_MILES = 80; // Spawn interval for small terrains in area4
var lastSmallTerrainSpawnProgress = 0; // Tracks spawning of small terrains
var smallTerrains = []; // Array to track small terrain pieces
// Player Lives
var MAX_PLAYER_LIVES = 5;
var playerLives = MAX_PLAYER_LIVES;
var livesTxt;
// Score Display
var scoreTxt = new Text2('0', {
	size: 100,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt); // Position score at top center
// Helper function to create terrain segments
function createTerrainSegment(isTop, xPos) {
	var segment = new TerrainSegment(isTop);
	segment.x = xPos;
	segment.y = isTop ? 0 : 2732;
	segment.speed = terrainSpeed;
	game.addChild(segment);
	if (isTop) {
		terrainSegmentsTop.push(segment);
	} else {
		terrainSegmentsBottom.push(segment);
	}
	return segment;
}
// Helper function to spawn mountains on terrain
function spawnMountain(terrainSegment) {
	var mountain;
	if (terrainSegment.isTop) {
		mountain = new TopMountain();
	} else {
		mountain = new BottomMountain();
	}
	// Position relative to the terrain segment
	// Ensure we use the actual height of the terrain graphic for positioning
	var terrainGraphic = terrainSegment.children[0]; // Assuming the graphic is the first child
	mountain.x = terrainSegment.x + Math.random() * terrainGraphic.width;
	// Position based on whether it's a top or bottom mountain
	mountain.y = terrainSegment.isTop ? terrainGraphic.height : 2732 - terrainGraphic.height;
	mountain.speed = terrainSpeed;
	game.addChild(mountain);
	mountains.push(mountain);
}
// Helper function to spawn ground enemies on terrain
function spawnGroundEnemy(terrainSegment) {
	var enemy = new GroundEnemy(terrainSegment.isTop);
	// Position relative to the terrain segment
	// Ensure we use the actual height of the terrain graphic for positioning
	var terrainGraphic = terrainSegment.children[0]; // Assuming the graphic is the first child
	enemy.x = terrainSegment.x + Math.random() * terrainGraphic.width;
	enemy.y = terrainSegment.isTop ? terrainGraphic.height : 2732 - terrainGraphic.height;
	enemy.speed = terrainSpeed;
	game.addChild(enemy);
	groundEnemies.push(enemy);
}
// Helper function to fire enemy bullets
function fireEnemyBullet(x, y, vx, vy, assetId) {
	// Added assetId parameter
	// If player exists and is not dead, target the player instead of using fixed direction
	if (player && !player.isDead) {
		// Calculate direction vector to player
		var dx = player.x - x;
		var dy = player.y - y;
		// Normalize the vector
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Use the bullet speed provided (or calculate from vx and vy if assetId is for styling only)
		// For simplicity, let's assume the passed vx,vy define the base speed.
		var baseSpeed = Math.sqrt(vx * vx + vy * vy);
		if (distance > 0 && baseSpeed > 0) {
			// Ensure distance and baseSpeed are valid
			vx = dx / distance * baseSpeed;
			vy = dy / distance * baseSpeed;
		}
		// If player is not available or too close, use original vx, vy
	}
	var bullet = new EnemyBullet(x, y, vx, vy, assetId); // Pass assetId to constructor
	game.addChild(bullet);
	enemyBullets.push(bullet);
	LK.getSound('enemyShoot').play();
}
// Helper function to spawn air enemies (simple version)
function spawnAirEnemy() {
	var startY = Math.random() * (2732 - 400) + 200; // Avoid edges
	var enemy = new AirEnemy(2048 + 100, startY); // Start off-screen right
	game.addChild(enemy);
	airEnemies.push(enemy);
}
// Helper function to fire boss lasers
function fireBossLasers(x, y) {
	var directions = 5;
	var laserSpeed = 12;
	var verticalSpread = 4; // Max vertical speed component
	for (var i = 0; i < directions; i++) {
		// Calculate vertical velocity component for spread
		// Example: i=0 -> -4, i=1 -> -2, i=2 -> 0, i=3 -> 2, i=4 -> 4
		var vy = -verticalSpread + verticalSpread * 2 / (directions - 1) * i;
		// Keep horizontal speed constant (moving left)
		var vx = -laserSpeed;
		var laser = new BossLaser(x, y, vx, vy);
		game.addChild(laser);
		bossLasers.push(laser);
	}
	// Add sound effect for laser fire (consider adding one e.g., LK.getSound('bossShoot').play(); if asset exists)
}
// Initialize Game Elements
function initGame() {
	// Reset state
	LK.setScore(0);
	scoreTxt.setText('0');
	// Hide score during intro
	scoreTxt.visible = !isGameStarted;
	// Initialize Lives
	playerLives = MAX_PLAYER_LIVES;
	if (!livesTxt) {
		// Create only if it doesn't exist (for game restarts)
		livesTxt = new Text2("Lives: x" + playerLives, {
			size: 80,
			// Slightly smaller than score
			fill: 0xFFFFFF
		});
		livesTxt.anchor.set(1, 0); // Anchor top-right
		LK.gui.topRight.addChild(livesTxt);
	} else {
		livesTxt.setText("Lives: x" + playerLives);
	}
	gamePhase = 0;
	phaseStartTime = LK.ticks;
	dragNode = null;
	playerBullets = []; // Clear player bullets
	playerFireCooldown = 0; // Reset fire cooldown
	// Clear existing elements from previous game (if any)
	// Note: LK engine handles full reset on GameOver/YouWin, but manual cleanup might be needed if restarting mid-game (not typical)
	// Let's assume full reset is handled by LK.
	// Create Player
	player = new UFO();
	player.x = 300;
	player.y = 2732 / 2;
	player.isDead = false;
	player.invincibleUntil = 0;
	player.alpha = 1; // Ensure player is visible
	game.addChild(player);
	// Create initial terrain
	var terrainWidth = LK.getAsset('terrain', {}).width; // Get width from asset
	for (var i = 0; i < Math.ceil(2048 / terrainWidth) + 1; i++) {
		createTerrainSegment(true, i * terrainWidth);
		createTerrainSegment(false, i * terrainWidth);
	}
	// Start Phase 1 Music
	LK.playMusic('phase1Music');
}
function initLevel2() {
	if (level2Started) return;
	level2Started = true;
	currentLevel = 2; // Explicitly set, though might be set at transition point too
	level2Progress = 0; // Reset progress for Level 2
	console.log("Initializing Level 2");
	LK.playMusic('level2Music'); // Play Level 2 music
	// Clean up any remaining Level 1 specific elements like air enemies
	airEnemies.forEach(function (ae) {
		if (ae && !ae.destroyed) ae.destroy();
	});
	airEnemies = [];
	// Boss should already be gone
	if (boss && !boss.destroyed) boss.destroy();
	boss = null;
	bossLasers.forEach(function (l) {
		if (l && !l.destroyed) l.destroy();
	});
	bossLasers = [];
	// Reset spawn progress markers for Level 2 elements
	lastWallSpawnProgress = 0;
	lastDiagonalEnemySpawnProgress = 0;
	lastTankSpawnProgress = 0;
	// Ensure terrain continues if it was cleared (e.g., after boss fight if phases stopped it)
	// The main terrain update loop should be modified to run during currentLevel === 2
	var terrainWidth = LK.getAsset('terrain', {}).width;
	var screenWidth = 2048;
	var numSegmentsNeeded = Math.ceil(screenWidth / terrainWidth) + 1;
	if (terrainSegmentsTop.length < numSegmentsNeeded) {
		for (var i = terrainSegmentsTop.length; i < numSegmentsNeeded; i++) {
			var xPos = i * terrainWidth;
			// Find max X of existing segments to append correctly
			if (terrainSegmentsTop.length > 0) {
				xPos = terrainSegmentsTop.reduce(function (max, s) {
					return s.x > max ? s.x : max;
				}, 0) + terrainWidth;
			}
			createTerrainSegment(true, xPos);
		}
	}
	if (terrainSegmentsBottom.length < numSegmentsNeeded) {
		for (var i = terrainSegmentsBottom.length; i < numSegmentsNeeded; i++) {
			var xPos = i * terrainWidth;
			if (terrainSegmentsBottom.length > 0) {
				xPos = terrainSegmentsBottom.reduce(function (max, s) {
					return s.x > max ? s.x : max;
				}, 0) + terrainWidth;
			}
			createTerrainSegment(false, xPos);
		}
	}
	// Announce Level 2 Start (Optional visual cue)
	var level2Text = new Text2("LEVEL 2", {
		size: 150,
		fill: 0xFFFF00
	});
	level2Text.anchor.set(0.5, 0.5);
	level2Text.x = 2048 / 2;
	level2Text.y = 2732 / 3;
	game.addChild(level2Text);
	LK.setTimeout(function () {
		if (level2Text && !level2Text.destroyed) level2Text.destroy();
	}, 3000); // Display for 3 seconds
	// gamePhase variable might be set to a new value (e.g., 3) if other systems rely on it.
	// For now, currentLevel = 2 will gate Level 2 logic.
	gamePhase = 3; // Indicate a new phase distinct from level 1's 0, 1, 2.
}
// Helper function already moved above
// Helper function to save highscore
function saveHighscore() {
	// Removed score argument, will use LK.getScore() internally
	var currentScore = LK.getScore();
	var currentPlayerId = LK.profile && LK.profile.id ? LK.profile.id : "guest";
	var currentPlayerName = LK.profile && LK.profile.name ? LK.profile.name : "FRVR Player";
	var highscores = [];
	try {
		if (storage && storage.available && storage.highscoresData) {
			var parsedData = JSON.parse(storage.highscoresData);
			if (Array.isArray(parsedData)) {
				highscores = parsedData;
			}
		}
	} catch (e) {
		console.log("Error parsing existing highscoresData, resetting: " + e.message);
		highscores = [];
	}
	// Add current score
	highscores.push({
		id: currentPlayerId,
		name: currentPlayerName,
		score: currentScore,
		date: Date.now() // Store timestamp for sorting or display
	});
	// Sort by score (descending), then by date (newest first for tie-breaking)
	highscores.sort(function (a, b) {
		if (b.score === a.score) {
			return b.date - a.date;
		}
		return b.score - a.score;
	});
	// Limit to a reasonable number of stored highscores, e.g., top 50
	var MAX_STORED_HIGHSCORES = 50;
	if (highscores.length > MAX_STORED_HIGHSCORES) {
		highscores = highscores.slice(0, MAX_STORED_HIGHSCORES);
	}
	// Save back to storage
	try {
		if (storage && storage.available) {
			storage.highscoresData = JSON.stringify(highscores);
		}
	} catch (e) {
		console.log("Error stringifying or saving highscoresData: " + e.message);
	}
	// Update the player's personal best score, stored separately for quick access
	// This key is used by createScoreBackground for "Your Best" display
	if (currentPlayerId !== "guest") {
		var personalBestKey = 'player_' + currentPlayerId;
		var currentPersonalBest = 0;
		try {
			if (storage && storage.available && storage[personalBestKey]) {
				currentPersonalBest = parseInt(storage[personalBestKey], 10) || 0;
			}
		} catch (parseError) {
			console.log("Error parsing personal best for key " + personalBestKey + ": " + parseError.message);
			currentPersonalBest = 0;
		}
		if (currentScore > currentPersonalBest) {
			if (storage && storage.available) {
				try {
					storage[personalBestKey] = currentScore.toString();
				} catch (saveError) {
					console.log("Error saving personal best for key " + personalBestKey + ": " + saveError.message);
				}
			}
		}
	}
}
// The createScoreBackground function is now defined earlier in the code
// This duplicate definition has been moved earlier in the code
// Helper function to handle player death
function handlePlayerDeath() {
	if (!player || player.isDead) {
		return;
	}
	// Event Handlers
	player.isDead = true;
	player.alpha = 0; // Make player invisible during death processing
	LK.getSound('playerExplosion').play();
	// Optional: Flash the player before making them fully invisible, or flash screen
	// LK.effects.flashObject(player, 0xFF0000, 500);
	LK.effects.flashScreen(0xFF0000, 200); // Short screen flash
	playerLives--;
	if (livesTxt) {
		livesTxt.setText("Lives: x" + playerLives);
	}
	LK.setTimeout(function () {
		if (playerLives > 0) {
			respawnPlayer();
		} else {
			// Save highscore before showing Game Over
			saveHighscore(); //{6o} // Argument removed
			// Create background for scores before showing game over
			createScoreBackground();
			LK.showGameOver();
		}
	}, 1000); // 1 second delay for effects and sound
}
// Helper function to create score background when game is won or lost
function createScoreBackground() {
	var createdTextElements = [];
	// Store reference to background for later access
	if (highscoreBackground) {
		highscoreBackground.destroy();
	}
	// Get current player information
	var currentPlayerId = LK.profile && LK.profile.id ? LK.profile.id : "guest";
	var currentPlayerName = LK.profile && LK.profile.name ? LK.profile.name : "FRVR Player";
	var currentScore = LK.getScore();
	// Get highscores from storage
	var highscores = [];
	try {
		if (storage && storage.available && storage.highscoresData) {
			highscores = JSON.parse(storage.highscoresData);
		}
	} catch (e) {
		console.log("Error parsing highscores:", e);
		highscores = [];
	}
	// Check if the current score is already in the list (for game over after saving score)
	var scoreExists = false;
	for (var i = 0; i < highscores.length; i++) {
		if (highscores[i].id === currentPlayerId && highscores[i].score === currentScore && Date.now() - highscores[i].date < 60000) {
			// Added in last minute
			scoreExists = true;
			highscores[i].isCurrent = true; // Mark as current game's score
			break;
		}
	}
	// Add the current score to the highscores immediately if not already there
	if (!scoreExists) {
		highscores.push({
			id: currentPlayerId,
			name: currentPlayerName,
			score: currentScore,
			date: Date.now(),
			isCurrent: true // Mark as current game's score
		});
	}
	// Sort highscores by date (most recent first)
	highscores.sort(function (a, b) {
		return b.date - a.date; // Most recent date first
	});
	var personalBest = 0;
	// Check if player has a personal best stored
	if (currentPlayerId !== "guest") {
		var personalKey = "player_" + currentPlayerId;
		try {
			if (storage && storage.available && storage[personalKey]) {
				personalBest = parseInt(storage[personalKey], 10) || 0;
			}
			// Also check from cloud storage
			if (storage && storage.available) {
				storage.load('player_score_' + currentPlayerId, function (savedScore) {
					if (savedScore) {
						var cloudScore = parseInt(savedScore, 10) || 0;
						if (cloudScore > personalBest) {
							personalBest = cloudScore;
							storage[personalKey] = personalBest.toString();
						}
					}
				});
			}
		} catch (e) {
			console.log("Error retrieving personal best:", e);
		}
	}
	// Create background
	highscoreBackground = game.addChild(LK.getAsset('Background2', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 / 2,
		scaleX: 20.48,
		scaleY: 27.32,
		alpha: 0.9
	}));
	// Create title
	var titleText = new Text2("GAME RESULTS", {
		size: 120,
		fill: 0xFFFFFF
	});
	titleText.anchor.set(0.5, 0);
	titleText.x = 2048 / 2;
	titleText.y = 200;
	game.addChild(titleText);
	createdTextElements.push(titleText);
	// Current score
	var currentScoreText = new Text2("Your Score: " + currentScore, {
		size: 100,
		fill: 0x00FF00
	});
	currentScoreText.anchor.set(0.5, 0);
	currentScoreText.x = 2048 / 2;
	currentScoreText.y = 350;
	game.addChild(currentScoreText);
	createdTextElements.push(currentScoreText);
	// Show personal best if it exists
	if (personalBest > 0 && personalBest !== currentScore) {
		var personalBestText = new Text2("Your Best: " + personalBest, {
			size: 80,
			fill: 0xFFD700
		});
		personalBestText.anchor.set(0.5, 0);
		personalBestText.x = 2048 / 2;
		personalBestText.y = 470;
		game.addChild(personalBestText);
		createdTextElements.push(personalBestText);
		// Show new record indicator
		if (currentScore > personalBest) {
			var newRecordText = new Text2("NEW RECORD!", {
				size: 80,
				fill: 0xFF00FF
			});
			newRecordText.anchor.set(0.5, 0);
			newRecordText.x = 2048 / 2;
			newRecordText.y = 560;
			game.addChild(newRecordText);
			createdTextElements.push(newRecordText);
		}
	}
	// Display up to 20 highscores instead of 10
	var maxToShow = Math.min(highscores.length, 20);
	if (maxToShow > 0) {
		// Display title for scores
		var titleScoreText = new Text2("Recent Player Scores", {
			size: 90,
			fill: 0xFFD700
		});
		titleScoreText.anchor.set(0.5, 0);
		titleScoreText.x = 2048 / 2;
		titleScoreText.y = 700;
		game.addChild(titleScoreText);
		createdTextElements.push(titleScoreText);
		// Adjust spacing based on number of scores
		var spacing = maxToShow > 10 ? 90 : maxToShow > 5 ? 120 : 150;
		var fontSize = maxToShow > 10 ? 60 : maxToShow > 5 ? 70 : 80;
		// Display player scores
		for (var i = 0; i < maxToShow; i++) {
			var entry = highscores[i];
			var isCurrentPlayer = entry.id === currentPlayerId;
			var isCurrentScore = entry.isCurrent === true;
			// Format score with comma separators
			var formattedScore = entry.score.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
			// Get player name, using ID if name is missing
			var playerName = entry.name || "Player " + entry.id.substring(0, 5);
			var scoreEntry = new Text2(i + 1 + ". " + playerName + ": " + formattedScore, {
				size: fontSize,
				fill: isCurrentScore ? "#FF00FF" : isCurrentPlayer ? "#00FF00" : "#FFFFFF" // Magenta for current score, green for other scores by current player
			});
			// If more than 10 entries, create two columns
			if (maxToShow > 10 && i >= 10) {
				// Second column (for entries 11-20)
				scoreEntry.anchor.set(0, 0); // Left align for second column
				scoreEntry.x = 2048 * 0.25; // Position at 1/4 of screen width
				scoreEntry.y = 800 + (i - 10) * spacing;
			} else if (maxToShow > 10) {
				// First column (for entries 1-10)
				scoreEntry.anchor.set(1, 0); // Right align for first column
				scoreEntry.x = 2048 * 0.75; // Position at 3/4 of screen width
				scoreEntry.y = 800 + i * spacing;
			} else {
				// Single column layout (for 10 or fewer entries)
				scoreEntry.anchor.set(0.5, 0);
				scoreEntry.x = 2048 / 2;
				scoreEntry.y = 800 + i * spacing;
			}
			game.addChild(scoreEntry);
			createdTextElements.push(scoreEntry);
		}
	} else {
		// No scores message
		var noScoresText = new Text2("No scores yet!", {
			size: 80,
			fill: 0xFFFFFF
		});
		noScoresText.anchor.set(0.5, 0);
		noScoresText.x = 2048 / 2;
		noScoresText.y = 800;
		game.addChild(noScoresText);
		createdTextElements.push(noScoresText);
	}
	return createdTextElements;
}
// The createScoreBackground function has been moved earlier in the code
// Helper function to respawn player at checkpoint
function respawnPlayer() {
	if (!player) {
		return;
	}
	player.x = 300;
	player.y = 2732 / 2;
	player.clampPosition();
	player.alpha = 1; // Make player visible again
	player.isDead = false;
	player.invincibleUntil = LK.ticks + 120; // 2 seconds of invincibility
	// Clear active threats
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		if (enemyBullets[i] && !enemyBullets[i].destroyed) {
			enemyBullets[i].destroy();
		}
	}
	enemyBullets = [];
	if (gamePhase === 2) {
		// Boss phase
		for (var i = bossLasers.length - 1; i >= 0; i--) {
			if (bossLasers[i] && !bossLasers[i].destroyed) {
				bossLasers[i].destroy();
			}
		}
		bossLasers = [];
	}
	// Player is reset, other game elements (enemies, boss health) remain.
}
// Create intro screen elements
var backgroundAsset = LK.getAsset('Background0', {});
var scaleX = 2048 / backgroundAsset.width;
var scaleY = 2732 / backgroundAsset.height;
var background = game.addChild(LK.getAsset('Background0', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2,
	scaleX: scaleX,
	scaleY: scaleY
}));
// Play intro music
LK.playMusic('Intromusic1');
var startButton = game.addChild(LK.getAsset('Startgamebutton', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2 + 700,
	scaleX: 1.5,
	scaleY: 1.5
}));
var highscoreButton = game.addChild(LK.getAsset('Highscorebutton', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2 + 1050,
	scaleX: 1.5,
	scaleY: 1.5
}));
function startGame() {
	// Remove intro elements
	background.destroy();
	startButton.destroy();
	highscoreButton.destroy();
	// Set game as started
	isGameStarted = true;
	// Show score
	scoreTxt.visible = true;
	// Initialize the game
	initGame();
}
function showHighscore() {
	if (showingHighscores) {
		// If currently showing, hide everything
		if (highscoreBackground) {
			// highscoreBackground is global, set by createScoreBackground
			highscoreBackground.destroy();
			highscoreBackground = null;
		}
		elementsShownByShowHighscore.forEach(function (el) {
			if (el && !el.destroyed) {
				el.destroy();
			}
		});
		elementsShownByShowHighscore = [];
		showingHighscores = false;
		return;
	}
	// Not showing, so display the highscore screen
	showingHighscores = true;
	// Clear any residual elements from a previous display, just in case
	if (highscoreBackground && !highscoreBackground.destroyed) {
		highscoreBackground.destroy();
		highscoreBackground = null;
	}
	elementsShownByShowHighscore.forEach(function (el) {
		if (el && !el.destroyed) {
			el.destroy();
		}
	});
	elementsShownByShowHighscore = [];
	// Call createScoreBackground to generate the main content.
	// This function sets the global 'highscoreBackground' and returns an array of its text elements.
	var textsFromCreateScoreBg = createScoreBackground();
	elementsShownByShowHighscore = elementsShownByShowHighscore.concat(textsFromCreateScoreBg);
	// Add "TAP ANYWHERE TO RETURN" text, specific to this highscore view
	var backText = new Text2("TAP ANYWHERE TO RETURN", {
		size: 70,
		fill: 0xFFFFFF //{dT} // Kept original fill and size
	});
	backText.anchor.set(0.5, 0);
	backText.x = 2048 / 2;
	backText.y = 2200; // Adjusted Y to be a bit lower if needed, or use original from createScoreBackground if it had one
	game.addChild(backText);
	elementsShownByShowHighscore.push(backText); // Add to our list for cleanup
	// Fallback to LK.showLeaderboard if our custom screen is up for too long
	if (typeof LK.showLeaderboard === 'function') {
		LK.setTimeout(function () {
			if (showingHighscores) {
				// Check if our screen is still active
				showingHighscores = false; // Toggle off state
				if (highscoreBackground && !highscoreBackground.destroyed) {
					highscoreBackground.destroy();
					highscoreBackground = null;
				}
				elementsShownByShowHighscore.forEach(function (el) {
					if (el && !el.destroyed) {
						el.destroy();
					}
				});
				elementsShownByShowHighscore = [];
				LK.showLeaderboard(); // Show the engine's leaderboard
			}
		}, 5000); // 5 second timeout
	}
}
// Add interactive behavior to buttons
startButton.interactive = true;
startButton.buttonMode = true;
startButton.down = function () {
	startGame();
};
highscoreButton.interactive = true;
highscoreButton.buttonMode = true;
highscoreButton.down = function () {
	showHighscore();
};
game.down = function (x, y, obj) {
	// Handle tapping on highscore screen to return to intro
	if (showingHighscores) {
		showHighscore(); // This will toggle off the highscore display
		return;
	}
	// Only process player dragging if game has started
	if (isGameStarted && player) {
		// Check if touch is on the player UFO
		var localPos = player.toLocal(game.toGlobal({
			x: x,
			y: y
		})); // Convert game coords to player's local coords
		// Use a slightly larger hit area for easier dragging
		var hitWidth = player.width * 1.5;
		var hitHeight = player.height * 1.5;
		if (Math.abs(localPos.x) < hitWidth / 2 && Math.abs(localPos.y) < hitHeight / 2) {
			dragNode = player;
			// Instantly move player to touch position for responsive feel
			var gamePos = game.toLocal(obj.global); // Use obj.global for precise position
			player.x = gamePos.x;
			player.y = gamePos.y;
			player.clampPosition();
		} else {
			dragNode = null;
		}
	}
};
game.move = function (x, y, obj) {
	if (dragNode) {
		var gamePos = game.toLocal(obj.global); // Convert event global position to game coordinates
		dragNode.x = gamePos.x;
		dragNode.y = gamePos.y;
		// Clamp player position within bounds immediately after move
		if (dragNode === player) {
			player.clampPosition();
		}
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Game Update Logic
game.update = function () {
	// If game hasn't started yet or player is gone, don't process game logic
	if (!isGameStarted || !player || player.destroyed) {
		// Check if we need to initialize level 2 due to a reload/restart mid-level 2
		// This is an edge case, main L2 init is after boss defeat.
		// if (currentLevel === 2 && !level2Started && isGameStarted && player) { initLevel2(); }
		// Make sure score is hidden during intro
		scoreTxt.visible = false;
		return; // Game not started or player fully gone, nothing to do.
	}
	// Make sure score is visible during gameplay
	scoreTxt.visible = true;
	// Initialize Level 2 if conditions are met (transitioned from Level 1)
	if (currentLevel === 2 && !level2Started && isGameStarted && player && !player.isDead) {
		initLevel2();
	}
	// If player is dead, stop their specific logic & wait for respawn/game over timeout
	// Other game elements (enemies, bullets) might still update.
	// Player input and collisions will be gated by player.isDead or invincibility.
	// Player invincibility blinking
	if (player && !player.isDead && LK.ticks < player.invincibleUntil) {
		player.alpha = LK.ticks % 20 < 10 ? 0.5 : 1; // Blink
	} else if (player && !player.isDead && player.alpha !== 1) {
		player.alpha = 1; // Ensure alpha is reset
	}
	// --- Global Updates ---
	// Player Shooting
	playerFireCooldown++;
	if (!player.isDead && dragNode === player && playerFireCooldown >= playerFireRate) {
		// Only shoot while dragging/controlling and alive
		playerFireCooldown = 0;
		var bullet = new PlayerBullet(player.x + player.width / 2, player.y);
		game.addChild(bullet);
		playerBullets.push(bullet);
		LK.getSound('playerShoot').play();
	}
	// Score increases over time
	scoreIncrementTimer++;
	if (scoreIncrementTimer >= 60) {
		// Add 10 points every second
		scoreIncrementTimer = 0;
		LK.setScore(LK.getScore() + 10);
		scoreTxt.setText(LK.getScore());
	}
	// Increment distance scrolled (used by Level 2)
	if (player && !player.isDead) {
		// Only scroll if player is active and game is running
		// gameDistanceScrolled += terrainSpeed; // This was for overall game, level2Progress is specific
		if (currentLevel === 2 && level2Started) {
			level2Progress += terrainSpeed;
		}
	}
	// --- Phase Management ---
	var elapsedTicks = LK.ticks - phaseStartTime;
	if (gamePhase === 0 && elapsedTicks >= phaseDuration) {
		// Transition to Phase 1 (Space)
		gamePhase = 1;
		phaseStartTime = LK.ticks; // Reset timer for next phase if needed
		console.log("Transitioning to Phase 1: Space");
		// Clean up terrain-specific elements
		terrainSegmentsTop.forEach(function (s) {
			return s.destroy();
		});
		terrainSegmentsBottom.forEach(function (s) {
			return s.destroy();
		});
		mountains.forEach(function (m) {
			return m.destroy();
		});
		groundEnemies.forEach(function (ge) {
			return ge.destroy();
		});
		terrainSegmentsTop = [];
		terrainSegmentsBottom = [];
		mountains = [];
		groundEnemies = [];
		// Spawn initial air enemies
		for (var i = 0; i < 5; i++) {
			// Start with 5 air enemies
			spawnAirEnemy();
		}
		LK.playMusic('phase2Music'); // Switch music
	} else if (gamePhase === 1 && elapsedTicks >= phaseDuration * 1.5) {
		// Example: Boss after 1.5x phase duration
		// Transition to Phase 2 (Boss)
		if (!boss) {
			// Ensure boss only spawns once
			gamePhase = 2;
			phaseStartTime = LK.ticks;
			console.log("Transitioning to Phase 2: Boss");
			// Clean up air enemies
			airEnemies.forEach(function (ae) {
				return ae.destroy();
			});
			airEnemies = [];
			// Spawn Boss
			boss = new Boss();
			game.addChild(boss);
			LK.playMusic('bossMusic'); // Boss music
		}
	}
	// --- Terrain Logic (Active in Level 1 Phase 0 and Level 2 except Area 4) ---
	var isArea4 = currentLevel === 2 && level2Progress >= LEVEL2_AREA3_END_PX;
	if ((gamePhase === 0 || currentLevel === 2) && !isArea4) {
		// Update and manage terrain segments
		var terrainWidth = LK.getAsset('terrain', {}).width;
		for (var i = terrainSegmentsTop.length - 1; i >= 0; i--) {
			var segment = terrainSegmentsTop[i];
			if (segment.x < -terrainWidth) {
				// Reposition segment to the right
				var maxX = 0;
				terrainSegmentsTop.forEach(function (s) {
					if (s.x > maxX) {
						maxX = s.x;
					}
				});
				segment.x = maxX + terrainWidth;
				// Always spawn an enemy on the reused segment
				spawnGroundEnemy(segment);
				// Additionally, 50% chance for a mountain
				if (Math.random() < 0.5) {
					spawnMountain(segment);
				}
			}
		}
		// Repeat for bottom terrain
		for (var i = terrainSegmentsBottom.length - 1; i >= 0; i--) {
			var segment = terrainSegmentsBottom[i];
			if (segment.x < -terrainWidth) {
				var maxX = 0;
				terrainSegmentsBottom.forEach(function (s) {
					if (s.x > maxX) {
						maxX = s.x;
					}
				});
				segment.x = maxX + terrainWidth;
				// Always spawn an enemy on the reused segment
				spawnGroundEnemy(segment);
				// Additionally, 50% chance for a mountain
				if (Math.random() < 0.5) {
					spawnMountain(segment);
				}
			}
		}
		// Update mountains & check collision
		for (var i = mountains.length - 1; i >= 0; i--) {
			var mountain = mountains[i];
			if (mountain.x < -mountain.width) {
				mountain.destroy();
				mountains.splice(i, 1);
			} else {
				if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(mountain)) {
					handlePlayerDeath();
					return; // Stop update processing
				}
			}
		}
		// Update ground enemies & check collision
		for (var i = groundEnemies.length - 1; i >= 0; i--) {
			var enemy = groundEnemies[i];
			if (enemy.x < -enemy.width) {
				enemy.destroy();
				groundEnemies.splice(i, 1);
			} else {
				// Collision check: Player vs Ground Enemy
				if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(enemy)) {
					LK.getSound('enemyExplosion').play(); //{3L} // Enemy explodes
					enemy.destroy(); // Destroy enemy on collision too
					groundEnemies.splice(i, 1);
					handlePlayerDeath();
					return;
				}
			}
		}
		// Re-clamp player position based on potentially moving terrain (simple clamp for now)
		player.clampPosition();
	}
	// --- Phase 1/2: Air Enemy Logic ---
	if (gamePhase === 1) {
		// Add more air enemies periodically?
		if (LK.ticks % 180 === 0 && airEnemies.length < 10) {
			// Spawn if less than 10, every 3 seconds
			spawnAirEnemy();
		}
		// Update air enemies & check collision
		for (var i = airEnemies.length - 1; i >= 0; i--) {
			var enemy = airEnemies[i];
			// Air enemies handle their own off-screen logic (respawn) in their update
			// Collision check: Player vs Air Enemy
			if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(enemy)) {
				LK.getSound('enemyExplosion').play(); //{41} // Enemy explodes
				enemy.destroy(); // Destroy enemy on collision
				airEnemies.splice(i, 1);
				// LK.setScore(LK.getScore() + 50); // Score for destroying enemy - player died, maybe no score for this? Or keep it. Let's keep for now.
				// scoreTxt.setText(LK.getScore());
				handlePlayerDeath();
				return;
			}
		}
	}
	// --- Phase 3: Boss Logic ---
	if (gamePhase === 2 && boss) {
		// Check collision: Player vs Boss
		if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(boss)) {
			// Don't destroy boss on collision
			handlePlayerDeath();
			return;
		}
		// Update boss lasers & check collision
		for (var i = bossLasers.length - 1; i >= 0; i--) {
			var laser = bossLasers[i];
			// Check if laser is off-screen
			if (laser.x < -laser.width || laser.x > 2048 + laser.width || laser.y < -laser.height || laser.y > 2732 + laser.height) {
				laser.destroy();
				bossLasers.splice(i, 1);
			} else {
				// Collision check: Player vs Boss Laser
				if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(laser)) {
					laser.destroy(); // Destroy laser
					bossLasers.splice(i, 1);
					handlePlayerDeath();
					return;
				}
			}
		}
		// Note: Boss defeat condition is now handled within the player bullet collision check loop.
	}
	// --- Update Enemy Bullets & Check Collision (All Phases) ---
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var bullet = enemyBullets[i];
		// Check if bullet is off-screen
		if (bullet.y < -bullet.height || bullet.y > 2732 + bullet.height) {
			bullet.destroy();
			enemyBullets.splice(i, 1);
		} else {
			// Collision check: Player vs Enemy Bullet
			if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(bullet)) {
				bullet.destroy(); // Destroy bullet
				enemyBullets.splice(i, 1);
				handlePlayerDeath(); // This function now handles the delay and sound
				return; // Stop update processing
			}
		}
	}
	// The saveHighscore function has been moved before handlePlayerDeath to fix the undefined error
	// --- Update Player Bullets & Check Collision ---
	for (var i = playerBullets.length - 1; i >= 0; i--) {
		var bullet = playerBullets[i];
		// Check if bullet is off-screen (right side)
		if (bullet.x > 2048 + bullet.width) {
			bullet.destroy();
			playerBullets.splice(i, 1);
			continue; // Skip collision checks if off-screen
		}
		// Collision Check: Player Bullet vs Ground Enemy (Phase 0)
		if (gamePhase === 0) {
			for (var j = groundEnemies.length - 1; j >= 0; j--) {
				var enemy = groundEnemies[j];
				if (bullet.intersects(enemy)) {
					LK.getSound('enemyExplosion').play();
					LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white
					enemy.destroy();
					groundEnemies.splice(j, 1);
					bullet.destroy();
					playerBullets.splice(i, 1);
					LK.setScore(LK.getScore() + 100); // Score for destroying ground enemy
					scoreTxt.setText(LK.getScore());
					break; // Bullet can only hit one enemy
				}
			}
			if (!bullet.exists) {
				continue;
			} // Check if bullet was destroyed in previous loop
		}
		// Collision Check: Player Bullet vs Air Enemy (Phase 1)
		if (gamePhase === 1) {
			for (var j = airEnemies.length - 1; j >= 0; j--) {
				var enemy = airEnemies[j];
				if (bullet.intersects(enemy)) {
					LK.getSound('enemyExplosion').play();
					LK.effects.flashObject(enemy, 0xFFFFFF, 100); // Flash enemy white
					enemy.destroy();
					airEnemies.splice(j, 1);
					bullet.destroy();
					playerBullets.splice(i, 1);
					LK.setScore(LK.getScore() + 150); // Score for destroying air enemy
					scoreTxt.setText(LK.getScore());
					break; // Bullet can only hit one enemy
				}
			}
			if (!bullet.exists) {
				continue;
			} // Check if bullet was destroyed in previous loop
		}
		// Collision Check: Player Bullet vs Boss (Phase 2)
		if (gamePhase === 2 && boss) {
			if (bullet.intersects(boss)) {
				LK.getSound('enemyExplosion').play(); // Use enemy explosion for hit sound
				LK.effects.flashObject(boss, 0xFFFFFF, 100); // Flash boss white
				bullet.destroy();
				playerBullets.splice(i, 1);
				boss.health -= 1; // Decrease boss health
				LK.setScore(LK.getScore() + 10); // Small score for hitting boss
				scoreTxt.setText(LK.getScore());
				// Boss defeat check is now inside the bullet loop
				if (boss.health <= 0) {
					LK.getSound('bossExplosion').play(); // Play boss explosion sound
					boss.destroy();
					boss = null;
					// Cleanup remaining lasers
					bossLasers.forEach(function (l) {
						return l.destroy();
					});
					bossLasers = [];
					LK.setScore(LK.getScore() + 5000); // Big score bonus
					scoreTxt.setText(LK.getScore());
					// Save highscore as a milestone for defeating the boss
					saveHighscore(); //{be} // Argument removed
					// Transition to Level 2
					currentLevel = 2;
					level2Started = false; // Flag to trigger initLevel2() once at the start of next update cycle
					// Note: Removed createScoreBackground(); call here as game transitions to Level 2
					LK.setScore(LK.getScore() + 5000); // Bonus for defeating boss (applied again, consider if this is intended or consolidate)
					scoreTxt.setText(LK.getScore());
					// saveHighscore(LK.getScore()); // Score is already saved above, this might be redundant unless intended for separate tracking
					// Clear boss specific elements
					if (boss && !boss.destroyed) boss.destroy();
					boss = null;
					bossLasers.forEach(function (l) {
						if (l && !l.destroyed) l.destroy();
					});
					bossLasers = [];
					console.log("Boss defeated! Preparing Level 2.");
					// initLevel2() will be called in the next game.update() loop at the top
					return; // Stop update processing this frame to allow initLevel2 to run cleanly
				}
				break; // Bullet is destroyed after hitting boss
			}
		}
		// --- Level 2 Logic ---
		if (currentLevel === 2 && level2Started) {
			var LEVEL2_AREA1_END_PX = LEVEL2_AREA1_END_MILES * PIXELS_PER_MILE;
			var LEVEL2_AREA2_END_PX = (LEVEL2_AREA1_END_MILES + LEVEL2_AREA2_DURATION_MILES) * PIXELS_PER_MILE;
			var LEVEL2_AREA3_END_PX = (LEVEL2_AREA1_END_MILES + LEVEL2_AREA2_DURATION_MILES + LEVEL2_AREA3_DURATION_MILES) * PIXELS_PER_MILE;
			var LEVEL2_FINAL_END_PX = (LEVEL2_AREA1_END_MILES + LEVEL2_AREA2_DURATION_MILES + LEVEL2_AREA3_DURATION_MILES + LEVEL2_AREA4_DURATION_MILES) * PIXELS_PER_MILE;
			// --- Level 2, Area 1 (Vertical Walls) ---
			if (level2Progress < LEVEL2_AREA1_END_PX) {
				if (level2Progress > lastWallSpawnProgress + WALL_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastWallSpawnProgress = level2Progress;
					var wall = new VerticalWall(2048 + 200); // Spawn off-screen right
					game.addChild(wall);
					verticalWalls.push(wall);
				}
			}
			// --- Level 2, Area 2 (Diagonal Enemies, Tanks) ---
			else if (level2Progress < LEVEL2_AREA2_END_PX) {
				// Clear any remaining walls from Area 1 when transitioning
				if (verticalWalls.length > 0 && level2Progress >= LEVEL2_AREA1_END_PX && level2Progress < LEVEL2_AREA1_END_PX + terrainSpeed * 2) {
					verticalWalls.forEach(function (w) {
						if (w && !w.isDestroyed) {
							w.turrets.forEach(function (t) {
								if (t && !t.isDestroyed) t.destroy();
							});
							w.destroy();
						}
					});
					verticalWalls = [];
				}
				if (level2Progress > lastDiagonalEnemySpawnProgress + DIAGONAL_ENEMY_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastDiagonalEnemySpawnProgress = level2Progress;
					var diagEnemy = new DiagonalEnemy(2048 + 150, 2732 / 2);
					game.addChild(diagEnemy);
					diagonalEnemies.push(diagEnemy);
				}
				if (level2Progress > lastTankSpawnProgress + TANK_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastTankSpawnProgress = level2Progress;
					var tankTop = new Tank(true, 2048 + 100);
					var tankBottom = new Tank(false, 2048 + 100);
					game.addChild(tankTop);
					game.addChild(tankBottom);
					tanks.push(tankTop);
					tanks.push(tankBottom);
				}
			}
			// --- Level 2, Area 3 (Serpent Formations) ---
			else if (level2Progress < LEVEL2_FINAL_END_PX) {
				// Clear any remaining Diagonal Enemies and Tanks from Area 2
				if ((diagonalEnemies.length > 0 || tanks.length > 0) && level2Progress >= LEVEL2_AREA2_END_PX && level2Progress < LEVEL2_AREA2_END_PX + terrainSpeed * 2) {
					diagonalEnemies.forEach(function (de) {
						if (de && !de.isDestroyed) de.destroy();
					});
					diagonalEnemies = [];
					tanks.forEach(function (t) {
						if (t && !t.isDestroyed) t.destroy();
					});
					tanks = [];
				}
				// Spawn Serpent Formations
				if (serpentFormations.length < MAX_SERPENT_FORMATIONS && level2Progress > lastSerpentSpawnProgress + SERPENT_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastSerpentSpawnProgress = level2Progress;
					var newSerpent = new SerpentFormation();
					game.addChild(newSerpent); // The formation is a Container
					serpentFormations.push(newSerpent);
				}
			}
			// --- Level 2, Area 4 (Small Terrains with Moving Tanks) ---
			else if (level2Progress < LEVEL2_FINAL_END_PX + LEVEL2_AREA4_DURATION_MILES * PIXELS_PER_MILE) {
				// Clear serpent formations from Area 3 when transitioning to Area 4
				if (serpentFormations.length > 0 && level2Progress >= LEVEL2_FINAL_END_PX && level2Progress < LEVEL2_FINAL_END_PX + terrainSpeed * 2) {
					serpentFormations.forEach(function (sf) {
						if (sf && !sf.isDestroyed()) sf.destroy();
					});
					serpentFormations = [];
					// Clear main terrain since area4 has no ground
					terrainSegmentsTop.forEach(function (s) {
						return s.destroy();
					});
					terrainSegmentsBottom.forEach(function (s) {
						return s.destroy();
					});
					terrainSegmentsTop = [];
					terrainSegmentsBottom = [];
				}
				// Spawn Small Terrains with tanks
				if (level2Progress > lastSmallTerrainSpawnProgress + SMALL_TERRAIN_SPAWN_INTERVAL_MILES * PIXELS_PER_MILE) {
					lastSmallTerrainSpawnProgress = level2Progress;
					var topTerrain = new SmallTerrain(true, 2048 + 200);
					var bottomTerrain = new SmallTerrain(false, 2048 + 200);
					game.addChild(topTerrain);
					game.addChild(bottomTerrain);
					smallTerrains.push(topTerrain);
					smallTerrains.push(bottomTerrain);
					// Add tanks to the terrains
					topTerrain.addTank();
					bottomTerrain.addTank();
				}
			}
			// --- Level 2 Completed ---
			else {
				if (player && !player.isDead) {
					// Ensure win condition only if player alive
					console.log("Level 2 Complete!");
					// Clean up any remaining serpent formations
					serpentFormations.forEach(function (sf) {
						if (sf && !sf.isDestroyed()) sf.destroy();
					});
					serpentFormations = [];
					saveHighscore(); //{bI} // Argument removed
					createScoreBackground();
					LK.setTimeout(function () {
						LK.showYouWin(); // Game ends after Level 2 (Area 3)
					}, 500);
					player.isDead = true; // Prevent further actions
					return;
				}
			}
			// Update and Collision for Level 2 Elements
			// Vertical Walls (and their turrets)
			for (var i = verticalWalls.length - 1; i >= 0; i--) {
				var wall = verticalWalls[i];
				if (wall.isDestroyed) {
					// Already handled by wall itself
					// verticalWalls.splice(i, 1); // Wall removes itself from array
					continue;
				}
				if (wall.x < -wall.width) {
					// Off-screen left
					wall.turrets.forEach(function (t) {
						if (t && !t.isDestroyed) t.destroy();
					});
					wall.destroy();
					verticalWalls.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(wall)) {
					handlePlayerDeath();
					return;
				}
			}
			// Turrets are updated via their own class or Wall. Bullets handled by main enemyBullets loop.
			// Diagonal Enemies
			for (var i = diagonalEnemies.length - 1; i >= 0; i--) {
				var diagEnemy = diagonalEnemies[i];
				if (diagEnemy.isDestroyed) {
					// diagonalEnemies.splice(i, 1); // Enemy removes itself
					continue;
				}
				if (diagEnemy.x < -diagEnemy.width) {
					diagEnemy.destroy();
					diagonalEnemies.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(diagEnemy)) {
					diagEnemy.takeDamage();
					handlePlayerDeath();
					return;
				}
			}
			// Tanks
			for (var i = tanks.length - 1; i >= 0; i--) {
				var tank = tanks[i];
				if (tank.isDestroyed) {
					// tanks.splice(i, 1); // Enemy removes itself
					continue;
				}
				if (tank.x < -tank.width) {
					tank.destroy();
					tanks.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(tank)) {
					tank.takeDamage();
					handlePlayerDeath();
					return;
				}
			}
			// Small Terrains (Area 4)
			for (var i = smallTerrains.length - 1; i >= 0; i--) {
				var smallTerrain = smallTerrains[i];
				if (smallTerrain.isDestroyed) {
					continue;
				}
				if (smallTerrain.x < -smallTerrain.width) {
					smallTerrain.destroy();
					smallTerrains.splice(i, 1);
				} else if (!player.isDead && LK.ticks > player.invincibleUntil && player.intersects(smallTerrain)) {
					handlePlayerDeath();
					return;
				}
			}
			// Update Serpent Formations (Area 3 specific, but update loop runs for all formations)
			for (var i = serpentFormations.length - 1; i >= 0; i--) {
				var serpent = serpentFormations[i];
				// serpent.update(); // Already called because it's a child of game
				if (serpent.isDone()) {
					serpent.destroy();
					serpentFormations.splice(i, 1);
				} else {
					// Player collision with individual serpent ships
					if (!player.isDead && LK.ticks > player.invincibleUntil) {
						for (var j = serpent.ships.length - 1; j >= 0; j--) {
							var ship = serpent.ships[j];
							if (!ship.isDestroyed) {
								// Need to get global position of the ship for intersection check
								var shipGlobalPos = serpent.toGlobal(ship.position);
								var shipGameAreaRect = new Rectangle(shipGlobalPos.x - ship.width / 2, shipGlobalPos.y - ship.height / 2, ship.width, ship.height);
								// Create a temporary object for player bounds for intersects method if player itself isn't a simple rectangle
								var playerBounds = new Rectangle(player.x - player.width / 2, player.y - player.height / 2, player.width, player.height);
								// AABB intersection check
								if (playerBounds.x < shipGameAreaRect.x + shipGameAreaRect.width && playerBounds.x + playerBounds.width > shipGameAreaRect.x && playerBounds.y < shipGameAreaRect.y + shipGameAreaRect.height && playerBounds.y + playerBounds.height > shipGameAreaRect.y) {
									ship.takeDamage(); // Serpent ship takes damage
									handlePlayerDeath(); // Player also dies
									return; // Stop further processing this frame
								}
							}
						}
					}
				}
			}
		} // End if (currentLevel === 2 && level2Started)
		// --- Update Player Bullets & Check Collision --- (Continued with Level 2 targets)
		// (This section is appended to the existing playerBullets loop, before the final closing brace of the loop)
		// The existing player bullet loop needs to be modified to include these checks.
		// This block should be inserted *inside* the `for (var i = playerBullets.length - 1; i >= 0; i--)` loop for player bullets,
		// after existing collision checks or as part of a conditional block for `currentLevel === 2`.
		// Existing player bullet loop:
		// for (var i = playerBullets.length - 1; i >= 0; i--) {
		//   var bullet = playerBullets[i];
		//   ...
		//   if (gamePhase === 2 && boss) { ... } // Existing boss collision
		//   // ADD LEVEL 2 COLLISION LOGIC HERE:
		if (currentLevel === 2 && bullet.exists) {
			// Check bullet.exists in case prior collision destroyed it
			// Vs WallTurrets (part of VerticalWalls)
			for (var k = verticalWalls.length - 1; k >= 0; k--) {
				var wall = verticalWalls[k];
				if (wall.isDestroyed) continue;
				for (var l = wall.turrets.length - 1; l >= 0; l--) {
					var turret = wall.turrets[l];
					if (turret.isDestroyed) continue;
					if (bullet.intersects(turret)) {
						if (turret.takeDamage()) {
							// true if destroyed
							LK.setScore(LK.getScore() + 75);
							scoreTxt.setText(LK.getScore());
						}
						bullet.destroy();
						playerBullets.splice(i, 1);
						break;
					}
				}
				if (!bullet.exists) break;
			}
			if (!bullet.exists) continue; // To next player bullet if this one was destroyed
			// Vs DiagonalEnemies
			for (var k = diagonalEnemies.length - 1; k >= 0; k--) {
				var diagEnemy = diagonalEnemies[k];
				if (diagEnemy.isDestroyed) continue;
				if (bullet.intersects(diagEnemy)) {
					if (diagEnemy.takeDamage()) {
						LK.setScore(LK.getScore() + 250);
						scoreTxt.setText(LK.getScore());
					}
					bullet.destroy();
					playerBullets.splice(i, 1);
					break;
				}
			}
			if (!bullet.exists) continue;
			// Vs Tanks
			for (var k = tanks.length - 1; k >= 0; k--) {
				var tank = tanks[k];
				if (tank.isDestroyed) continue;
				if (bullet.intersects(tank)) {
					if (tank.takeDamage()) {
						LK.setScore(LK.getScore() + 175);
						scoreTxt.setText(LK.getScore());
					}
					bullet.destroy();
					playerBullets.splice(i, 1);
					break;
				}
			}
			if (!bullet.exists) continue;
			// Vs SerpentEnemyShips (within SerpentFormations)
			if (bullet.exists) {
				// Check again in case previous collision destroyed it
				for (var k = serpentFormations.length - 1; k >= 0; k--) {
					var formation = serpentFormations[k];
					if (formation.isDestroyed()) continue;
					for (var l = formation.ships.length - 1; l >= 0; l--) {
						var serpentShip = formation.ships[l];
						if (serpentShip.isDestroyed) continue;
						// Get global position of the serpent ship for accurate intersection
						var shipGlobalPos = formation.toGlobal(serpentShip.position);
						// Create a temporary rectangle for the serpent ship in game coordinates
						// Assuming serpentShip.width and serpentShip.height are available (from its graphic)
						var serpentShipGameRect = new Rectangle(shipGlobalPos.x - serpentShip.width / 2, shipGlobalPos.y - serpentShip.height / 2, serpentShip.width, serpentShip.height);
						// Create a temporary rectangle for the bullet
						var bulletRect = new Rectangle(bullet.x - bullet.width / 2, bullet.y - bullet.height / 2, bullet.width, bullet.height);
						// Manual AABB intersection check
						if (bulletRect.x < serpentShipGameRect.x + serpentShipGameRect.width && bulletRect.x + bulletRect.width > serpentShipGameRect.x && bulletRect.y < serpentShipGameRect.y + serpentShipGameRect.height && bulletRect.y + bulletRect.height > serpentShipGameRect.y) {
							if (serpentShip.takeDamage()) {
								// true if destroyed
								LK.setScore(LK.getScore() + 200); // Score for serpent ship
								scoreTxt.setText(LK.getScore());
							}
							bullet.destroy();
							playerBullets.splice(i, 1);
							break; // Bullet hits one serpent ship
						}
					}
					if (!bullet.exists) break; // If bullet was destroyed, move to next player bullet
				}
			}
			if (!bullet.exists) continue; // To next player bullet
		}
		// } // End of playerBullets loop (this closing brace is illustrative, don't add a new one)
	} // End of playerBullets loop
};
:quality(85)/https://cdn.frvr.ai/68199af5e85d4d5144683e94.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/68199bb3e85d4d5144683ea7.png%3F3) 
 Alien Airships of boss, HD colors. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68199f09e85d4d5144683edb.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6819a323e85d4d5144683f20.png%3F3) 
 pack mountain, yellow, HD colors. In-Game asset. 2d. High contrast. No shadows.no black lines
:quality(85)/https://cdn.frvr.ai/681a24e683b2d6fa3331b3a3.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/681a262883b2d6fa3331b3c5.png%3F3) 
 shot circle. blur, light, HD colors In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68267530be409647e7b5ccaa.png%3F3) 
 gunTurret aiming diagonal. yellow, HD colors. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6826801dbe409647e7b5ccc5.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/68268112be409647e7b5ccd6.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/684f0a30da883c0da5d79fd8.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/684f0d2cda883c0da5d7a042.png%3F3) 
 Square & diagonal tank enemies from the future have 4 turrets on its 4 sides, HD colors. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/684f1056da883c0da5d7a097.png%3F3)