/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/**** 
* Classes
****/ 
var Boss = Container.expand(function () {
	var self = Container.call(this);
	// States
	var ENTERING = 'entering';
	var WALKING = 'walking';
	var ARROW_ATTACK = 'arrow_attack';
	var CHARGING_LEFT = 'charging_left';
	var CHARGING_RIGHT = 'charging_right';
	var FIST_LEFT = 'fist_left';
	var FIST_RIGHT = 'fist_right';
	var RETRACTING_LEFT = 'retracting_left';
	var RETRACTING_RIGHT = 'retracting_right';
	var DYING = 'dying';
	// All boss sprites
	var normalBody = self.attachAsset('boss1', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 1
	});
	var leftBody = self.attachAsset('boss1left', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	var rightBody = self.attachAsset('boss1right', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	var leftNoFist = self.attachAsset('boss1leftnofist', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	var rightNoFist = self.attachAsset('boss1rightnofist', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	// Properties
	self.health = 100;
	self.state = ENTERING;
	self.hasCompletedFirstAttack = false;
	self.stateDuration = 0;
	self.bobSpeed = 0.1;
	self.bobOffset = 0;
	self.bobBaseY = 2732 / 1.35; // Add base Y position
	self.activeFist = null;
	self.attackTimer = 0;
	self.attackDelay = 120;
	self.hasPlayedDeathSound = false;
	// Initial position
	self.x = 2048 / 2;
	self.y = 2732;
	function setBodyState(state) {
		normalBody.alpha = 0;
		leftBody.alpha = 0;
		rightBody.alpha = 0;
		leftNoFist.alpha = 0;
		rightNoFist.alpha = 0;
		switch (state) {
			case 'normal':
				normalBody.alpha = 1;
				break;
			case 'left':
				leftBody.alpha = 1;
				break;
			case 'right':
				rightBody.alpha = 1;
				break;
			case 'leftNoFist':
				leftNoFist.alpha = 1;
				break;
			case 'rightNoFist':
				rightNoFist.alpha = 1;
				break;
		}
	}
	function flashDamage() {
		[normalBody, leftBody, rightBody, leftNoFist, rightNoFist].forEach(function (sprite) {
			if (sprite.alpha > 0) {
				sprite.tint = 0xFF0000;
				LK.setTimeout(function () {
					sprite.tint = 0xFFFFFF;
				}, 5);
			}
		});
	}
	self.update = function () {
		self.stateDuration++;
		self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 15;
		switch (self.state) {
			case ENTERING:
				setBodyState('normal');
				self.y -= 2;
				if (self.y <= 2732 / 1.35) {
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
				}
				break;
			case WALKING:
				setBodyState('normal');
				self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 15;
				self.y = self.bobBaseY + self.bobOffset;
				self.attackTimer--;
				if (self.attackTimer <= 0) {
					if (!self.hasCompletedFirstAttack) {
						self.state = ARROW_ATTACK;
						self.hasCompletedFirstAttack = true;
					} else {
						var rand = Math.random();
						if (rand < 0.6) {
							self.state = ARROW_ATTACK;
						} else {
							self.state = Math.random() < 0.5 ? CHARGING_LEFT : CHARGING_RIGHT;
						}
					}
					self.stateDuration = 0;
				}
				break;
			case ARROW_ATTACK:
				// Keep bobbing motion during arrow attack
				self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 15;
				self.y = self.bobBaseY + self.bobOffset;
				if (self.stateDuration === 1) {
					LK.getSound('arrow').play(); // Play arrow sound effect
					var centerY = self.y + 200;
					enemyArrowPool.spawn(self.x, centerY).activate(self.x, centerY, dragon.x, dragon.y);
					enemyArrowPool.spawn(self.x - 100, centerY).activate(self.x - 100, centerY, dragon.x - 300, dragon.y);
					enemyArrowPool.spawn(self.x + 100, centerY).activate(self.x + 100, centerY, dragon.x + 300, dragon.y);
				} else if (self.stateDuration > 60) {
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
					self.stateDuration = 0;
				}
				break;
			case CHARGING_LEFT:
			case CHARGING_RIGHT:
				var isLeft = self.state === CHARGING_LEFT;
				setBodyState(isLeft ? 'left' : 'right');
				if (self.stateDuration < 70) {
					var targetX = self.x + (isLeft ? -200 : 200);
					var targetY = self.y + 300;
					if (Math.random() < 0.3) {
						var angle = Math.random() * Math.PI * 2;
						var radius = Math.random() * 200 + 100;
						var px = targetX + Math.cos(angle) * radius;
						var py = targetY + Math.sin(angle) * radius;
						var particle = particlePool.spawn(px, py);
						if (particle) {
							var dx = targetX - px;
							var dy = targetY - py;
							var dist = Math.sqrt(dx * dx + dy * dy);
							particle.vx = dx / dist * 10;
							particle.vy = dy / dist * 10;
						}
					}
				} else {
					if (self.activeFist) {
						bossFistPool.recycle(self.activeFist);
						self.activeFist = null;
					}
					self.state = isLeft ? FIST_LEFT : FIST_RIGHT;
					self.stateDuration = 0;
					setBodyState(isLeft ? 'leftNoFist' : 'rightNoFist');
					self.activeFist = bossFistPool.spawn(self.x + (isLeft ? -200 : 200), self.y + 300, isLeft);
					if (self.activeFist) {
						self.activeFist.extend(dragon.x, dragon.y);
						LK.getSound('bossPunch').play();
					}
				}
				break;
			case FIST_LEFT:
			case FIST_RIGHT:
				if (!self.activeFist || !self.activeFist.visible) {
					// If fist is somehow missing, recover
					setBodyState('normal');
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
					self.stateDuration = 0;
					break;
				}
				if (self.activeFist && !self.activeFist.extending) {
					self.state = self.state === FIST_LEFT ? RETRACTING_LEFT : RETRACTING_RIGHT;
					self.stateDuration = 0;
					if (self.activeFist) {
						self.activeFist.retract();
					}
				}
				break;
			case RETRACTING_LEFT:
			case RETRACTING_RIGHT:
				if (!self.activeFist || !self.activeFist.visible) {
					setBodyState('normal');
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
					self.stateDuration = 0;
					if (self.activeFist) {
						bossFistPool.recycle(self.activeFist); // Add this line
					}
					self.activeFist = null; // Add this line to clear the reference
				}
				break;
			case DYING:
				self.y += 1;
				self.x += Math.sin(self.stateDuration * 0.2) * 5;
				// More frequent and spread out particles
				if (self.stateDuration % 10 === 0) {
					for (var i = 0; i < 5; i++) {
						defeatParticlePool.spawn(self.x + (Math.random() * 800 - 400), self.y + Math.random() * 800, 0xff0000);
					}
				}
				// Random explosions every second
				if (self.stateDuration % 60 === 0) {
					var explosionX = self.x + (Math.random() * 600 - 300);
					var explosionY = self.y + (Math.random() * 600 - 300);
					var explosion = LK.getAsset('explosion', {
						anchorX: 0.5,
						anchorY: 0.5,
						x: explosionX,
						y: explosionY,
						scaleX: 0.5,
						//{39}  // Start bigger
						scaleY: 0.5,
						alpha: 1
					});
					game.addChild(explosion);
					LK.getSound('explosion').play();
					tween(explosion, {
						scaleX: 4,
						//{3g}  // End much bigger
						scaleY: 4,
						alpha: 0
					}, {
						duration: 500,
						//{3k}  // Faster animation
						easing: tween.easeOut,
						onFinish: function onFinish() {
							game.removeChild(explosion);
						}
					});
				}
				if (self.y > 2732 + 200) {
					//{3r}  // Reduced height check
					game.removeChild(self);
					bossHealthBar.visible = false;
					if (!self.hasPlayedDeathSound) {
						LK.getSound('dragonScream').play();
						self.hasPlayedDeathSound = true;
					}
					LK.setTimeout(function () {
						LK.showYouWin();
					}, 3000);
				}
				break;
		}
		self.lastBobOffset = self.bobOffset;
	};
	self.damage = function (amount) {
		self.health -= amount;
		bossHealthBar.updateHealth(self.health / 100);
		flashDamage();
		if (self.health <= 0 && self.state !== DYING) {
			self.state = DYING;
			self.stateDuration = 0;
			bossHealthBar.hide();
			// Add boss defeat score
			score += 5000;
			scorePopupPool.spawn(self.x, self.y, 5000);
			scoreTxt.setText(score);
			updateScoreMeter(score);
			LK.setScore(score);
			tween(game, {
				x: game.x + 20
			}, {
				duration: 1000,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					game.x = 0;
				}
			});
		}
	};
	return self;
});
var BossFist = Container.expand(function () {
	var self = Container.call(this);
	// Create both fist sprites and manage visibility
	var leftFist = self.attachAsset('boss1leftfist', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false,
		rotation: -Math.PI / 12 // 15 degrees counterclockwise
	});
	var rightFist = self.attachAsset('boss1rightfist', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false,
		rotation: Math.PI / 12 // 15 degrees clockwise
	});
	self.activate = function (x, y, isLeft) {
		self.x = x;
		self.y = y;
		self.startX = x;
		self.startY = y;
		self.isLeft = isLeft;
		self.visible = true;
		self.extending = false;
		self.retracting = false;
		// Show correct fist, hide other
		leftFist.visible = isLeft;
		rightFist.visible = !isLeft;
	};
	self.extend = function (targetX, targetY) {
		self.targetX = targetX;
		self.targetY = targetY;
		self.extending = true;
		self.retracting = false;
	};
	self.update = function () {
		if (!self.visible) {
			return;
		}
		if (self.extending || self.retracting) {
			var dx = self.targetX - self.x;
			var dy = self.targetY - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist > self.speed) {
				self.x += dx / dist * self.speed;
				self.y += dy / dist * self.speed;
				// Update chain segments
				var segmentSpacing = 40;
				var numSegments = Math.floor(dist / segmentSpacing);
				// Clean up old segments
				while (self.chainSegments.length > 0) {
					chainSegmentPool.recycle(self.chainSegments.pop());
				}
				// Create new segments
				for (var i = 1; i <= numSegments; i++) {
					var t = i / numSegments;
					var segX = self.startX + (self.x - self.startX) * t;
					var segY = self.startY + (self.y - self.startY) * t;
					var segment = chainSegmentPool.spawn(segX, segY);
					if (segment) {
						var angle = Math.atan2(dy, dx);
						segment.rotation = angle;
						self.chainSegments.push(segment);
					}
				}
			} else {
				if (self.extending) {
					self.extending = false;
					// Pause briefly at extension
					LK.setTimeout(function () {
						self.retract();
					}, 30);
				} else if (self.retracting) {
					self.deactivate();
				}
			}
		}
	};
	self.retract = function () {
		self.targetX = self.startX;
		self.targetY = self.startY;
		self.extending = false;
		self.retracting = true;
	};
	self.deactivate = function () {
		while (self.chainSegments.length > 0) {
			chainSegmentPool.recycle(self.chainSegments.pop());
		}
		self.visible = false;
		self.extending = false;
		self.retracting = false;
		leftFist.visible = false;
		rightFist.visible = false;
	};
	// Initialize properties
	self.chainSegments = [];
	self.speed = 15;
	return self;
});
// In the BossHealthBar class, add position setting
// Modify the BossHealthBar class
var BossHealthBar = Container.expand(function () {
	var self = Container.call(this);
	var emptyMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0x333333,
		// Dark gray for empty
		scaleX: 0 // Start with zero width
	});
	var healthMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0xff0000,
		// Red for health
		scaleX: 0 // Start with zero width
	});
	// Position settings
	self.x = 2048 / 2; // Center horizontally
	self.y = 2732 - 100; // Position from the top
	self.show = function () {
		self.visible = true;
		// Reset both meters to zero width
		healthMeter.scaleX = 0;
		if (self.currentTween) {
			self.currentTween.stop();
		}
		// First animate the empty meter
		self.currentTween = tween(emptyMeter, {
			scaleX: 1
		}, {
			duration: 800,
			easing: tween.easeOutBack,
			onFinish: function onFinish() {
				// Then animate the health meter
				self.currentTween = tween(healthMeter, {
					scaleX: 1
				}, {
					duration: 400,
					easing: tween.easeOut
				});
			}
		});
	};
	self.hide = function () {
		if (self.currentTween) {
			self.currentTween.stop();
		}
		// First shrink the health meter
		self.currentTween = tween(healthMeter, {
			scaleX: 0
		}, {
			duration: 400,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				// Then shrink the empty meter
				self.currentTween = tween(emptyMeter, {
					scaleX: 0
				}, {
					duration: 800,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.visible = false;
					}
				});
			}
		});
	};
	self.updateHealth = function (percent) {
		// Only animate the health meter, not the empty meter
		if (self.healthTween) {
			self.healthTween.stop();
		}
		self.healthTween = tween(healthMeter, {
			scaleX: percent
		}, {
			duration: 300,
			easing: tween.easeOut
		});
	};
	return self;
});
var BossText = Container.expand(function () {
	var self = Container.call(this);
	var text = self.attachAsset('bosstext', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0
	});
	self.x = 2048 / 2; // Center horizontally
	self.y = 2732 / 2; // Center vertically
	self.flashCount = 0;
	self.maxFlashes = 3;
	self.flash = function () {
		self.flashCount = 0;
		self.doFlash();
	};
	self.doFlash = function () {
		if (self.flashCount >= self.maxFlashes) {
			text.alpha = 0;
			return;
		}
		if (self.currentTween) {
			self.currentTween.stop();
		}
		LK.getSound('alert').play();
		// Fade in
		self.currentTween = tween(text, {
			alpha: 1,
			scaleX: 1.2,
			scaleY: 1.2
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Hold
				LK.setTimeout(function () {
					// Fade out
					self.currentTween = tween(text, {
						alpha: 0,
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 500,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.flashCount++;
							// Wait before next flash
							LK.setTimeout(function () {
								self.doFlash();
							}, 20);
						}
					});
				}, 40);
			}
		});
	};
	return self;
});
var ChainSegment = Container.expand(function () {
	var self = Container.call(this);
	var link = self.attachAsset('fistlink', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y, rotation) {
		self.x = x;
		self.y = y;
		self.rotation = rotation;
		self.visible = true;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var Cloud = Container.expand(function () {
	var self = Container.call(this);
	var cloud = self.attachAsset('cloudShape', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y, scale, alpha) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.speedY = 1 + Math.random() * 2;
		self.speedX = (Math.random() - 0.5) * 1.5;
		self.targetY = self.horizonY;
		cloud.scaleX = scale;
		cloud.scaleY = scale * 0.8;
		cloud.alpha = alpha || 0.8;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var DefeatParticle = Container.expand(function () {
	var self = Container.call(this);
	var particle = self.attachAsset('particle', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.15,
		scaleY: 0.15
	});
	self.activate = function (x, y, tint) {
		self.x = x + (Math.random() * 40 - 20); // Wider initial spread
		self.y = y + (Math.random() * 40 - 20); // Wider initial spread
		self.visible = true;
		self.age = 0;
		self.lifespan = 225; // Tripled lifespan for longer visual impact 
		// More dramatic explosion velocities
		var angle = Math.PI * 2 * Math.random();
		var speed = 15 + Math.random() * 25; // Adjusted speed for more variance
		self.vx = Math.cos(angle) * speed;
		self.vy = Math.sin(angle) * speed;
		self.rotation = Math.random() * Math.PI * 2;
		particle.alpha = 1;
		// Larger, more varied particle sizes
		var scaleVariance = 0.3 + Math.random() * 0.6; // Increased variance for scale
		particle.scaleX = scaleVariance;
		particle.scaleY = scaleVariance;
		// Apply tint if provided
		if (tint !== undefined) {
			particle.tint = tint;
		} else {
			particle.tint = 0xffffff; // Default white
		}
	};
	self.update = function () {
		// Check bounds first
		if (self.y < -50 || self.y > 2732 || self.x < -50 || self.x > 2048) {
			defeatParticlePool.recycle(self);
			return;
		}
		self.x += self.vx;
		self.y += self.vy;
		self.age++;
		// Keep strong deceleration
		self.vx *= 0.87;
		self.vy *= 0.87;
		var lifePercent = self.age / self.lifespan;
		// Fade out curve
		particle.alpha = Math.max(0, 1 - lifePercent * 1.7);
		// More dramatic shrink effect as particles fade
		var scale = (0.5 - 0.3 * lifePercent) * (1 - lifePercent * 0.5);
		particle.scaleX = scale;
		particle.scaleY = scale;
		if (lifePercent >= 1) {
			defeatParticlePool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
		// Reset tint when deactivated
		particle.tint = 0xffffff;
	};
	return self;
});
var DragonHead = Container.expand(function () {
	var self = Container.call(this);
	// Dragon sprites
	var body = self.attachAsset('dragonBody', {
		anchorX: 0.5,
		anchorY: 0.7,
		scaleX: 2,
		scaleY: 2
	});
	var head = self.attachAsset('dragonHead', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2
	});
	var headOpen = self.attachAsset('dragonHeadOpen', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	});
	var lookLeft = self.attachAsset('dragonLook', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: -2,
		// Mirror for left direction
		scaleY: 2,
		alpha: 0
	});
	var lookRight = self.attachAsset('dragonLook', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	});
	var lookLeftOpen = self.attachAsset('dragonLookOpen', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: -2,
		// Mirror for left direction
		scaleY: 2,
		alpha: 0
	});
	var lookRightOpen = self.attachAsset('dragonLookOpen', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	});
	self.stateBuffer = [];
	self.bufferSize = 10; // Adjust 3-5 frames for balance between stability and responsiveness
	self.currentState = 'forward';
	// Add smoothing properties
	self.mouthOpenness = 0; // Track mouth state from 0 (closed) to 1 (open)
	self.mouthSmoothingSpeed = 0.2; // Adjust this value to change transition speed
	self.currentScale = 2; // Starting scale
	var horizontalSpeed = 0;
	self.invulnerableTime = 0;
	self.invulnerableDuration = 30;
	// Position tracking variables
	var targetX = 2048 / 2;
	var targetY = 2732 * 0.2;
	var smoothingFactor = 0.12;
	var prevX = null;
	var prevY = null;
	// Rotation variables
	var targetTilt = 0;
	var tiltSmoothingFactor = 0.11;
	var tiltScaleFactor = 0.09;
	// Scale tracking
	var scaleHistory = new Array(5).fill(2); // Start with default scale of 2
	var scaleIndex = 0;
	self.update = function () {
		// Add in self.update function
		if (self.invulnerableTime > 0) {
			self.invulnerableTime--;
		}
		// Position tracking
		if (facekit.noseTip) {
			targetX = facekit.noseTip.x;
			targetY = facekit.noseTip.y - 800;
			// Initialize previous positions if not set
			if (prevX === null) {
				prevX = targetX;
				prevY = targetY;
			}
			// Weighted average between previous and target position
			var newX = prevX * (1 - smoothingFactor) + targetX * smoothingFactor;
			var newY = prevY * (1 - smoothingFactor) + targetY * smoothingFactor;
			self.x = newX;
			if (newY > dragonShadow.y - 100) {
				// -100 for visual offset so dragon stays above shadow
				newY = dragonShadow.y - 100;
			}
			self.y = newY;
			if (prevX !== null) {
				horizontalSpeed = Math.abs(self.x - prevX);
			}
			self.currentShakeSpeed = horizontalSpeed;
			// Update previous positions
			prevX = newX;
			prevY = newY;
		}
		// Rotation tracking - CORRECTED VERSION
		if (facekit.leftEye && facekit.rightEye) {
			targetTilt = calculateFaceTilt() * tiltScaleFactor;
			// Limit rotation to Β±15 degrees - DON'T convert to radians here
			targetTilt = Math.max(-15, Math.min(15, targetTilt));
			self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor;
		}
		if (facekit.leftEye && facekit.rightEye && facekit.noseTip) {
			// Calculate face direction
			var faceCenter = (facekit.leftEye.x + facekit.rightEye.x) / 2;
			var noseDiff = facekit.noseTip.x - faceCenter;
			var eyeYDiff = facekit.rightEye.y - facekit.leftEye.y;
			var newState = 'forward';
			if (noseDiff < -120 && Math.abs(eyeYDiff) < 30 || eyeYDiff > 50) {
				newState = 'left';
			} else if (noseDiff > 120 && Math.abs(eyeYDiff) < 30 || eyeYDiff < -50) {
				newState = 'right';
			}
			// Add to buffer
			self.stateBuffer.push(newState);
			if (self.stateBuffer.length > self.bufferSize) {
				self.stateBuffer.shift();
			}
			// Only change state if buffer is unanimous
			if (self.stateBuffer.length === self.bufferSize) {
				var unanimous = self.stateBuffer.every(function (state) {
					return state === self.stateBuffer[0];
				});
				if (unanimous) {
					self.currentState = self.stateBuffer[0];
				}
			}
			// Reset visibilities based on current state
			lookLeft.alpha = 0;
			lookRight.alpha = 0;
			lookLeftOpen.alpha = 0;
			lookRightOpen.alpha = 0;
			head.alpha = 0;
			headOpen.alpha = 0;
			if (self.currentState === 'forward') {
				if (facekit.mouthOpen) {
					headOpen.alpha = 1;
				} else {
					head.alpha = 1;
				}
			} else if (self.currentState === 'left') {
				if (facekit.mouthOpen) {
					lookLeftOpen.alpha = 1;
				} else {
					lookLeft.alpha = 1;
				}
			} else if (self.currentState === 'right') {
				if (facekit.mouthOpen) {
					lookRightOpen.alpha = 1;
				} else {
					lookRight.alpha = 1;
				}
			}
		}
		// Scale adjustment based on face size
		if (facekit.leftEye && facekit.rightEye) {
			var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x);
			var newScale = eyeDistance / 250; // Adjusted divisor for dragon head
			// Update rolling average
			scaleHistory[scaleIndex] = newScale;
			scaleIndex = (scaleIndex + 1) % scaleHistory.length;
			// Calculate average scale
			var avgScale = scaleHistory.reduce(function (a, b) {
				return a + b;
			}, 0) / scaleHistory.length;
			// Apply with gentle smoothing (limited range)
			var targetScale = Math.max(1.5, Math.min(2.5, avgScale));
			head.scaleX = head.scaleX * 0.85 + targetScale * 0.15;
			self.currentScale = head.scaleX; // Track the current scale
			head.scaleY = head.scaleY * 0.85 + targetScale * 0.15;
			headOpen.scaleX = headOpen.scaleX * 0.85 + targetScale * 0.15;
			headOpen.scaleY = headOpen.scaleY * 0.85 + targetScale * 0.15;
			body.scaleX = body.scaleX * 0.85 + targetScale * 0.15;
			body.scaleY = body.scaleY * 0.85 + targetScale * 0.15;
			lookLeft.scaleX = lookLeft.scaleX * 0.85 - targetScale * 0.15;
			lookLeft.scaleY = lookLeft.scaleY * 0.85 + targetScale * 0.15;
			lookRight.scaleX = lookRight.scaleX * 0.85 + targetScale * 0.15;
			lookRight.scaleY = lookRight.scaleY * 0.85 + targetScale * 0.15;
			lookLeftOpen.scaleX = lookLeftOpen.scaleX * 0.85 - targetScale * 0.15;
			lookLeftOpen.scaleY = lookLeftOpen.scaleY * 0.85 + targetScale * 0.15;
			lookRightOpen.scaleX = lookRightOpen.scaleX * 0.85 + targetScale * 0.15;
			lookRightOpen.scaleY = lookRightOpen.scaleY * 0.85 + targetScale * 0.15;
		}
	};
	function calculateFaceTilt() {
		if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) {
			// Calculate midpoint between eyes
			var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2;
			var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2;
			// Calculate angle between eye midpoint and mouth, negated to fix direction
			var dx = facekit.mouthCenter.x - eyeMidX;
			var dy = facekit.mouthCenter.y - eyeMidY;
			var angle = -(Math.atan2(dx, dy) * (180 / Math.PI));
			// Reduced angle impact
			return Math.max(-15, Math.min(15, angle * 0.15));
		}
		return 0; // Default to straight when face points aren't available
	}
	self.flashDamage = function (damageAmount) {
		// Show game over after effect
		if (self.invulnerableTime > 0) {
			return;
		}
		// Set invulnerability
		self.invulnerableTime = self.invulnerableDuration;
		// Flash effect
		var dragonSprites = [body];
		if (head && head.alpha > 0) {
			dragonSprites.push(head);
		}
		if (headOpen && headOpen.alpha > 0) {
			dragonSprites.push(headOpen);
		}
		if (lookLeft && lookLeft.alpha > 0) {
			dragonSprites.push(lookLeft);
		}
		if (lookRight && lookRight.alpha > 0) {
			dragonSprites.push(lookRight);
		}
		if (lookLeftOpen && lookLeftOpen.alpha > 0) {
			dragonSprites.push(lookLeftOpen);
		}
		if (lookRightOpen && lookRightOpen.alpha > 0) {
			dragonSprites.push(lookRightOpen);
		}
		dragonSprites.forEach(function (sprite) {
			sprite.tint = 0xFF0000;
			LK.setTimeout(function () {
				sprite.tint = 0xFFFFFF;
			}, 10);
		});
		// Apply damage and check for death
		dragon.health -= damageAmount;
		dragonHealthBar.updateHealth(dragon.health / 100);
		if (dragon.health <= 0 && gameActive) {
			LK.getSound('dragonScream').play();
			gameActive = false;
			// Explode dragon
			for (var i = 0; i < 60; i++) {
				defeatParticlePool.spawn(dragon.x, dragon.y, 0xff0000);
			}
			// Hide dragon
			dragon.visible = false;
			// Show game over after effect
			LK.setTimeout(function () {
				LK.showGameOver();
			}, 2000);
		}
	};
	return self;
});
var DragonHealthBar = Container.expand(function () {
	var self = Container.call(this);
	var emptyMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0x333333,
		scaleX: 1
	});
	var healthMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0x00ff00,
		scaleX: 1
	});
	// Position settings
	self.x = 2048 / 2;
	self.y = 220; // 100px from top + some padding
	self.updateHealth = function (percent) {
		if (self.healthTween) {
			self.healthTween.stop();
		}
		self.healthTween = tween(healthMeter, {
			scaleX: percent
		}, {
			duration: 300,
			easing: tween.easeOut
		});
	};
	return self;
});
var DragonShadow = Container.expand(function () {
	var self = Container.call(this);
	var shadow = self.attachAsset('dragonShadow', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.5,
		scaleX: 1,
		scaleY: 0.3
	});
	self.x = 2048 / 2; // Match dragon's initial x
	self.y = 2732 * 0.6; // Positioned below dragon
	var positionSmoothing = 0.12;
	var scaleSmoothing = 0.08;
	self.update = function (dragonX, dragonY, dragonScale) {
		if (dragonX !== undefined && dragonY !== undefined && dragonScale !== undefined) {
			// X position follow
			self.x += (dragonX - self.x) * positionSmoothing;
			// Y position based on scale (Z-depth)
			var baseY = 2732 * 0.6;
			var scaleOffset = (dragonScale - 1) * 300;
			var targetY = baseY + scaleOffset;
			self.y += (targetY - self.y) * positionSmoothing;
			// Scale calculation based on dragon's Y position
			var heightRatio = dragonY / 2732;
			var scaleMultiplier = 0.2 + heightRatio * 1.5;
			// Add Y-position based size adjustment (0-20% increase based on Y position)
			var yPositionScale = 1 + self.y / 2732 * 0.2;
			var targetScaleX = scaleMultiplier * yPositionScale;
			var targetScaleY = scaleMultiplier * 0.3 * yPositionScale;
			var shadow = self.getChildAt(0); // Get the shadow sprite
			shadow.scaleX += (targetScaleX - shadow.scaleX) * scaleSmoothing;
			shadow.scaleY += (targetScaleY - shadow.scaleY) * scaleSmoothing;
			shadow.alpha = 0.3 + heightRatio * 0.2;
		}
	};
	return self;
});
var DustParticle = Container.expand(function () {
	var self = Container.call(this);
	var dust = self.attachAsset('dust', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y) {
		self.x = x + (Math.random() * 20 - 10);
		self.y = y;
		self.visible = true;
		self.age = 0;
		self.lifespan = 60; // Fixed lifespan for consistency
		dust.alpha = 0.9;
		// Vertical velocity - move upward
		self.vy = -1.5; // Faster upward movement
		self.vx = (Math.random() - 0.5) * 5; // Slightly more horizontal movement
		// Add rotation for visual interest
		self.rotation = Math.random() * Math.PI * 2;
	};
	self.update = function () {
		// Update position
		self.x += self.vx;
		self.y += self.vy;
		self.age++;
		// Calculate life percentage
		var lifePercent = self.age / self.lifespan;
		// Fade out
		dust.alpha = 0.8 * (1 - lifePercent);
		// Grow slightly as it rises
		var scale = 1 + lifePercent * 0.2; // Linear growth from 0.2 to 0.3
		dust.scaleX = scale;
		dust.scaleY = scale;
		// Recycle when lifetime is over
		if (lifePercent >= 1) {
			dustParticlePool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// States
	var RUNNING = 'running';
	var LEAPING = 'leaping';
	var ATTACHED = 'attached';
	var FALLING = 'falling';
	// Running enemy sprites
	var runSprite = self.attachAsset('enemy1', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 1
	});
	var runSpriteMirrored = self.attachAsset('enemy1', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: -1,
		alpha: 0
	});
	// Properties
	self.health = 1;
	self.rotationSpeed = 0;
	self.animTick = 0;
	self.animRate = 30;
	self.pulseRate = self.animRate * 2;
	self.state = RUNNING;
	self.leapSpeed = 9;
	self.targetX = 0;
	self.targetY = 0;
	self.hasExploded = false; // Add this flag
	self.activate = function (x, y) {
		self.visible = true;
		self.x = x;
		self.y = y;
		self.state = RUNNING;
		self.rotation = 0; // Reset rotation
		self.health = 1;
		self.rotationSpeed = 0;
		self.fallSpeed = 0;
		self.acceleration = 0;
		self.leapDuration = 0;
		self.shadow = enemyShadowPool.spawn(x, y, self.scaleX);
		self.isPulsedOut = false;
		self.hasExploded = false; // Reset explosion flag
		// If there was a tween running, stop it
		if (self.currentTween) {
			self.currentTween.stop();
			self.currentTween = null;
		}
		// Reset animation state
		self.animTick = 0;
		runSprite.alpha = 1;
		runSpriteMirrored.alpha = 0;
		// Set initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		var scale = 0.5 + progress;
		self.scaleX = scale;
		self.scaleY = scale;
	};
	function checkLeapDistance() {
		// Get distance on Y-axis only
		var dy = Math.abs(self.y - dragonShadow.y);
		// Get relative scales as depth indicators
		var enemyDepth = self.scaleX;
		var shadowDepth = dragonShadow.scaleX;
		// Leap when on same Y-plane regardless of X position
		var depthDiff = Math.abs(enemyDepth - shadowDepth);
		var yThreshold = 10; // Close on the Y-axis
		// If the enemy is on screen and at the right Y position
		if (dy < yThreshold && depthDiff < 0.3 && self.x > 0 && self.x < 2048) {
			startLeap();
			return true;
		}
		return false;
	}
	function startLeap() {
		self.state = LEAPING;
		LK.getSound('orcShout').play();
		// Store where the dragon was when leap started
		self.leapTargetX = dragon.x;
		self.leapTargetY = dragon.y;
		var dx = self.leapTargetX - self.x;
		var dy = self.leapTargetY - self.y;
		self.initialLeapDistance = Math.sqrt(dx * dx + dy * dy);
		self.initialScale = self.scaleX;
		self.isPulsedOut = false;
		runSprite.alpha = 1;
		runSpriteMirrored.alpha = 0;
	}
	self.update = function () {
		if (!self.visible) {
			return;
		}
		switch (self.state) {
			case RUNNING:
				// Existing running code
				var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
				var speed = (flyingBackground.scrollSpeed * 0.05 + flyingBackground.scrollSpeed * (progress * 2.5)) * 0.8;
				self.y -= speed;
				// Update scale based on distance
				var scale = 0.5 + progress;
				self.scaleX = scale;
				self.scaleY = scale;
				// Running animation
				self.animTick++;
				if (self.animTick >= self.animRate) {
					self.animTick = 0;
					runSprite.alpha = runSprite.alpha === 0 ? 1 : 0;
					runSpriteMirrored.alpha = runSpriteMirrored.alpha === 0 ? 1 : 0;
				}
				// In the Enemy class RUNNING state section, replace the dust spawning code with:
				if (LK.ticks % 10 === 0 && self.y < 2732) {
					// More frequent spawning (every 10 ticks)
					var footY = self.y + 50 * self.scaleY;
					dustParticlePool.spawn(self.x, footY);
				}
				// Check for leap
				checkLeapDistance();
				break;
			case LEAPING:
				// Calculate current distance to dragon (not original leap target)
				var dragonDx = dragon.x - self.x;
				var dragonDy = dragon.y - self.y;
				var dragonDistance = Math.sqrt(dragonDx * dragonDx + dragonDy * dragonDy);
				// If we're very close to dragon, attach
				if (dragonDistance < 50) {
					self.state = ATTACHED;
					break;
				}
				// Continue homing leap motion
				if (dragonDistance > 10) {
					var dirX = dragonDx / dragonDistance;
					var dirY = dragonDy / dragonDistance;
					var speedMultiplier = Math.min(1.5, dragonDistance / 100);
					self.x += dirX * self.leapSpeed * speedMultiplier;
					self.y += dirY * self.leapSpeed * speedMultiplier;
					self.scaleX = self.initialScale * 0.75;
					self.scaleY = self.initialScale * 0.75;
				}
				// Add safety timeout to prevent infinite leaps
				self.leapDuration = (self.leapDuration || 0) + 1;
				if (self.leapDuration > 100) {
					self.state = FALLING;
					self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
					self.fallSpeed = 2;
					self.acceleration = 0.2;
				}
				break;
			case ATTACHED:
				// Stick to dragon position
				self.x = dragon.x;
				self.y = dragon.y;
				// Check for shake-off
				if (dragon.currentShakeSpeed > 30) {
					// Threshold for shake-off
					self.state = FALLING;
					self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
					self.fallSpeed = 2;
					self.acceleration = 0.2;
					break;
				}
				// Pulsing animation
				self.animTick++;
				if (self.animTick >= self.pulseRate) {
					self.animTick = 0;
					// Pulse between 0.7 and 0.8 scale
					tween(self, {
						scaleX: self.initialScale * (self.isPulsedOut ? 0.7 : 0.8),
						scaleY: self.initialScale * (self.isPulsedOut ? 0.7 : 0.8)
					}, {
						duration: 200,
						easing: tween.easeOut
					});
					self.isPulsedOut = !self.isPulsedOut;
					dragon.flashDamage(2);
				}
				break;
			case FALLING:
				self.rotation += self.rotationSpeed;
				self.fallSpeed += self.acceleration;
				self.y += self.fallSpeed;
				// Check for shadow collision with explosion flag
				if (self.y >= dragonShadow.y && !self.hasExploded) {
					self.hasExploded = true;
					// Create MUCH bigger explosion with red tint
					for (var i = 0; i < 20; i++) {
						defeatParticlePool.spawn(self.x, self.y, 0xff0000); // Red tint (0xff0000)
					}
					score += 50;
					scorePopupPool.spawn(self.x, self.y, 50);
					scoreTxt.setText(score);
					updateScoreMeter(score);
					LK.setScore(score);
					LK.getSound('enemyDefeat').play();
					trySpawnHealthPowerup(self.x, self.y);
					enemyPool.recycle(self);
				}
				break;
		}
		if (self.shadow) {
			self.shadow.update(self);
		}
	};
	self.hit = function () {
		self.health--;
		if (self.health <= 0) {
			if (self.state !== FALLING) {
				self.state = FALLING;
				self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
				self.fallSpeed = 2;
				self.acceleration = 0.2;
				return true;
			}
		}
		return false;
	};
	self.deactivate = function () {
		self.visible = false;
		runSprite.alpha = 1;
		runSpriteMirrored.alpha = 0;
		if (self.shadow) {
			enemyShadowPool.recycle(self.shadow);
			self.shadow = null;
		}
	};
	return self;
});
var EnemyArrow = Container.expand(function () {
	var self = Container.call(this);
	var arrow = self.attachAsset('enemyArrow', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.5,
		scaleY: 0.5
	});
	self.speed = 8;
	self.update = function () {
		if (!self.active) {
			return;
		}
		self.x += self.vx;
		self.y += self.vy;
		// Point arrow in direction of travel
		self.rotation = Math.atan2(self.vy, self.vx) + Math.PI / 2;
		if (self.y < 0 || self.y > 2732 || self.x < 0 || self.x > 2048) {
			enemyArrowPool.recycle(self);
		}
	};
	self.activate = function (x, y, targetX, targetY) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.active = true;
		// Calculate direction to target
		var dx = targetX - x;
		var dy = targetY - y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		self.vx = dx / dist * self.speed;
		self.vy = dy / dist * self.speed;
	};
	self.deactivate = function () {
		self.visible = false;
		self.active = false;
	};
	return self;
});
var EnemyShadow = Container.expand(function () {
	var self = Container.call(this);
	var shadow = self.attachAsset('enemyShadow', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.3,
		scaleX: 1,
		scaleY: 0.3
	});
	// In the EnemyShadow class, update method (around line 1018)
	self.update = function (enemy) {
		if (!enemy || !enemy.visible || enemy.hasExploded) {
			self.visible = false;
			return;
		}
		self.visible = true;
		// Always follow enemy's X position
		self.x = enemy.x;
		// For running enemies, shadow is slightly below them
		if (enemy.state === 'running') {
			self.y = enemy.y + 200; // Shadow slightly below enemy
		}
		// For leaping enemies, shadow moves to dragon shadow position
		else if (enemy.state === 'leaping') {
			self.y = dragonShadow.y + 50; // Position just below dragon shadow
		}
		// For attached enemies, follow dragon shadow
		else if (enemy.state === 'attached') {
			self.y = dragonShadow.y + 50; // Keep following dragon shadow
		}
		// For falling enemies, shadow holds last position
		else if (enemy.state === 'falling') {
			// Y position stays the same
		}
		// Special case for EnemyTwo type
		else if (enemy.type === 2) {
			self.y = enemy.y + 600; // Position higher for enemy type 2
		}
		// Scale shadow based on enemy's scale
		shadow.scaleX = enemy.scaleX * 1.2;
		shadow.scaleY = enemy.scaleX * 0.3;
	};
	self.activate = function (x, y, enemyScale) {
		self.x = x;
		self.y = y + 200; // Initially position shadow slightly below enemy
		self.visible = true;
		shadow.scaleX = (enemyScale || 1) * 1.2;
		shadow.scaleY = (enemyScale || 1) * 0.3;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var EnemyThree = Container.expand(function () {
	var self = Container.call(this);
	// States
	var GROUNDED = 'grounded';
	var FLYING = 'flying';
	// Main sprite
	var sprite = self.attachAsset('enemy3', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Jet flames
	var leftFlame = new JetFlame();
	var rightFlame = new JetFlame();
	self.addChild(leftFlame);
	self.addChild(rightFlame);
	// Properties
	self.health = 1;
	self.state = GROUNDED;
	self.hasExploded = false;
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.stateDuration = 0;
		self.visible = true;
		self.state = GROUNDED;
		self.health = 1;
		self.hasExploded = false;
		// Add this line to create the shadow
		self.shadow = enemyShadowPool.spawn(x, y, self.scaleX);
		// Position flames at percentage-based positions
		var flameY = sprite.height * 0.45;
		var flameX = sprite.width * 0.15;
		leftFlame.x = -flameX;
		leftFlame.y = flameY;
		rightFlame.x = flameX;
		rightFlame.y = flameY;
		// Initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		var scale = 0.5 + progress;
		self.scaleX = scale;
		self.scaleY = scale;
	};
	self.startFlying = function () {
		self.state = FLYING;
		// Calculate rough trajectory toward dragon
		var dx = dragon.x - self.x;
		var dy = dragon.y - self.y;
		var angle = Math.atan2(dy, dx);
		// Add intentional inaccuracy (they're bad at this)
		angle += (Math.random() - 0.5) * 0.5; // Β±0.25 radians of error
		// Set velocities
		var speed = 8;
		self.vx = Math.cos(angle) * speed;
		self.vy = Math.sin(angle) * speed;
		// Start jet flames
		leftFlame.startPulse();
		rightFlame.startPulse();
	};
	self.update = function () {
		if (!self.visible) {
			return;
		}
		if (self.state === FLYING) {
			self.stateDuration++;
		}
		switch (self.state) {
			case GROUNDED:
				// Move with background scroll
				var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
				var speed = (flyingBackground.scrollSpeed * 0.05 + flyingBackground.scrollSpeed * (progress * 2.5)) * 0.8;
				self.y -= speed;
				// Scale with distance
				var scale = 0.5 + progress;
				self.scaleX = scale;
				self.scaleY = scale;
				// Check for ignition trigger
				if (self.y <= dragonShadow.y + 50) {
					self.startFlying();
				}
				break;
			case FLYING:
				if (self.stateDuration === 1) {
					LK.getSound('jetPack').play(); // Play jetPack sound effect
				}
				// Update position
				self.x += self.vx;
				self.y += self.vy;
				// Create jet particles
				if (Math.random() < 0.3) {
					var particle = particlePool.spawn(self.x + leftFlame.x, self.y + leftFlame.y);
					if (particle) {
						particle.vy = Math.abs(particle.vy); // Force downward
					}
					particle = particlePool.spawn(self.x + rightFlame.x, self.y + rightFlame.y);
					if (particle) {
						particle.vy = Math.abs(particle.vy); // Force downward
					}
				}
				// Check bounds
				if (self.y < -100 || self.y > 2732 || self.x < -100 || self.x > 2148) {
					enemyThreePool.recycle(self);
				}
				break;
		}
		if (self.shadow) {
			self.shadow.update(self);
		}
		// In EnemyThree class, modify the part of the update method that handles the shadow:
		// Update shadow position
		if (self.shadow) {
			if (self.state === GROUNDED) {
				self.shadow.y = self.y + 200; // Shadow slightly below enemy
				self.shadow.x = self.x;
			} else if (self.state === FLYING) {
				self.shadow.y = dragonShadow.y + 50;
				self.shadow.x = self.x;
				// Don't update Y position to let it stay where it was
			}
			// Scale shadow based on enemy's scale
			var shadowSprite = self.shadow.getChildAt(0);
			shadowSprite.scaleX = self.scaleX * 1.2;
			shadowSprite.scaleY = self.scaleX * 0.3;
			// Update shadow alpha based on height
			var heightRatio = self.y / 2732;
			shadowSprite.alpha = 0.3 + heightRatio * 0.2;
		}
	};
	self.hit = function () {
		self.health--;
		if (self.health <= 0 && !self.hasExploded) {
			self.hasExploded = true;
			// Create explosion
			for (var i = 0; i < 20; i++) {
				defeatParticlePool.spawn(self.x, self.y, 0xff0000);
			}
			score += 25;
			scorePopupPool.spawn(self.x, self.y, 25);
			scoreTxt.setText(score.toString());
			updateScoreMeter(score);
			LK.setScore(score);
			LK.getSound('enemyDefeat').play();
			trySpawnHealthPowerup(self.x, self.y);
			enemyThreePool.recycle(self);
			return true;
		}
		return false;
	};
	self.deactivate = function () {
		self.visible = false;
		if (self.shadow) {
			enemyShadowPool.recycle(self.shadow);
			self.shadow = null;
		}
		leftFlame.deactivate();
		rightFlame.deactivate();
	};
	return self;
});
var EnemyTwo = Container.expand(function () {
	var self = Container.call(this);
	var sprite = self.attachAsset('enemy2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Properties
	self.health = 1;
	self.type = 2; // For scoring
	self.state = 'approaching'; // approaching, holding
	self.holdDistance = 800;
	self.bobOffset = 0;
	self.bobSpeed = 0.05;
	self.lastShotTime = 0;
	self.shotInterval = 2000; // 2 seconds
	self.activate = function (x, y) {
		self.visible = true;
		self.x = x;
		self.y = y;
		self.state = 'approaching';
		self.health = 1;
		self.rotation = 0;
		self.hasExploded = false; // Make sure this flag is set
		// Ensure shadow is created and stored
		if (!self.shadow) {
			self.shadow = enemyShadowPool.spawn(x, y, self.scaleX);
		}
		// Moving direction
		self.moveRight = x < 1024; // If spawned on left side, move right
		// Initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		self.scaleX = 0.5 + progress;
		self.scaleY = 0.5 + progress;
	};
	self.update = function () {
		if (!self.visible) {
			return;
		}
		switch (self.state) {
			case 'approaching':
				// Bobbing motion
				self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 50;
				// Move towards dragon
				var dx = dragon.x - self.x;
				var dy = dragon.y - self.y + self.bobOffset;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > self.holdDistance) {
					self.x += dx * 0.01; // Reduced from 0.02
					self.y += dy * 0.01; // Reduced from 0.02
					// Modified scale calculation to maintain larger size
					var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
					self.scaleX = 0.7 + progress * 0.5; // Modified from 0.5 + progress
					self.scaleY = 0.7 + progress * 0.5; // Modified from 0.5 + progress
				} else {
					self.state = 'holding';
				}
				break;
			case 'holding':
				// Maintain position relative to dragon
				var dx = dragon.x - self.x;
				var targetX = self.x + dx * 0.01;
				// Keep on screen
				targetX = Math.max(100, Math.min(1948, targetX));
				self.x = targetX;
				// Stay below dragon with offset
				var targetY = dragon.y + 800; // Stay 200 pixels below dragon
				var currentY = self.y - self.bobOffset; // Remove bobbing to get true position
				self.y = currentY + (targetY - currentY) * 0.1; // Smooth movement to target
				// Apply bobbing to final position
				self.y += self.bobOffset;
				// Shoot at intervals
				var now = Date.now();
				if (now - self.lastShotTime >= self.shotInterval) {
					self.shoot();
					self.lastShotTime = now;
				}
				break;
			case 'falling':
				self.rotation += self.rotationSpeed;
				self.fallSpeed += self.acceleration;
				self.y += self.fallSpeed;
				// Check for ground collision
				if (self.shadow && self.y >= self.shadow.y && !self.hasExploded) {
					self.hasExploded = true;
					for (var i = 0; i < 20; i++) {
						defeatParticlePool.spawn(self.x, self.y, 0xff0000);
					}
					score += 75;
					scorePopupPool.spawn(self.x, self.y, 75);
					scoreTxt.setText(score);
					updateScoreMeter(score);
					LK.setScore(score);
					LK.getSound('enemyDefeat').play();
					trySpawnHealthPowerup(self.x, self.y);
					enemyTwoPool.recycle(self);
				}
				break;
		}
		if (self.shadow) {
			self.shadow.update(self);
		}
	};
	self.shoot = function () {
		var arrow = enemyArrowPool.spawn(self.x, self.y);
		if (arrow) {
			arrow.activate(self.x, self.y, dragon.x, dragon.y);
			LK.getSound('arrow').play(); // Play arrow sound effect
		}
	};
	self.hit = function () {
		self.health--;
		if (self.health <= 0 && self.state !== 'falling') {
			// Prevent double-triggers
			if (Math.random() < 0.5) {
				// Mid-air explosion
				for (var i = 0; i < 20; i++) {
					defeatParticlePool.spawn(self.x, self.y, 0xff0000);
				}
				score += 75;
				scorePopupPool.spawn(self.x, self.y, 75);
				scoreTxt.setText(score);
				updateScoreMeter(score);
				LK.setScore(score);
				LK.getSound('enemyDefeat').play();
				trySpawnHealthPowerup(self.x, self.y);
				enemyTwoPool.recycle(self);
			} else {
				// Fall and explode
				self.state = 'falling';
				self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
				self.fallSpeed = 2;
				self.acceleration = 0.2;
			}
			return true;
		}
		return false;
	};
	self.deactivate = function () {
		self.visible = false;
		if (self.shadow) {
			enemyShadowPool.recycle(self.shadow);
			self.shadow = null;
		}
	};
	return self;
});
var FieldElement = Container.expand(function () {
	var self = Container.call(this);
	var element = self.attachAsset('fieldElement', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y, scale, alpha) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.speedY = 2 + Math.random() * 3;
		self.initialX = x;
		element.scaleX = scale;
		element.scaleY = scale * 0.8;
		element.alpha = alpha || 0.9;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var FireParticle = Container.expand(function () {
	var self = Container.call(this);
	var particle = self.attachAsset('fireParticle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		self.age++;
		// Update alpha
		var lifePercent = self.age / self.lifespan;
		particle.alpha = 1 - lifePercent;
		// Recycle if lifetime is over OR particle is off screen
		if (lifePercent >= 1 || self.y < 0 || self.y > 2732 ||
		// Screen height
		self.x < 0 || self.x > 2048) {
			// Screen width
			particlePool.recycle(self);
		}
	};
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.vx = Math.random() * 8 - 4; // Doubled velocity range
		self.vy = -(Math.random() * 4 + 2); // Make particles move upward
		self.lifespan = 45 + Math.random() * 30; // Increased lifespan
		self.age = 0;
		particle.alpha = 1;
		// Add scaling
		particle.scaleX = 0.5 + Math.random() * 0.5;
		particle.scaleY = 0.5 + Math.random() * 0.5;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
// In the Fireball class, update the properties and update method
var Fireball = Container.expand(function () {
	var self = Container.call(this);
	var fireballGraphic = self.attachAsset('fireball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10;
	self.vx = 0;
	// Add these new properties
	self.weaveDirection = 1; // Will be set to 1 or -1 on activate
	self.weaveAmplitude = 50; // Adjust this to control width of weave
	self.weaveFrequency = 0.1; // Adjust this to control speed of weave
	self.initialY = 0; // Track starting Y position
	self.update = function () {
		if (!self.active) {
			return;
		}
		// Update base position along trajectory
		self.y += self.speed;
		self.x += self.vx;
		// Add weaving motion
		var distanceTraveled = self.y - self.initialY;
		var weaveOffset = Math.sin(distanceTraveled * self.weaveFrequency) * self.weaveAmplitude * self.weaveDirection;
		self.x += weaveOffset;
		// Calculate rotation based only on base trajectory, ignoring weave
		var angle = Math.atan2(self.speed, self.vx) - Math.PI / 2;
		self.rotation = angle;
		// Create fire trail particles
		if (Math.random() < 0.3) {
			particlePool.spawn(self.x + (Math.random() * 40 - 20), self.y + 20);
		}
		// In Fireball class update method, replace the recycle check with:
		// In Fireball class update method, replace the recycle check with:
		var groundImpactY = 2732 * 0.9;
		// Make impact decision only when first crossing the threshold
		if (self.y > groundImpactY && self.lastY <= groundImpactY && !self.hasImpacted && self.x > 100 && self.x < 1948) {
			if (Math.random() < 0.5) {
				self.hasImpacted = true;
				flamePool.spawn(self.x, groundImpactY);
				scorchPool.spawn(self.x, groundImpactY);
				// Spawn more particles
				for (var i = 0; i < 15; i++) {
					// Increased from 8 to 15
					var particle = particlePool.spawn(self.x + (Math.random() * 40 - 20), groundImpactY);
					if (particle) {
						particle.vy = -(Math.random() * 6 + 3); // More upward velocity
						particle.vx = (Math.random() - 0.5) * 8; // More spread
					}
				}
				fireballPool.recycle(self);
				return;
			}
		}
		// Track last Y position
		self.lastY = self.y;
		// Only recycle if off screen
		if (self.y > 2732 || self.x < -100 || self.x > 2148) {
			fireballPool.recycle(self);
		}
	};
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.initialY = y;
		self.lastY = y;
		self.visible = true;
		self.active = true;
		self.hasImpacted = false;
		self.vx = 0;
		self.rotation = 0;
		fireballGraphic.alpha = 1;
	};
	self.deactivate = function () {
		self.visible = false;
		self.active = false;
		// Clear any references that might cause memory leaks
		self.currentTween = null;
	};
	return self;
});
var FlameEffect = Container.expand(function () {
	var self = Container.call(this);
	var flame = self.attachAsset('flame', {
		anchorX: 0.5,
		anchorY: 1.0,
		scaleX: 1,
		scaleY: 0.5
	});
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.age = 0;
		flame.scaleX = 0.75;
		flame.scaleY = 0.5;
		var initialHeight = flame.height * flame.scaleY;
		var targetScale = 2.5;
		if (self.currentTween) {
			self.currentTween.stop();
		}
		self.currentTween = tween(flame, {
			scaleY: targetScale,
			y: -(initialHeight * (targetScale - 0.5)) / 2,
			// Offset upward to compensate for scaling
			alpha: 1
		}, {
			duration: 400,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				flamePool.recycle(self);
			}
		});
	};
	self.deactivate = function () {
		self.visible = false;
		if (self.currentTween) {
			self.currentTween.stop();
			self.currentTween = null;
		}
		flame.y = 0; // Reset position
	};
	return self;
});
var FlyingBackground = Container.expand(function () {
	var self = Container.call(this);
	// Create bottom container
	self.bottomContainer = new Container();
	self.addChild(self.bottomContainer);
	// Store the horizon line
	self.horizonY = 2732 / 2;
	self.totalHeight = 2732 - self.horizonY;
	self.fieldStripes = [];
	// Create field stripes (keep this the same as original)
	var nbStripes = 30;
	var lastY = self.horizonY + 10;
	var stripe = self.bottomContainer.attachAsset('fieldStripes', {
		anchorX: 0.5,
		anchorY: 0,
		x: 2048 / 2,
		y: lastY
	});
	var progress = Math.max(0, lastY - self.horizonY) / self.totalHeight;
	stripe.height = 1 + 400 * progress;
	self.fieldStripes.push({
		sprite: stripe,
		progress: progress
	});
	for (var i = 1; i < nbStripes; i++) {
		var spacing = 400 * (lastY - self.horizonY) / self.totalHeight;
		var y = lastY + spacing;
		var stripe = self.bottomContainer.attachAsset('fieldStripes', {
			anchorX: 0.5,
			anchorY: 0,
			x: 2048 / 2,
			y: y
		});
		var progress = Math.max(0, y - self.horizonY) / self.totalHeight;
		stripe.height = 1 + 400 * progress;
		self.fieldStripes.push({
			sprite: stripe,
			progress: progress
		});
		lastY = y;
	}
	// Create top container
	self.topContainer = new Container();
	self.addChild(self.topContainer);
	// Create sky background in top container
	var sky = self.topContainer.attachAsset('skyBackground', {
		anchorX: 0.5,
		anchorY: 1.0,
		x: 2048 / 2,
		y: self.horizonY + 10
	});
	// Field scroll speed
	self.scrollSpeed = 4;
	// Create object pools
	self.cloudPool = new ObjectPool(Cloud, 15);
	self.fieldElementPool = new ObjectPool(FieldElement, 20);
	// Add pools to containers
	self.topContainer.addChild(self.cloudPool);
	self.bottomContainer.addChild(self.fieldElementPool);
	// Initialize clouds
	for (var i = 0; i < 8; i++) {
		// Place clouds above the screen
		var startY = -600 - Math.random() * 600;
		var distanceFromHorizon = Math.abs(startY - self.horizonY);
		var startScale = 0.5 + distanceFromHorizon / 800;
		var cloud = self.cloudPool.spawn(Math.random() * 2048, startY, startScale, 0.8);
		if (cloud) {
			cloud.horizonY = self.horizonY;
		}
	}
	// Initialize field elements
	for (var j = 0; j < 12; j++) {
		var fieldStartY = self.horizonY + Math.random() * (2732 - self.horizonY);
		var fieldDistanceFromHorizon = Math.abs(fieldStartY - self.horizonY);
		var fieldStartScale = 0.5 + fieldDistanceFromHorizon / 1000;
		var fieldElement = self.fieldElementPool.spawn(Math.random() * 2048, fieldStartY, fieldStartScale, 0.9);
		if (fieldElement) {
			fieldElement.horizonY = self.horizonY;
		}
	}
	self.update = function () {
		// Update field stripes (keep original code)
		for (var i = 0; i < self.fieldStripes.length; i++) {
			var stripe = self.fieldStripes[i];
			stripe.progress = Math.max(0, stripe.sprite.y - self.horizonY) / self.totalHeight;
			var tempSpeed = self.scrollSpeed * 0.05 + self.scrollSpeed * (stripe.progress * 3);
			stripe.sprite.y -= tempSpeed;
		}
		// Sort stripes by Y position
		self.fieldStripes.sort(function (a, b) {
			return a.sprite.y - b.sprite.y;
		});
		// Reset stripes that moved above horizon
		for (var i = 0; i < self.fieldStripes.length; i++) {
			if (self.fieldStripes[i].sprite.y < self.horizonY) {
				var lowestStripe = self.fieldStripes[self.fieldStripes.length - 1];
				self.fieldStripes[i].sprite.y = lowestStripe.sprite.y + 400 * (lowestStripe.sprite.y - self.horizonY) / self.totalHeight;
				self.fieldStripes[i].progress = Math.max(0, self.fieldStripes[i].sprite.y - self.horizonY) / self.totalHeight;
			}
		}
		// Re-sort after repositioning
		self.fieldStripes.sort(function (a, b) {
			return a.sprite.y - b.sprite.y;
		});
		// Adjust stripe heights
		for (var i = 0; i < self.fieldStripes.length - 1; i++) {
			var currentStripe = self.fieldStripes[i];
			var nextStripe = self.fieldStripes[i + 1];
			currentStripe.sprite.height = nextStripe.sprite.y - currentStripe.sprite.y;
		}
		// Handle last stripe
		var lastStripe = self.fieldStripes[self.fieldStripes.length - 1];
		lastStripe.sprite.height = Math.max(1 + 400 * lastStripe.progress, self.horizonY + self.totalHeight - lastStripe.sprite.y + 100);
		// Update clouds and field elements
		updateCloudPool();
		updateFieldElementPool();
	};
	function updateCloudPool() {
		var activeObjects = self.cloudPool.getActiveObjects();
		for (var i = 0; i < activeObjects.length; i++) {
			var cloud = activeObjects[i];
			// Move cloud toward horizon
			cloud.y += cloud.speedY;
			cloud.x += cloud.speedX;
			// Get the cloud's sprite
			var sprite = cloud.getChildAt(0);
			// Calculate scale based on distance from horizon
			var distanceFactor = Math.max(0.05, (cloud.y - self.horizonY) / -500);
			sprite.scaleX = distanceFactor;
			sprite.scaleY = distanceFactor * 0.8;
			// Adjust alpha for fade effect near horizon
			sprite.alpha = Math.min(0.9, distanceFactor);
			// Reset cloud if it reaches horizon or gets too small
			if (cloud.y >= self.horizonY - 10 || sprite.scaleX < 0.1) {
				// Recycle and spawn new cloud above screen
				self.cloudPool.recycle(cloud);
				var newCloud = self.cloudPool.spawn(Math.random() * 2048,
				// Random x position
				-600 - Math.random() * 400,
				// Above screen
				0.5 + 600 / 800,
				// Scale based on distance
				0.8);
				if (newCloud) {
					newCloud.horizonY = self.horizonY;
				}
			}
		}
	}
	function updateFieldElementPool() {
		var activeObjects = self.fieldElementPool.getActiveObjects();
		for (var j = 0; j < activeObjects.length; j++) {
			var element = activeObjects[j];
			// Calculate progress based on distance from horizon
			var progress = Math.max(0, element.y - self.horizonY) / self.totalHeight;
			// Calculate speed using same logic as stripes
			var tempSpeed = self.scrollSpeed * 0.05 + self.scrollSpeed * (progress * 3);
			// Move element toward horizon
			element.y -= tempSpeed;
			// Get the element's sprite
			var sprite = element.getChildAt(0);
			// Calculate scale based on distance from horizon
			var fieldDistanceFactor = Math.max(0.05, (element.y - self.horizonY) / 300);
			sprite.scaleX = fieldDistanceFactor * 1.2;
			sprite.scaleY = fieldDistanceFactor * 1.2;
			// Adjust alpha for fade effect
			//sprite.alpha = Math.min(0.9, fieldDistanceFactor);
			// Reset element if it reaches horizon
			if (element.y <= self.horizonY + 10 || sprite.scaleX < 0.1) {
				// Recycle and spawn new element
				self.fieldElementPool.recycle(element);
				// Calculate position for new element
				var section = Math.floor(Math.random() * 8);
				var sectionWidth = 2048 / 8;
				var newX = section * sectionWidth + Math.random() * sectionWidth;
				var newY = 2732 + Math.random() * 600;
				var newScale = (newY - self.horizonY) / 300;
				var newElement = self.fieldElementPool.spawn(newX, newY, newScale, 0.9);
				if (newElement) {
					newElement.horizonY = self.horizonY;
					newElement.initialX = newX;
				}
			}
			element.zIndex = element.y;
		}
		// After updating all elements, sort them by z-index
		activeObjects.sort(function (a, b) {
			return a.y - b.y; // Sort by y position (smaller y values first)
		});
		// Remove and re-add in the sorted order
		for (var k = 0; k < activeObjects.length; k++) {
			var element = activeObjects[k];
			self.bottomContainer.removeChild(element);
			self.bottomContainer.addChild(element);
		}
	}
	return self;
});
// Modify the HealthPopup class
var HealthPopup = Container.expand(function () {
	var self = Container.call(this);
	var text = new Text2('+10', {
		size: 150,
		fill: 0x00FF00,
		// Green
		stroke: 0x000000,
		strokeThickness: 3
	});
	text.anchor.set(0.5, 0.5);
	self.addChild(text);
	// Initially hide the popup
	self.visible = false;
	self.show = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		text.scaleX = 0.1;
		text.scaleY = 0.1;
		text.y = 0; // Reset position before animation
		if (self.currentTween) {
			self.currentTween.stop();
		}
		self.currentTween = tween(text, {
			scaleX: 1.5,
			scaleY: 1.5,
			y: -50
		}, {
			duration: 300,
			easing: tween.easeOutBack,
			onFinish: function onFinish() {
				tween(text, {
					alpha: 0,
					y: -100
				}, {
					duration: 400,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.visible = false;
						text.alpha = 1;
						text.y = 0;
					}
				});
			}
		});
	};
	return self;
});
var HealthPowerup = Container.expand(function () {
	var self = Container.call(this);
	var heart = self.attachAsset('heart', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.age = 0;
		heart.scaleX = heart.scaleY = 1;
	};
	self.update = function () {
		self.age++;
		// Wave pattern movement
		self.x += Math.sin(self.age * 0.05) * 2;
		self.y -= 3; // Float upward
		// Pulse scale
		var pulse = 1 + Math.sin(self.age * 0.1) * 0.2;
		heart.scaleX = heart.scaleY = pulse;
		// Remove if off screen
		if (self.y < -50) {
			healthPowerupPool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var JetFlame = Container.expand(function () {
	var self = Container.call(this);
	var flame = self.attachAsset('flame', {
		anchorX: 0.5,
		anchorY: 0,
		// Keep bottom anchor for natural flame shape
		scaleX: 1,
		scaleY: 0.5,
		rotation: Math.PI // 180 degrees to point downward
	});
	self.startPulse = function () {
		flame.scaleX = 0.5;
		flame.scaleY = 0.3;
		flame.alpha = 0.8;
		self.pulse();
	};
	self.pulse = function () {
		if (self.currentTween) {
			self.currentTween.stop();
		}
		self.currentTween = tween(flame, {
			scaleX: 0.75,
			scaleY: 0.6,
			alpha: 1
		}, {
			duration: 300,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				self.currentTween = tween(flame, {
					scaleX: 0.5,
					scaleY: 0.3,
					alpha: 0.8
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: self.pulse
				});
			}
		});
	};
	self.deactivate = function () {
		if (self.currentTween) {
			self.currentTween.stop();
			self.currentTween = null;
		}
		flame.scaleY = 0.5;
	};
	return self;
});
var ObjectPool = Container.expand(function (ObjectClass, size) {
	var self = Container.call(this);
	var objects = [];
	var activeCount = 0;
	for (var i = 0; i < size; i++) {
		var obj = new ObjectClass();
		if (typeof obj.update !== 'function') {
			obj.update = function () {}; // Provide a default update method if not defined
		}
		obj.visible = false;
		obj._poolIndex = i;
		objects.push(obj);
		self.addChild(obj);
	}
	self.spawn = function (x, y, params) {
		if (activeCount >= objects.length) {
			return null;
		}
		var obj = objects[activeCount];
		activeCount++; // Increment AFTER getting object
		obj.visible = true;
		obj.activate(x, y, params);
		return obj;
	};
	self.recycle = function (obj) {
		if (!obj || typeof obj._poolIndex !== 'number' || obj._poolIndex >= activeCount) {
			return;
		}
		activeCount--; // Decrement count
		// Swap with last active object if needed
		if (obj._poolIndex < activeCount) {
			var temp = objects[activeCount];
			objects[activeCount] = obj;
			objects[obj._poolIndex] = temp;
			// Update indices
			temp._poolIndex = obj._poolIndex;
			obj._poolIndex = activeCount;
		}
		obj.deactivate();
		obj.visible = false;
	};
	self.recycleAll = function () {
		while (activeCount > 0) {
			self.recycle(objects[0]);
		}
	};
	self.update = function () {
		for (var i = 0; i < activeCount; i++) {
			objects[i].update();
		}
	};
	self.getActiveObjects = function () {
		return objects.slice(0, activeCount);
	};
	return self;
});
var ProgressMeter = Container.expand(function () {
	var self = Container.call(this);
	// Create meter background (now horizontal)
	var meter = self.attachAsset('meter', {
		anchorX: 0,
		anchorY: 0.5,
		scaleX: 1.2,
		// Adjust width to preference
		scaleY: 0.6,
		// Make thinner
		tint: 0x666666
	});
	// Progress icons
	var dragonIcon = self.attachAsset('dragonHead', {
		anchorX: 0.5,
		anchorY: 0.7,
		scaleX: 0.9,
		scaleY: 0.9
	});
	var bossIcon = self.attachAsset('skull', {
		anchorX: 0.5,
		anchorY: 0.7
	});
	// Position at top center
	// Position elements relative to meter center
	var totalWidth = meter.width * 1.2 + 120; // Include icon spaces
	self.x = 2048 / 2 - totalWidth / 2; // Center the whole assembly
	self.y = 80;
	// Position icons relative to meter edges
	dragonIcon.x = 0; // Left icon at start
	dragonIcon.y = meter.height / 2;
	bossIcon.x = totalWidth; // Right icon at end
	bossIcon.y = meter.height / 2;
	// Center meter between icons
	meter.x = 60; // Space for left icon
	self.updateProgress = function (progress) {
		dragonIcon.x = progress * (totalWidth - 60); // Move between start and end positions
	};
	return self;
});
var ScorchMark = Container.expand(function () {
	var self = Container.call(this);
	var mark = self.attachAsset('scorchMark', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.8
	});
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.speedY = flyingBackground.scrollSpeed;
		// Initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		mark.scaleX = 0.5 + progress;
		mark.scaleY = (0.5 + progress) * 0.8;
	};
	self.update = function () {
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		// Drastically reduce base speed to match field elements
		var tempSpeed = 0.2 + progress * 3;
		self.y -= tempSpeed;
		mark.scaleX = 0.5 + progress;
		mark.scaleY = (0.5 + progress) * 0.8;
		mark.alpha = Math.min(0.8, progress);
		if (self.y <= flyingBackground.horizonY) {
			scorchPool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var ScorePopup = Container.expand(function () {
	var self = Container.call(this);
	// Create text with white color instead of red
	var scoreTxt = new Text2('', {
		size: 120,
		fill: 0xFFFFFF,
		// White color
		stroke: 0x000000,
		strokeThickness: 3
	});
	scoreTxt.anchor.set(0.5, 0.5);
	self.addChild(scoreTxt);
	self.activate = function (x, y, amount, color) {
		self.x = x;
		self.y = y;
		self.visible = true;
		scoreTxt.setText('+' + amount);
		// Special case for boss defeat score
		if (amount === 5000) {
			scoreTxt.size = 300; // Much larger text
			color = 0xFFD700; // Gold color
		} else {
			scoreTxt.size = 120; // Normal size
		}
		// Apply tint if provided
		if (color !== undefined) {
			scoreTxt.tint = color;
		} else {
			scoreTxt.tint = 0xFF0000; // Default red tint
		}
		scoreTxt.scaleX = 0.1;
		scoreTxt.scaleY = 0.1;
		if (self.currentTween) {
			self.currentTween.stop();
		}
		// Special animation for boss defeat
		if (amount === 5000) {
			self.currentTween = tween(scoreTxt, {
				scaleX: 2.5,
				scaleY: 2.5,
				y: -150 // Move higher for boss defeat
			}, {
				duration: 600,
				// Longer duration
				easing: tween.easeOutBack,
				onFinish: function onFinish() {
					tween(scoreTxt, {
						alpha: 0,
						y: -250 // Float up higher
					}, {
						duration: 800,
						// Longer fade
						easing: tween.easeIn,
						onFinish: function onFinish() {
							scorePopupPool.recycle(self);
						}
					});
				}
			});
		} else {
			// Original animation for regular scores
			self.currentTween = tween(scoreTxt, {
				scaleX: 1.5,
				scaleY: 1.5,
				y: -50
			}, {
				duration: 300,
				easing: tween.easeOutBack,
				onFinish: function onFinish() {
					tween(scoreTxt, {
						alpha: 0,
						y: -100
					}, {
						duration: 400,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							scorePopupPool.recycle(self);
						}
					});
				}
			});
		}
	};
	self.deactivate = function () {
		self.visible = false;
		scoreTxt.alpha = 1;
		scoreTxt.y = 0;
		scoreTxt.tint = 0xFFFFFF; // Reset to white (no tint)
		if (self.currentTween) {
			self.currentTween.stop();
		}
	};
	return self;
});
var TitleScreen = Container.expand(function () {
	var self = Container.call(this);
	var fadeOverlay = self.attachAsset('particle', {
		anchorX: 0,
		anchorY: 0,
		scaleX: 2048,
		scaleY: 2732,
		tint: 0x000000,
		alpha: 1
	});
	var titleImage = self.attachAsset('titleimage', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0
	});
	var startButton = self.attachAsset('startbutton', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0,
		scaleY: 0,
		alpha: 0
	});
	titleImage.x = 2048 / 2;
	titleImage.y = 2732 / 3;
	startButton.x = 2048 / 2;
	startButton.y = titleImage.y + 1100;
	self.start = function () {
		// Fade in title
		tween(fadeOverlay, {
			alpha: 0
		}, {
			duration: 1500,
			easing: tween.easeOut
		});
		tween(titleImage, {
			alpha: 1,
			scaleX: 1,
			// Add scale pulse start
			scaleY: 1 // Add scale pulse start
		}, {
			duration: 1500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Add pulsing animation
				function pulseTitle() {
					tween(titleImage, {
						tint: 0xFFFF00,
						scaleX: 1.1,
						scaleY: 1.1
					}, {
						duration: 1100,
						easing: tween.easeInOut,
						onFinish: function onFinish() {
							tween(titleImage, {
								tint: 0xFFA500,
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 1100,
								easing: tween.easeInOut,
								onFinish: pulseTitle
							});
						}
					});
				}
				pulseTitle();
				// Grow button
				tween(startButton, {
					scaleX: 1,
					scaleY: 1,
					alpha: 1
				}, {
					duration: 800,
					easing: tween.easeOutBack,
					onFinish: function onFinish() {
						// Add pulsing animation
						function pulse() {
							tween(startButton, {
								tint: 0xFFFF00
							}, {
								duration: 1000,
								easing: tween.easeInOut,
								onFinish: function onFinish() {
									tween(startButton, {
										tint: 0xFFA500
									}, {
										duration: 1000,
										easing: tween.easeInOut,
										onFinish: pulse
									});
								}
							});
						}
						pulse();
					}
				});
			}
		});
	};
	startButton.down = function () {
		self.startGame();
		return true;
	};
	self.startGame = function () {
		// Prevent multiple clicks
		LK.getSound('dragonScream').play();
		startButton.down = null;
		// Fade out title elements
		tween(titleImage, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				// Enable gameplay
				gameActive = true;
				// Show UI
				dragonHealthBar.visible = true;
				scoreTxt.visible = true;
				scoreMeterBg.visible = true;
				progressMeter.visible = true;
				// Enable dragon and shadow
				dragon.visible = true;
				dragonShadow.visible = true;
				// Remove title screen
				game.removeChild(self);
			}
		});
		tween(startButton, {
			alpha: 0
		}, {
			duration: 500
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
function processCollisions() {
	var fireballs = fireballPool.getActiveObjects();
	var enemies = enemyPool.getActiveObjects();
	var enemiesTwo = enemyTwoPool.getActiveObjects();
	// Process enemy arrows first
	var arrows = enemyArrowPool.getActiveObjects();
	// Add after arrow collision checks in processCollisions()
	var enemiesThree = enemyThreePool.getActiveObjects();
	for (var i = enemiesThree.length - 1; i >= 0; i--) {
		var enemy = enemiesThree[i];
		var dx = enemy.x - dragon.x;
		var dy = enemy.y - dragon.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < 210 * enemy.scaleX) {
			// Adjust collision radius based on enemy scale
			// Create explosion effect
			for (var j = 0; j < 20; j++) {
				defeatParticlePool.spawn(enemy.x, enemy.y, 0xff0000);
			}
			enemyThreePool.recycle(enemy);
			dragon.flashDamage(6);
		}
	}
	// Add inside processCollisions() function, after the existing collision checks:
	// Check boss fist collisions with dragon
	if (boss && boss.activeFist) {
		var fist = boss.activeFist;
		var dx = fist.x - dragon.x;
		var dy = fist.y - dragon.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Use dragon's current scale for collision radius
		var collisionRadius = 150 * dragon.currentScale;
		if (distance < collisionRadius) {
			dragon.flashDamage(12);
			// Should the fist retract after hitting? Let me know if you want this behavior
		}
	}
	// Replace the existing fireball-boss collision check with this:
	if (boss && boss.state !== 'dying') {
		var fireballs = fireballPool.getActiveObjects();
		for (var i = fireballs.length - 1; i >= 0; i--) {
			var fireball = fireballs[i];
			var dx = fireball.x - boss.x;
			var dy = fireball.y - boss.y;
			// Use elliptical hitbox: wider horizontally, same vertically
			var horizontalRange = 300; // Wider horizontal hitbox (was effectively 100)
			var verticalRange = 100; // Keep the same vertical hitbox
			// Elliptical distance formula
			var ellipticalDist = Math.sqrt(dx * dx / (horizontalRange * horizontalRange) + dy * dy / (verticalRange * verticalRange));
			if (ellipticalDist < 1) {
				boss.damage(1);
				fireballPool.recycle(fireball);
			}
		}
	}
	// Replace the existing arrow collision check with:
	for (var i = arrows.length - 1; i >= 0; i--) {
		var arrow = arrows[i];
		var dx = arrow.x - dragon.x;
		var dy = arrow.y - dragon.y;
		// Only check collisions if arrow isn't below dragon
		if (arrow.y <= dragon.y + 50) {
			// Allow slight vertical tolerance
			// Wider horizontal check, original vertical bounds
			var horizontalDistance = Math.abs(dx);
			var verticalDistance = Math.abs(dy);
			// Check if within wing range (wider horizontally)
			if (horizontalDistance < 300 && verticalDistance < 75) {
				enemyArrowPool.recycle(arrow);
				// Flash dragon red (keep existing code)
				dragon.flashDamage(7);
			}
		}
	}
	var fireballs = fireballPool.getActiveObjects();
	var arrows = enemyArrowPool.getActiveObjects();
	for (var i = fireballs.length - 1; i >= 0; i--) {
		var fireball = fireballs[i];
		for (var j = arrows.length - 1; j >= 0; j--) {
			var arrow = arrows[j];
			var dx = fireball.x - arrow.x;
			var dy = fireball.y - arrow.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < 60) {
				// Small collision radius since these are projectiles
				// Create small explosion
				for (var k = 0; k < 8; k++) {
					// Fewer particles than full defeat
					var particle = defeatParticlePool.spawn(arrow.x + (Math.random() * 20 - 10),
					// Smaller spread
					arrow.y + (Math.random() * 20 - 10), 0xff0000 // Red tint
					);
					if (particle) {
						// Smaller scale for particles
						var sprite = particle.getChildAt(0);
						sprite.scaleX = 0.2;
						sprite.scaleY = 0.2;
					}
				}
				// Remove both projectiles
				fireballPool.recycle(fireball);
				enemyArrowPool.recycle(arrow);
				// Play explosion sound with lower volume
				LK.getSound('enemyDefeat').play({
					volume: 0.5
				});
				break; // Break inner loop since fireball is gone
			}
		}
	}
	// Process fireballs against both enemy types
	for (var i = fireballs.length - 1; i >= 0; i--) {
		var fireball = fireballs[i];
		// Check against type 1 enemies
		for (var j = enemies.length - 1; j >= 0; j--) {
			var enemy = enemies[j];
			// Check if enemy is fully on screen (accounting for scaled size)
			var enemyHeight = 403 * enemy.scaleY; // Original height * scale
			var enemyWidth = 200 * enemy.scaleX; // Original width * scale
			if (enemy.y > enemyHeight / 2 && enemy.y < 2732 - enemyHeight / 2 && enemy.x > enemyWidth / 2 && enemy.x < 2048 - enemyWidth / 2) {
				var dx = fireball.x - enemy.x;
				var dy = fireball.y - enemy.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 120 * enemy.scaleX) {
					enemy.hit();
					fireballPool.recycle(fireball);
					break;
				}
			}
		}
		// Check against type 2 enemies
		for (var j = enemiesTwo.length - 1; j >= 0; j--) {
			var enemy = enemiesTwo[j];
			var enemyHeight = 412.5 * enemy.scaleY;
			var enemyWidth = 550 * enemy.scaleX;
			if (enemy.y > enemyHeight / 2 && enemy.y < 2732 - enemyHeight / 2 && enemy.x > enemyWidth / 2 && enemy.x < 2048 - enemyWidth / 2) {
				var dx = fireball.x - enemy.x;
				var dy = fireball.y - enemy.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 170 * enemy.scaleX) {
					enemy.hit();
					fireballPool.recycle(fireball);
					break;
				}
			}
		}
		// Check against type 3 enemies
		for (var j = enemiesThree.length - 1; j >= 0; j--) {
			var enemy = enemiesThree[j];
			var enemyHeight = 253 * enemy.scaleY;
			var enemyWidth = 300 * enemy.scaleX;
			if (enemy.y > enemyHeight / 2 && enemy.y < 2732 - enemyHeight / 2 && enemy.x > enemyWidth / 2 && enemy.x < 2048 - enemyWidth / 2) {
				var dx = fireball.x - enemy.x;
				var dy = fireball.y - enemy.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 120 * enemy.scaleX) {
					enemy.hit();
					fireballPool.recycle(fireball);
					break;
				}
			}
		}
	}
	var powerups = healthPowerupPool.getActiveObjects();
	for (var i = powerups.length - 1; i >= 0; i--) {
		var powerup = powerups[i];
		var dx = powerup.x - dragon.x;
		var dy = powerup.y - dragon.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < 240) {
			dragon.health = Math.min(100, dragon.health + 10);
			dragonHealthBar.updateHealth(dragon.health / 100);
			LK.getSound('health').play();
			healthPowerupPool.recycle(powerup);
			healthPopup.show(powerup.x, powerup.y);
		}
	}
}
function trySpawnHealthPowerup(x, y) {
	if (Math.random() < 0.10) {
		// 10% chance 
		// 100% chance
		// 10% chance
		// 7% chance
		// 10% chance 
		// 15% chance
		var powerup = healthPowerupPool.spawn(x, y);
		if (powerup) {
			scorePopupPool.spawn(x, y - 50, "HEALTH", 0x00ff00);
		}
	}
}
// Set dark blue background for sky effect
game.setBackgroundColor(0x2c3e50);
// Game state variables
var score = 0;
var fireballPool = new ObjectPool(Fireball, 100);
var particlePool = new ObjectPool(FireParticle, 400);
var enemyPool = new ObjectPool(Enemy, 25);
var defeatParticlePool = new ObjectPool(DefeatParticle, 200);
var dustParticlePool = new ObjectPool(DustParticle, 100);
var enemyShadowPool = new ObjectPool(EnemyShadow, 50);
var enemyArrowPool = new ObjectPool(EnemyArrow, 50);
var enemyTwoPool = new ObjectPool(EnemyTwo, 25);
var enemyThreePool = new ObjectPool(EnemyThree, 25);
var flamePool = new ObjectPool(FlameEffect, 20);
var scorchPool = new ObjectPool(ScorchMark, 30);
var chainSegmentPool = new ObjectPool(ChainSegment, 30);
var scorePopupPool = new ObjectPool(ScorePopup, 20);
var healthPowerupPool = new ObjectPool(HealthPowerup, 10);
var bossFistPool = new ObjectPool(BossFist, 2); // Left and right fists
var boss = null; // Will be created when needed
var bossHealthBar = new BossHealthBar();
bossHealthBar.visible = false;
bossHealthBar.updateHealth(1.0);
var LEVEL_DURATION = 180 * 60; // 3 minutes at 60fps
var levelTimer = 0;
var progressMeter = new ProgressMeter();
var isFiring = false;
var lastFireTime = 0;
var fireRate = 200; // ms between fireballs
var enemy1StartTime = 30 * 60; // 30 seconds
var enemy2StartTime = 15 * 60; // 15 seconds
var enemy3StartTime = 5 * 60; // 5 seconds
var enemy1SpawnRate = 300; // ~3 seconds
var enemy2SpawnRate = 240; // ~4 seconds
var enemy3SpawnRate = 180; // ~5 seconds
var ENEMY1_MIN_RATE = 150; // Half of 300
var ENEMY2_MIN_RATE = 120; // Half of 240  
var ENEMY3_MIN_RATE = 100; // Half of 180
var difficultyScaling = 0;
var flyingBackground = new FlyingBackground();
game.addChild(flyingBackground);
// Create dragon head (player character)
var dragon = game.addChild(new DragonHead());
dragon.x = 2048 / 2;
dragon.y = 2732 * 0.2; // Place dragon at top fifth of screen
var dragonShadow = new DragonShadow();
game.addChild(dragonShadow);
game.addChild(enemyShadowPool);
game.addChild(fireballPool);
game.addChild(particlePool);
game.addChild(enemyPool);
game.addChild(enemyTwoPool);
game.addChild(enemyThreePool);
game.addChild(chainSegmentPool);
game.addChild(bossFistPool);
game.addChild(scorePopupPool);
game.addChild(defeatParticlePool);
game.addChild(dustParticlePool);
game.addChild(enemyArrowPool);
game.addChild(scorchPool);
game.addChild(flamePool);
game.addChild(healthPowerupPool);
var healthPopup = new HealthPopup();
game.addChild(healthPopup);
dragon.health = 100;
var dragonHealthBar = new DragonHealthBar();
game.addChild(dragonHealthBar);
game.addChild(progressMeter);
var bossText = new BossText();
game.addChild(bossText);
game.cleanupPools = function () {
	fireballPool.recycleAll();
	particlePool.recycleAll();
	enemyPool.recycleAll();
	enemyTwoPool.recycleAll();
	defeatParticlePool.recycleAll();
	dustParticlePool.recycleAll();
	enemyShadowPool.recycleAll();
	enemyArrowPool.recycleAll();
	scorchPool.recycleAll();
	flamePool.recycleAll();
	enemyThreePool.recycleAll();
};
var scoreMeterBg = game.attachAsset('particle', {
	anchorX: 0,
	anchorY: 0.5,
	tint: 0x333333,
	alpha: 0.5,
	scaleY: 1
});
// Score display
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF,
	stroke: 0x000000,
	strokeThickness: 3
});
// Position meter and score
scoreMeterBg.x = 2048 / 2; // Center X
scoreMeterBg.anchorX = 0.5; // Center anchor for background
scoreMeterBg.y = 300;
scoreTxt.anchor.set(0.5, 0.5); // Center anchor for text
scoreTxt.x = 2048 / 2; // Center X
scoreTxt.y = 300;
game.addChild(scoreMeterBg);
game.addChild(scoreTxt);
function updateScoreMeter(score) {
	var minWidth = 200;
	var scoreStr = score.toString();
	var padding = 40; // Total padding (20 each side)
	// Adjust width per digit based on digit count
	var widthPerDigit;
	if (scoreStr.length === 1) {
		widthPerDigit = 70;
	} else if (scoreStr.length === 2) {
		widthPerDigit = 60;
	} else {
		widthPerDigit = 70;
	}
	var targetWidth = Math.max(minWidth, scoreStr.length * widthPerDigit + padding);
	scoreMeterBg.scaleX = targetWidth / scoreMeterBg.width;
	// Text stays centered automatically now
}
// Create a function to add fire particles
function createFireParticle(x, y) {
	particlePool.spawn(x, y);
}
// Function to spawn a fireball
// Update the spawnFireball function
function spawnFireball() {
	if (!gameActive) {
		return;
	}
	var now = Date.now();
	if (now - lastFireTime < fireRate) {
		return;
	}
	lastFireTime = now;
	// Initialize horizontal velocity components
	var angleOffset = 0;
	// Get direction from dragon head facing - match thresholds with DragonHead class
	if (facekit.leftEye && facekit.rightEye && facekit.noseTip) {
		var faceCenter = (facekit.leftEye.x + facekit.rightEye.x) / 2;
		var noseDiff = facekit.noseTip.x - faceCenter;
		var eyeYDiff = facekit.rightEye.y - facekit.leftEye.y;
		// Keep the original thresholds but require more pronounced movement
		// to trigger the sideways shots (higher threshold values)
		if (noseDiff < -120 && Math.abs(eyeYDiff) < 30 || eyeYDiff > 50) {
			// Facing left - fireballs go left (maintain strong angle)
			angleOffset = -8; // Original value for strong effect
		} else if (noseDiff > 120 && Math.abs(eyeYDiff) < 30 || eyeYDiff < -50) {
			// Facing right - fireballs go right (maintain strong angle)
			angleOffset = 8; // Original value for strong effect
		}
	}
	// Keep the original tilt impact for consistent feel
	if (dragon.rotation) {
		angleOffset += dragon.rotation * 5; // Original value
	}
	// Use the new pool's spawn method
	var fireball = fireballPool.spawn(dragon.x, dragon.y + 50);
	if (fireball) {
		fireball.vx = angleOffset;
		// Add this line to alternate weave direction
		fireball.weaveDirection = lastFireTime % (fireRate * 2) === 0 ? 1 : -1;
	}
	// Play sound
	LK.getSound('firebreathSound').play();
}
dragonHealthBar.visible = false;
scoreTxt.visible = false;
scoreMeterBg.visible = false;
progressMeter.visible = false;
dragon.visible = false;
dragonShadow.visible = false;
gameActive = false;
var titleScreen = new TitleScreen();
game.addChild(titleScreen);
titleScreen.start();
// Game update logic
game.update = function () {
	if (!gameActive) {
		return;
	}
	// Check if mouth is open for fire breathing
	if (facekit && facekit.mouthOpen) {
		isFiring = true;
		spawnFireball();
	} else {
		isFiring = false;
	}
	if (boss) {
		boss.update();
	}
	levelTimer++;
	// Only update progress if boss hasn't spawned yet
	if (!boss) {
		progressMeter.updateProgress(levelTimer / LEVEL_DURATION);
	}
	// Enemy spawning logic
	// Enemy spawning logic
	if (!boss || boss.state !== 'dying') {
		// Add a spawn rate multiplier that's 2x when boss is present
		var spawnRateMultiplier = boss ? 2 : 1;
		if (levelTimer >= enemy3StartTime) {
			// Scale from initial 180 to minimum 90 over level duration
			var scaled3Rate = Math.max(ENEMY3_MIN_RATE, enemy3SpawnRate - (enemy3SpawnRate - ENEMY3_MIN_RATE) * (levelTimer / LEVEL_DURATION));
			// Apply the multiplier to the spawn rate
			if (LK.ticks % Math.floor(scaled3Rate * spawnRateMultiplier) === 0) {
				var enemy = enemyThreePool.spawn(Math.random() * (2048 - 200) + 100, 2732 + 100);
			}
		}
		if (levelTimer >= enemy2StartTime) {
			var scaled2Rate = Math.max(ENEMY2_MIN_RATE, enemy2SpawnRate - (enemy2SpawnRate - ENEMY2_MIN_RATE) * (levelTimer / LEVEL_DURATION));
			// Apply the multiplier to the spawn rate
			if (LK.ticks % Math.floor(scaled2Rate * spawnRateMultiplier) === 0) {
				var spawnX = Math.random() < 0.5 ? -50 : 2098;
				var enemy = enemyTwoPool.spawn(spawnX, 2732 - 500);
			}
		}
		if (levelTimer >= enemy1StartTime) {
			var scaled1Rate = Math.max(ENEMY1_MIN_RATE, enemy1SpawnRate - (enemy1SpawnRate - ENEMY1_MIN_RATE) * (levelTimer / LEVEL_DURATION));
			// Apply the multiplier to the spawn rate
			if (LK.ticks % Math.floor(scaled1Rate * spawnRateMultiplier) === 0) {
				var enemy = enemyPool.spawn(Math.random() * (2048 - 200) + 100, 2732 + 100);
			}
		}
	}
	// Boss spawn check
	if (levelTimer >= LEVEL_DURATION && !boss) {
		bossText.flash();
		boss = new Boss();
		game.addChild(boss);
		game.addChild(bossHealthBar);
		bossHealthBar.visible = true;
		bossHealthBar.show();
	}
	dragonShadow.update(dragon.x, dragon.y, dragon.currentScale);
	// Update all pools
	fireballPool.update();
	enemyPool.update();
	particlePool.update();
	defeatParticlePool.update();
	dustParticlePool.update();
	bossFistPool.update();
	flamePool.update();
	scorchPool.update();
	enemyThreePool.update();
	enemyTwoPool.update();
	scorePopupPool.update();
	healthPowerupPool.update();
	// Process collisions
	processCollisions();
};
// Start background music
LK.playMusic('gameMusic', {
	fade: {
		start: 0,
		end: 0.7,
		duration: 1000
	}
}); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/**** 
* Classes
****/ 
var Boss = Container.expand(function () {
	var self = Container.call(this);
	// States
	var ENTERING = 'entering';
	var WALKING = 'walking';
	var ARROW_ATTACK = 'arrow_attack';
	var CHARGING_LEFT = 'charging_left';
	var CHARGING_RIGHT = 'charging_right';
	var FIST_LEFT = 'fist_left';
	var FIST_RIGHT = 'fist_right';
	var RETRACTING_LEFT = 'retracting_left';
	var RETRACTING_RIGHT = 'retracting_right';
	var DYING = 'dying';
	// All boss sprites
	var normalBody = self.attachAsset('boss1', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 1
	});
	var leftBody = self.attachAsset('boss1left', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	var rightBody = self.attachAsset('boss1right', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	var leftNoFist = self.attachAsset('boss1leftnofist', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	var rightNoFist = self.attachAsset('boss1rightnofist', {
		anchorX: 0.5,
		anchorY: 0,
		alpha: 0
	});
	// Properties
	self.health = 100;
	self.state = ENTERING;
	self.hasCompletedFirstAttack = false;
	self.stateDuration = 0;
	self.bobSpeed = 0.1;
	self.bobOffset = 0;
	self.bobBaseY = 2732 / 1.35; // Add base Y position
	self.activeFist = null;
	self.attackTimer = 0;
	self.attackDelay = 120;
	self.hasPlayedDeathSound = false;
	// Initial position
	self.x = 2048 / 2;
	self.y = 2732;
	function setBodyState(state) {
		normalBody.alpha = 0;
		leftBody.alpha = 0;
		rightBody.alpha = 0;
		leftNoFist.alpha = 0;
		rightNoFist.alpha = 0;
		switch (state) {
			case 'normal':
				normalBody.alpha = 1;
				break;
			case 'left':
				leftBody.alpha = 1;
				break;
			case 'right':
				rightBody.alpha = 1;
				break;
			case 'leftNoFist':
				leftNoFist.alpha = 1;
				break;
			case 'rightNoFist':
				rightNoFist.alpha = 1;
				break;
		}
	}
	function flashDamage() {
		[normalBody, leftBody, rightBody, leftNoFist, rightNoFist].forEach(function (sprite) {
			if (sprite.alpha > 0) {
				sprite.tint = 0xFF0000;
				LK.setTimeout(function () {
					sprite.tint = 0xFFFFFF;
				}, 5);
			}
		});
	}
	self.update = function () {
		self.stateDuration++;
		self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 15;
		switch (self.state) {
			case ENTERING:
				setBodyState('normal');
				self.y -= 2;
				if (self.y <= 2732 / 1.35) {
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
				}
				break;
			case WALKING:
				setBodyState('normal');
				self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 15;
				self.y = self.bobBaseY + self.bobOffset;
				self.attackTimer--;
				if (self.attackTimer <= 0) {
					if (!self.hasCompletedFirstAttack) {
						self.state = ARROW_ATTACK;
						self.hasCompletedFirstAttack = true;
					} else {
						var rand = Math.random();
						if (rand < 0.6) {
							self.state = ARROW_ATTACK;
						} else {
							self.state = Math.random() < 0.5 ? CHARGING_LEFT : CHARGING_RIGHT;
						}
					}
					self.stateDuration = 0;
				}
				break;
			case ARROW_ATTACK:
				// Keep bobbing motion during arrow attack
				self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 15;
				self.y = self.bobBaseY + self.bobOffset;
				if (self.stateDuration === 1) {
					LK.getSound('arrow').play(); // Play arrow sound effect
					var centerY = self.y + 200;
					enemyArrowPool.spawn(self.x, centerY).activate(self.x, centerY, dragon.x, dragon.y);
					enemyArrowPool.spawn(self.x - 100, centerY).activate(self.x - 100, centerY, dragon.x - 300, dragon.y);
					enemyArrowPool.spawn(self.x + 100, centerY).activate(self.x + 100, centerY, dragon.x + 300, dragon.y);
				} else if (self.stateDuration > 60) {
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
					self.stateDuration = 0;
				}
				break;
			case CHARGING_LEFT:
			case CHARGING_RIGHT:
				var isLeft = self.state === CHARGING_LEFT;
				setBodyState(isLeft ? 'left' : 'right');
				if (self.stateDuration < 70) {
					var targetX = self.x + (isLeft ? -200 : 200);
					var targetY = self.y + 300;
					if (Math.random() < 0.3) {
						var angle = Math.random() * Math.PI * 2;
						var radius = Math.random() * 200 + 100;
						var px = targetX + Math.cos(angle) * radius;
						var py = targetY + Math.sin(angle) * radius;
						var particle = particlePool.spawn(px, py);
						if (particle) {
							var dx = targetX - px;
							var dy = targetY - py;
							var dist = Math.sqrt(dx * dx + dy * dy);
							particle.vx = dx / dist * 10;
							particle.vy = dy / dist * 10;
						}
					}
				} else {
					if (self.activeFist) {
						bossFistPool.recycle(self.activeFist);
						self.activeFist = null;
					}
					self.state = isLeft ? FIST_LEFT : FIST_RIGHT;
					self.stateDuration = 0;
					setBodyState(isLeft ? 'leftNoFist' : 'rightNoFist');
					self.activeFist = bossFistPool.spawn(self.x + (isLeft ? -200 : 200), self.y + 300, isLeft);
					if (self.activeFist) {
						self.activeFist.extend(dragon.x, dragon.y);
						LK.getSound('bossPunch').play();
					}
				}
				break;
			case FIST_LEFT:
			case FIST_RIGHT:
				if (!self.activeFist || !self.activeFist.visible) {
					// If fist is somehow missing, recover
					setBodyState('normal');
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
					self.stateDuration = 0;
					break;
				}
				if (self.activeFist && !self.activeFist.extending) {
					self.state = self.state === FIST_LEFT ? RETRACTING_LEFT : RETRACTING_RIGHT;
					self.stateDuration = 0;
					if (self.activeFist) {
						self.activeFist.retract();
					}
				}
				break;
			case RETRACTING_LEFT:
			case RETRACTING_RIGHT:
				if (!self.activeFist || !self.activeFist.visible) {
					setBodyState('normal');
					self.state = WALKING;
					self.attackTimer = self.attackDelay;
					self.stateDuration = 0;
					if (self.activeFist) {
						bossFistPool.recycle(self.activeFist); // Add this line
					}
					self.activeFist = null; // Add this line to clear the reference
				}
				break;
			case DYING:
				self.y += 1;
				self.x += Math.sin(self.stateDuration * 0.2) * 5;
				// More frequent and spread out particles
				if (self.stateDuration % 10 === 0) {
					for (var i = 0; i < 5; i++) {
						defeatParticlePool.spawn(self.x + (Math.random() * 800 - 400), self.y + Math.random() * 800, 0xff0000);
					}
				}
				// Random explosions every second
				if (self.stateDuration % 60 === 0) {
					var explosionX = self.x + (Math.random() * 600 - 300);
					var explosionY = self.y + (Math.random() * 600 - 300);
					var explosion = LK.getAsset('explosion', {
						anchorX: 0.5,
						anchorY: 0.5,
						x: explosionX,
						y: explosionY,
						scaleX: 0.5,
						//{39}  // Start bigger
						scaleY: 0.5,
						alpha: 1
					});
					game.addChild(explosion);
					LK.getSound('explosion').play();
					tween(explosion, {
						scaleX: 4,
						//{3g}  // End much bigger
						scaleY: 4,
						alpha: 0
					}, {
						duration: 500,
						//{3k}  // Faster animation
						easing: tween.easeOut,
						onFinish: function onFinish() {
							game.removeChild(explosion);
						}
					});
				}
				if (self.y > 2732 + 200) {
					//{3r}  // Reduced height check
					game.removeChild(self);
					bossHealthBar.visible = false;
					if (!self.hasPlayedDeathSound) {
						LK.getSound('dragonScream').play();
						self.hasPlayedDeathSound = true;
					}
					LK.setTimeout(function () {
						LK.showYouWin();
					}, 3000);
				}
				break;
		}
		self.lastBobOffset = self.bobOffset;
	};
	self.damage = function (amount) {
		self.health -= amount;
		bossHealthBar.updateHealth(self.health / 100);
		flashDamage();
		if (self.health <= 0 && self.state !== DYING) {
			self.state = DYING;
			self.stateDuration = 0;
			bossHealthBar.hide();
			// Add boss defeat score
			score += 5000;
			scorePopupPool.spawn(self.x, self.y, 5000);
			scoreTxt.setText(score);
			updateScoreMeter(score);
			LK.setScore(score);
			tween(game, {
				x: game.x + 20
			}, {
				duration: 1000,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					game.x = 0;
				}
			});
		}
	};
	return self;
});
var BossFist = Container.expand(function () {
	var self = Container.call(this);
	// Create both fist sprites and manage visibility
	var leftFist = self.attachAsset('boss1leftfist', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false,
		rotation: -Math.PI / 12 // 15 degrees counterclockwise
	});
	var rightFist = self.attachAsset('boss1rightfist', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false,
		rotation: Math.PI / 12 // 15 degrees clockwise
	});
	self.activate = function (x, y, isLeft) {
		self.x = x;
		self.y = y;
		self.startX = x;
		self.startY = y;
		self.isLeft = isLeft;
		self.visible = true;
		self.extending = false;
		self.retracting = false;
		// Show correct fist, hide other
		leftFist.visible = isLeft;
		rightFist.visible = !isLeft;
	};
	self.extend = function (targetX, targetY) {
		self.targetX = targetX;
		self.targetY = targetY;
		self.extending = true;
		self.retracting = false;
	};
	self.update = function () {
		if (!self.visible) {
			return;
		}
		if (self.extending || self.retracting) {
			var dx = self.targetX - self.x;
			var dy = self.targetY - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist > self.speed) {
				self.x += dx / dist * self.speed;
				self.y += dy / dist * self.speed;
				// Update chain segments
				var segmentSpacing = 40;
				var numSegments = Math.floor(dist / segmentSpacing);
				// Clean up old segments
				while (self.chainSegments.length > 0) {
					chainSegmentPool.recycle(self.chainSegments.pop());
				}
				// Create new segments
				for (var i = 1; i <= numSegments; i++) {
					var t = i / numSegments;
					var segX = self.startX + (self.x - self.startX) * t;
					var segY = self.startY + (self.y - self.startY) * t;
					var segment = chainSegmentPool.spawn(segX, segY);
					if (segment) {
						var angle = Math.atan2(dy, dx);
						segment.rotation = angle;
						self.chainSegments.push(segment);
					}
				}
			} else {
				if (self.extending) {
					self.extending = false;
					// Pause briefly at extension
					LK.setTimeout(function () {
						self.retract();
					}, 30);
				} else if (self.retracting) {
					self.deactivate();
				}
			}
		}
	};
	self.retract = function () {
		self.targetX = self.startX;
		self.targetY = self.startY;
		self.extending = false;
		self.retracting = true;
	};
	self.deactivate = function () {
		while (self.chainSegments.length > 0) {
			chainSegmentPool.recycle(self.chainSegments.pop());
		}
		self.visible = false;
		self.extending = false;
		self.retracting = false;
		leftFist.visible = false;
		rightFist.visible = false;
	};
	// Initialize properties
	self.chainSegments = [];
	self.speed = 15;
	return self;
});
// In the BossHealthBar class, add position setting
// Modify the BossHealthBar class
var BossHealthBar = Container.expand(function () {
	var self = Container.call(this);
	var emptyMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0x333333,
		// Dark gray for empty
		scaleX: 0 // Start with zero width
	});
	var healthMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0xff0000,
		// Red for health
		scaleX: 0 // Start with zero width
	});
	// Position settings
	self.x = 2048 / 2; // Center horizontally
	self.y = 2732 - 100; // Position from the top
	self.show = function () {
		self.visible = true;
		// Reset both meters to zero width
		healthMeter.scaleX = 0;
		if (self.currentTween) {
			self.currentTween.stop();
		}
		// First animate the empty meter
		self.currentTween = tween(emptyMeter, {
			scaleX: 1
		}, {
			duration: 800,
			easing: tween.easeOutBack,
			onFinish: function onFinish() {
				// Then animate the health meter
				self.currentTween = tween(healthMeter, {
					scaleX: 1
				}, {
					duration: 400,
					easing: tween.easeOut
				});
			}
		});
	};
	self.hide = function () {
		if (self.currentTween) {
			self.currentTween.stop();
		}
		// First shrink the health meter
		self.currentTween = tween(healthMeter, {
			scaleX: 0
		}, {
			duration: 400,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				// Then shrink the empty meter
				self.currentTween = tween(emptyMeter, {
					scaleX: 0
				}, {
					duration: 800,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.visible = false;
					}
				});
			}
		});
	};
	self.updateHealth = function (percent) {
		// Only animate the health meter, not the empty meter
		if (self.healthTween) {
			self.healthTween.stop();
		}
		self.healthTween = tween(healthMeter, {
			scaleX: percent
		}, {
			duration: 300,
			easing: tween.easeOut
		});
	};
	return self;
});
var BossText = Container.expand(function () {
	var self = Container.call(this);
	var text = self.attachAsset('bosstext', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0
	});
	self.x = 2048 / 2; // Center horizontally
	self.y = 2732 / 2; // Center vertically
	self.flashCount = 0;
	self.maxFlashes = 3;
	self.flash = function () {
		self.flashCount = 0;
		self.doFlash();
	};
	self.doFlash = function () {
		if (self.flashCount >= self.maxFlashes) {
			text.alpha = 0;
			return;
		}
		if (self.currentTween) {
			self.currentTween.stop();
		}
		LK.getSound('alert').play();
		// Fade in
		self.currentTween = tween(text, {
			alpha: 1,
			scaleX: 1.2,
			scaleY: 1.2
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Hold
				LK.setTimeout(function () {
					// Fade out
					self.currentTween = tween(text, {
						alpha: 0,
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 500,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.flashCount++;
							// Wait before next flash
							LK.setTimeout(function () {
								self.doFlash();
							}, 20);
						}
					});
				}, 40);
			}
		});
	};
	return self;
});
var ChainSegment = Container.expand(function () {
	var self = Container.call(this);
	var link = self.attachAsset('fistlink', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y, rotation) {
		self.x = x;
		self.y = y;
		self.rotation = rotation;
		self.visible = true;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var Cloud = Container.expand(function () {
	var self = Container.call(this);
	var cloud = self.attachAsset('cloudShape', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y, scale, alpha) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.speedY = 1 + Math.random() * 2;
		self.speedX = (Math.random() - 0.5) * 1.5;
		self.targetY = self.horizonY;
		cloud.scaleX = scale;
		cloud.scaleY = scale * 0.8;
		cloud.alpha = alpha || 0.8;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var DefeatParticle = Container.expand(function () {
	var self = Container.call(this);
	var particle = self.attachAsset('particle', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.15,
		scaleY: 0.15
	});
	self.activate = function (x, y, tint) {
		self.x = x + (Math.random() * 40 - 20); // Wider initial spread
		self.y = y + (Math.random() * 40 - 20); // Wider initial spread
		self.visible = true;
		self.age = 0;
		self.lifespan = 225; // Tripled lifespan for longer visual impact 
		// More dramatic explosion velocities
		var angle = Math.PI * 2 * Math.random();
		var speed = 15 + Math.random() * 25; // Adjusted speed for more variance
		self.vx = Math.cos(angle) * speed;
		self.vy = Math.sin(angle) * speed;
		self.rotation = Math.random() * Math.PI * 2;
		particle.alpha = 1;
		// Larger, more varied particle sizes
		var scaleVariance = 0.3 + Math.random() * 0.6; // Increased variance for scale
		particle.scaleX = scaleVariance;
		particle.scaleY = scaleVariance;
		// Apply tint if provided
		if (tint !== undefined) {
			particle.tint = tint;
		} else {
			particle.tint = 0xffffff; // Default white
		}
	};
	self.update = function () {
		// Check bounds first
		if (self.y < -50 || self.y > 2732 || self.x < -50 || self.x > 2048) {
			defeatParticlePool.recycle(self);
			return;
		}
		self.x += self.vx;
		self.y += self.vy;
		self.age++;
		// Keep strong deceleration
		self.vx *= 0.87;
		self.vy *= 0.87;
		var lifePercent = self.age / self.lifespan;
		// Fade out curve
		particle.alpha = Math.max(0, 1 - lifePercent * 1.7);
		// More dramatic shrink effect as particles fade
		var scale = (0.5 - 0.3 * lifePercent) * (1 - lifePercent * 0.5);
		particle.scaleX = scale;
		particle.scaleY = scale;
		if (lifePercent >= 1) {
			defeatParticlePool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
		// Reset tint when deactivated
		particle.tint = 0xffffff;
	};
	return self;
});
var DragonHead = Container.expand(function () {
	var self = Container.call(this);
	// Dragon sprites
	var body = self.attachAsset('dragonBody', {
		anchorX: 0.5,
		anchorY: 0.7,
		scaleX: 2,
		scaleY: 2
	});
	var head = self.attachAsset('dragonHead', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2
	});
	var headOpen = self.attachAsset('dragonHeadOpen', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	});
	var lookLeft = self.attachAsset('dragonLook', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: -2,
		// Mirror for left direction
		scaleY: 2,
		alpha: 0
	});
	var lookRight = self.attachAsset('dragonLook', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	});
	var lookLeftOpen = self.attachAsset('dragonLookOpen', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: -2,
		// Mirror for left direction
		scaleY: 2,
		alpha: 0
	});
	var lookRightOpen = self.attachAsset('dragonLookOpen', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	});
	self.stateBuffer = [];
	self.bufferSize = 10; // Adjust 3-5 frames for balance between stability and responsiveness
	self.currentState = 'forward';
	// Add smoothing properties
	self.mouthOpenness = 0; // Track mouth state from 0 (closed) to 1 (open)
	self.mouthSmoothingSpeed = 0.2; // Adjust this value to change transition speed
	self.currentScale = 2; // Starting scale
	var horizontalSpeed = 0;
	self.invulnerableTime = 0;
	self.invulnerableDuration = 30;
	// Position tracking variables
	var targetX = 2048 / 2;
	var targetY = 2732 * 0.2;
	var smoothingFactor = 0.12;
	var prevX = null;
	var prevY = null;
	// Rotation variables
	var targetTilt = 0;
	var tiltSmoothingFactor = 0.11;
	var tiltScaleFactor = 0.09;
	// Scale tracking
	var scaleHistory = new Array(5).fill(2); // Start with default scale of 2
	var scaleIndex = 0;
	self.update = function () {
		// Add in self.update function
		if (self.invulnerableTime > 0) {
			self.invulnerableTime--;
		}
		// Position tracking
		if (facekit.noseTip) {
			targetX = facekit.noseTip.x;
			targetY = facekit.noseTip.y - 800;
			// Initialize previous positions if not set
			if (prevX === null) {
				prevX = targetX;
				prevY = targetY;
			}
			// Weighted average between previous and target position
			var newX = prevX * (1 - smoothingFactor) + targetX * smoothingFactor;
			var newY = prevY * (1 - smoothingFactor) + targetY * smoothingFactor;
			self.x = newX;
			if (newY > dragonShadow.y - 100) {
				// -100 for visual offset so dragon stays above shadow
				newY = dragonShadow.y - 100;
			}
			self.y = newY;
			if (prevX !== null) {
				horizontalSpeed = Math.abs(self.x - prevX);
			}
			self.currentShakeSpeed = horizontalSpeed;
			// Update previous positions
			prevX = newX;
			prevY = newY;
		}
		// Rotation tracking - CORRECTED VERSION
		if (facekit.leftEye && facekit.rightEye) {
			targetTilt = calculateFaceTilt() * tiltScaleFactor;
			// Limit rotation to Β±15 degrees - DON'T convert to radians here
			targetTilt = Math.max(-15, Math.min(15, targetTilt));
			self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor;
		}
		if (facekit.leftEye && facekit.rightEye && facekit.noseTip) {
			// Calculate face direction
			var faceCenter = (facekit.leftEye.x + facekit.rightEye.x) / 2;
			var noseDiff = facekit.noseTip.x - faceCenter;
			var eyeYDiff = facekit.rightEye.y - facekit.leftEye.y;
			var newState = 'forward';
			if (noseDiff < -120 && Math.abs(eyeYDiff) < 30 || eyeYDiff > 50) {
				newState = 'left';
			} else if (noseDiff > 120 && Math.abs(eyeYDiff) < 30 || eyeYDiff < -50) {
				newState = 'right';
			}
			// Add to buffer
			self.stateBuffer.push(newState);
			if (self.stateBuffer.length > self.bufferSize) {
				self.stateBuffer.shift();
			}
			// Only change state if buffer is unanimous
			if (self.stateBuffer.length === self.bufferSize) {
				var unanimous = self.stateBuffer.every(function (state) {
					return state === self.stateBuffer[0];
				});
				if (unanimous) {
					self.currentState = self.stateBuffer[0];
				}
			}
			// Reset visibilities based on current state
			lookLeft.alpha = 0;
			lookRight.alpha = 0;
			lookLeftOpen.alpha = 0;
			lookRightOpen.alpha = 0;
			head.alpha = 0;
			headOpen.alpha = 0;
			if (self.currentState === 'forward') {
				if (facekit.mouthOpen) {
					headOpen.alpha = 1;
				} else {
					head.alpha = 1;
				}
			} else if (self.currentState === 'left') {
				if (facekit.mouthOpen) {
					lookLeftOpen.alpha = 1;
				} else {
					lookLeft.alpha = 1;
				}
			} else if (self.currentState === 'right') {
				if (facekit.mouthOpen) {
					lookRightOpen.alpha = 1;
				} else {
					lookRight.alpha = 1;
				}
			}
		}
		// Scale adjustment based on face size
		if (facekit.leftEye && facekit.rightEye) {
			var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x);
			var newScale = eyeDistance / 250; // Adjusted divisor for dragon head
			// Update rolling average
			scaleHistory[scaleIndex] = newScale;
			scaleIndex = (scaleIndex + 1) % scaleHistory.length;
			// Calculate average scale
			var avgScale = scaleHistory.reduce(function (a, b) {
				return a + b;
			}, 0) / scaleHistory.length;
			// Apply with gentle smoothing (limited range)
			var targetScale = Math.max(1.5, Math.min(2.5, avgScale));
			head.scaleX = head.scaleX * 0.85 + targetScale * 0.15;
			self.currentScale = head.scaleX; // Track the current scale
			head.scaleY = head.scaleY * 0.85 + targetScale * 0.15;
			headOpen.scaleX = headOpen.scaleX * 0.85 + targetScale * 0.15;
			headOpen.scaleY = headOpen.scaleY * 0.85 + targetScale * 0.15;
			body.scaleX = body.scaleX * 0.85 + targetScale * 0.15;
			body.scaleY = body.scaleY * 0.85 + targetScale * 0.15;
			lookLeft.scaleX = lookLeft.scaleX * 0.85 - targetScale * 0.15;
			lookLeft.scaleY = lookLeft.scaleY * 0.85 + targetScale * 0.15;
			lookRight.scaleX = lookRight.scaleX * 0.85 + targetScale * 0.15;
			lookRight.scaleY = lookRight.scaleY * 0.85 + targetScale * 0.15;
			lookLeftOpen.scaleX = lookLeftOpen.scaleX * 0.85 - targetScale * 0.15;
			lookLeftOpen.scaleY = lookLeftOpen.scaleY * 0.85 + targetScale * 0.15;
			lookRightOpen.scaleX = lookRightOpen.scaleX * 0.85 + targetScale * 0.15;
			lookRightOpen.scaleY = lookRightOpen.scaleY * 0.85 + targetScale * 0.15;
		}
	};
	function calculateFaceTilt() {
		if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) {
			// Calculate midpoint between eyes
			var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2;
			var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2;
			// Calculate angle between eye midpoint and mouth, negated to fix direction
			var dx = facekit.mouthCenter.x - eyeMidX;
			var dy = facekit.mouthCenter.y - eyeMidY;
			var angle = -(Math.atan2(dx, dy) * (180 / Math.PI));
			// Reduced angle impact
			return Math.max(-15, Math.min(15, angle * 0.15));
		}
		return 0; // Default to straight when face points aren't available
	}
	self.flashDamage = function (damageAmount) {
		// Show game over after effect
		if (self.invulnerableTime > 0) {
			return;
		}
		// Set invulnerability
		self.invulnerableTime = self.invulnerableDuration;
		// Flash effect
		var dragonSprites = [body];
		if (head && head.alpha > 0) {
			dragonSprites.push(head);
		}
		if (headOpen && headOpen.alpha > 0) {
			dragonSprites.push(headOpen);
		}
		if (lookLeft && lookLeft.alpha > 0) {
			dragonSprites.push(lookLeft);
		}
		if (lookRight && lookRight.alpha > 0) {
			dragonSprites.push(lookRight);
		}
		if (lookLeftOpen && lookLeftOpen.alpha > 0) {
			dragonSprites.push(lookLeftOpen);
		}
		if (lookRightOpen && lookRightOpen.alpha > 0) {
			dragonSprites.push(lookRightOpen);
		}
		dragonSprites.forEach(function (sprite) {
			sprite.tint = 0xFF0000;
			LK.setTimeout(function () {
				sprite.tint = 0xFFFFFF;
			}, 10);
		});
		// Apply damage and check for death
		dragon.health -= damageAmount;
		dragonHealthBar.updateHealth(dragon.health / 100);
		if (dragon.health <= 0 && gameActive) {
			LK.getSound('dragonScream').play();
			gameActive = false;
			// Explode dragon
			for (var i = 0; i < 60; i++) {
				defeatParticlePool.spawn(dragon.x, dragon.y, 0xff0000);
			}
			// Hide dragon
			dragon.visible = false;
			// Show game over after effect
			LK.setTimeout(function () {
				LK.showGameOver();
			}, 2000);
		}
	};
	return self;
});
var DragonHealthBar = Container.expand(function () {
	var self = Container.call(this);
	var emptyMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0x333333,
		scaleX: 1
	});
	var healthMeter = self.attachAsset('meter', {
		anchorX: 0.5,
		anchorY: 1.0,
		tint: 0x00ff00,
		scaleX: 1
	});
	// Position settings
	self.x = 2048 / 2;
	self.y = 220; // 100px from top + some padding
	self.updateHealth = function (percent) {
		if (self.healthTween) {
			self.healthTween.stop();
		}
		self.healthTween = tween(healthMeter, {
			scaleX: percent
		}, {
			duration: 300,
			easing: tween.easeOut
		});
	};
	return self;
});
var DragonShadow = Container.expand(function () {
	var self = Container.call(this);
	var shadow = self.attachAsset('dragonShadow', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.5,
		scaleX: 1,
		scaleY: 0.3
	});
	self.x = 2048 / 2; // Match dragon's initial x
	self.y = 2732 * 0.6; // Positioned below dragon
	var positionSmoothing = 0.12;
	var scaleSmoothing = 0.08;
	self.update = function (dragonX, dragonY, dragonScale) {
		if (dragonX !== undefined && dragonY !== undefined && dragonScale !== undefined) {
			// X position follow
			self.x += (dragonX - self.x) * positionSmoothing;
			// Y position based on scale (Z-depth)
			var baseY = 2732 * 0.6;
			var scaleOffset = (dragonScale - 1) * 300;
			var targetY = baseY + scaleOffset;
			self.y += (targetY - self.y) * positionSmoothing;
			// Scale calculation based on dragon's Y position
			var heightRatio = dragonY / 2732;
			var scaleMultiplier = 0.2 + heightRatio * 1.5;
			// Add Y-position based size adjustment (0-20% increase based on Y position)
			var yPositionScale = 1 + self.y / 2732 * 0.2;
			var targetScaleX = scaleMultiplier * yPositionScale;
			var targetScaleY = scaleMultiplier * 0.3 * yPositionScale;
			var shadow = self.getChildAt(0); // Get the shadow sprite
			shadow.scaleX += (targetScaleX - shadow.scaleX) * scaleSmoothing;
			shadow.scaleY += (targetScaleY - shadow.scaleY) * scaleSmoothing;
			shadow.alpha = 0.3 + heightRatio * 0.2;
		}
	};
	return self;
});
var DustParticle = Container.expand(function () {
	var self = Container.call(this);
	var dust = self.attachAsset('dust', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y) {
		self.x = x + (Math.random() * 20 - 10);
		self.y = y;
		self.visible = true;
		self.age = 0;
		self.lifespan = 60; // Fixed lifespan for consistency
		dust.alpha = 0.9;
		// Vertical velocity - move upward
		self.vy = -1.5; // Faster upward movement
		self.vx = (Math.random() - 0.5) * 5; // Slightly more horizontal movement
		// Add rotation for visual interest
		self.rotation = Math.random() * Math.PI * 2;
	};
	self.update = function () {
		// Update position
		self.x += self.vx;
		self.y += self.vy;
		self.age++;
		// Calculate life percentage
		var lifePercent = self.age / self.lifespan;
		// Fade out
		dust.alpha = 0.8 * (1 - lifePercent);
		// Grow slightly as it rises
		var scale = 1 + lifePercent * 0.2; // Linear growth from 0.2 to 0.3
		dust.scaleX = scale;
		dust.scaleY = scale;
		// Recycle when lifetime is over
		if (lifePercent >= 1) {
			dustParticlePool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// States
	var RUNNING = 'running';
	var LEAPING = 'leaping';
	var ATTACHED = 'attached';
	var FALLING = 'falling';
	// Running enemy sprites
	var runSprite = self.attachAsset('enemy1', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 1
	});
	var runSpriteMirrored = self.attachAsset('enemy1', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: -1,
		alpha: 0
	});
	// Properties
	self.health = 1;
	self.rotationSpeed = 0;
	self.animTick = 0;
	self.animRate = 30;
	self.pulseRate = self.animRate * 2;
	self.state = RUNNING;
	self.leapSpeed = 9;
	self.targetX = 0;
	self.targetY = 0;
	self.hasExploded = false; // Add this flag
	self.activate = function (x, y) {
		self.visible = true;
		self.x = x;
		self.y = y;
		self.state = RUNNING;
		self.rotation = 0; // Reset rotation
		self.health = 1;
		self.rotationSpeed = 0;
		self.fallSpeed = 0;
		self.acceleration = 0;
		self.leapDuration = 0;
		self.shadow = enemyShadowPool.spawn(x, y, self.scaleX);
		self.isPulsedOut = false;
		self.hasExploded = false; // Reset explosion flag
		// If there was a tween running, stop it
		if (self.currentTween) {
			self.currentTween.stop();
			self.currentTween = null;
		}
		// Reset animation state
		self.animTick = 0;
		runSprite.alpha = 1;
		runSpriteMirrored.alpha = 0;
		// Set initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		var scale = 0.5 + progress;
		self.scaleX = scale;
		self.scaleY = scale;
	};
	function checkLeapDistance() {
		// Get distance on Y-axis only
		var dy = Math.abs(self.y - dragonShadow.y);
		// Get relative scales as depth indicators
		var enemyDepth = self.scaleX;
		var shadowDepth = dragonShadow.scaleX;
		// Leap when on same Y-plane regardless of X position
		var depthDiff = Math.abs(enemyDepth - shadowDepth);
		var yThreshold = 10; // Close on the Y-axis
		// If the enemy is on screen and at the right Y position
		if (dy < yThreshold && depthDiff < 0.3 && self.x > 0 && self.x < 2048) {
			startLeap();
			return true;
		}
		return false;
	}
	function startLeap() {
		self.state = LEAPING;
		LK.getSound('orcShout').play();
		// Store where the dragon was when leap started
		self.leapTargetX = dragon.x;
		self.leapTargetY = dragon.y;
		var dx = self.leapTargetX - self.x;
		var dy = self.leapTargetY - self.y;
		self.initialLeapDistance = Math.sqrt(dx * dx + dy * dy);
		self.initialScale = self.scaleX;
		self.isPulsedOut = false;
		runSprite.alpha = 1;
		runSpriteMirrored.alpha = 0;
	}
	self.update = function () {
		if (!self.visible) {
			return;
		}
		switch (self.state) {
			case RUNNING:
				// Existing running code
				var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
				var speed = (flyingBackground.scrollSpeed * 0.05 + flyingBackground.scrollSpeed * (progress * 2.5)) * 0.8;
				self.y -= speed;
				// Update scale based on distance
				var scale = 0.5 + progress;
				self.scaleX = scale;
				self.scaleY = scale;
				// Running animation
				self.animTick++;
				if (self.animTick >= self.animRate) {
					self.animTick = 0;
					runSprite.alpha = runSprite.alpha === 0 ? 1 : 0;
					runSpriteMirrored.alpha = runSpriteMirrored.alpha === 0 ? 1 : 0;
				}
				// In the Enemy class RUNNING state section, replace the dust spawning code with:
				if (LK.ticks % 10 === 0 && self.y < 2732) {
					// More frequent spawning (every 10 ticks)
					var footY = self.y + 50 * self.scaleY;
					dustParticlePool.spawn(self.x, footY);
				}
				// Check for leap
				checkLeapDistance();
				break;
			case LEAPING:
				// Calculate current distance to dragon (not original leap target)
				var dragonDx = dragon.x - self.x;
				var dragonDy = dragon.y - self.y;
				var dragonDistance = Math.sqrt(dragonDx * dragonDx + dragonDy * dragonDy);
				// If we're very close to dragon, attach
				if (dragonDistance < 50) {
					self.state = ATTACHED;
					break;
				}
				// Continue homing leap motion
				if (dragonDistance > 10) {
					var dirX = dragonDx / dragonDistance;
					var dirY = dragonDy / dragonDistance;
					var speedMultiplier = Math.min(1.5, dragonDistance / 100);
					self.x += dirX * self.leapSpeed * speedMultiplier;
					self.y += dirY * self.leapSpeed * speedMultiplier;
					self.scaleX = self.initialScale * 0.75;
					self.scaleY = self.initialScale * 0.75;
				}
				// Add safety timeout to prevent infinite leaps
				self.leapDuration = (self.leapDuration || 0) + 1;
				if (self.leapDuration > 100) {
					self.state = FALLING;
					self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
					self.fallSpeed = 2;
					self.acceleration = 0.2;
				}
				break;
			case ATTACHED:
				// Stick to dragon position
				self.x = dragon.x;
				self.y = dragon.y;
				// Check for shake-off
				if (dragon.currentShakeSpeed > 30) {
					// Threshold for shake-off
					self.state = FALLING;
					self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
					self.fallSpeed = 2;
					self.acceleration = 0.2;
					break;
				}
				// Pulsing animation
				self.animTick++;
				if (self.animTick >= self.pulseRate) {
					self.animTick = 0;
					// Pulse between 0.7 and 0.8 scale
					tween(self, {
						scaleX: self.initialScale * (self.isPulsedOut ? 0.7 : 0.8),
						scaleY: self.initialScale * (self.isPulsedOut ? 0.7 : 0.8)
					}, {
						duration: 200,
						easing: tween.easeOut
					});
					self.isPulsedOut = !self.isPulsedOut;
					dragon.flashDamage(2);
				}
				break;
			case FALLING:
				self.rotation += self.rotationSpeed;
				self.fallSpeed += self.acceleration;
				self.y += self.fallSpeed;
				// Check for shadow collision with explosion flag
				if (self.y >= dragonShadow.y && !self.hasExploded) {
					self.hasExploded = true;
					// Create MUCH bigger explosion with red tint
					for (var i = 0; i < 20; i++) {
						defeatParticlePool.spawn(self.x, self.y, 0xff0000); // Red tint (0xff0000)
					}
					score += 50;
					scorePopupPool.spawn(self.x, self.y, 50);
					scoreTxt.setText(score);
					updateScoreMeter(score);
					LK.setScore(score);
					LK.getSound('enemyDefeat').play();
					trySpawnHealthPowerup(self.x, self.y);
					enemyPool.recycle(self);
				}
				break;
		}
		if (self.shadow) {
			self.shadow.update(self);
		}
	};
	self.hit = function () {
		self.health--;
		if (self.health <= 0) {
			if (self.state !== FALLING) {
				self.state = FALLING;
				self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
				self.fallSpeed = 2;
				self.acceleration = 0.2;
				return true;
			}
		}
		return false;
	};
	self.deactivate = function () {
		self.visible = false;
		runSprite.alpha = 1;
		runSpriteMirrored.alpha = 0;
		if (self.shadow) {
			enemyShadowPool.recycle(self.shadow);
			self.shadow = null;
		}
	};
	return self;
});
var EnemyArrow = Container.expand(function () {
	var self = Container.call(this);
	var arrow = self.attachAsset('enemyArrow', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.5,
		scaleY: 0.5
	});
	self.speed = 8;
	self.update = function () {
		if (!self.active) {
			return;
		}
		self.x += self.vx;
		self.y += self.vy;
		// Point arrow in direction of travel
		self.rotation = Math.atan2(self.vy, self.vx) + Math.PI / 2;
		if (self.y < 0 || self.y > 2732 || self.x < 0 || self.x > 2048) {
			enemyArrowPool.recycle(self);
		}
	};
	self.activate = function (x, y, targetX, targetY) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.active = true;
		// Calculate direction to target
		var dx = targetX - x;
		var dy = targetY - y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		self.vx = dx / dist * self.speed;
		self.vy = dy / dist * self.speed;
	};
	self.deactivate = function () {
		self.visible = false;
		self.active = false;
	};
	return self;
});
var EnemyShadow = Container.expand(function () {
	var self = Container.call(this);
	var shadow = self.attachAsset('enemyShadow', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.3,
		scaleX: 1,
		scaleY: 0.3
	});
	// In the EnemyShadow class, update method (around line 1018)
	self.update = function (enemy) {
		if (!enemy || !enemy.visible || enemy.hasExploded) {
			self.visible = false;
			return;
		}
		self.visible = true;
		// Always follow enemy's X position
		self.x = enemy.x;
		// For running enemies, shadow is slightly below them
		if (enemy.state === 'running') {
			self.y = enemy.y + 200; // Shadow slightly below enemy
		}
		// For leaping enemies, shadow moves to dragon shadow position
		else if (enemy.state === 'leaping') {
			self.y = dragonShadow.y + 50; // Position just below dragon shadow
		}
		// For attached enemies, follow dragon shadow
		else if (enemy.state === 'attached') {
			self.y = dragonShadow.y + 50; // Keep following dragon shadow
		}
		// For falling enemies, shadow holds last position
		else if (enemy.state === 'falling') {
			// Y position stays the same
		}
		// Special case for EnemyTwo type
		else if (enemy.type === 2) {
			self.y = enemy.y + 600; // Position higher for enemy type 2
		}
		// Scale shadow based on enemy's scale
		shadow.scaleX = enemy.scaleX * 1.2;
		shadow.scaleY = enemy.scaleX * 0.3;
	};
	self.activate = function (x, y, enemyScale) {
		self.x = x;
		self.y = y + 200; // Initially position shadow slightly below enemy
		self.visible = true;
		shadow.scaleX = (enemyScale || 1) * 1.2;
		shadow.scaleY = (enemyScale || 1) * 0.3;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var EnemyThree = Container.expand(function () {
	var self = Container.call(this);
	// States
	var GROUNDED = 'grounded';
	var FLYING = 'flying';
	// Main sprite
	var sprite = self.attachAsset('enemy3', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Jet flames
	var leftFlame = new JetFlame();
	var rightFlame = new JetFlame();
	self.addChild(leftFlame);
	self.addChild(rightFlame);
	// Properties
	self.health = 1;
	self.state = GROUNDED;
	self.hasExploded = false;
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.stateDuration = 0;
		self.visible = true;
		self.state = GROUNDED;
		self.health = 1;
		self.hasExploded = false;
		// Add this line to create the shadow
		self.shadow = enemyShadowPool.spawn(x, y, self.scaleX);
		// Position flames at percentage-based positions
		var flameY = sprite.height * 0.45;
		var flameX = sprite.width * 0.15;
		leftFlame.x = -flameX;
		leftFlame.y = flameY;
		rightFlame.x = flameX;
		rightFlame.y = flameY;
		// Initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		var scale = 0.5 + progress;
		self.scaleX = scale;
		self.scaleY = scale;
	};
	self.startFlying = function () {
		self.state = FLYING;
		// Calculate rough trajectory toward dragon
		var dx = dragon.x - self.x;
		var dy = dragon.y - self.y;
		var angle = Math.atan2(dy, dx);
		// Add intentional inaccuracy (they're bad at this)
		angle += (Math.random() - 0.5) * 0.5; // Β±0.25 radians of error
		// Set velocities
		var speed = 8;
		self.vx = Math.cos(angle) * speed;
		self.vy = Math.sin(angle) * speed;
		// Start jet flames
		leftFlame.startPulse();
		rightFlame.startPulse();
	};
	self.update = function () {
		if (!self.visible) {
			return;
		}
		if (self.state === FLYING) {
			self.stateDuration++;
		}
		switch (self.state) {
			case GROUNDED:
				// Move with background scroll
				var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
				var speed = (flyingBackground.scrollSpeed * 0.05 + flyingBackground.scrollSpeed * (progress * 2.5)) * 0.8;
				self.y -= speed;
				// Scale with distance
				var scale = 0.5 + progress;
				self.scaleX = scale;
				self.scaleY = scale;
				// Check for ignition trigger
				if (self.y <= dragonShadow.y + 50) {
					self.startFlying();
				}
				break;
			case FLYING:
				if (self.stateDuration === 1) {
					LK.getSound('jetPack').play(); // Play jetPack sound effect
				}
				// Update position
				self.x += self.vx;
				self.y += self.vy;
				// Create jet particles
				if (Math.random() < 0.3) {
					var particle = particlePool.spawn(self.x + leftFlame.x, self.y + leftFlame.y);
					if (particle) {
						particle.vy = Math.abs(particle.vy); // Force downward
					}
					particle = particlePool.spawn(self.x + rightFlame.x, self.y + rightFlame.y);
					if (particle) {
						particle.vy = Math.abs(particle.vy); // Force downward
					}
				}
				// Check bounds
				if (self.y < -100 || self.y > 2732 || self.x < -100 || self.x > 2148) {
					enemyThreePool.recycle(self);
				}
				break;
		}
		if (self.shadow) {
			self.shadow.update(self);
		}
		// In EnemyThree class, modify the part of the update method that handles the shadow:
		// Update shadow position
		if (self.shadow) {
			if (self.state === GROUNDED) {
				self.shadow.y = self.y + 200; // Shadow slightly below enemy
				self.shadow.x = self.x;
			} else if (self.state === FLYING) {
				self.shadow.y = dragonShadow.y + 50;
				self.shadow.x = self.x;
				// Don't update Y position to let it stay where it was
			}
			// Scale shadow based on enemy's scale
			var shadowSprite = self.shadow.getChildAt(0);
			shadowSprite.scaleX = self.scaleX * 1.2;
			shadowSprite.scaleY = self.scaleX * 0.3;
			// Update shadow alpha based on height
			var heightRatio = self.y / 2732;
			shadowSprite.alpha = 0.3 + heightRatio * 0.2;
		}
	};
	self.hit = function () {
		self.health--;
		if (self.health <= 0 && !self.hasExploded) {
			self.hasExploded = true;
			// Create explosion
			for (var i = 0; i < 20; i++) {
				defeatParticlePool.spawn(self.x, self.y, 0xff0000);
			}
			score += 25;
			scorePopupPool.spawn(self.x, self.y, 25);
			scoreTxt.setText(score.toString());
			updateScoreMeter(score);
			LK.setScore(score);
			LK.getSound('enemyDefeat').play();
			trySpawnHealthPowerup(self.x, self.y);
			enemyThreePool.recycle(self);
			return true;
		}
		return false;
	};
	self.deactivate = function () {
		self.visible = false;
		if (self.shadow) {
			enemyShadowPool.recycle(self.shadow);
			self.shadow = null;
		}
		leftFlame.deactivate();
		rightFlame.deactivate();
	};
	return self;
});
var EnemyTwo = Container.expand(function () {
	var self = Container.call(this);
	var sprite = self.attachAsset('enemy2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Properties
	self.health = 1;
	self.type = 2; // For scoring
	self.state = 'approaching'; // approaching, holding
	self.holdDistance = 800;
	self.bobOffset = 0;
	self.bobSpeed = 0.05;
	self.lastShotTime = 0;
	self.shotInterval = 2000; // 2 seconds
	self.activate = function (x, y) {
		self.visible = true;
		self.x = x;
		self.y = y;
		self.state = 'approaching';
		self.health = 1;
		self.rotation = 0;
		self.hasExploded = false; // Make sure this flag is set
		// Ensure shadow is created and stored
		if (!self.shadow) {
			self.shadow = enemyShadowPool.spawn(x, y, self.scaleX);
		}
		// Moving direction
		self.moveRight = x < 1024; // If spawned on left side, move right
		// Initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		self.scaleX = 0.5 + progress;
		self.scaleY = 0.5 + progress;
	};
	self.update = function () {
		if (!self.visible) {
			return;
		}
		switch (self.state) {
			case 'approaching':
				// Bobbing motion
				self.bobOffset = Math.sin(LK.ticks * self.bobSpeed) * 50;
				// Move towards dragon
				var dx = dragon.x - self.x;
				var dy = dragon.y - self.y + self.bobOffset;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > self.holdDistance) {
					self.x += dx * 0.01; // Reduced from 0.02
					self.y += dy * 0.01; // Reduced from 0.02
					// Modified scale calculation to maintain larger size
					var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
					self.scaleX = 0.7 + progress * 0.5; // Modified from 0.5 + progress
					self.scaleY = 0.7 + progress * 0.5; // Modified from 0.5 + progress
				} else {
					self.state = 'holding';
				}
				break;
			case 'holding':
				// Maintain position relative to dragon
				var dx = dragon.x - self.x;
				var targetX = self.x + dx * 0.01;
				// Keep on screen
				targetX = Math.max(100, Math.min(1948, targetX));
				self.x = targetX;
				// Stay below dragon with offset
				var targetY = dragon.y + 800; // Stay 200 pixels below dragon
				var currentY = self.y - self.bobOffset; // Remove bobbing to get true position
				self.y = currentY + (targetY - currentY) * 0.1; // Smooth movement to target
				// Apply bobbing to final position
				self.y += self.bobOffset;
				// Shoot at intervals
				var now = Date.now();
				if (now - self.lastShotTime >= self.shotInterval) {
					self.shoot();
					self.lastShotTime = now;
				}
				break;
			case 'falling':
				self.rotation += self.rotationSpeed;
				self.fallSpeed += self.acceleration;
				self.y += self.fallSpeed;
				// Check for ground collision
				if (self.shadow && self.y >= self.shadow.y && !self.hasExploded) {
					self.hasExploded = true;
					for (var i = 0; i < 20; i++) {
						defeatParticlePool.spawn(self.x, self.y, 0xff0000);
					}
					score += 75;
					scorePopupPool.spawn(self.x, self.y, 75);
					scoreTxt.setText(score);
					updateScoreMeter(score);
					LK.setScore(score);
					LK.getSound('enemyDefeat').play();
					trySpawnHealthPowerup(self.x, self.y);
					enemyTwoPool.recycle(self);
				}
				break;
		}
		if (self.shadow) {
			self.shadow.update(self);
		}
	};
	self.shoot = function () {
		var arrow = enemyArrowPool.spawn(self.x, self.y);
		if (arrow) {
			arrow.activate(self.x, self.y, dragon.x, dragon.y);
			LK.getSound('arrow').play(); // Play arrow sound effect
		}
	};
	self.hit = function () {
		self.health--;
		if (self.health <= 0 && self.state !== 'falling') {
			// Prevent double-triggers
			if (Math.random() < 0.5) {
				// Mid-air explosion
				for (var i = 0; i < 20; i++) {
					defeatParticlePool.spawn(self.x, self.y, 0xff0000);
				}
				score += 75;
				scorePopupPool.spawn(self.x, self.y, 75);
				scoreTxt.setText(score);
				updateScoreMeter(score);
				LK.setScore(score);
				LK.getSound('enemyDefeat').play();
				trySpawnHealthPowerup(self.x, self.y);
				enemyTwoPool.recycle(self);
			} else {
				// Fall and explode
				self.state = 'falling';
				self.rotationSpeed = (Math.random() * 0.1 + 0.05) * (Math.random() < 0.5 ? 1 : -1);
				self.fallSpeed = 2;
				self.acceleration = 0.2;
			}
			return true;
		}
		return false;
	};
	self.deactivate = function () {
		self.visible = false;
		if (self.shadow) {
			enemyShadowPool.recycle(self.shadow);
			self.shadow = null;
		}
	};
	return self;
});
var FieldElement = Container.expand(function () {
	var self = Container.call(this);
	var element = self.attachAsset('fieldElement', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y, scale, alpha) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.speedY = 2 + Math.random() * 3;
		self.initialX = x;
		element.scaleX = scale;
		element.scaleY = scale * 0.8;
		element.alpha = alpha || 0.9;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var FireParticle = Container.expand(function () {
	var self = Container.call(this);
	var particle = self.attachAsset('fireParticle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		self.age++;
		// Update alpha
		var lifePercent = self.age / self.lifespan;
		particle.alpha = 1 - lifePercent;
		// Recycle if lifetime is over OR particle is off screen
		if (lifePercent >= 1 || self.y < 0 || self.y > 2732 ||
		// Screen height
		self.x < 0 || self.x > 2048) {
			// Screen width
			particlePool.recycle(self);
		}
	};
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.vx = Math.random() * 8 - 4; // Doubled velocity range
		self.vy = -(Math.random() * 4 + 2); // Make particles move upward
		self.lifespan = 45 + Math.random() * 30; // Increased lifespan
		self.age = 0;
		particle.alpha = 1;
		// Add scaling
		particle.scaleX = 0.5 + Math.random() * 0.5;
		particle.scaleY = 0.5 + Math.random() * 0.5;
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
// In the Fireball class, update the properties and update method
var Fireball = Container.expand(function () {
	var self = Container.call(this);
	var fireballGraphic = self.attachAsset('fireball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10;
	self.vx = 0;
	// Add these new properties
	self.weaveDirection = 1; // Will be set to 1 or -1 on activate
	self.weaveAmplitude = 50; // Adjust this to control width of weave
	self.weaveFrequency = 0.1; // Adjust this to control speed of weave
	self.initialY = 0; // Track starting Y position
	self.update = function () {
		if (!self.active) {
			return;
		}
		// Update base position along trajectory
		self.y += self.speed;
		self.x += self.vx;
		// Add weaving motion
		var distanceTraveled = self.y - self.initialY;
		var weaveOffset = Math.sin(distanceTraveled * self.weaveFrequency) * self.weaveAmplitude * self.weaveDirection;
		self.x += weaveOffset;
		// Calculate rotation based only on base trajectory, ignoring weave
		var angle = Math.atan2(self.speed, self.vx) - Math.PI / 2;
		self.rotation = angle;
		// Create fire trail particles
		if (Math.random() < 0.3) {
			particlePool.spawn(self.x + (Math.random() * 40 - 20), self.y + 20);
		}
		// In Fireball class update method, replace the recycle check with:
		// In Fireball class update method, replace the recycle check with:
		var groundImpactY = 2732 * 0.9;
		// Make impact decision only when first crossing the threshold
		if (self.y > groundImpactY && self.lastY <= groundImpactY && !self.hasImpacted && self.x > 100 && self.x < 1948) {
			if (Math.random() < 0.5) {
				self.hasImpacted = true;
				flamePool.spawn(self.x, groundImpactY);
				scorchPool.spawn(self.x, groundImpactY);
				// Spawn more particles
				for (var i = 0; i < 15; i++) {
					// Increased from 8 to 15
					var particle = particlePool.spawn(self.x + (Math.random() * 40 - 20), groundImpactY);
					if (particle) {
						particle.vy = -(Math.random() * 6 + 3); // More upward velocity
						particle.vx = (Math.random() - 0.5) * 8; // More spread
					}
				}
				fireballPool.recycle(self);
				return;
			}
		}
		// Track last Y position
		self.lastY = self.y;
		// Only recycle if off screen
		if (self.y > 2732 || self.x < -100 || self.x > 2148) {
			fireballPool.recycle(self);
		}
	};
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.initialY = y;
		self.lastY = y;
		self.visible = true;
		self.active = true;
		self.hasImpacted = false;
		self.vx = 0;
		self.rotation = 0;
		fireballGraphic.alpha = 1;
	};
	self.deactivate = function () {
		self.visible = false;
		self.active = false;
		// Clear any references that might cause memory leaks
		self.currentTween = null;
	};
	return self;
});
var FlameEffect = Container.expand(function () {
	var self = Container.call(this);
	var flame = self.attachAsset('flame', {
		anchorX: 0.5,
		anchorY: 1.0,
		scaleX: 1,
		scaleY: 0.5
	});
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.age = 0;
		flame.scaleX = 0.75;
		flame.scaleY = 0.5;
		var initialHeight = flame.height * flame.scaleY;
		var targetScale = 2.5;
		if (self.currentTween) {
			self.currentTween.stop();
		}
		self.currentTween = tween(flame, {
			scaleY: targetScale,
			y: -(initialHeight * (targetScale - 0.5)) / 2,
			// Offset upward to compensate for scaling
			alpha: 1
		}, {
			duration: 400,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				flamePool.recycle(self);
			}
		});
	};
	self.deactivate = function () {
		self.visible = false;
		if (self.currentTween) {
			self.currentTween.stop();
			self.currentTween = null;
		}
		flame.y = 0; // Reset position
	};
	return self;
});
var FlyingBackground = Container.expand(function () {
	var self = Container.call(this);
	// Create bottom container
	self.bottomContainer = new Container();
	self.addChild(self.bottomContainer);
	// Store the horizon line
	self.horizonY = 2732 / 2;
	self.totalHeight = 2732 - self.horizonY;
	self.fieldStripes = [];
	// Create field stripes (keep this the same as original)
	var nbStripes = 30;
	var lastY = self.horizonY + 10;
	var stripe = self.bottomContainer.attachAsset('fieldStripes', {
		anchorX: 0.5,
		anchorY: 0,
		x: 2048 / 2,
		y: lastY
	});
	var progress = Math.max(0, lastY - self.horizonY) / self.totalHeight;
	stripe.height = 1 + 400 * progress;
	self.fieldStripes.push({
		sprite: stripe,
		progress: progress
	});
	for (var i = 1; i < nbStripes; i++) {
		var spacing = 400 * (lastY - self.horizonY) / self.totalHeight;
		var y = lastY + spacing;
		var stripe = self.bottomContainer.attachAsset('fieldStripes', {
			anchorX: 0.5,
			anchorY: 0,
			x: 2048 / 2,
			y: y
		});
		var progress = Math.max(0, y - self.horizonY) / self.totalHeight;
		stripe.height = 1 + 400 * progress;
		self.fieldStripes.push({
			sprite: stripe,
			progress: progress
		});
		lastY = y;
	}
	// Create top container
	self.topContainer = new Container();
	self.addChild(self.topContainer);
	// Create sky background in top container
	var sky = self.topContainer.attachAsset('skyBackground', {
		anchorX: 0.5,
		anchorY: 1.0,
		x: 2048 / 2,
		y: self.horizonY + 10
	});
	// Field scroll speed
	self.scrollSpeed = 4;
	// Create object pools
	self.cloudPool = new ObjectPool(Cloud, 15);
	self.fieldElementPool = new ObjectPool(FieldElement, 20);
	// Add pools to containers
	self.topContainer.addChild(self.cloudPool);
	self.bottomContainer.addChild(self.fieldElementPool);
	// Initialize clouds
	for (var i = 0; i < 8; i++) {
		// Place clouds above the screen
		var startY = -600 - Math.random() * 600;
		var distanceFromHorizon = Math.abs(startY - self.horizonY);
		var startScale = 0.5 + distanceFromHorizon / 800;
		var cloud = self.cloudPool.spawn(Math.random() * 2048, startY, startScale, 0.8);
		if (cloud) {
			cloud.horizonY = self.horizonY;
		}
	}
	// Initialize field elements
	for (var j = 0; j < 12; j++) {
		var fieldStartY = self.horizonY + Math.random() * (2732 - self.horizonY);
		var fieldDistanceFromHorizon = Math.abs(fieldStartY - self.horizonY);
		var fieldStartScale = 0.5 + fieldDistanceFromHorizon / 1000;
		var fieldElement = self.fieldElementPool.spawn(Math.random() * 2048, fieldStartY, fieldStartScale, 0.9);
		if (fieldElement) {
			fieldElement.horizonY = self.horizonY;
		}
	}
	self.update = function () {
		// Update field stripes (keep original code)
		for (var i = 0; i < self.fieldStripes.length; i++) {
			var stripe = self.fieldStripes[i];
			stripe.progress = Math.max(0, stripe.sprite.y - self.horizonY) / self.totalHeight;
			var tempSpeed = self.scrollSpeed * 0.05 + self.scrollSpeed * (stripe.progress * 3);
			stripe.sprite.y -= tempSpeed;
		}
		// Sort stripes by Y position
		self.fieldStripes.sort(function (a, b) {
			return a.sprite.y - b.sprite.y;
		});
		// Reset stripes that moved above horizon
		for (var i = 0; i < self.fieldStripes.length; i++) {
			if (self.fieldStripes[i].sprite.y < self.horizonY) {
				var lowestStripe = self.fieldStripes[self.fieldStripes.length - 1];
				self.fieldStripes[i].sprite.y = lowestStripe.sprite.y + 400 * (lowestStripe.sprite.y - self.horizonY) / self.totalHeight;
				self.fieldStripes[i].progress = Math.max(0, self.fieldStripes[i].sprite.y - self.horizonY) / self.totalHeight;
			}
		}
		// Re-sort after repositioning
		self.fieldStripes.sort(function (a, b) {
			return a.sprite.y - b.sprite.y;
		});
		// Adjust stripe heights
		for (var i = 0; i < self.fieldStripes.length - 1; i++) {
			var currentStripe = self.fieldStripes[i];
			var nextStripe = self.fieldStripes[i + 1];
			currentStripe.sprite.height = nextStripe.sprite.y - currentStripe.sprite.y;
		}
		// Handle last stripe
		var lastStripe = self.fieldStripes[self.fieldStripes.length - 1];
		lastStripe.sprite.height = Math.max(1 + 400 * lastStripe.progress, self.horizonY + self.totalHeight - lastStripe.sprite.y + 100);
		// Update clouds and field elements
		updateCloudPool();
		updateFieldElementPool();
	};
	function updateCloudPool() {
		var activeObjects = self.cloudPool.getActiveObjects();
		for (var i = 0; i < activeObjects.length; i++) {
			var cloud = activeObjects[i];
			// Move cloud toward horizon
			cloud.y += cloud.speedY;
			cloud.x += cloud.speedX;
			// Get the cloud's sprite
			var sprite = cloud.getChildAt(0);
			// Calculate scale based on distance from horizon
			var distanceFactor = Math.max(0.05, (cloud.y - self.horizonY) / -500);
			sprite.scaleX = distanceFactor;
			sprite.scaleY = distanceFactor * 0.8;
			// Adjust alpha for fade effect near horizon
			sprite.alpha = Math.min(0.9, distanceFactor);
			// Reset cloud if it reaches horizon or gets too small
			if (cloud.y >= self.horizonY - 10 || sprite.scaleX < 0.1) {
				// Recycle and spawn new cloud above screen
				self.cloudPool.recycle(cloud);
				var newCloud = self.cloudPool.spawn(Math.random() * 2048,
				// Random x position
				-600 - Math.random() * 400,
				// Above screen
				0.5 + 600 / 800,
				// Scale based on distance
				0.8);
				if (newCloud) {
					newCloud.horizonY = self.horizonY;
				}
			}
		}
	}
	function updateFieldElementPool() {
		var activeObjects = self.fieldElementPool.getActiveObjects();
		for (var j = 0; j < activeObjects.length; j++) {
			var element = activeObjects[j];
			// Calculate progress based on distance from horizon
			var progress = Math.max(0, element.y - self.horizonY) / self.totalHeight;
			// Calculate speed using same logic as stripes
			var tempSpeed = self.scrollSpeed * 0.05 + self.scrollSpeed * (progress * 3);
			// Move element toward horizon
			element.y -= tempSpeed;
			// Get the element's sprite
			var sprite = element.getChildAt(0);
			// Calculate scale based on distance from horizon
			var fieldDistanceFactor = Math.max(0.05, (element.y - self.horizonY) / 300);
			sprite.scaleX = fieldDistanceFactor * 1.2;
			sprite.scaleY = fieldDistanceFactor * 1.2;
			// Adjust alpha for fade effect
			//sprite.alpha = Math.min(0.9, fieldDistanceFactor);
			// Reset element if it reaches horizon
			if (element.y <= self.horizonY + 10 || sprite.scaleX < 0.1) {
				// Recycle and spawn new element
				self.fieldElementPool.recycle(element);
				// Calculate position for new element
				var section = Math.floor(Math.random() * 8);
				var sectionWidth = 2048 / 8;
				var newX = section * sectionWidth + Math.random() * sectionWidth;
				var newY = 2732 + Math.random() * 600;
				var newScale = (newY - self.horizonY) / 300;
				var newElement = self.fieldElementPool.spawn(newX, newY, newScale, 0.9);
				if (newElement) {
					newElement.horizonY = self.horizonY;
					newElement.initialX = newX;
				}
			}
			element.zIndex = element.y;
		}
		// After updating all elements, sort them by z-index
		activeObjects.sort(function (a, b) {
			return a.y - b.y; // Sort by y position (smaller y values first)
		});
		// Remove and re-add in the sorted order
		for (var k = 0; k < activeObjects.length; k++) {
			var element = activeObjects[k];
			self.bottomContainer.removeChild(element);
			self.bottomContainer.addChild(element);
		}
	}
	return self;
});
// Modify the HealthPopup class
var HealthPopup = Container.expand(function () {
	var self = Container.call(this);
	var text = new Text2('+10', {
		size: 150,
		fill: 0x00FF00,
		// Green
		stroke: 0x000000,
		strokeThickness: 3
	});
	text.anchor.set(0.5, 0.5);
	self.addChild(text);
	// Initially hide the popup
	self.visible = false;
	self.show = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		text.scaleX = 0.1;
		text.scaleY = 0.1;
		text.y = 0; // Reset position before animation
		if (self.currentTween) {
			self.currentTween.stop();
		}
		self.currentTween = tween(text, {
			scaleX: 1.5,
			scaleY: 1.5,
			y: -50
		}, {
			duration: 300,
			easing: tween.easeOutBack,
			onFinish: function onFinish() {
				tween(text, {
					alpha: 0,
					y: -100
				}, {
					duration: 400,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.visible = false;
						text.alpha = 1;
						text.y = 0;
					}
				});
			}
		});
	};
	return self;
});
var HealthPowerup = Container.expand(function () {
	var self = Container.call(this);
	var heart = self.attachAsset('heart', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.age = 0;
		heart.scaleX = heart.scaleY = 1;
	};
	self.update = function () {
		self.age++;
		// Wave pattern movement
		self.x += Math.sin(self.age * 0.05) * 2;
		self.y -= 3; // Float upward
		// Pulse scale
		var pulse = 1 + Math.sin(self.age * 0.1) * 0.2;
		heart.scaleX = heart.scaleY = pulse;
		// Remove if off screen
		if (self.y < -50) {
			healthPowerupPool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var JetFlame = Container.expand(function () {
	var self = Container.call(this);
	var flame = self.attachAsset('flame', {
		anchorX: 0.5,
		anchorY: 0,
		// Keep bottom anchor for natural flame shape
		scaleX: 1,
		scaleY: 0.5,
		rotation: Math.PI // 180 degrees to point downward
	});
	self.startPulse = function () {
		flame.scaleX = 0.5;
		flame.scaleY = 0.3;
		flame.alpha = 0.8;
		self.pulse();
	};
	self.pulse = function () {
		if (self.currentTween) {
			self.currentTween.stop();
		}
		self.currentTween = tween(flame, {
			scaleX: 0.75,
			scaleY: 0.6,
			alpha: 1
		}, {
			duration: 300,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				self.currentTween = tween(flame, {
					scaleX: 0.5,
					scaleY: 0.3,
					alpha: 0.8
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: self.pulse
				});
			}
		});
	};
	self.deactivate = function () {
		if (self.currentTween) {
			self.currentTween.stop();
			self.currentTween = null;
		}
		flame.scaleY = 0.5;
	};
	return self;
});
var ObjectPool = Container.expand(function (ObjectClass, size) {
	var self = Container.call(this);
	var objects = [];
	var activeCount = 0;
	for (var i = 0; i < size; i++) {
		var obj = new ObjectClass();
		if (typeof obj.update !== 'function') {
			obj.update = function () {}; // Provide a default update method if not defined
		}
		obj.visible = false;
		obj._poolIndex = i;
		objects.push(obj);
		self.addChild(obj);
	}
	self.spawn = function (x, y, params) {
		if (activeCount >= objects.length) {
			return null;
		}
		var obj = objects[activeCount];
		activeCount++; // Increment AFTER getting object
		obj.visible = true;
		obj.activate(x, y, params);
		return obj;
	};
	self.recycle = function (obj) {
		if (!obj || typeof obj._poolIndex !== 'number' || obj._poolIndex >= activeCount) {
			return;
		}
		activeCount--; // Decrement count
		// Swap with last active object if needed
		if (obj._poolIndex < activeCount) {
			var temp = objects[activeCount];
			objects[activeCount] = obj;
			objects[obj._poolIndex] = temp;
			// Update indices
			temp._poolIndex = obj._poolIndex;
			obj._poolIndex = activeCount;
		}
		obj.deactivate();
		obj.visible = false;
	};
	self.recycleAll = function () {
		while (activeCount > 0) {
			self.recycle(objects[0]);
		}
	};
	self.update = function () {
		for (var i = 0; i < activeCount; i++) {
			objects[i].update();
		}
	};
	self.getActiveObjects = function () {
		return objects.slice(0, activeCount);
	};
	return self;
});
var ProgressMeter = Container.expand(function () {
	var self = Container.call(this);
	// Create meter background (now horizontal)
	var meter = self.attachAsset('meter', {
		anchorX: 0,
		anchorY: 0.5,
		scaleX: 1.2,
		// Adjust width to preference
		scaleY: 0.6,
		// Make thinner
		tint: 0x666666
	});
	// Progress icons
	var dragonIcon = self.attachAsset('dragonHead', {
		anchorX: 0.5,
		anchorY: 0.7,
		scaleX: 0.9,
		scaleY: 0.9
	});
	var bossIcon = self.attachAsset('skull', {
		anchorX: 0.5,
		anchorY: 0.7
	});
	// Position at top center
	// Position elements relative to meter center
	var totalWidth = meter.width * 1.2 + 120; // Include icon spaces
	self.x = 2048 / 2 - totalWidth / 2; // Center the whole assembly
	self.y = 80;
	// Position icons relative to meter edges
	dragonIcon.x = 0; // Left icon at start
	dragonIcon.y = meter.height / 2;
	bossIcon.x = totalWidth; // Right icon at end
	bossIcon.y = meter.height / 2;
	// Center meter between icons
	meter.x = 60; // Space for left icon
	self.updateProgress = function (progress) {
		dragonIcon.x = progress * (totalWidth - 60); // Move between start and end positions
	};
	return self;
});
var ScorchMark = Container.expand(function () {
	var self = Container.call(this);
	var mark = self.attachAsset('scorchMark', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.8
	});
	self.activate = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
		self.speedY = flyingBackground.scrollSpeed;
		// Initial scale based on distance from horizon
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		mark.scaleX = 0.5 + progress;
		mark.scaleY = (0.5 + progress) * 0.8;
	};
	self.update = function () {
		var progress = Math.max(0, self.y - flyingBackground.horizonY) / (2732 - flyingBackground.horizonY);
		// Drastically reduce base speed to match field elements
		var tempSpeed = 0.2 + progress * 3;
		self.y -= tempSpeed;
		mark.scaleX = 0.5 + progress;
		mark.scaleY = (0.5 + progress) * 0.8;
		mark.alpha = Math.min(0.8, progress);
		if (self.y <= flyingBackground.horizonY) {
			scorchPool.recycle(self);
		}
	};
	self.deactivate = function () {
		self.visible = false;
	};
	return self;
});
var ScorePopup = Container.expand(function () {
	var self = Container.call(this);
	// Create text with white color instead of red
	var scoreTxt = new Text2('', {
		size: 120,
		fill: 0xFFFFFF,
		// White color
		stroke: 0x000000,
		strokeThickness: 3
	});
	scoreTxt.anchor.set(0.5, 0.5);
	self.addChild(scoreTxt);
	self.activate = function (x, y, amount, color) {
		self.x = x;
		self.y = y;
		self.visible = true;
		scoreTxt.setText('+' + amount);
		// Special case for boss defeat score
		if (amount === 5000) {
			scoreTxt.size = 300; // Much larger text
			color = 0xFFD700; // Gold color
		} else {
			scoreTxt.size = 120; // Normal size
		}
		// Apply tint if provided
		if (color !== undefined) {
			scoreTxt.tint = color;
		} else {
			scoreTxt.tint = 0xFF0000; // Default red tint
		}
		scoreTxt.scaleX = 0.1;
		scoreTxt.scaleY = 0.1;
		if (self.currentTween) {
			self.currentTween.stop();
		}
		// Special animation for boss defeat
		if (amount === 5000) {
			self.currentTween = tween(scoreTxt, {
				scaleX: 2.5,
				scaleY: 2.5,
				y: -150 // Move higher for boss defeat
			}, {
				duration: 600,
				// Longer duration
				easing: tween.easeOutBack,
				onFinish: function onFinish() {
					tween(scoreTxt, {
						alpha: 0,
						y: -250 // Float up higher
					}, {
						duration: 800,
						// Longer fade
						easing: tween.easeIn,
						onFinish: function onFinish() {
							scorePopupPool.recycle(self);
						}
					});
				}
			});
		} else {
			// Original animation for regular scores
			self.currentTween = tween(scoreTxt, {
				scaleX: 1.5,
				scaleY: 1.5,
				y: -50
			}, {
				duration: 300,
				easing: tween.easeOutBack,
				onFinish: function onFinish() {
					tween(scoreTxt, {
						alpha: 0,
						y: -100
					}, {
						duration: 400,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							scorePopupPool.recycle(self);
						}
					});
				}
			});
		}
	};
	self.deactivate = function () {
		self.visible = false;
		scoreTxt.alpha = 1;
		scoreTxt.y = 0;
		scoreTxt.tint = 0xFFFFFF; // Reset to white (no tint)
		if (self.currentTween) {
			self.currentTween.stop();
		}
	};
	return self;
});
var TitleScreen = Container.expand(function () {
	var self = Container.call(this);
	var fadeOverlay = self.attachAsset('particle', {
		anchorX: 0,
		anchorY: 0,
		scaleX: 2048,
		scaleY: 2732,
		tint: 0x000000,
		alpha: 1
	});
	var titleImage = self.attachAsset('titleimage', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0
	});
	var startButton = self.attachAsset('startbutton', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0,
		scaleY: 0,
		alpha: 0
	});
	titleImage.x = 2048 / 2;
	titleImage.y = 2732 / 3;
	startButton.x = 2048 / 2;
	startButton.y = titleImage.y + 1100;
	self.start = function () {
		// Fade in title
		tween(fadeOverlay, {
			alpha: 0
		}, {
			duration: 1500,
			easing: tween.easeOut
		});
		tween(titleImage, {
			alpha: 1,
			scaleX: 1,
			// Add scale pulse start
			scaleY: 1 // Add scale pulse start
		}, {
			duration: 1500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Add pulsing animation
				function pulseTitle() {
					tween(titleImage, {
						tint: 0xFFFF00,
						scaleX: 1.1,
						scaleY: 1.1
					}, {
						duration: 1100,
						easing: tween.easeInOut,
						onFinish: function onFinish() {
							tween(titleImage, {
								tint: 0xFFA500,
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 1100,
								easing: tween.easeInOut,
								onFinish: pulseTitle
							});
						}
					});
				}
				pulseTitle();
				// Grow button
				tween(startButton, {
					scaleX: 1,
					scaleY: 1,
					alpha: 1
				}, {
					duration: 800,
					easing: tween.easeOutBack,
					onFinish: function onFinish() {
						// Add pulsing animation
						function pulse() {
							tween(startButton, {
								tint: 0xFFFF00
							}, {
								duration: 1000,
								easing: tween.easeInOut,
								onFinish: function onFinish() {
									tween(startButton, {
										tint: 0xFFA500
									}, {
										duration: 1000,
										easing: tween.easeInOut,
										onFinish: pulse
									});
								}
							});
						}
						pulse();
					}
				});
			}
		});
	};
	startButton.down = function () {
		self.startGame();
		return true;
	};
	self.startGame = function () {
		// Prevent multiple clicks
		LK.getSound('dragonScream').play();
		startButton.down = null;
		// Fade out title elements
		tween(titleImage, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				// Enable gameplay
				gameActive = true;
				// Show UI
				dragonHealthBar.visible = true;
				scoreTxt.visible = true;
				scoreMeterBg.visible = true;
				progressMeter.visible = true;
				// Enable dragon and shadow
				dragon.visible = true;
				dragonShadow.visible = true;
				// Remove title screen
				game.removeChild(self);
			}
		});
		tween(startButton, {
			alpha: 0
		}, {
			duration: 500
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
function processCollisions() {
	var fireballs = fireballPool.getActiveObjects();
	var enemies = enemyPool.getActiveObjects();
	var enemiesTwo = enemyTwoPool.getActiveObjects();
	// Process enemy arrows first
	var arrows = enemyArrowPool.getActiveObjects();
	// Add after arrow collision checks in processCollisions()
	var enemiesThree = enemyThreePool.getActiveObjects();
	for (var i = enemiesThree.length - 1; i >= 0; i--) {
		var enemy = enemiesThree[i];
		var dx = enemy.x - dragon.x;
		var dy = enemy.y - dragon.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < 210 * enemy.scaleX) {
			// Adjust collision radius based on enemy scale
			// Create explosion effect
			for (var j = 0; j < 20; j++) {
				defeatParticlePool.spawn(enemy.x, enemy.y, 0xff0000);
			}
			enemyThreePool.recycle(enemy);
			dragon.flashDamage(6);
		}
	}
	// Add inside processCollisions() function, after the existing collision checks:
	// Check boss fist collisions with dragon
	if (boss && boss.activeFist) {
		var fist = boss.activeFist;
		var dx = fist.x - dragon.x;
		var dy = fist.y - dragon.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Use dragon's current scale for collision radius
		var collisionRadius = 150 * dragon.currentScale;
		if (distance < collisionRadius) {
			dragon.flashDamage(12);
			// Should the fist retract after hitting? Let me know if you want this behavior
		}
	}
	// Replace the existing fireball-boss collision check with this:
	if (boss && boss.state !== 'dying') {
		var fireballs = fireballPool.getActiveObjects();
		for (var i = fireballs.length - 1; i >= 0; i--) {
			var fireball = fireballs[i];
			var dx = fireball.x - boss.x;
			var dy = fireball.y - boss.y;
			// Use elliptical hitbox: wider horizontally, same vertically
			var horizontalRange = 300; // Wider horizontal hitbox (was effectively 100)
			var verticalRange = 100; // Keep the same vertical hitbox
			// Elliptical distance formula
			var ellipticalDist = Math.sqrt(dx * dx / (horizontalRange * horizontalRange) + dy * dy / (verticalRange * verticalRange));
			if (ellipticalDist < 1) {
				boss.damage(1);
				fireballPool.recycle(fireball);
			}
		}
	}
	// Replace the existing arrow collision check with:
	for (var i = arrows.length - 1; i >= 0; i--) {
		var arrow = arrows[i];
		var dx = arrow.x - dragon.x;
		var dy = arrow.y - dragon.y;
		// Only check collisions if arrow isn't below dragon
		if (arrow.y <= dragon.y + 50) {
			// Allow slight vertical tolerance
			// Wider horizontal check, original vertical bounds
			var horizontalDistance = Math.abs(dx);
			var verticalDistance = Math.abs(dy);
			// Check if within wing range (wider horizontally)
			if (horizontalDistance < 300 && verticalDistance < 75) {
				enemyArrowPool.recycle(arrow);
				// Flash dragon red (keep existing code)
				dragon.flashDamage(7);
			}
		}
	}
	var fireballs = fireballPool.getActiveObjects();
	var arrows = enemyArrowPool.getActiveObjects();
	for (var i = fireballs.length - 1; i >= 0; i--) {
		var fireball = fireballs[i];
		for (var j = arrows.length - 1; j >= 0; j--) {
			var arrow = arrows[j];
			var dx = fireball.x - arrow.x;
			var dy = fireball.y - arrow.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < 60) {
				// Small collision radius since these are projectiles
				// Create small explosion
				for (var k = 0; k < 8; k++) {
					// Fewer particles than full defeat
					var particle = defeatParticlePool.spawn(arrow.x + (Math.random() * 20 - 10),
					// Smaller spread
					arrow.y + (Math.random() * 20 - 10), 0xff0000 // Red tint
					);
					if (particle) {
						// Smaller scale for particles
						var sprite = particle.getChildAt(0);
						sprite.scaleX = 0.2;
						sprite.scaleY = 0.2;
					}
				}
				// Remove both projectiles
				fireballPool.recycle(fireball);
				enemyArrowPool.recycle(arrow);
				// Play explosion sound with lower volume
				LK.getSound('enemyDefeat').play({
					volume: 0.5
				});
				break; // Break inner loop since fireball is gone
			}
		}
	}
	// Process fireballs against both enemy types
	for (var i = fireballs.length - 1; i >= 0; i--) {
		var fireball = fireballs[i];
		// Check against type 1 enemies
		for (var j = enemies.length - 1; j >= 0; j--) {
			var enemy = enemies[j];
			// Check if enemy is fully on screen (accounting for scaled size)
			var enemyHeight = 403 * enemy.scaleY; // Original height * scale
			var enemyWidth = 200 * enemy.scaleX; // Original width * scale
			if (enemy.y > enemyHeight / 2 && enemy.y < 2732 - enemyHeight / 2 && enemy.x > enemyWidth / 2 && enemy.x < 2048 - enemyWidth / 2) {
				var dx = fireball.x - enemy.x;
				var dy = fireball.y - enemy.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 120 * enemy.scaleX) {
					enemy.hit();
					fireballPool.recycle(fireball);
					break;
				}
			}
		}
		// Check against type 2 enemies
		for (var j = enemiesTwo.length - 1; j >= 0; j--) {
			var enemy = enemiesTwo[j];
			var enemyHeight = 412.5 * enemy.scaleY;
			var enemyWidth = 550 * enemy.scaleX;
			if (enemy.y > enemyHeight / 2 && enemy.y < 2732 - enemyHeight / 2 && enemy.x > enemyWidth / 2 && enemy.x < 2048 - enemyWidth / 2) {
				var dx = fireball.x - enemy.x;
				var dy = fireball.y - enemy.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 170 * enemy.scaleX) {
					enemy.hit();
					fireballPool.recycle(fireball);
					break;
				}
			}
		}
		// Check against type 3 enemies
		for (var j = enemiesThree.length - 1; j >= 0; j--) {
			var enemy = enemiesThree[j];
			var enemyHeight = 253 * enemy.scaleY;
			var enemyWidth = 300 * enemy.scaleX;
			if (enemy.y > enemyHeight / 2 && enemy.y < 2732 - enemyHeight / 2 && enemy.x > enemyWidth / 2 && enemy.x < 2048 - enemyWidth / 2) {
				var dx = fireball.x - enemy.x;
				var dy = fireball.y - enemy.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 120 * enemy.scaleX) {
					enemy.hit();
					fireballPool.recycle(fireball);
					break;
				}
			}
		}
	}
	var powerups = healthPowerupPool.getActiveObjects();
	for (var i = powerups.length - 1; i >= 0; i--) {
		var powerup = powerups[i];
		var dx = powerup.x - dragon.x;
		var dy = powerup.y - dragon.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < 240) {
			dragon.health = Math.min(100, dragon.health + 10);
			dragonHealthBar.updateHealth(dragon.health / 100);
			LK.getSound('health').play();
			healthPowerupPool.recycle(powerup);
			healthPopup.show(powerup.x, powerup.y);
		}
	}
}
function trySpawnHealthPowerup(x, y) {
	if (Math.random() < 0.10) {
		// 10% chance 
		// 100% chance
		// 10% chance
		// 7% chance
		// 10% chance 
		// 15% chance
		var powerup = healthPowerupPool.spawn(x, y);
		if (powerup) {
			scorePopupPool.spawn(x, y - 50, "HEALTH", 0x00ff00);
		}
	}
}
// Set dark blue background for sky effect
game.setBackgroundColor(0x2c3e50);
// Game state variables
var score = 0;
var fireballPool = new ObjectPool(Fireball, 100);
var particlePool = new ObjectPool(FireParticle, 400);
var enemyPool = new ObjectPool(Enemy, 25);
var defeatParticlePool = new ObjectPool(DefeatParticle, 200);
var dustParticlePool = new ObjectPool(DustParticle, 100);
var enemyShadowPool = new ObjectPool(EnemyShadow, 50);
var enemyArrowPool = new ObjectPool(EnemyArrow, 50);
var enemyTwoPool = new ObjectPool(EnemyTwo, 25);
var enemyThreePool = new ObjectPool(EnemyThree, 25);
var flamePool = new ObjectPool(FlameEffect, 20);
var scorchPool = new ObjectPool(ScorchMark, 30);
var chainSegmentPool = new ObjectPool(ChainSegment, 30);
var scorePopupPool = new ObjectPool(ScorePopup, 20);
var healthPowerupPool = new ObjectPool(HealthPowerup, 10);
var bossFistPool = new ObjectPool(BossFist, 2); // Left and right fists
var boss = null; // Will be created when needed
var bossHealthBar = new BossHealthBar();
bossHealthBar.visible = false;
bossHealthBar.updateHealth(1.0);
var LEVEL_DURATION = 180 * 60; // 3 minutes at 60fps
var levelTimer = 0;
var progressMeter = new ProgressMeter();
var isFiring = false;
var lastFireTime = 0;
var fireRate = 200; // ms between fireballs
var enemy1StartTime = 30 * 60; // 30 seconds
var enemy2StartTime = 15 * 60; // 15 seconds
var enemy3StartTime = 5 * 60; // 5 seconds
var enemy1SpawnRate = 300; // ~3 seconds
var enemy2SpawnRate = 240; // ~4 seconds
var enemy3SpawnRate = 180; // ~5 seconds
var ENEMY1_MIN_RATE = 150; // Half of 300
var ENEMY2_MIN_RATE = 120; // Half of 240  
var ENEMY3_MIN_RATE = 100; // Half of 180
var difficultyScaling = 0;
var flyingBackground = new FlyingBackground();
game.addChild(flyingBackground);
// Create dragon head (player character)
var dragon = game.addChild(new DragonHead());
dragon.x = 2048 / 2;
dragon.y = 2732 * 0.2; // Place dragon at top fifth of screen
var dragonShadow = new DragonShadow();
game.addChild(dragonShadow);
game.addChild(enemyShadowPool);
game.addChild(fireballPool);
game.addChild(particlePool);
game.addChild(enemyPool);
game.addChild(enemyTwoPool);
game.addChild(enemyThreePool);
game.addChild(chainSegmentPool);
game.addChild(bossFistPool);
game.addChild(scorePopupPool);
game.addChild(defeatParticlePool);
game.addChild(dustParticlePool);
game.addChild(enemyArrowPool);
game.addChild(scorchPool);
game.addChild(flamePool);
game.addChild(healthPowerupPool);
var healthPopup = new HealthPopup();
game.addChild(healthPopup);
dragon.health = 100;
var dragonHealthBar = new DragonHealthBar();
game.addChild(dragonHealthBar);
game.addChild(progressMeter);
var bossText = new BossText();
game.addChild(bossText);
game.cleanupPools = function () {
	fireballPool.recycleAll();
	particlePool.recycleAll();
	enemyPool.recycleAll();
	enemyTwoPool.recycleAll();
	defeatParticlePool.recycleAll();
	dustParticlePool.recycleAll();
	enemyShadowPool.recycleAll();
	enemyArrowPool.recycleAll();
	scorchPool.recycleAll();
	flamePool.recycleAll();
	enemyThreePool.recycleAll();
};
var scoreMeterBg = game.attachAsset('particle', {
	anchorX: 0,
	anchorY: 0.5,
	tint: 0x333333,
	alpha: 0.5,
	scaleY: 1
});
// Score display
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF,
	stroke: 0x000000,
	strokeThickness: 3
});
// Position meter and score
scoreMeterBg.x = 2048 / 2; // Center X
scoreMeterBg.anchorX = 0.5; // Center anchor for background
scoreMeterBg.y = 300;
scoreTxt.anchor.set(0.5, 0.5); // Center anchor for text
scoreTxt.x = 2048 / 2; // Center X
scoreTxt.y = 300;
game.addChild(scoreMeterBg);
game.addChild(scoreTxt);
function updateScoreMeter(score) {
	var minWidth = 200;
	var scoreStr = score.toString();
	var padding = 40; // Total padding (20 each side)
	// Adjust width per digit based on digit count
	var widthPerDigit;
	if (scoreStr.length === 1) {
		widthPerDigit = 70;
	} else if (scoreStr.length === 2) {
		widthPerDigit = 60;
	} else {
		widthPerDigit = 70;
	}
	var targetWidth = Math.max(minWidth, scoreStr.length * widthPerDigit + padding);
	scoreMeterBg.scaleX = targetWidth / scoreMeterBg.width;
	// Text stays centered automatically now
}
// Create a function to add fire particles
function createFireParticle(x, y) {
	particlePool.spawn(x, y);
}
// Function to spawn a fireball
// Update the spawnFireball function
function spawnFireball() {
	if (!gameActive) {
		return;
	}
	var now = Date.now();
	if (now - lastFireTime < fireRate) {
		return;
	}
	lastFireTime = now;
	// Initialize horizontal velocity components
	var angleOffset = 0;
	// Get direction from dragon head facing - match thresholds with DragonHead class
	if (facekit.leftEye && facekit.rightEye && facekit.noseTip) {
		var faceCenter = (facekit.leftEye.x + facekit.rightEye.x) / 2;
		var noseDiff = facekit.noseTip.x - faceCenter;
		var eyeYDiff = facekit.rightEye.y - facekit.leftEye.y;
		// Keep the original thresholds but require more pronounced movement
		// to trigger the sideways shots (higher threshold values)
		if (noseDiff < -120 && Math.abs(eyeYDiff) < 30 || eyeYDiff > 50) {
			// Facing left - fireballs go left (maintain strong angle)
			angleOffset = -8; // Original value for strong effect
		} else if (noseDiff > 120 && Math.abs(eyeYDiff) < 30 || eyeYDiff < -50) {
			// Facing right - fireballs go right (maintain strong angle)
			angleOffset = 8; // Original value for strong effect
		}
	}
	// Keep the original tilt impact for consistent feel
	if (dragon.rotation) {
		angleOffset += dragon.rotation * 5; // Original value
	}
	// Use the new pool's spawn method
	var fireball = fireballPool.spawn(dragon.x, dragon.y + 50);
	if (fireball) {
		fireball.vx = angleOffset;
		// Add this line to alternate weave direction
		fireball.weaveDirection = lastFireTime % (fireRate * 2) === 0 ? 1 : -1;
	}
	// Play sound
	LK.getSound('firebreathSound').play();
}
dragonHealthBar.visible = false;
scoreTxt.visible = false;
scoreMeterBg.visible = false;
progressMeter.visible = false;
dragon.visible = false;
dragonShadow.visible = false;
gameActive = false;
var titleScreen = new TitleScreen();
game.addChild(titleScreen);
titleScreen.start();
// Game update logic
game.update = function () {
	if (!gameActive) {
		return;
	}
	// Check if mouth is open for fire breathing
	if (facekit && facekit.mouthOpen) {
		isFiring = true;
		spawnFireball();
	} else {
		isFiring = false;
	}
	if (boss) {
		boss.update();
	}
	levelTimer++;
	// Only update progress if boss hasn't spawned yet
	if (!boss) {
		progressMeter.updateProgress(levelTimer / LEVEL_DURATION);
	}
	// Enemy spawning logic
	// Enemy spawning logic
	if (!boss || boss.state !== 'dying') {
		// Add a spawn rate multiplier that's 2x when boss is present
		var spawnRateMultiplier = boss ? 2 : 1;
		if (levelTimer >= enemy3StartTime) {
			// Scale from initial 180 to minimum 90 over level duration
			var scaled3Rate = Math.max(ENEMY3_MIN_RATE, enemy3SpawnRate - (enemy3SpawnRate - ENEMY3_MIN_RATE) * (levelTimer / LEVEL_DURATION));
			// Apply the multiplier to the spawn rate
			if (LK.ticks % Math.floor(scaled3Rate * spawnRateMultiplier) === 0) {
				var enemy = enemyThreePool.spawn(Math.random() * (2048 - 200) + 100, 2732 + 100);
			}
		}
		if (levelTimer >= enemy2StartTime) {
			var scaled2Rate = Math.max(ENEMY2_MIN_RATE, enemy2SpawnRate - (enemy2SpawnRate - ENEMY2_MIN_RATE) * (levelTimer / LEVEL_DURATION));
			// Apply the multiplier to the spawn rate
			if (LK.ticks % Math.floor(scaled2Rate * spawnRateMultiplier) === 0) {
				var spawnX = Math.random() < 0.5 ? -50 : 2098;
				var enemy = enemyTwoPool.spawn(spawnX, 2732 - 500);
			}
		}
		if (levelTimer >= enemy1StartTime) {
			var scaled1Rate = Math.max(ENEMY1_MIN_RATE, enemy1SpawnRate - (enemy1SpawnRate - ENEMY1_MIN_RATE) * (levelTimer / LEVEL_DURATION));
			// Apply the multiplier to the spawn rate
			if (LK.ticks % Math.floor(scaled1Rate * spawnRateMultiplier) === 0) {
				var enemy = enemyPool.spawn(Math.random() * (2048 - 200) + 100, 2732 + 100);
			}
		}
	}
	// Boss spawn check
	if (levelTimer >= LEVEL_DURATION && !boss) {
		bossText.flash();
		boss = new Boss();
		game.addChild(boss);
		game.addChild(bossHealthBar);
		bossHealthBar.visible = true;
		bossHealthBar.show();
	}
	dragonShadow.update(dragon.x, dragon.y, dragon.currentScale);
	// Update all pools
	fireballPool.update();
	enemyPool.update();
	particlePool.update();
	defeatParticlePool.update();
	dustParticlePool.update();
	bossFistPool.update();
	flamePool.update();
	scorchPool.update();
	enemyThreePool.update();
	enemyTwoPool.update();
	scorePopupPool.update();
	healthPowerupPool.update();
	// Process collisions
	processCollisions();
};
// Start background music
LK.playMusic('gameMusic', {
	fade: {
		start: 0,
		end: 0.7,
		duration: 1000
	}
});
:quality(85)/https://cdn.frvr.ai/67db42c016a72d6be958a257.png%3F3) 
 A clear blue sky background with no clouds.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67dc8b60cb1aadfe5b876136.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67dd8a8418c018e03ce22fec.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67ddbcfb80c994e12f823a02.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67ddc12180c994e12f823a87.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67ddecbd9d8cc9d5bc23c73e.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67ddecf59d8cc9d5bc23c742.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67ddfca69d8cc9d5bc23c760.png%3F3) 
 a small bush. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e17a1350386d955cdb9c9d.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e2d0b8eb88f01d7a14285c.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e373e4f4509c053e8b39fe.png%3F3) 
 a wooden arrow with red feathers and a metal arrow head. Completely vertical orientation. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e37dfaa9b5a34b9f51774b.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e4383f0de700590fa36cea.png%3F3) 
 A small vertical flame. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e43daf010d770a13abb813.png%3F3) 
 a black scorch mark on the ground left by a meteor impact. cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e44215258796807174b22d.png%3F3) 
 A bright spark. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e44782258796807174b23e.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e4d3ca000ead8a904dd63b.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c15639298bd9fa52d8dd.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c19a39298bd9fa52d8ef.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c1dc39298bd9fa52d8fe.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c20c39298bd9fa52d902.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c2d039298bd9fa52d92a.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c33c39298bd9fa52d93c.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c56839298bd9fa52d952.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e5c75139298bd9fa52d95d.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e810e10bf83f5289aafb3c.png%3F3) 
 a red heart. cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e8168b0bf83f5289aafbd8.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67e818200bf83f5289aafc32.png%3F3) 
 An SVG of the word **BOSS** in sharp red font.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67eaedc8b6f22e1325c60b9a.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67eaeeaeb6f22e1325c60bd9.png%3F3) 
 An SVG of the word βStartβ written in fire. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67ecac4be043b22751c9e9b0.png%3F3)