/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Define a class for enemies
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 5;
	self.update = function () {
		self.x -= self.speed;
		if (self.x < -50) {
			self.destroy();
		}
	};
});
// Define a class for explosion effects when enemies die
var Explosion = Container.expand(function () {
	var self = Container.call(this);
	// Track explosion duration
	self.lifetime = 0;
	self.maxLifetime = 60; // reduced frames duration for shorter lasting neon glow effects
	// Create particles for the explosion
	self.createParticles = function (color) {
		// Use intense neon red colors exclusively for ultra-vibrant glow effect
		var particleColor = 0xFF0000; // Pure red base color
		// Ultra-vibrant neon red color palette with intense red variations for maximum glow effect
		var neonColors = [0xFF0000, 0xFF1100, 0xFF0500, 0xFF2200, 0xFF3333, 0xFF0033, 0xFF2211, 0xFF1111, 0xFF4444, 0xFF0022];
		var colorVariations = [0xFF0000,
		// Pure red
		0xFF2222,
		// Lighter red
		0xFF3333,
		// Even brighter red
		0xFFAAAA,
		// Intense bright red for highlights
		neonColors[Math.floor(Math.random() * neonColors.length)] // Add random neon red variation
		];
		// Create more particles for enhanced effect - reduced size for smaller explosions
		for (var i = 0; i < 35; i++) {
			// Reduced from 50 to 35 particles for smaller effect
			var size = Math.random() * 20 + 10; // Smaller particles for less dramatic impact
			// Use only circular particles with neon red glow for better visual effect
			var useNeon = Math.random() < 0.9; // 90% chance for neon particles
			var particleColor = useNeon ? neonColors[Math.floor(Math.random() * neonColors.length)] : colorVariations[Math.floor(Math.random() * colorVariations.length)];
			var particle = self.attachAsset('rect', {
				width: size,
				height: size,
				color: particleColor,
				shape: 'ellipse',
				// Always use circles for more consistent red neon glow effect
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: useNeon ? 0.99 : 0.9 // Even higher alpha for neon particles to enhance glow
			});
			// Randomize particle position, direction and speed
			var angle = Math.random() * Math.PI * 2;
			var distance = Math.random() * 30; // Smaller initial spread
			particle.x = Math.cos(angle) * distance;
			particle.y = Math.sin(angle) * distance;
			// Store particle speed and direction with more variation
			particle.speedX = Math.cos(angle) * (Math.random() * 6 + 3); // Slower movement
			particle.speedY = Math.sin(angle) * (Math.random() * 6 + 3);
			particle.rotSpeed = (Math.random() - 0.5) * 0.8; // Less rotation
			particle.isNeon = useNeon; // Track if this is a neon particle
			// Set initial scale and rotation for more dynamic look
			particle.scaleX = 0.1;
			particle.scaleY = 0.1;
			particle.rotation = Math.random() * Math.PI * 2; // Random initial rotation
			// Animate particle with smaller neon red glow effects
			tween(particle, {
				scaleX: useNeon ? 2.0 : 1.0,
				// Smaller scale for neon particles to create less intense glow
				//{m} // Smaller scale for less dramatic visual
				scaleY: useNeon ? 2.0 : 1.0,
				rotation: particle.rotation + Math.PI * (Math.random() * 2),
				// Add rotation animation
				tint: useNeon ? neonColors[Math.floor(Math.random() * neonColors.length)] : particleColor // Add color transitions
			}, {
				duration: useNeon ? 800 : 300,
				// Shorter animation duration for neon particles for less dramatic effect
				//{o} // Shorter animation for smaller visual
				easing: tween.easeOutBack,
				onFinish: function (p) {
					return function () {
						// Enhanced neon particle fade-out for lingering glow effect
						var endScale = p.isNeon ? 0.6 : Math.random() < 0.5 ? 0 : 0.2;
						var endAlpha = p.isNeon ? 0.4 : endScale > 0 ? 0.1 : 0;
						var endRotation = p.rotation + Math.PI * (Math.random() + 1);
						tween(p, {
							scaleX: endScale,
							scaleY: endScale,
							alpha: endAlpha,
							rotation: endRotation
						}, {
							duration: p.isNeon ? 1400 : 600,
							// Much longer fade for neon particles for extended glow effect
							//{q} // Longer fade for better visual
							easing: tween.easeInOutQuad,
							onFinish: function onFinish() {
								if (p.parent) {
									p.parent.removeChild(p);
								}
							}
						});
					};
				}(particle)
			});
		}
		// Add multiple shockwave effects (smaller)
		for (var i = 0; i < 2; i++) {
			var shockwaveColor = i === 0 ? 0xFFFFFF : neonColors[Math.floor(Math.random() * neonColors.length)];
			var shockwave = self.attachAsset('rect', {
				width: 8,
				height: 8,
				color: shockwaveColor,
				shape: 'ellipse',
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: i === 0 ? 0.7 : 0.5
			});
			// Animate shockwave expanding and fading with delay for sequential effect
			tween(shockwave, {
				scaleX: 8 + i * 3,
				// Each shockwave is smaller
				scaleY: 8 + i * 3,
				alpha: 0
			}, {
				duration: 500 + i * 100,
				//{D} // Each shockwave lasts shorter
				delay: i * 100,
				// Stagger the shockwaves
				easing: tween.easeOutQuad
			});
		}
		// Add central glow effect (smaller)
		var glow = self.attachAsset('rect', {
			width: 15,
			height: 15,
			color: neonColors[Math.floor(Math.random() * neonColors.length)],
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.9
		});
		// Animate central glow (smaller scale)
		tween(glow, {
			scaleX: 4,
			scaleY: 4,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeOutQuad
		});
	};
	// Update explosion particles
	self.update = function () {
		self.lifetime++;
		// Update each particle
		for (var i = 0; i < self.children.length; i++) {
			var particle = self.children[i];
			if (particle.speedX !== undefined) {
				particle.x += particle.speedX;
				particle.y += particle.speedY;
				// Add gravity effect to particles
				particle.speedY += 0.1;
				// Slow down particles over time with variable drag
				particle.speedX *= 0.94 + Math.random() * 0.02;
				particle.speedY *= 0.94 + Math.random() * 0.02;
				// Add ultra-enhanced neon glow pulse effect to neon particles
				if (particle.isNeon) {
					// Dramatically enhanced pulse effect for neon particles
					var pulseRate = 0.1; // Even faster pulse rate for more dynamic effect
					var pulseMagnitude = 0.4; // More dramatic pulse intensity
					var pulseOffset = self.lifetime * pulseRate + i * 0.15;
					var pulseValue = Math.sin(pulseOffset) * pulseMagnitude;
					// Apply much stronger pulse to alpha and scale for intense glow effect
					particle.alpha = Math.max(0.3, Math.min(0.98, 0.8 + pulseValue));
					var baseScale = 1.2 + self.lifetime / self.maxLifetime * -0.3; // Even slower shrink rate for longer-lasting glow
					particle.scale.x = baseScale + pulseValue * 0.6; // Much stronger scale pulse
					particle.scale.y = baseScale + pulseValue * 0.6;
					// More frequent color changes for enhanced twinkling effect (neon particles only)
					if (Math.random() < 0.18) {
						// 18% chance each frame (increased from 15%)
						// Create ultra-intense neon red color variations for maximum sparkle effect
						var neonColors = [0xFF0000, 0xFF1100, 0xFF0500, 0xFF2200, 0xFF2222, 0xFF0033, 0xFF1111, 0xFF2211, 0xFF3311, 0xFF4422];
						particle.tint = neonColors[Math.floor(Math.random() * neonColors.length)];
						// Use tweening for smoother color transitions with enhanced glow effect
						tween(particle, {
							alpha: Math.random() * 0.3 + 0.7,
							// Random alpha between 0.7 and 1.0 for pulsing effect
							scaleX: particle.scaleX * (Math.random() * 0.4 + 0.9),
							// Add slight scale pulse
							scaleY: particle.scaleY * (Math.random() * 0.4 + 0.9) // Add slight scale pulse
						}, {
							duration: 180,
							easing: tween.easeOut
						});
					}
				}
				// Rotate particles with variable speeds
				if (particle.rotSpeed) {
					particle.rotation += particle.rotSpeed;
					// Slightly vary rotation speed for more natural look
					particle.rotSpeed *= 0.97; // Slower deceleration for longer rotation
				}
				// Add more dynamic wobble to particle movement
				if (Math.random() < 0.15) {
					// Increased chance for movement variation
					particle.x += (Math.random() - 0.5) * 3; // Stronger wobble
					particle.y += (Math.random() - 0.5) * 3;
				}
			}
		}
		// Random chance to emit a secondary spark or neon trail particle (reduced size)
		if (self.lifetime < self.maxLifetime * 0.5 && Math.random() < 0.2) {
			// Reduced chance (20% down from 28%) for less frequent and shorter-lasting effects
			// Ultra-intense neon red colors for maximum spark brilliance and glow
			var neonColors = [0xFF0000, 0xFF1100, 0xFF0500, 0xFF2200, 0xFF2222, 0xFF1111, 0xFF0011, 0xFF3300, 0xFF4400];
			var useNeon = Math.random() < 0.95; // 95% chance of neon particle
			var spark = self.attachAsset('rect', {
				width: useNeon ? 8 : 5,
				// Smaller particles for less visible glow
				height: useNeon ? 8 : 5,
				// Smaller particles for less visible glow
				color: useNeon ? neonColors[Math.floor(Math.random() * neonColors.length)] : 0xFF5555,
				// Use light red instead of white
				shape: 'ellipse',
				// Always use circles for enhanced red neon glow effect
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: useNeon ? 0.95 : 0.8 // Slightly reduced alpha for less intense visibility
			});
			// Position spark near an existing particle for trail effect
			var particleIndex = Math.floor(Math.random() * self.children.length);
			if (particleIndex < self.children.length && self.children[particleIndex].speedX !== undefined) {
				// Position near existing particle
				spark.x = self.children[particleIndex].x + (Math.random() - 0.5) * 10;
				spark.y = self.children[particleIndex].y + (Math.random() - 0.5) * 10;
			} else {
				// Fallback random position
				spark.x = (Math.random() - 0.5) * 40;
				spark.y = (Math.random() - 0.5) * 40;
			}
			// Animate spark with neon glow effect if it's a neon particle
			if (useNeon) {
				tween(spark, {
					alpha: 0.2,
					scaleX: 2,
					// Grow before fading
					scaleY: 2
				}, {
					duration: 200,
					easing: tween.easeOutQuad,
					onFinish: function onFinish() {
						tween(spark, {
							alpha: 0,
							scaleX: 0,
							scaleY: 0
						}, {
							duration: 400,
							easing: tween.easeInQuad
						});
					}
				});
			} else {
				// Regular spark animation
				tween(spark, {
					alpha: 0,
					scaleX: 0,
					scaleY: 0
				}, {
					duration: 300,
					easing: tween.easeOutQuad
				});
			}
		}
		// Add less frequent energy burst effect during explosion lifetime - reduced frequency and size
		if (self.lifetime > 3 && self.lifetime < self.maxLifetime * 0.6 && Math.random() < 0.08) {
			// Reduced chance (8% down from 15%) for less frequent bursts and shorter visual duration
			var neonColors = [0xFF0000, 0xFF0500, 0xFF1100, 0xFF2200, 0xFF3300, 0xFF1111, 0xFF2211, 0xFF3311, 0xFF4411, 0xFF0022];
			// Always use the most intense neon red colors for maximum visual impact
			var burstColor = neonColors[Math.floor(Math.random() * neonColors.length)];
			var energyBurst = self.attachAsset('rect', {
				width: 15,
				// Smaller burst size
				height: 15,
				color: burstColor,
				shape: 'ellipse',
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.95
			});
			// Create less dramatic expanding ring effect
			tween(energyBurst, {
				scaleX: 5,
				//{1B} // Smaller final scale
				scaleY: 5,
				alpha: 0
			}, {
				duration: 500,
				//{1F} // Shorter duration
				easing: tween.easeOutQuad
			});
			// Add a second smaller, faster burst for layered effect (reduced frequency)
			if (Math.random() < 0.5) {
				// 50% chance for secondary burst (reduced from 80%)
				var secondaryBurst = self.attachAsset('rect', {
					width: 10,
					height: 10,
					color: neonColors[Math.floor(Math.random() * neonColors.length)],
					// Different color
					shape: 'ellipse',
					anchorX: 0.5,
					anchorY: 0.5,
					alpha: 0.9
				});
				// Create faster expanding secondary ring effect (smaller)
				tween(secondaryBurst, {
					scaleX: 3,
					scaleY: 3,
					alpha: 0
				}, {
					duration: 300,
					// Faster duration
					easing: tween.easeOutCubic // Different easing
				});
			}
		}
		// Remove explosion when lifetime is up
		if (self.lifetime >= self.maxLifetime) {
			self.destroy();
		}
	};
	return self;
});
// Define a class for flying dinosaur enemy
var FlyingDino = Container.expand(function () {
	var self = Container.call(this);
	var dinoGraphics = self.attachAsset('flyingDino', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.0,
		scaleY: 1.0
	});
	// Customize appearance for dinosaur
	dinoGraphics.tint = 0xFFFFFF; // No tint needed for proper dinosaur asset
	self.speed = 8; // Faster than regular enemies
	self.verticalSpeed = 3;
	self.verticalDirection = 1; // 1 for down, -1 for up
	self.lastY = self.y;
	self.lastX = self.x;
	self.maxVerticalOffset = 150; // Reduced maximum vertical movement to keep in upper portion
	self.startY = 0; // Will store initial Y position
	self.update = function () {
		// Store last position for collision detection
		self.lastY = self.y;
		self.lastX = self.x;
		// Move horizontally
		self.x -= self.speed;
		// Move vertically in a wave pattern
		self.y += self.verticalSpeed * self.verticalDirection;
		// Change direction when reaching max offset from start position
		if (Math.abs(self.y - self.startY) > self.maxVerticalOffset) {
			self.verticalDirection *= -1;
		}
		if (self.x < -50) {
			self.destroy();
		}
	};
	return self;
});
// Define a class for collectible hearts
var Heart = Container.expand(function () {
	var self = Container.call(this);
	var heartGraphics = self.attachAsset('heart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1,
		scaleY: 1
	});
	self.speed = 5;
	self.lastY = self.y;
	self.lastX = self.x;
	// Add some floating animation
	self.floatOffset = Math.random() * Math.PI * 2;
	self.floatSpeed = 0.05;
	self.baseY = 0;
	self.update = function () {
		// Store last position for collision detection
		self.lastY = self.y;
		self.lastX = self.x;
		// Move the heart
		self.x -= self.speed;
		// Floating animation
		self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 20;
		// Remove if offscreen
		if (self.x < -50) {
			self.destroy();
		}
	};
	return self;
});
//<Assets used in the game will automatically appear here>
// Define a class for the player character
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 5;
	self.jumpHeight = 40;
	self.isJumping = false;
	self.canDoubleJump = false; // Track if player can perform double jump
	self.velocityY = 0;
	self.update = function () {
		// No need for physics-based jump calculation anymore
		// Animation is handled by tweens in jump method
	};
	self.jump = function () {
		// First jump
		if (!self.isJumping) {
			self.isJumping = true;
			self.canDoubleJump = true; // Enable double jump after first jump
			// Use tween for smoother jump animation
			var initialY = self.y;
			var peakY = initialY - 500; // Jump peak height - increased from 300 to 500
			// Store current X position to prevent horizontal movement during jump
			var currentX = self.x;
			tween(self, {
				y: peakY
			}, {
				duration: 500,
				easing: tween.easeOutQuad,
				onFinish: function onFinish() {
					// Fall back down with easing
					tween(self, {
						y: 2732 / 2 // Ground level
					}, {
						duration: 600,
						easing: tween.easeInQuad,
						onFinish: function onFinish() {
							self.isJumping = false;
							self.canDoubleJump = false; // Reset double jump ability
							self.velocityY = 0;
						}
					});
				}
			});
		}
		// Second jump (double jump)
		else if (self.canDoubleJump) {
			self.canDoubleJump = false; // Used double jump
			// Cancel any existing tweens on player
			tween.cancelAll(self);
			// Current Y position becomes the new starting point
			var currentY = self.y;
			var doubleJumpPeakY = currentY - 400; // Slightly lower second jump
			// Store current X position to prevent horizontal movement during double jump
			var currentX = self.x;
			// Perform double jump animation
			tween(self, {
				y: doubleJumpPeakY
			}, {
				duration: 400,
				easing: tween.easeOutQuad,
				onFinish: function onFinish() {
					// Fall back down with easing
					tween(self, {
						y: 2732 / 2 // Ground level
					}, {
						duration: 500,
						easing: tween.easeInQuad,
						onFinish: function onFinish() {
							self.isJumping = false;
							self.velocityY = 0;
						}
					});
				}
			});
		}
	};
});
// Define a class for collectible power-up stars
var PowerStar = Container.expand(function () {
	var self = Container.call(this);
	var starGraphics = self.attachAsset('star', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2
	});
	self.speed = 4;
	self.lastY = self.y;
	self.lastX = self.x;
	// Add floating animation
	self.floatOffset = Math.random() * Math.PI * 2;
	self.floatSpeed = 0.07;
	self.baseY = 0;
	// Add spinning animation
	self.rotation = 0;
	self.rotationSpeed = 0.05;
	self.update = function () {
		// Store last position for collision detection
		self.lastY = self.y;
		self.lastX = self.x;
		// Move the star
		self.x -= self.speed;
		// Floating animation
		self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 25;
		// Spinning animation
		self.rotation += self.rotationSpeed;
		// Remove if offscreen
		if (self.x < -50) {
			self.destroy();
		}
	};
	return self;
});
// Define a class for rounded rectangle backgrounds
var RoundedRect = Container.expand(function () {
	var self = Container.call(this);
	// Create a rounded rectangle by using multiple assets
	self.create = function (width, height, radius, color, alpha) {
		// Default values
		radius = radius || 15;
		color = color || 0x000000;
		alpha = alpha || 0.6;
		// Clear any existing children
		while (self.children.length > 0) {
			self.removeChildAt(0);
		}
		// Create center rectangle
		var center = self.attachAsset('rect', {
			width: width - radius * 2,
			height: height - radius * 2,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		// Create horizontal rectangles (top and bottom)
		var top = self.attachAsset('rect', {
			width: width - radius * 2,
			height: radius,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		top.y = -(height / 2 - radius / 2);
		var bottom = self.attachAsset('rect', {
			width: width - radius * 2,
			height: radius,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		bottom.y = height / 2 - radius / 2;
		// Create vertical rectangles (left and right)
		var left = self.attachAsset('rect', {
			width: radius,
			height: height - radius * 2,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		left.x = -(width / 2 - radius / 2);
		var right = self.attachAsset('rect', {
			width: radius,
			height: height - radius * 2,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		right.x = width / 2 - radius / 2;
		// Create corner circles
		var topLeft = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		topLeft.x = -(width / 2 - radius);
		topLeft.y = -(height / 2 - radius);
		var topRight = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		topRight.x = width / 2 - radius;
		topRight.y = -(height / 2 - radius);
		var bottomLeft = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		bottomLeft.x = -(width / 2 - radius);
		bottomLeft.y = height / 2 - radius;
		var bottomRight = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		bottomRight.x = width / 2 - radius;
		bottomRight.y = height / 2 - radius;
		return self;
	};
	return self;
});
// Define a class for star bullets
var Star = Container.expand(function () {
	var self = Container.call(this);
	// Create a yellow star shape using the built-in shape feature
	var starGraphics = self.attachAsset('star', {
		width: 50,
		height: 50,
		color: 0xffff00,
		shape: 'box',
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Create trailing effect container
	var trailContainer = new Container();
	self.addChild(trailContainer);
	// Place it behind the star by removing and re-adding in correct order
	self.removeChild(trailContainer);
	self.removeChild(starGraphics);
	self.addChild(trailContainer); // Add trail container first (bottom layer)
	self.addChild(starGraphics); // Add star graphics last (top layer)
	self.speed = 10;
	self.speedX = 10; // Horizontal speed
	self.speedY = 0; // Vertical speed (default to 0 for straight shots)
	self.rotation = 0; // Current rotation
	self.rotationSpeed = 0.1; // Rotation speed for spinning stars
	// Store the last position for collision detection
	self.lastY = self.y;
	self.lastX = self.x;
	// Add a pulsing effect
	self.scaleDirection = 1;
	self.scaleSpeed = 0.02;
	self.minScale = 0.8;
	self.maxScale = 1.2;
	// Trail effect variables
	self.trailCount = 0;
	self.trailInterval = 2; // Create trail every n frames
	self.trailLifetime = 400; // Trail lifetime in ms
	self.maxTrails = 6; // Maximum number of trails
	// Function to create a gradient trail
	self.createTrail = function () {
		// Create a copy of the star graphic for the trail
		var trail = trailContainer.addChild(LK.getAsset('star', {
			width: 50,
			height: 50,
			color: 0xffff00,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.8,
			scaleX: starGraphics.scale.x * 0.9,
			scaleY: starGraphics.scale.y * 0.9,
			rotation: starGraphics.rotation
		}));
		// Position at current star position
		trail.x = 0; // Local coordinates relative to star
		trail.y = 0;
		// Animate the trail to fade out and scale down
		tween(trail, {
			alpha: 0,
			scaleX: trail.scale.x * 0.5,
			scaleY: trail.scale.y * 0.5
		}, {
			duration: self.trailLifetime,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				if (trail && trail.parent) {
					trail.parent.removeChild(trail);
				}
			}
		});
		// Return trail for further manipulation
		return trail;
	};
	// Add shooting animation
	self.animate = function () {
		// Initial rapid spinning animation
		tween(self, {
			rotation: Math.PI * 4 // Spin 720 degrees
		}, {
			duration: 800,
			easing: tween.easeOutQuad,
			onFinish: function onFinish() {
				// After initial spin, continue with normal rotation in update()
				self.rotation = Math.PI * 4 % (Math.PI * 2); // Keep within 0-360 range
			}
		});
		// Flash effect with scaling
		tween(starGraphics, {
			scaleX: 1.5,
			scaleY: 1.5
		}, {
			duration: 150,
			easing: tween.easeOutQuad,
			onFinish: function onFinish() {
				tween(starGraphics, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 150,
					easing: tween.easeInQuad
				});
			}
		});
		// Add color gradient animation to the star
		var colors = [0xffff00, 0xff9900, 0xff0000, 0xff00ff, 0x00ffff, 0xffff00];
		var colorDuration = 600;
		function animateGradient(index) {
			if (index >= colors.length - 1) {
				return;
			}
			tween(starGraphics, {
				tint: colors[index + 1]
			}, {
				duration: colorDuration,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					animateGradient((index + 1) % (colors.length - 1));
				}
			});
		}
		// Start the gradient animation
		starGraphics.tint = colors[0];
		animateGradient(0);
	};
	// Call animation when created
	self.animate();
	self.update = function () {
		// Store last position before update
		self.lastY = self.y;
		self.lastX = self.x;
		// Move the star according to its speed components
		self.x += self.speedX;
		self.y += self.speedY;
		// Rotate the star for visual effect
		self.rotation += self.rotationSpeed;
		starGraphics.rotation = self.rotation;
		// Pulse scaling effect
		if (self.scaleDirection > 0) {
			starGraphics.scale.x += self.scaleSpeed;
			starGraphics.scale.y += self.scaleSpeed;
			if (starGraphics.scale.x >= self.maxScale) {
				self.scaleDirection = -1;
			}
		} else {
			starGraphics.scale.x -= self.scaleSpeed;
			starGraphics.scale.y -= self.scaleSpeed;
			if (starGraphics.scale.x <= self.minScale) {
				self.scaleDirection = 1;
			}
		}
		// Create trail effect
		self.trailCount++;
		if (self.trailCount >= self.trailInterval) {
			self.trailCount = 0;
			// Only maintain a certain number of trails to avoid memory issues
			if (trailContainer.children.length < self.maxTrails) {
				self.createTrail();
			}
		}
		// Remove if it goes off-screen
		if (self.x > 2048 + 50 || self.y < -50 || self.y > 2732 + 50) {
			self.destroy();
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x87CEEB // Sky blue background
});
/**** 
* Game Code
****/ 
// Ensure tween.cancelAll is available
if (!tween.cancelAll) {
	tween.cancelAll = function (target) {
		// Find all active tweens affecting this target and cancel them
		var allTweens = [];
		// Get all tweens
		if (tween.getAll && typeof tween.getAll === 'function') {
			allTweens = tween.getAll();
		} else {
			// Fallback implementation if getAll is not available
			if (tween._tweens && Array.isArray(tween._tweens)) {
				allTweens = tween._tweens;
			}
		}
		// Cancel tweens for target
		if (allTweens.length > 0) {
			allTweens.forEach(function (t) {
				if (t && t._target === target && typeof t.cancel === 'function') {
					t.cancel();
				}
			});
		}
		// If no direct way to access tweens, cancel by calling tween with duration 0
		tween(target, {}, {
			duration: 0
		});
	};
}
var background = game.addChild(LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0
}));
background.x = 0;
background.y = 0;
game.desertLevelActive = false;
game.nightmareLevelActive = false;
game.infernoLevelActive = false;
game.levelTransition = false; // Track when we transition back to main level
// Initialize explosions array
var explosions = [];
// Initialize player
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 / 2;
player.lives = 3;
player.invulnerable = false;
player.invulnerableTime = 0;
player.hasPowerStar = false;
player.powerStarTime = 0;
player.originalTint = 0xFFFFFF;
// Initialize enemies
var enemies = [];
var enemySpawnInterval = 100;
var enemySpawnCounter = 0;
// Initialize flying dinosaurs
var flyingDinos = [];
var dinoSpawnInterval = 200;
var dinoSpawnCounter = 0;
// Initialize collectible hearts
var collectibleHearts = [];
var heartSpawnInterval = 300; // Less frequent than enemies
var heartSpawnCounter = 0;
// Initialize power stars
var powerStars = [];
var powerStarSpawnInterval = 600; // Even less frequent than hearts
var powerStarSpawnCounter = 0;
// Create life display with proper heart images
var maxHearts = 5; // Maximum number of hearts
var heartsContainer = new Container();
LK.gui.top.addChild(heartsContainer);
heartsContainer.x = 0; // Will be centered
heartsContainer.y = 150; // Offset from top edge
// Create heart icons array - we'll display both filled and empty hearts
var heartIcons = [];
// Function to update heart display
function updateHeartDisplay() {
	// Remove existing hearts
	while (heartsContainer.children.length > 0) {
		heartsContainer.removeChildAt(0);
	}
	// Add heart icons
	for (var i = 0; i < player.lives; i++) {
		var heart = heartsContainer.addChild(LK.getAsset('heart', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		}));
		// Position hearts in a row, centered
		var heartSpacing = 130;
		var totalWidth = (player.lives - 1) * heartSpacing;
		heart.x = -totalWidth / 2 + i * heartSpacing;
		heartIcons[i] = heart;
	}
}
// Helper function to update text and resize its container
function updateTextWithResize(textObj, container, bg, newText, minWidth) {
	textObj.setText(newText);
	if (bg && container) {
		// Resize background based on updated text width
		bg.width = Math.max(minWidth, textObj.width + 80);
	}
}
// Initialize heart display
updateHeartDisplay();
// Create a container for score to control background size
var scoreContainer = new Container();
LK.gui.top.addChild(scoreContainer);
scoreContainer.x = 2048 / 2;
scoreContainer.y = 50;
// Create score background using rounded rectangle
var scoreBg = new RoundedRect();
scoreContainer.addChild(scoreBg);
scoreBg.create(250, 120, 20, 0x000000, 0.5);
// Create a new Text2 object to display the score
var scoreText = new Text2('0', {
	size: 100,
	fill: 0xFFFFFF,
	background: 'none'
});
// Add the score text to the container
scoreText.anchor.set(0.5, 0.5);
scoreContainer.addChild(scoreText);
// Create points container with background
var pointsContainer = new Container();
LK.gui.topRight.addChild(pointsContainer);
pointsContainer.x = -20;
pointsContainer.y = 50;
// Create points background with rounded rectangle
var pointsBg = new RoundedRect();
pointsContainer.addChild(pointsBg);
pointsBg.create(320, 100, 15, 0x000000, 0.5);
// Adjust position since RoundedRect has center anchor
pointsBg.x = -160;
pointsBg.y = 0;
// Create points counter and display
var points = 0;
var pointsText = new Text2('Points: 0', {
	size: 80,
	fill: 0xFFFFFF,
	background: 'none'
});
pointsText.anchor.set(1, 0.5);
pointsContainer.addChild(pointsText);
// Create instruction text with rounded rectangle background
var instructionContainer = new Container();
LK.gui.center.addChild(instructionContainer);
instructionContainer.y = 300;
// Create temporary text to measure its dimensions
var tempText = new Text2('TAP to JUMP\nHOLD to continuously SHOOT', {
	size: 60,
	fill: 0xFFFFFF,
	align: 'center',
	background: 'none'
});
// Get text width and add padding
var textWidth = tempText.width + 100;
var textHeight = tempText.height + 80;
// Create instruction text with more detailed controls including double jump
var instructionText = new Text2('TAP to JUMP\nTAP while JUMPING for DOUBLE JUMP\nHOLD to continuously SHOOT', {
	size: 60,
	fill: 0xFFFFFF,
	align: 'center',
	background: 'none',
	shadow: {
		offsetX: 5,
		offsetY: 5,
		color: 0x000000,
		blur: 15,
		alpha: 1.0
	}
});
instructionText.anchor.set(0.5, 0.5);
instructionContainer.addChild(instructionText);
// Create a timeout to hide instructions after 6 seconds (reduced by 2 seconds)
LK.setTimeout(function () {
	// Fade out instructions
	var alpha = 1;
	var fadeInterval = LK.setInterval(function () {
		alpha -= 0.05; // Slower fade for better readability
		instructionContainer.alpha = alpha; // Fade the entire container including background
		if (alpha <= 0) {
			LK.clearInterval(fadeInterval);
			instructionContainer.visible = false;
		}
	}, 100);
}, 6000);
// Handle game updates
// Array to store bullets
var stars = [];
var shootTimer = 0;
game.update = function () {
	player.update();
	// Handle player invulnerability from damage
	if (player.invulnerable && !player.hasPowerStar) {
		// Make player flash to indicate invulnerability
		player.alpha = Math.sin(Date.now() * 0.01) * 0.5 + 0.5;
		// End invulnerability after 2 seconds
		if (Date.now() - player.invulnerableTime > 2000) {
			player.invulnerable = false;
			player.alpha = 1;
		}
	}
	// Handle power star invincibility
	if (player.hasPowerStar) {
		// Make player glow with neon colors
		var elapsed = Date.now() - player.powerStarTime;
		var colorIndex = Math.floor(elapsed / 300 % 4);
		var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00];
		player.children[0].tint = neonColors[colorIndex];
		// Player is invulnerable during power star effect
		player.invulnerable = true;
		player.alpha = 1;
		// End power star effect after 10 seconds instead of 20
		if (elapsed > 10000) {
			player.hasPowerStar = false;
			player.invulnerable = false;
			// Restore original appearance
			player.children[0].tint = player.originalTint;
			// Show power star end indicator
			showActionIndicator("POWER LOST", 1000);
		}
	}
	// Removed auto-shooting to only allow double tap shooting
	// Update stars
	for (var i = stars.length - 1; i >= 0; i--) {
		stars[i].update();
		// Remove stars that are destroyed
		if (!stars[i].parent) {
			stars.splice(i, 1);
			continue;
		}
		// Check for star-enemy collisions
		for (var j = enemies.length - 1; j >= 0; j--) {
			if (stars[i] && enemies[j] && stars[i].intersects(enemies[j])) {
				// Create explosion effect before destroying the enemy
				var explosion = new Explosion();
				explosion.x = enemies[j].x;
				explosion.y = enemies[j].y;
				explosion.createParticles(enemies[j].tint || 0xFFAA00);
				game.addChild(explosion);
				explosions.push(explosion);
				// Remove the enemy and the star
				enemies[j].destroy();
				enemies.splice(j, 1);
				stars[i].destroy();
				stars.splice(i, 1);
				// Update score
				LK.setScore(points + 10);
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 10).toString(), 250);
				// Update points
				points += 10;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Nothing here - removing this redundant check as it's handled elsewhere
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					// Ensure the score is properly set before showing win screen
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					// Resize score background based on updated text width
					scoreBg.width = Math.max(250, scoreText.width + 80);
					pointsText.setText('Points: ' + points);
					// Resize points background based on updated text width
					pointsBg.width = Math.max(320, pointsText.width + 80);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// Return to main level after 600 points
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
				// Check if we just passed 150 points for the enemy increase announcement
				if (points - 10 < 200 && points >= 150) {
					showActionIndicator("MORE ENEMIES!", 2000);
				}
				// Check level changes - use a single consistent approach
				if (points >= 500 && !game.infernoLevelActive) {
					// After 500 points, transition to inferno level
					game.infernoLevelActive = true;
					game.nightmareLevelActive = false;
					game.desertLevelActive = false;
					// No color transition for inferno level
				} else if (points >= 300 && !game.nightmareLevelActive && !game.infernoLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
				} else if (points >= 100 && !game.desertLevelActive && !game.nightmareLevelActive && !game.infernoLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
				}
				break;
			}
		}
	}
	// Hearts are now managed by updateHeartDisplay function
	// Update collectible hearts
	for (var i = collectibleHearts.length - 1; i >= 0; i--) {
		collectibleHearts[i].update();
		// Remove hearts that are destroyed
		if (!collectibleHearts[i].parent) {
			collectibleHearts.splice(i, 1);
			continue;
		}
		// Check for player-heart collisions
		if (player.intersects(collectibleHearts[i])) {
			// Player collected a heart
			collectibleHearts[i].destroy();
			collectibleHearts.splice(i, 1);
			// Add a life if not at maximum
			if (player.lives < 5) {
				player.lives++;
				// Show heart collection indicator
				showActionIndicator("+1 LIFE!", 1000);
				// Update heart display
				updateHeartDisplay();
				// Show special indicators at different milestone points
				if (points >= 900 && points < 1000) {
					showActionIndicator("ALMOST THERE! " + (1000 - points) + " TO WIN!", 1000);
				} else if (points >= 550 && points < 600) {
					showActionIndicator("LEVEL CHANGE AT 600 POINTS!", 1000);
				}
				// Get the newest heart for animation
				var newHeartIndex = player.lives - 1;
				var heart = heartIcons[newHeartIndex];
				// Show animation effect
				tween(heart, {
					scaleX: 1.5,
					scaleY: 1.5
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(heart, {
							scaleX: 1,
							scaleY: 1
						}, {
							duration: 300,
							easing: tween.easeIn
						});
					}
				});
			}
		}
	}
	// Spawn enemies
	enemySpawnCounter++;
	if (enemySpawnCounter >= enemySpawnInterval) {
		var enemy = new Enemy();
		enemy.x = 2048;
		enemy.y = 2732 / 2;
		// Make enemies faster and with different colors based on level
		if (game.infernoLevelActive) {
			enemy.speed = 12; // Even faster enemies in inferno level
			enemy.tint = 0xFF3300; // Orange-red tint for inferno enemies
			// Spawn duplicate enemies in inferno level - guaranteed 1-2 extras
			var extraCount = 1 + Math.floor(Math.random() * 2); // 1 or 2 extra enemies
			for (var i = 0; i < extraCount; i++) {
				var extraEnemy = new Enemy();
				extraEnemy.x = 2048;
				// Position enemies at different vertical positions
				extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 150 + Math.random() * 100 : -(150 + Math.random() * 100)); // Varied positions
				extraEnemy.speed = 10 + Math.random() * 4; // Varied speeds
				extraEnemy.tint = 0xFF6600;
				enemies.push(extraEnemy);
				game.addChild(extraEnemy);
			}
		} else if (game.nightmareLevelActive) {
			enemy.speed = 8; // Faster enemies in nightmare level
			enemy.tint = 0xFF0000; // Red tint for nightmare enemies
		} else if (points >= 150 && game.desertLevelActive) {
			// More enemies after 150 points in desert level
			enemy.speed = 6;
			enemy.tint = 0xCC9900; // Darker desert tint
			// Occasionally spawn a second enemy after 150 points
			if (Math.random() < 0.3) {
				var extraEnemy = new Enemy();
				extraEnemy.x = 2048;
				extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 150 : -150); // Above or below main path
				extraEnemy.speed = 5;
				extraEnemy.tint = 0xCCAA00;
				enemies.push(extraEnemy);
				game.addChild(extraEnemy);
			}
		}
		enemies.push(enemy);
		game.addChild(enemy);
		// Randomize the spawn interval for the next enemy based on level
		var interval, minInterval;
		if (game.infernoLevelActive) {
			interval = 80; // Even more frequent spawns in inferno
			minInterval = 20;
		} else if (game.nightmareLevelActive) {
			interval = 100;
			minInterval = 30;
		} else if (points >= 150) {
			interval = 120; // More frequent after 150 points
			minInterval = 40;
		} else {
			interval = 150;
			minInterval = 50;
		}
		enemySpawnInterval = Math.floor(Math.random() * interval) + minInterval;
		enemySpawnCounter = 0;
	}
	// Spawn flying dinosaurs
	dinoSpawnCounter++;
	if (dinoSpawnCounter >= dinoSpawnInterval) {
		var dino = new FlyingDino();
		dino.x = 2048;
		dino.y = Math.random() * 600 + 200; // Spawn in upper portion of screen
		dino.startY = dino.y; // Store starting Y position
		// Make dinosaurs faster and more aggressive based on level
		if (game.infernoLevelActive) {
			dino.speed = 15; // Even faster in inferno level
			dino.verticalSpeed = 5;
			dino.tint = 0xFF3300; // Orange-red tint for inferno dinos
		} else if (game.nightmareLevelActive) {
			dino.speed = 12;
			dino.verticalSpeed = 4;
			dino.tint = 0xFF00FF; // Purple tint for nightmare dinos
		} else if (game.desertLevelActive) {
			dino.speed = 10;
			dino.verticalSpeed = 3.5;
			dino.tint = 0xDDA020; // Golden tint for desert dinos
		}
		flyingDinos.push(dino);
		game.addChild(dino);
		// Randomize spawn interval based on game level
		var interval, minInterval;
		if (game.infernoLevelActive) {
			interval = 150;
			minInterval = 50;
		} else if (game.nightmareLevelActive) {
			interval = 200;
			minInterval = 100;
		} else {
			interval = 250;
			minInterval = 150;
		}
		dinoSpawnInterval = Math.floor(Math.random() * interval) + minInterval;
		dinoSpawnCounter = 0;
	}
	// Spawn collectible hearts
	heartSpawnCounter++;
	if (heartSpawnCounter >= heartSpawnInterval) {
		var heart = new Heart();
		heart.x = 2048;
		heart.y = Math.random() * 600 + 200; // Only spawn in upper third of screen
		heart.baseY = heart.y;
		collectibleHearts.push(heart);
		game.addChild(heart);
		// Randomize the spawn interval for the next heart (less frequent than enemies)
		heartSpawnInterval = Math.floor(Math.random() * 300) + 300;
		heartSpawnCounter = 0;
	}
	// Spawn power stars
	powerStarSpawnCounter++;
	if (powerStarSpawnCounter >= powerStarSpawnInterval) {
		var powerStar = new PowerStar();
		powerStar.x = 2048;
		powerStar.y = Math.random() * 600 + 200; // Only spawn in upper third of screen
		powerStar.baseY = powerStar.y;
		powerStars.push(powerStar);
		game.addChild(powerStar);
		// Randomize the spawn interval for the next power star (less frequent than hearts)
		powerStarSpawnInterval = Math.floor(Math.random() * 400) + 600;
		powerStarSpawnCounter = 0;
	}
	// Update explosions
	for (var i = explosions.length - 1; i >= 0; i--) {
		explosions[i].update();
		// Remove explosions that are destroyed
		if (!explosions[i].parent) {
			explosions.splice(i, 1);
		}
	}
	// Update power stars
	for (var i = powerStars.length - 1; i >= 0; i--) {
		powerStars[i].update();
		// Remove power stars that are destroyed
		if (!powerStars[i].parent) {
			powerStars.splice(i, 1);
			continue;
		}
		// Check for player-power star collisions
		if (player.intersects(powerStars[i])) {
			// Player collected a power star
			powerStars[i].destroy();
			powerStars.splice(i, 1);
			// Activate power star effect
			player.hasPowerStar = true;
			player.powerStarTime = Date.now();
			// Apply neon glow effect to player
			var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00];
			player.originalTint = player.children[0].tint;
			tween(player.children[0], {
				tint: neonColors[0]
			}, {
				duration: 500
			});
		}
	}
	// Update flying dinosaurs
	for (var d = flyingDinos.length - 1; d >= 0; d--) {
		flyingDinos[d].update();
		// Check if dinosaur intersects with player
		if (player.intersects(flyingDinos[d])) {
			if (player.hasPowerStar) {
				// Create explosion effect before destroying the dinosaur
				var explosion = new Explosion();
				explosion.x = flyingDinos[d].x;
				explosion.y = flyingDinos[d].y;
				explosion.createParticles(flyingDinos[d].tint || 0xFF00FF);
				game.addChild(explosion);
				explosions.push(explosion);
				explosions.push(explosion);
				// With power star, destroy dinosaurs on contact
				flyingDinos[d].destroy();
				flyingDinos.splice(d, 1);
				// Increase score - more points for dinosaurs
				LK.setScore(points + 30); // More points for dinosaur during power star
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 30).toString(), 250);
				points += 30;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				}
				// Check level changes
				if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
					game.infernoLevelActive = true;
					// No color transition for inferno level
					showActionIndicator("INFERNO LEVEL!", 4000);
				} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
					showActionIndicator("NIGHTMARE LEVEL!", 4000);
				} else if (points >= 100 && !game.desertLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
					showActionIndicator("DESERT LEVEL!", 4000);
				}
			} else if (player.y < flyingDinos[d].y - 50) {
				// Player is above dinosaur - jumped on it!
				// Create explosion effect
				var explosion = new Explosion();
				explosion.x = flyingDinos[d].x;
				explosion.y = flyingDinos[d].y;
				explosion.createParticles(flyingDinos[d].tint || 0xFF00FF);
				game.addChild(explosion);
				explosions.push(explosion);
				flyingDinos[d].destroy();
				flyingDinos.splice(d, 1);
				// Boost player up slightly after jump (small bounce)
				tween.cancelAll(player);
				player.jump();
				// Increase score
				LK.setScore(points + 20); // More points for jumping on dinosaur
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 20).toString(), 250);
				points += 20;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Show feedback
				showActionIndicator("DINO STOMP!", 1000);
				// Check win condition
				if (points >= 1000) {
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// After 600 points, transition back to main level
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
			} else if (points >= 600 && !game.levelTransition) {
				// Return to main level after 600 points
				game.levelTransition = true;
				game.desertLevelActive = false;
				game.nightmareLevelActive = false;
				game.infernoLevelActive = false;
				// No color transition when returning to main level
			} else if (!player.invulnerable) {
				// Player was hit, lose a life
				player.lives--;
				// Play hit sound
				LK.getSound('hit').play();
				// Flash screen to indicate damage
				LK.effects.flashScreen(0xff0000, 500);
				// Make player temporarily invulnerable
				player.invulnerable = true;
				player.invulnerableTime = Date.now();
				// Update hearts display
				updateHeartDisplay();
				// Check if player is out of lives
				if (player.lives <= 0) {
					LK.showGameOver();
				} else {
					// Destroy the dinosaur that hit the player
					flyingDinos[d].destroy();
					flyingDinos.splice(d, 1);
				}
			}
		} else if (player.x > flyingDinos[d].x && !flyingDinos[d].passed) {
			flyingDinos[d].passed = true;
			// Update points for passing dinosaur
			points += 15; // More points for passing flying dinosaur
			LK.setScore(points);
			// Update score with container resize
			updateTextWithResize(scoreText, scoreContainer, scoreBg, points.toString(), 250);
			// Update points with container resize
			updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
		}
		// Check for star-dinosaur collisions
		for (var s = stars.length - 1; s >= 0; s--) {
			if (stars[s] && flyingDinos[d] && stars[s].intersects(flyingDinos[d])) {
				// Create explosion effect before destroying the dinosaur
				var explosion = new Explosion();
				explosion.x = flyingDinos[d].x;
				explosion.y = flyingDinos[d].y;
				explosion.createParticles(flyingDinos[d].tint || 0xFF00FF);
				game.addChild(explosion);
				// Remove the dinosaur and the star
				flyingDinos[d].destroy();
				flyingDinos.splice(d, 1);
				stars[s].destroy();
				stars.splice(s, 1);
				// Increase score
				LK.setScore(points + 15); // More points for shooting dinosaur
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 15).toString(), 250);
				points += 15;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// Return to main level after 600 points
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
				// Check level changes
				if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
					game.infernoLevelActive = true;
					// No color transition for inferno level
				} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
				} else if (points >= 100 && !game.desertLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
				}
				break;
			}
		}
	}
	// Update enemies
	for (var j = enemies.length - 1; j >= 0; j--) {
		enemies[j].update();
		if (player.intersects(enemies[j])) {
			if (player.hasPowerStar) {
				// Create explosion effect before destroying the enemy
				var explosion = new Explosion();
				explosion.x = enemies[j].x;
				explosion.y = enemies[j].y;
				explosion.createParticles(enemies[j].tint || 0xFFFF00);
				game.addChild(explosion);
				explosions.push(explosion);
				// With power star, destroy enemies on contact
				enemies[j].destroy();
				enemies.splice(j, 1);
				// Increase score
				LK.setScore(points + 20); // Double points during power star
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 20).toString(), 250);
				// Increase points - doubled from 10 to 20
				points += 20;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					// Ensure the score is properly set before showing win screen
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// Return to main level after 600 points
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
				// Check if we need to change level
				// We already handled win condition above, no need for duplicate check
				// Check if we need to change level
				if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
					game.infernoLevelActive = true;
					game.nightmareLevelActive = false;
					game.desertLevelActive = false;
					// No color transition for inferno level
				} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
				} else if (points >= 100 && !game.desertLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
				}
			} else if (!player.invulnerable) {
				// Player was hit, lose a life
				player.lives--;
				// Play hit sound
				LK.getSound('hit').play();
				// Flash screen to indicate damage
				LK.effects.flashScreen(0xff0000, 500);
				// Make player temporarily invulnerable
				player.invulnerable = true;
				player.invulnerableTime = Date.now();
				// Update hearts display
				updateHeartDisplay();
				// Check if player is out of lives
				if (player.lives <= 0) {
					LK.showGameOver();
				} else {
					// Destroy the enemy that hit the player
					enemies[j].destroy();
					enemies.splice(j, 1);
				}
			}
		} else if (player.x > enemies[j].x && !enemies[j].passed) {
			enemies[j].passed = true;
			// Update points for passing enemy
			points += 10;
			LK.setScore(points);
			// Update score with container resize
			updateTextWithResize(scoreText, scoreContainer, scoreBg, points.toString(), 250);
			// Update points with container resize
			updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
		}
	}
};
// Handle player interaction
var dragNode = null;
var actionIndicator = null;
// Create visual indicators for player actions
function showActionIndicator(text, duration) {
	// Remove any existing indicator, except for level announcements
	var isLevelAnnouncement = text.includes("LEVEL");
	if (actionIndicator && actionIndicator.parent && !isLevelAnnouncement) {
		actionIndicator.parent.removeChild(actionIndicator);
	}
	// Create new indicator
	actionIndicator = new Container();
	game.addChild(actionIndicator);
	// Create temporary text to measure its dimensions
	var tempText = new Text2(text, {
		size: isLevelAnnouncement ? 100 : 50,
		fill: 0xFFFFFF,
		align: 'center',
		background: 'none'
	});
	// Get text width and add padding
	var textWidth = tempText.width + (isLevelAnnouncement ? 120 : 80);
	var textHeight = tempText.height + (isLevelAnnouncement ? 50 : 30);
	// Set minimum width/height
	var textSize = isLevelAnnouncement ? 100 : 50;
	// Add text
	var txt = new Text2(text, {
		size: textSize,
		fill: isLevelAnnouncement ? 0xFFFF00 : 0xFFFFFF,
		align: 'center',
		background: 'none'
	});
	txt.anchor.set(0.5, 0.5);
	actionIndicator.addChild(txt);
	// Position differently based on type
	if (isLevelAnnouncement) {
		// Position at center of the screen for level announcements
		actionIndicator.x = 2048 / 2; // Center horizontally
		actionIndicator.y = 2732 / 2; // Center vertically
		// Add pulsing animation for level announcements
		tween(txt.scale, {
			x: 1.2,
			y: 1.2
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else {
		// Position above player for regular announcements
		actionIndicator.x = player.x;
		actionIndicator.y = player.y - 150;
	}
	// Fade out after duration - shorter for level announcements
	var displayDuration = isLevelAnnouncement ? 2000 : duration;
	// Apply initial scaling effect for level announcements
	if (isLevelAnnouncement) {
		actionIndicator.scale.x = 0.1;
		actionIndicator.scale.y = 0.1;
		tween(actionIndicator.scale, {
			x: 1,
			y: 1
		}, {
			duration: 500,
			easing: tween.easeOutBack
		});
	}
	// Set timeout for fade-out
	LK.setTimeout(function () {
		// Cancel any existing tweens on text scaling
		if (isLevelAnnouncement) {
			tween.cancelAll(txt.scale);
		}
		// Fade out and move up
		tween(actionIndicator, {
			alpha: 0,
			y: isLevelAnnouncement ? actionIndicator.y - 100 : actionIndicator.y - 50
		}, {
			duration: 1000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				if (actionIndicator && actionIndicator.parent) {
					actionIndicator.parent.removeChild(actionIndicator);
				}
			}
		});
	}, displayDuration - 1000);
}
// Function to handle movement and shooting while holding
function handleMove(x, y, obj) {
	if (dragNode) {
		// Only move player horizontally when dragging
		// Limit movement to keep player on screen
		var minX = 100; // Minimum x-coordinate
		var maxX = 2048 - 100; // Maximum x-coordinate
		dragNode.x = Math.max(minX, Math.min(x, maxX));
		// Keep the player at the same vertical position if not jumping
		// (but don't override the tween animation when jumping)
		if (!player.isJumping) {
			dragNode.y = 2732 / 2;
		}
		// If holding finger on screen, continuously shoot
		if (shootTimer > 0) {
			// Reduced fire interval based on power star status
			var fireInterval = player.hasPowerStar ? 5 : 10;
			// Only shoot every interval ticks to control fire rate
			if (LK.ticks % fireInterval === 0) {
				// Create main star
				var star = new Star();
				star.x = player.x + 100;
				star.y = player.y;
				stars.push(star);
				game.addChild(star);
				// If player has power star, create spread shots
				if (player.hasPowerStar) {
					// Add two additional stars with slight angle variations
					for (var i = -1; i <= 1; i += 2) {
						var spreadStar = new Star();
						spreadStar.x = player.x + 100;
						spreadStar.y = player.y;
						// Apply small angular deviation
						var angle = i * 0.2; // ~11 degrees up/down
						spreadStar.speedY = Math.sin(angle) * 5;
						spreadStar.speedX = Math.cos(angle) * spreadStar.speed;
						// Override default update method for angled stars
						spreadStar.update = function () {
							this.lastY = this.y;
							this.lastX = this.x;
							this.x += this.speedX;
							this.y += this.speedY;
							if (this.x > 2048 + 50) {
								this.destroy();
							}
						};
						stars.push(spreadStar);
						game.addChild(spreadStar);
					}
				}
				// Play shooting sound
				LK.getSound('shoot').play();
			}
		}
	}
}
// shootTimer already declared earlier in the code
// Start tracking player movement on touch down and shoot on hold
game.down = function (x, y, obj) {
	// Always make the player jump on tap
	player.jump();
	// Start shooting - fire immediately when pressing
	shootTimer = Date.now();
	// Fire initial shot burst
	var initialStar = new Star();
	initialStar.x = player.x + 100;
	initialStar.y = player.y;
	stars.push(initialStar);
	game.addChild(initialStar);
	LK.getSound('shoot').play();
	// If player has power star, add enhanced initial burst
	if (player.hasPowerStar) {
		// Create a burst of 3 stars in a spread pattern
		for (var angle = -0.3; angle <= 0.3; angle += 0.3) {
			if (angle === 0) {
				continue;
			} // Skip center (already created)
			var spreadStar = new Star();
			spreadStar.x = player.x + 100;
			spreadStar.y = player.y;
			spreadStar.speedY = Math.sin(angle) * 8;
			spreadStar.speedX = Math.cos(angle) * spreadStar.speed;
			spreadStar.rotationSpeed = 0.15; // Faster rotation
			stars.push(spreadStar);
			game.addChild(spreadStar);
		}
	}
	// Handle regular movement without repositioning the player at tap position
	dragNode = player;
};
// Update player position during movement
game.move = handleMove;
// Stop tracking player movement and shooting on touch up
game.up = function (x, y, obj) {
	dragNode = null;
	shootTimer = 0; // Reset shoot timer
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Define a class for enemies
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 5;
	self.update = function () {
		self.x -= self.speed;
		if (self.x < -50) {
			self.destroy();
		}
	};
});
// Define a class for explosion effects when enemies die
var Explosion = Container.expand(function () {
	var self = Container.call(this);
	// Track explosion duration
	self.lifetime = 0;
	self.maxLifetime = 60; // reduced frames duration for shorter lasting neon glow effects
	// Create particles for the explosion
	self.createParticles = function (color) {
		// Use intense neon red colors exclusively for ultra-vibrant glow effect
		var particleColor = 0xFF0000; // Pure red base color
		// Ultra-vibrant neon red color palette with intense red variations for maximum glow effect
		var neonColors = [0xFF0000, 0xFF1100, 0xFF0500, 0xFF2200, 0xFF3333, 0xFF0033, 0xFF2211, 0xFF1111, 0xFF4444, 0xFF0022];
		var colorVariations = [0xFF0000,
		// Pure red
		0xFF2222,
		// Lighter red
		0xFF3333,
		// Even brighter red
		0xFFAAAA,
		// Intense bright red for highlights
		neonColors[Math.floor(Math.random() * neonColors.length)] // Add random neon red variation
		];
		// Create more particles for enhanced effect - reduced size for smaller explosions
		for (var i = 0; i < 35; i++) {
			// Reduced from 50 to 35 particles for smaller effect
			var size = Math.random() * 20 + 10; // Smaller particles for less dramatic impact
			// Use only circular particles with neon red glow for better visual effect
			var useNeon = Math.random() < 0.9; // 90% chance for neon particles
			var particleColor = useNeon ? neonColors[Math.floor(Math.random() * neonColors.length)] : colorVariations[Math.floor(Math.random() * colorVariations.length)];
			var particle = self.attachAsset('rect', {
				width: size,
				height: size,
				color: particleColor,
				shape: 'ellipse',
				// Always use circles for more consistent red neon glow effect
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: useNeon ? 0.99 : 0.9 // Even higher alpha for neon particles to enhance glow
			});
			// Randomize particle position, direction and speed
			var angle = Math.random() * Math.PI * 2;
			var distance = Math.random() * 30; // Smaller initial spread
			particle.x = Math.cos(angle) * distance;
			particle.y = Math.sin(angle) * distance;
			// Store particle speed and direction with more variation
			particle.speedX = Math.cos(angle) * (Math.random() * 6 + 3); // Slower movement
			particle.speedY = Math.sin(angle) * (Math.random() * 6 + 3);
			particle.rotSpeed = (Math.random() - 0.5) * 0.8; // Less rotation
			particle.isNeon = useNeon; // Track if this is a neon particle
			// Set initial scale and rotation for more dynamic look
			particle.scaleX = 0.1;
			particle.scaleY = 0.1;
			particle.rotation = Math.random() * Math.PI * 2; // Random initial rotation
			// Animate particle with smaller neon red glow effects
			tween(particle, {
				scaleX: useNeon ? 2.0 : 1.0,
				// Smaller scale for neon particles to create less intense glow
				//{m} // Smaller scale for less dramatic visual
				scaleY: useNeon ? 2.0 : 1.0,
				rotation: particle.rotation + Math.PI * (Math.random() * 2),
				// Add rotation animation
				tint: useNeon ? neonColors[Math.floor(Math.random() * neonColors.length)] : particleColor // Add color transitions
			}, {
				duration: useNeon ? 800 : 300,
				// Shorter animation duration for neon particles for less dramatic effect
				//{o} // Shorter animation for smaller visual
				easing: tween.easeOutBack,
				onFinish: function (p) {
					return function () {
						// Enhanced neon particle fade-out for lingering glow effect
						var endScale = p.isNeon ? 0.6 : Math.random() < 0.5 ? 0 : 0.2;
						var endAlpha = p.isNeon ? 0.4 : endScale > 0 ? 0.1 : 0;
						var endRotation = p.rotation + Math.PI * (Math.random() + 1);
						tween(p, {
							scaleX: endScale,
							scaleY: endScale,
							alpha: endAlpha,
							rotation: endRotation
						}, {
							duration: p.isNeon ? 1400 : 600,
							// Much longer fade for neon particles for extended glow effect
							//{q} // Longer fade for better visual
							easing: tween.easeInOutQuad,
							onFinish: function onFinish() {
								if (p.parent) {
									p.parent.removeChild(p);
								}
							}
						});
					};
				}(particle)
			});
		}
		// Add multiple shockwave effects (smaller)
		for (var i = 0; i < 2; i++) {
			var shockwaveColor = i === 0 ? 0xFFFFFF : neonColors[Math.floor(Math.random() * neonColors.length)];
			var shockwave = self.attachAsset('rect', {
				width: 8,
				height: 8,
				color: shockwaveColor,
				shape: 'ellipse',
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: i === 0 ? 0.7 : 0.5
			});
			// Animate shockwave expanding and fading with delay for sequential effect
			tween(shockwave, {
				scaleX: 8 + i * 3,
				// Each shockwave is smaller
				scaleY: 8 + i * 3,
				alpha: 0
			}, {
				duration: 500 + i * 100,
				//{D} // Each shockwave lasts shorter
				delay: i * 100,
				// Stagger the shockwaves
				easing: tween.easeOutQuad
			});
		}
		// Add central glow effect (smaller)
		var glow = self.attachAsset('rect', {
			width: 15,
			height: 15,
			color: neonColors[Math.floor(Math.random() * neonColors.length)],
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.9
		});
		// Animate central glow (smaller scale)
		tween(glow, {
			scaleX: 4,
			scaleY: 4,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeOutQuad
		});
	};
	// Update explosion particles
	self.update = function () {
		self.lifetime++;
		// Update each particle
		for (var i = 0; i < self.children.length; i++) {
			var particle = self.children[i];
			if (particle.speedX !== undefined) {
				particle.x += particle.speedX;
				particle.y += particle.speedY;
				// Add gravity effect to particles
				particle.speedY += 0.1;
				// Slow down particles over time with variable drag
				particle.speedX *= 0.94 + Math.random() * 0.02;
				particle.speedY *= 0.94 + Math.random() * 0.02;
				// Add ultra-enhanced neon glow pulse effect to neon particles
				if (particle.isNeon) {
					// Dramatically enhanced pulse effect for neon particles
					var pulseRate = 0.1; // Even faster pulse rate for more dynamic effect
					var pulseMagnitude = 0.4; // More dramatic pulse intensity
					var pulseOffset = self.lifetime * pulseRate + i * 0.15;
					var pulseValue = Math.sin(pulseOffset) * pulseMagnitude;
					// Apply much stronger pulse to alpha and scale for intense glow effect
					particle.alpha = Math.max(0.3, Math.min(0.98, 0.8 + pulseValue));
					var baseScale = 1.2 + self.lifetime / self.maxLifetime * -0.3; // Even slower shrink rate for longer-lasting glow
					particle.scale.x = baseScale + pulseValue * 0.6; // Much stronger scale pulse
					particle.scale.y = baseScale + pulseValue * 0.6;
					// More frequent color changes for enhanced twinkling effect (neon particles only)
					if (Math.random() < 0.18) {
						// 18% chance each frame (increased from 15%)
						// Create ultra-intense neon red color variations for maximum sparkle effect
						var neonColors = [0xFF0000, 0xFF1100, 0xFF0500, 0xFF2200, 0xFF2222, 0xFF0033, 0xFF1111, 0xFF2211, 0xFF3311, 0xFF4422];
						particle.tint = neonColors[Math.floor(Math.random() * neonColors.length)];
						// Use tweening for smoother color transitions with enhanced glow effect
						tween(particle, {
							alpha: Math.random() * 0.3 + 0.7,
							// Random alpha between 0.7 and 1.0 for pulsing effect
							scaleX: particle.scaleX * (Math.random() * 0.4 + 0.9),
							// Add slight scale pulse
							scaleY: particle.scaleY * (Math.random() * 0.4 + 0.9) // Add slight scale pulse
						}, {
							duration: 180,
							easing: tween.easeOut
						});
					}
				}
				// Rotate particles with variable speeds
				if (particle.rotSpeed) {
					particle.rotation += particle.rotSpeed;
					// Slightly vary rotation speed for more natural look
					particle.rotSpeed *= 0.97; // Slower deceleration for longer rotation
				}
				// Add more dynamic wobble to particle movement
				if (Math.random() < 0.15) {
					// Increased chance for movement variation
					particle.x += (Math.random() - 0.5) * 3; // Stronger wobble
					particle.y += (Math.random() - 0.5) * 3;
				}
			}
		}
		// Random chance to emit a secondary spark or neon trail particle (reduced size)
		if (self.lifetime < self.maxLifetime * 0.5 && Math.random() < 0.2) {
			// Reduced chance (20% down from 28%) for less frequent and shorter-lasting effects
			// Ultra-intense neon red colors for maximum spark brilliance and glow
			var neonColors = [0xFF0000, 0xFF1100, 0xFF0500, 0xFF2200, 0xFF2222, 0xFF1111, 0xFF0011, 0xFF3300, 0xFF4400];
			var useNeon = Math.random() < 0.95; // 95% chance of neon particle
			var spark = self.attachAsset('rect', {
				width: useNeon ? 8 : 5,
				// Smaller particles for less visible glow
				height: useNeon ? 8 : 5,
				// Smaller particles for less visible glow
				color: useNeon ? neonColors[Math.floor(Math.random() * neonColors.length)] : 0xFF5555,
				// Use light red instead of white
				shape: 'ellipse',
				// Always use circles for enhanced red neon glow effect
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: useNeon ? 0.95 : 0.8 // Slightly reduced alpha for less intense visibility
			});
			// Position spark near an existing particle for trail effect
			var particleIndex = Math.floor(Math.random() * self.children.length);
			if (particleIndex < self.children.length && self.children[particleIndex].speedX !== undefined) {
				// Position near existing particle
				spark.x = self.children[particleIndex].x + (Math.random() - 0.5) * 10;
				spark.y = self.children[particleIndex].y + (Math.random() - 0.5) * 10;
			} else {
				// Fallback random position
				spark.x = (Math.random() - 0.5) * 40;
				spark.y = (Math.random() - 0.5) * 40;
			}
			// Animate spark with neon glow effect if it's a neon particle
			if (useNeon) {
				tween(spark, {
					alpha: 0.2,
					scaleX: 2,
					// Grow before fading
					scaleY: 2
				}, {
					duration: 200,
					easing: tween.easeOutQuad,
					onFinish: function onFinish() {
						tween(spark, {
							alpha: 0,
							scaleX: 0,
							scaleY: 0
						}, {
							duration: 400,
							easing: tween.easeInQuad
						});
					}
				});
			} else {
				// Regular spark animation
				tween(spark, {
					alpha: 0,
					scaleX: 0,
					scaleY: 0
				}, {
					duration: 300,
					easing: tween.easeOutQuad
				});
			}
		}
		// Add less frequent energy burst effect during explosion lifetime - reduced frequency and size
		if (self.lifetime > 3 && self.lifetime < self.maxLifetime * 0.6 && Math.random() < 0.08) {
			// Reduced chance (8% down from 15%) for less frequent bursts and shorter visual duration
			var neonColors = [0xFF0000, 0xFF0500, 0xFF1100, 0xFF2200, 0xFF3300, 0xFF1111, 0xFF2211, 0xFF3311, 0xFF4411, 0xFF0022];
			// Always use the most intense neon red colors for maximum visual impact
			var burstColor = neonColors[Math.floor(Math.random() * neonColors.length)];
			var energyBurst = self.attachAsset('rect', {
				width: 15,
				// Smaller burst size
				height: 15,
				color: burstColor,
				shape: 'ellipse',
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.95
			});
			// Create less dramatic expanding ring effect
			tween(energyBurst, {
				scaleX: 5,
				//{1B} // Smaller final scale
				scaleY: 5,
				alpha: 0
			}, {
				duration: 500,
				//{1F} // Shorter duration
				easing: tween.easeOutQuad
			});
			// Add a second smaller, faster burst for layered effect (reduced frequency)
			if (Math.random() < 0.5) {
				// 50% chance for secondary burst (reduced from 80%)
				var secondaryBurst = self.attachAsset('rect', {
					width: 10,
					height: 10,
					color: neonColors[Math.floor(Math.random() * neonColors.length)],
					// Different color
					shape: 'ellipse',
					anchorX: 0.5,
					anchorY: 0.5,
					alpha: 0.9
				});
				// Create faster expanding secondary ring effect (smaller)
				tween(secondaryBurst, {
					scaleX: 3,
					scaleY: 3,
					alpha: 0
				}, {
					duration: 300,
					// Faster duration
					easing: tween.easeOutCubic // Different easing
				});
			}
		}
		// Remove explosion when lifetime is up
		if (self.lifetime >= self.maxLifetime) {
			self.destroy();
		}
	};
	return self;
});
// Define a class for flying dinosaur enemy
var FlyingDino = Container.expand(function () {
	var self = Container.call(this);
	var dinoGraphics = self.attachAsset('flyingDino', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.0,
		scaleY: 1.0
	});
	// Customize appearance for dinosaur
	dinoGraphics.tint = 0xFFFFFF; // No tint needed for proper dinosaur asset
	self.speed = 8; // Faster than regular enemies
	self.verticalSpeed = 3;
	self.verticalDirection = 1; // 1 for down, -1 for up
	self.lastY = self.y;
	self.lastX = self.x;
	self.maxVerticalOffset = 150; // Reduced maximum vertical movement to keep in upper portion
	self.startY = 0; // Will store initial Y position
	self.update = function () {
		// Store last position for collision detection
		self.lastY = self.y;
		self.lastX = self.x;
		// Move horizontally
		self.x -= self.speed;
		// Move vertically in a wave pattern
		self.y += self.verticalSpeed * self.verticalDirection;
		// Change direction when reaching max offset from start position
		if (Math.abs(self.y - self.startY) > self.maxVerticalOffset) {
			self.verticalDirection *= -1;
		}
		if (self.x < -50) {
			self.destroy();
		}
	};
	return self;
});
// Define a class for collectible hearts
var Heart = Container.expand(function () {
	var self = Container.call(this);
	var heartGraphics = self.attachAsset('heart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1,
		scaleY: 1
	});
	self.speed = 5;
	self.lastY = self.y;
	self.lastX = self.x;
	// Add some floating animation
	self.floatOffset = Math.random() * Math.PI * 2;
	self.floatSpeed = 0.05;
	self.baseY = 0;
	self.update = function () {
		// Store last position for collision detection
		self.lastY = self.y;
		self.lastX = self.x;
		// Move the heart
		self.x -= self.speed;
		// Floating animation
		self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 20;
		// Remove if offscreen
		if (self.x < -50) {
			self.destroy();
		}
	};
	return self;
});
//<Assets used in the game will automatically appear here>
// Define a class for the player character
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 5;
	self.jumpHeight = 40;
	self.isJumping = false;
	self.canDoubleJump = false; // Track if player can perform double jump
	self.velocityY = 0;
	self.update = function () {
		// No need for physics-based jump calculation anymore
		// Animation is handled by tweens in jump method
	};
	self.jump = function () {
		// First jump
		if (!self.isJumping) {
			self.isJumping = true;
			self.canDoubleJump = true; // Enable double jump after first jump
			// Use tween for smoother jump animation
			var initialY = self.y;
			var peakY = initialY - 500; // Jump peak height - increased from 300 to 500
			// Store current X position to prevent horizontal movement during jump
			var currentX = self.x;
			tween(self, {
				y: peakY
			}, {
				duration: 500,
				easing: tween.easeOutQuad,
				onFinish: function onFinish() {
					// Fall back down with easing
					tween(self, {
						y: 2732 / 2 // Ground level
					}, {
						duration: 600,
						easing: tween.easeInQuad,
						onFinish: function onFinish() {
							self.isJumping = false;
							self.canDoubleJump = false; // Reset double jump ability
							self.velocityY = 0;
						}
					});
				}
			});
		}
		// Second jump (double jump)
		else if (self.canDoubleJump) {
			self.canDoubleJump = false; // Used double jump
			// Cancel any existing tweens on player
			tween.cancelAll(self);
			// Current Y position becomes the new starting point
			var currentY = self.y;
			var doubleJumpPeakY = currentY - 400; // Slightly lower second jump
			// Store current X position to prevent horizontal movement during double jump
			var currentX = self.x;
			// Perform double jump animation
			tween(self, {
				y: doubleJumpPeakY
			}, {
				duration: 400,
				easing: tween.easeOutQuad,
				onFinish: function onFinish() {
					// Fall back down with easing
					tween(self, {
						y: 2732 / 2 // Ground level
					}, {
						duration: 500,
						easing: tween.easeInQuad,
						onFinish: function onFinish() {
							self.isJumping = false;
							self.velocityY = 0;
						}
					});
				}
			});
		}
	};
});
// Define a class for collectible power-up stars
var PowerStar = Container.expand(function () {
	var self = Container.call(this);
	var starGraphics = self.attachAsset('star', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2
	});
	self.speed = 4;
	self.lastY = self.y;
	self.lastX = self.x;
	// Add floating animation
	self.floatOffset = Math.random() * Math.PI * 2;
	self.floatSpeed = 0.07;
	self.baseY = 0;
	// Add spinning animation
	self.rotation = 0;
	self.rotationSpeed = 0.05;
	self.update = function () {
		// Store last position for collision detection
		self.lastY = self.y;
		self.lastX = self.x;
		// Move the star
		self.x -= self.speed;
		// Floating animation
		self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 25;
		// Spinning animation
		self.rotation += self.rotationSpeed;
		// Remove if offscreen
		if (self.x < -50) {
			self.destroy();
		}
	};
	return self;
});
// Define a class for rounded rectangle backgrounds
var RoundedRect = Container.expand(function () {
	var self = Container.call(this);
	// Create a rounded rectangle by using multiple assets
	self.create = function (width, height, radius, color, alpha) {
		// Default values
		radius = radius || 15;
		color = color || 0x000000;
		alpha = alpha || 0.6;
		// Clear any existing children
		while (self.children.length > 0) {
			self.removeChildAt(0);
		}
		// Create center rectangle
		var center = self.attachAsset('rect', {
			width: width - radius * 2,
			height: height - radius * 2,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		// Create horizontal rectangles (top and bottom)
		var top = self.attachAsset('rect', {
			width: width - radius * 2,
			height: radius,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		top.y = -(height / 2 - radius / 2);
		var bottom = self.attachAsset('rect', {
			width: width - radius * 2,
			height: radius,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		bottom.y = height / 2 - radius / 2;
		// Create vertical rectangles (left and right)
		var left = self.attachAsset('rect', {
			width: radius,
			height: height - radius * 2,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		left.x = -(width / 2 - radius / 2);
		var right = self.attachAsset('rect', {
			width: radius,
			height: height - radius * 2,
			color: color,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		right.x = width / 2 - radius / 2;
		// Create corner circles
		var topLeft = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		topLeft.x = -(width / 2 - radius);
		topLeft.y = -(height / 2 - radius);
		var topRight = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		topRight.x = width / 2 - radius;
		topRight.y = -(height / 2 - radius);
		var bottomLeft = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		bottomLeft.x = -(width / 2 - radius);
		bottomLeft.y = height / 2 - radius;
		var bottomRight = self.attachAsset('rect', {
			width: radius * 2,
			height: radius * 2,
			color: color,
			shape: 'ellipse',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: alpha
		});
		bottomRight.x = width / 2 - radius;
		bottomRight.y = height / 2 - radius;
		return self;
	};
	return self;
});
// Define a class for star bullets
var Star = Container.expand(function () {
	var self = Container.call(this);
	// Create a yellow star shape using the built-in shape feature
	var starGraphics = self.attachAsset('star', {
		width: 50,
		height: 50,
		color: 0xffff00,
		shape: 'box',
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Create trailing effect container
	var trailContainer = new Container();
	self.addChild(trailContainer);
	// Place it behind the star by removing and re-adding in correct order
	self.removeChild(trailContainer);
	self.removeChild(starGraphics);
	self.addChild(trailContainer); // Add trail container first (bottom layer)
	self.addChild(starGraphics); // Add star graphics last (top layer)
	self.speed = 10;
	self.speedX = 10; // Horizontal speed
	self.speedY = 0; // Vertical speed (default to 0 for straight shots)
	self.rotation = 0; // Current rotation
	self.rotationSpeed = 0.1; // Rotation speed for spinning stars
	// Store the last position for collision detection
	self.lastY = self.y;
	self.lastX = self.x;
	// Add a pulsing effect
	self.scaleDirection = 1;
	self.scaleSpeed = 0.02;
	self.minScale = 0.8;
	self.maxScale = 1.2;
	// Trail effect variables
	self.trailCount = 0;
	self.trailInterval = 2; // Create trail every n frames
	self.trailLifetime = 400; // Trail lifetime in ms
	self.maxTrails = 6; // Maximum number of trails
	// Function to create a gradient trail
	self.createTrail = function () {
		// Create a copy of the star graphic for the trail
		var trail = trailContainer.addChild(LK.getAsset('star', {
			width: 50,
			height: 50,
			color: 0xffff00,
			shape: 'box',
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.8,
			scaleX: starGraphics.scale.x * 0.9,
			scaleY: starGraphics.scale.y * 0.9,
			rotation: starGraphics.rotation
		}));
		// Position at current star position
		trail.x = 0; // Local coordinates relative to star
		trail.y = 0;
		// Animate the trail to fade out and scale down
		tween(trail, {
			alpha: 0,
			scaleX: trail.scale.x * 0.5,
			scaleY: trail.scale.y * 0.5
		}, {
			duration: self.trailLifetime,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				if (trail && trail.parent) {
					trail.parent.removeChild(trail);
				}
			}
		});
		// Return trail for further manipulation
		return trail;
	};
	// Add shooting animation
	self.animate = function () {
		// Initial rapid spinning animation
		tween(self, {
			rotation: Math.PI * 4 // Spin 720 degrees
		}, {
			duration: 800,
			easing: tween.easeOutQuad,
			onFinish: function onFinish() {
				// After initial spin, continue with normal rotation in update()
				self.rotation = Math.PI * 4 % (Math.PI * 2); // Keep within 0-360 range
			}
		});
		// Flash effect with scaling
		tween(starGraphics, {
			scaleX: 1.5,
			scaleY: 1.5
		}, {
			duration: 150,
			easing: tween.easeOutQuad,
			onFinish: function onFinish() {
				tween(starGraphics, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 150,
					easing: tween.easeInQuad
				});
			}
		});
		// Add color gradient animation to the star
		var colors = [0xffff00, 0xff9900, 0xff0000, 0xff00ff, 0x00ffff, 0xffff00];
		var colorDuration = 600;
		function animateGradient(index) {
			if (index >= colors.length - 1) {
				return;
			}
			tween(starGraphics, {
				tint: colors[index + 1]
			}, {
				duration: colorDuration,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					animateGradient((index + 1) % (colors.length - 1));
				}
			});
		}
		// Start the gradient animation
		starGraphics.tint = colors[0];
		animateGradient(0);
	};
	// Call animation when created
	self.animate();
	self.update = function () {
		// Store last position before update
		self.lastY = self.y;
		self.lastX = self.x;
		// Move the star according to its speed components
		self.x += self.speedX;
		self.y += self.speedY;
		// Rotate the star for visual effect
		self.rotation += self.rotationSpeed;
		starGraphics.rotation = self.rotation;
		// Pulse scaling effect
		if (self.scaleDirection > 0) {
			starGraphics.scale.x += self.scaleSpeed;
			starGraphics.scale.y += self.scaleSpeed;
			if (starGraphics.scale.x >= self.maxScale) {
				self.scaleDirection = -1;
			}
		} else {
			starGraphics.scale.x -= self.scaleSpeed;
			starGraphics.scale.y -= self.scaleSpeed;
			if (starGraphics.scale.x <= self.minScale) {
				self.scaleDirection = 1;
			}
		}
		// Create trail effect
		self.trailCount++;
		if (self.trailCount >= self.trailInterval) {
			self.trailCount = 0;
			// Only maintain a certain number of trails to avoid memory issues
			if (trailContainer.children.length < self.maxTrails) {
				self.createTrail();
			}
		}
		// Remove if it goes off-screen
		if (self.x > 2048 + 50 || self.y < -50 || self.y > 2732 + 50) {
			self.destroy();
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x87CEEB // Sky blue background
});
/**** 
* Game Code
****/ 
// Ensure tween.cancelAll is available
if (!tween.cancelAll) {
	tween.cancelAll = function (target) {
		// Find all active tweens affecting this target and cancel them
		var allTweens = [];
		// Get all tweens
		if (tween.getAll && typeof tween.getAll === 'function') {
			allTweens = tween.getAll();
		} else {
			// Fallback implementation if getAll is not available
			if (tween._tweens && Array.isArray(tween._tweens)) {
				allTweens = tween._tweens;
			}
		}
		// Cancel tweens for target
		if (allTweens.length > 0) {
			allTweens.forEach(function (t) {
				if (t && t._target === target && typeof t.cancel === 'function') {
					t.cancel();
				}
			});
		}
		// If no direct way to access tweens, cancel by calling tween with duration 0
		tween(target, {}, {
			duration: 0
		});
	};
}
var background = game.addChild(LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0
}));
background.x = 0;
background.y = 0;
game.desertLevelActive = false;
game.nightmareLevelActive = false;
game.infernoLevelActive = false;
game.levelTransition = false; // Track when we transition back to main level
// Initialize explosions array
var explosions = [];
// Initialize player
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 / 2;
player.lives = 3;
player.invulnerable = false;
player.invulnerableTime = 0;
player.hasPowerStar = false;
player.powerStarTime = 0;
player.originalTint = 0xFFFFFF;
// Initialize enemies
var enemies = [];
var enemySpawnInterval = 100;
var enemySpawnCounter = 0;
// Initialize flying dinosaurs
var flyingDinos = [];
var dinoSpawnInterval = 200;
var dinoSpawnCounter = 0;
// Initialize collectible hearts
var collectibleHearts = [];
var heartSpawnInterval = 300; // Less frequent than enemies
var heartSpawnCounter = 0;
// Initialize power stars
var powerStars = [];
var powerStarSpawnInterval = 600; // Even less frequent than hearts
var powerStarSpawnCounter = 0;
// Create life display with proper heart images
var maxHearts = 5; // Maximum number of hearts
var heartsContainer = new Container();
LK.gui.top.addChild(heartsContainer);
heartsContainer.x = 0; // Will be centered
heartsContainer.y = 150; // Offset from top edge
// Create heart icons array - we'll display both filled and empty hearts
var heartIcons = [];
// Function to update heart display
function updateHeartDisplay() {
	// Remove existing hearts
	while (heartsContainer.children.length > 0) {
		heartsContainer.removeChildAt(0);
	}
	// Add heart icons
	for (var i = 0; i < player.lives; i++) {
		var heart = heartsContainer.addChild(LK.getAsset('heart', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		}));
		// Position hearts in a row, centered
		var heartSpacing = 130;
		var totalWidth = (player.lives - 1) * heartSpacing;
		heart.x = -totalWidth / 2 + i * heartSpacing;
		heartIcons[i] = heart;
	}
}
// Helper function to update text and resize its container
function updateTextWithResize(textObj, container, bg, newText, minWidth) {
	textObj.setText(newText);
	if (bg && container) {
		// Resize background based on updated text width
		bg.width = Math.max(minWidth, textObj.width + 80);
	}
}
// Initialize heart display
updateHeartDisplay();
// Create a container for score to control background size
var scoreContainer = new Container();
LK.gui.top.addChild(scoreContainer);
scoreContainer.x = 2048 / 2;
scoreContainer.y = 50;
// Create score background using rounded rectangle
var scoreBg = new RoundedRect();
scoreContainer.addChild(scoreBg);
scoreBg.create(250, 120, 20, 0x000000, 0.5);
// Create a new Text2 object to display the score
var scoreText = new Text2('0', {
	size: 100,
	fill: 0xFFFFFF,
	background: 'none'
});
// Add the score text to the container
scoreText.anchor.set(0.5, 0.5);
scoreContainer.addChild(scoreText);
// Create points container with background
var pointsContainer = new Container();
LK.gui.topRight.addChild(pointsContainer);
pointsContainer.x = -20;
pointsContainer.y = 50;
// Create points background with rounded rectangle
var pointsBg = new RoundedRect();
pointsContainer.addChild(pointsBg);
pointsBg.create(320, 100, 15, 0x000000, 0.5);
// Adjust position since RoundedRect has center anchor
pointsBg.x = -160;
pointsBg.y = 0;
// Create points counter and display
var points = 0;
var pointsText = new Text2('Points: 0', {
	size: 80,
	fill: 0xFFFFFF,
	background: 'none'
});
pointsText.anchor.set(1, 0.5);
pointsContainer.addChild(pointsText);
// Create instruction text with rounded rectangle background
var instructionContainer = new Container();
LK.gui.center.addChild(instructionContainer);
instructionContainer.y = 300;
// Create temporary text to measure its dimensions
var tempText = new Text2('TAP to JUMP\nHOLD to continuously SHOOT', {
	size: 60,
	fill: 0xFFFFFF,
	align: 'center',
	background: 'none'
});
// Get text width and add padding
var textWidth = tempText.width + 100;
var textHeight = tempText.height + 80;
// Create instruction text with more detailed controls including double jump
var instructionText = new Text2('TAP to JUMP\nTAP while JUMPING for DOUBLE JUMP\nHOLD to continuously SHOOT', {
	size: 60,
	fill: 0xFFFFFF,
	align: 'center',
	background: 'none',
	shadow: {
		offsetX: 5,
		offsetY: 5,
		color: 0x000000,
		blur: 15,
		alpha: 1.0
	}
});
instructionText.anchor.set(0.5, 0.5);
instructionContainer.addChild(instructionText);
// Create a timeout to hide instructions after 6 seconds (reduced by 2 seconds)
LK.setTimeout(function () {
	// Fade out instructions
	var alpha = 1;
	var fadeInterval = LK.setInterval(function () {
		alpha -= 0.05; // Slower fade for better readability
		instructionContainer.alpha = alpha; // Fade the entire container including background
		if (alpha <= 0) {
			LK.clearInterval(fadeInterval);
			instructionContainer.visible = false;
		}
	}, 100);
}, 6000);
// Handle game updates
// Array to store bullets
var stars = [];
var shootTimer = 0;
game.update = function () {
	player.update();
	// Handle player invulnerability from damage
	if (player.invulnerable && !player.hasPowerStar) {
		// Make player flash to indicate invulnerability
		player.alpha = Math.sin(Date.now() * 0.01) * 0.5 + 0.5;
		// End invulnerability after 2 seconds
		if (Date.now() - player.invulnerableTime > 2000) {
			player.invulnerable = false;
			player.alpha = 1;
		}
	}
	// Handle power star invincibility
	if (player.hasPowerStar) {
		// Make player glow with neon colors
		var elapsed = Date.now() - player.powerStarTime;
		var colorIndex = Math.floor(elapsed / 300 % 4);
		var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00];
		player.children[0].tint = neonColors[colorIndex];
		// Player is invulnerable during power star effect
		player.invulnerable = true;
		player.alpha = 1;
		// End power star effect after 10 seconds instead of 20
		if (elapsed > 10000) {
			player.hasPowerStar = false;
			player.invulnerable = false;
			// Restore original appearance
			player.children[0].tint = player.originalTint;
			// Show power star end indicator
			showActionIndicator("POWER LOST", 1000);
		}
	}
	// Removed auto-shooting to only allow double tap shooting
	// Update stars
	for (var i = stars.length - 1; i >= 0; i--) {
		stars[i].update();
		// Remove stars that are destroyed
		if (!stars[i].parent) {
			stars.splice(i, 1);
			continue;
		}
		// Check for star-enemy collisions
		for (var j = enemies.length - 1; j >= 0; j--) {
			if (stars[i] && enemies[j] && stars[i].intersects(enemies[j])) {
				// Create explosion effect before destroying the enemy
				var explosion = new Explosion();
				explosion.x = enemies[j].x;
				explosion.y = enemies[j].y;
				explosion.createParticles(enemies[j].tint || 0xFFAA00);
				game.addChild(explosion);
				explosions.push(explosion);
				// Remove the enemy and the star
				enemies[j].destroy();
				enemies.splice(j, 1);
				stars[i].destroy();
				stars.splice(i, 1);
				// Update score
				LK.setScore(points + 10);
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 10).toString(), 250);
				// Update points
				points += 10;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Nothing here - removing this redundant check as it's handled elsewhere
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					// Ensure the score is properly set before showing win screen
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					// Resize score background based on updated text width
					scoreBg.width = Math.max(250, scoreText.width + 80);
					pointsText.setText('Points: ' + points);
					// Resize points background based on updated text width
					pointsBg.width = Math.max(320, pointsText.width + 80);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// Return to main level after 600 points
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
				// Check if we just passed 150 points for the enemy increase announcement
				if (points - 10 < 200 && points >= 150) {
					showActionIndicator("MORE ENEMIES!", 2000);
				}
				// Check level changes - use a single consistent approach
				if (points >= 500 && !game.infernoLevelActive) {
					// After 500 points, transition to inferno level
					game.infernoLevelActive = true;
					game.nightmareLevelActive = false;
					game.desertLevelActive = false;
					// No color transition for inferno level
				} else if (points >= 300 && !game.nightmareLevelActive && !game.infernoLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
				} else if (points >= 100 && !game.desertLevelActive && !game.nightmareLevelActive && !game.infernoLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
				}
				break;
			}
		}
	}
	// Hearts are now managed by updateHeartDisplay function
	// Update collectible hearts
	for (var i = collectibleHearts.length - 1; i >= 0; i--) {
		collectibleHearts[i].update();
		// Remove hearts that are destroyed
		if (!collectibleHearts[i].parent) {
			collectibleHearts.splice(i, 1);
			continue;
		}
		// Check for player-heart collisions
		if (player.intersects(collectibleHearts[i])) {
			// Player collected a heart
			collectibleHearts[i].destroy();
			collectibleHearts.splice(i, 1);
			// Add a life if not at maximum
			if (player.lives < 5) {
				player.lives++;
				// Show heart collection indicator
				showActionIndicator("+1 LIFE!", 1000);
				// Update heart display
				updateHeartDisplay();
				// Show special indicators at different milestone points
				if (points >= 900 && points < 1000) {
					showActionIndicator("ALMOST THERE! " + (1000 - points) + " TO WIN!", 1000);
				} else if (points >= 550 && points < 600) {
					showActionIndicator("LEVEL CHANGE AT 600 POINTS!", 1000);
				}
				// Get the newest heart for animation
				var newHeartIndex = player.lives - 1;
				var heart = heartIcons[newHeartIndex];
				// Show animation effect
				tween(heart, {
					scaleX: 1.5,
					scaleY: 1.5
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(heart, {
							scaleX: 1,
							scaleY: 1
						}, {
							duration: 300,
							easing: tween.easeIn
						});
					}
				});
			}
		}
	}
	// Spawn enemies
	enemySpawnCounter++;
	if (enemySpawnCounter >= enemySpawnInterval) {
		var enemy = new Enemy();
		enemy.x = 2048;
		enemy.y = 2732 / 2;
		// Make enemies faster and with different colors based on level
		if (game.infernoLevelActive) {
			enemy.speed = 12; // Even faster enemies in inferno level
			enemy.tint = 0xFF3300; // Orange-red tint for inferno enemies
			// Spawn duplicate enemies in inferno level - guaranteed 1-2 extras
			var extraCount = 1 + Math.floor(Math.random() * 2); // 1 or 2 extra enemies
			for (var i = 0; i < extraCount; i++) {
				var extraEnemy = new Enemy();
				extraEnemy.x = 2048;
				// Position enemies at different vertical positions
				extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 150 + Math.random() * 100 : -(150 + Math.random() * 100)); // Varied positions
				extraEnemy.speed = 10 + Math.random() * 4; // Varied speeds
				extraEnemy.tint = 0xFF6600;
				enemies.push(extraEnemy);
				game.addChild(extraEnemy);
			}
		} else if (game.nightmareLevelActive) {
			enemy.speed = 8; // Faster enemies in nightmare level
			enemy.tint = 0xFF0000; // Red tint for nightmare enemies
		} else if (points >= 150 && game.desertLevelActive) {
			// More enemies after 150 points in desert level
			enemy.speed = 6;
			enemy.tint = 0xCC9900; // Darker desert tint
			// Occasionally spawn a second enemy after 150 points
			if (Math.random() < 0.3) {
				var extraEnemy = new Enemy();
				extraEnemy.x = 2048;
				extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 150 : -150); // Above or below main path
				extraEnemy.speed = 5;
				extraEnemy.tint = 0xCCAA00;
				enemies.push(extraEnemy);
				game.addChild(extraEnemy);
			}
		}
		enemies.push(enemy);
		game.addChild(enemy);
		// Randomize the spawn interval for the next enemy based on level
		var interval, minInterval;
		if (game.infernoLevelActive) {
			interval = 80; // Even more frequent spawns in inferno
			minInterval = 20;
		} else if (game.nightmareLevelActive) {
			interval = 100;
			minInterval = 30;
		} else if (points >= 150) {
			interval = 120; // More frequent after 150 points
			minInterval = 40;
		} else {
			interval = 150;
			minInterval = 50;
		}
		enemySpawnInterval = Math.floor(Math.random() * interval) + minInterval;
		enemySpawnCounter = 0;
	}
	// Spawn flying dinosaurs
	dinoSpawnCounter++;
	if (dinoSpawnCounter >= dinoSpawnInterval) {
		var dino = new FlyingDino();
		dino.x = 2048;
		dino.y = Math.random() * 600 + 200; // Spawn in upper portion of screen
		dino.startY = dino.y; // Store starting Y position
		// Make dinosaurs faster and more aggressive based on level
		if (game.infernoLevelActive) {
			dino.speed = 15; // Even faster in inferno level
			dino.verticalSpeed = 5;
			dino.tint = 0xFF3300; // Orange-red tint for inferno dinos
		} else if (game.nightmareLevelActive) {
			dino.speed = 12;
			dino.verticalSpeed = 4;
			dino.tint = 0xFF00FF; // Purple tint for nightmare dinos
		} else if (game.desertLevelActive) {
			dino.speed = 10;
			dino.verticalSpeed = 3.5;
			dino.tint = 0xDDA020; // Golden tint for desert dinos
		}
		flyingDinos.push(dino);
		game.addChild(dino);
		// Randomize spawn interval based on game level
		var interval, minInterval;
		if (game.infernoLevelActive) {
			interval = 150;
			minInterval = 50;
		} else if (game.nightmareLevelActive) {
			interval = 200;
			minInterval = 100;
		} else {
			interval = 250;
			minInterval = 150;
		}
		dinoSpawnInterval = Math.floor(Math.random() * interval) + minInterval;
		dinoSpawnCounter = 0;
	}
	// Spawn collectible hearts
	heartSpawnCounter++;
	if (heartSpawnCounter >= heartSpawnInterval) {
		var heart = new Heart();
		heart.x = 2048;
		heart.y = Math.random() * 600 + 200; // Only spawn in upper third of screen
		heart.baseY = heart.y;
		collectibleHearts.push(heart);
		game.addChild(heart);
		// Randomize the spawn interval for the next heart (less frequent than enemies)
		heartSpawnInterval = Math.floor(Math.random() * 300) + 300;
		heartSpawnCounter = 0;
	}
	// Spawn power stars
	powerStarSpawnCounter++;
	if (powerStarSpawnCounter >= powerStarSpawnInterval) {
		var powerStar = new PowerStar();
		powerStar.x = 2048;
		powerStar.y = Math.random() * 600 + 200; // Only spawn in upper third of screen
		powerStar.baseY = powerStar.y;
		powerStars.push(powerStar);
		game.addChild(powerStar);
		// Randomize the spawn interval for the next power star (less frequent than hearts)
		powerStarSpawnInterval = Math.floor(Math.random() * 400) + 600;
		powerStarSpawnCounter = 0;
	}
	// Update explosions
	for (var i = explosions.length - 1; i >= 0; i--) {
		explosions[i].update();
		// Remove explosions that are destroyed
		if (!explosions[i].parent) {
			explosions.splice(i, 1);
		}
	}
	// Update power stars
	for (var i = powerStars.length - 1; i >= 0; i--) {
		powerStars[i].update();
		// Remove power stars that are destroyed
		if (!powerStars[i].parent) {
			powerStars.splice(i, 1);
			continue;
		}
		// Check for player-power star collisions
		if (player.intersects(powerStars[i])) {
			// Player collected a power star
			powerStars[i].destroy();
			powerStars.splice(i, 1);
			// Activate power star effect
			player.hasPowerStar = true;
			player.powerStarTime = Date.now();
			// Apply neon glow effect to player
			var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00];
			player.originalTint = player.children[0].tint;
			tween(player.children[0], {
				tint: neonColors[0]
			}, {
				duration: 500
			});
		}
	}
	// Update flying dinosaurs
	for (var d = flyingDinos.length - 1; d >= 0; d--) {
		flyingDinos[d].update();
		// Check if dinosaur intersects with player
		if (player.intersects(flyingDinos[d])) {
			if (player.hasPowerStar) {
				// Create explosion effect before destroying the dinosaur
				var explosion = new Explosion();
				explosion.x = flyingDinos[d].x;
				explosion.y = flyingDinos[d].y;
				explosion.createParticles(flyingDinos[d].tint || 0xFF00FF);
				game.addChild(explosion);
				explosions.push(explosion);
				explosions.push(explosion);
				// With power star, destroy dinosaurs on contact
				flyingDinos[d].destroy();
				flyingDinos.splice(d, 1);
				// Increase score - more points for dinosaurs
				LK.setScore(points + 30); // More points for dinosaur during power star
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 30).toString(), 250);
				points += 30;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				}
				// Check level changes
				if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
					game.infernoLevelActive = true;
					// No color transition for inferno level
					showActionIndicator("INFERNO LEVEL!", 4000);
				} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
					showActionIndicator("NIGHTMARE LEVEL!", 4000);
				} else if (points >= 100 && !game.desertLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
					showActionIndicator("DESERT LEVEL!", 4000);
				}
			} else if (player.y < flyingDinos[d].y - 50) {
				// Player is above dinosaur - jumped on it!
				// Create explosion effect
				var explosion = new Explosion();
				explosion.x = flyingDinos[d].x;
				explosion.y = flyingDinos[d].y;
				explosion.createParticles(flyingDinos[d].tint || 0xFF00FF);
				game.addChild(explosion);
				explosions.push(explosion);
				flyingDinos[d].destroy();
				flyingDinos.splice(d, 1);
				// Boost player up slightly after jump (small bounce)
				tween.cancelAll(player);
				player.jump();
				// Increase score
				LK.setScore(points + 20); // More points for jumping on dinosaur
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 20).toString(), 250);
				points += 20;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Show feedback
				showActionIndicator("DINO STOMP!", 1000);
				// Check win condition
				if (points >= 1000) {
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// After 600 points, transition back to main level
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
			} else if (points >= 600 && !game.levelTransition) {
				// Return to main level after 600 points
				game.levelTransition = true;
				game.desertLevelActive = false;
				game.nightmareLevelActive = false;
				game.infernoLevelActive = false;
				// No color transition when returning to main level
			} else if (!player.invulnerable) {
				// Player was hit, lose a life
				player.lives--;
				// Play hit sound
				LK.getSound('hit').play();
				// Flash screen to indicate damage
				LK.effects.flashScreen(0xff0000, 500);
				// Make player temporarily invulnerable
				player.invulnerable = true;
				player.invulnerableTime = Date.now();
				// Update hearts display
				updateHeartDisplay();
				// Check if player is out of lives
				if (player.lives <= 0) {
					LK.showGameOver();
				} else {
					// Destroy the dinosaur that hit the player
					flyingDinos[d].destroy();
					flyingDinos.splice(d, 1);
				}
			}
		} else if (player.x > flyingDinos[d].x && !flyingDinos[d].passed) {
			flyingDinos[d].passed = true;
			// Update points for passing dinosaur
			points += 15; // More points for passing flying dinosaur
			LK.setScore(points);
			// Update score with container resize
			updateTextWithResize(scoreText, scoreContainer, scoreBg, points.toString(), 250);
			// Update points with container resize
			updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
		}
		// Check for star-dinosaur collisions
		for (var s = stars.length - 1; s >= 0; s--) {
			if (stars[s] && flyingDinos[d] && stars[s].intersects(flyingDinos[d])) {
				// Create explosion effect before destroying the dinosaur
				var explosion = new Explosion();
				explosion.x = flyingDinos[d].x;
				explosion.y = flyingDinos[d].y;
				explosion.createParticles(flyingDinos[d].tint || 0xFF00FF);
				game.addChild(explosion);
				// Remove the dinosaur and the star
				flyingDinos[d].destroy();
				flyingDinos.splice(d, 1);
				stars[s].destroy();
				stars.splice(s, 1);
				// Increase score
				LK.setScore(points + 15); // More points for shooting dinosaur
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 15).toString(), 250);
				points += 15;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// Return to main level after 600 points
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
				// Check level changes
				if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
					game.infernoLevelActive = true;
					// No color transition for inferno level
				} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
				} else if (points >= 100 && !game.desertLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
				}
				break;
			}
		}
	}
	// Update enemies
	for (var j = enemies.length - 1; j >= 0; j--) {
		enemies[j].update();
		if (player.intersects(enemies[j])) {
			if (player.hasPowerStar) {
				// Create explosion effect before destroying the enemy
				var explosion = new Explosion();
				explosion.x = enemies[j].x;
				explosion.y = enemies[j].y;
				explosion.createParticles(enemies[j].tint || 0xFFFF00);
				game.addChild(explosion);
				explosions.push(explosion);
				// With power star, destroy enemies on contact
				enemies[j].destroy();
				enemies.splice(j, 1);
				// Increase score
				LK.setScore(points + 20); // Double points during power star
				// Update score with container resize
				updateTextWithResize(scoreText, scoreContainer, scoreBg, (points + 20).toString(), 250);
				// Increase points - doubled from 10 to 20
				points += 20;
				// Update points with container resize
				updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
				// Check if player reached 1000 points to win
				if (points >= 1000) {
					// Ensure the score is properly set before showing win screen
					var finalScore = points;
					LK.setScore(points);
					scoreText.setText(points.toString());
					pointsText.setText('Points: ' + points);
					LK.showYouWin();
				} else if (points >= 600 && !game.levelTransition) {
					// Return to main level after 600 points
					game.levelTransition = true;
					game.desertLevelActive = false;
					game.nightmareLevelActive = false;
					game.infernoLevelActive = false;
					// No color transition when returning to main level
				}
				// Check if we need to change level
				// We already handled win condition above, no need for duplicate check
				// Check if we need to change level
				if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
					game.infernoLevelActive = true;
					game.nightmareLevelActive = false;
					game.desertLevelActive = false;
					// No color transition for inferno level
				} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
					game.nightmareLevelActive = true;
					// No color transition for nightmare level
				} else if (points >= 100 && !game.desertLevelActive) {
					game.desertLevelActive = true;
					// No color transition for desert level
				}
			} else if (!player.invulnerable) {
				// Player was hit, lose a life
				player.lives--;
				// Play hit sound
				LK.getSound('hit').play();
				// Flash screen to indicate damage
				LK.effects.flashScreen(0xff0000, 500);
				// Make player temporarily invulnerable
				player.invulnerable = true;
				player.invulnerableTime = Date.now();
				// Update hearts display
				updateHeartDisplay();
				// Check if player is out of lives
				if (player.lives <= 0) {
					LK.showGameOver();
				} else {
					// Destroy the enemy that hit the player
					enemies[j].destroy();
					enemies.splice(j, 1);
				}
			}
		} else if (player.x > enemies[j].x && !enemies[j].passed) {
			enemies[j].passed = true;
			// Update points for passing enemy
			points += 10;
			LK.setScore(points);
			// Update score with container resize
			updateTextWithResize(scoreText, scoreContainer, scoreBg, points.toString(), 250);
			// Update points with container resize
			updateTextWithResize(pointsText, pointsContainer, pointsBg, 'Points: ' + points, 320);
		}
	}
};
// Handle player interaction
var dragNode = null;
var actionIndicator = null;
// Create visual indicators for player actions
function showActionIndicator(text, duration) {
	// Remove any existing indicator, except for level announcements
	var isLevelAnnouncement = text.includes("LEVEL");
	if (actionIndicator && actionIndicator.parent && !isLevelAnnouncement) {
		actionIndicator.parent.removeChild(actionIndicator);
	}
	// Create new indicator
	actionIndicator = new Container();
	game.addChild(actionIndicator);
	// Create temporary text to measure its dimensions
	var tempText = new Text2(text, {
		size: isLevelAnnouncement ? 100 : 50,
		fill: 0xFFFFFF,
		align: 'center',
		background: 'none'
	});
	// Get text width and add padding
	var textWidth = tempText.width + (isLevelAnnouncement ? 120 : 80);
	var textHeight = tempText.height + (isLevelAnnouncement ? 50 : 30);
	// Set minimum width/height
	var textSize = isLevelAnnouncement ? 100 : 50;
	// Add text
	var txt = new Text2(text, {
		size: textSize,
		fill: isLevelAnnouncement ? 0xFFFF00 : 0xFFFFFF,
		align: 'center',
		background: 'none'
	});
	txt.anchor.set(0.5, 0.5);
	actionIndicator.addChild(txt);
	// Position differently based on type
	if (isLevelAnnouncement) {
		// Position at center of the screen for level announcements
		actionIndicator.x = 2048 / 2; // Center horizontally
		actionIndicator.y = 2732 / 2; // Center vertically
		// Add pulsing animation for level announcements
		tween(txt.scale, {
			x: 1.2,
			y: 1.2
		}, {
			duration: 500,
			repeat: -1,
			yoyo: true,
			easing: tween.easeInOut
		});
	} else {
		// Position above player for regular announcements
		actionIndicator.x = player.x;
		actionIndicator.y = player.y - 150;
	}
	// Fade out after duration - shorter for level announcements
	var displayDuration = isLevelAnnouncement ? 2000 : duration;
	// Apply initial scaling effect for level announcements
	if (isLevelAnnouncement) {
		actionIndicator.scale.x = 0.1;
		actionIndicator.scale.y = 0.1;
		tween(actionIndicator.scale, {
			x: 1,
			y: 1
		}, {
			duration: 500,
			easing: tween.easeOutBack
		});
	}
	// Set timeout for fade-out
	LK.setTimeout(function () {
		// Cancel any existing tweens on text scaling
		if (isLevelAnnouncement) {
			tween.cancelAll(txt.scale);
		}
		// Fade out and move up
		tween(actionIndicator, {
			alpha: 0,
			y: isLevelAnnouncement ? actionIndicator.y - 100 : actionIndicator.y - 50
		}, {
			duration: 1000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				if (actionIndicator && actionIndicator.parent) {
					actionIndicator.parent.removeChild(actionIndicator);
				}
			}
		});
	}, displayDuration - 1000);
}
// Function to handle movement and shooting while holding
function handleMove(x, y, obj) {
	if (dragNode) {
		// Only move player horizontally when dragging
		// Limit movement to keep player on screen
		var minX = 100; // Minimum x-coordinate
		var maxX = 2048 - 100; // Maximum x-coordinate
		dragNode.x = Math.max(minX, Math.min(x, maxX));
		// Keep the player at the same vertical position if not jumping
		// (but don't override the tween animation when jumping)
		if (!player.isJumping) {
			dragNode.y = 2732 / 2;
		}
		// If holding finger on screen, continuously shoot
		if (shootTimer > 0) {
			// Reduced fire interval based on power star status
			var fireInterval = player.hasPowerStar ? 5 : 10;
			// Only shoot every interval ticks to control fire rate
			if (LK.ticks % fireInterval === 0) {
				// Create main star
				var star = new Star();
				star.x = player.x + 100;
				star.y = player.y;
				stars.push(star);
				game.addChild(star);
				// If player has power star, create spread shots
				if (player.hasPowerStar) {
					// Add two additional stars with slight angle variations
					for (var i = -1; i <= 1; i += 2) {
						var spreadStar = new Star();
						spreadStar.x = player.x + 100;
						spreadStar.y = player.y;
						// Apply small angular deviation
						var angle = i * 0.2; // ~11 degrees up/down
						spreadStar.speedY = Math.sin(angle) * 5;
						spreadStar.speedX = Math.cos(angle) * spreadStar.speed;
						// Override default update method for angled stars
						spreadStar.update = function () {
							this.lastY = this.y;
							this.lastX = this.x;
							this.x += this.speedX;
							this.y += this.speedY;
							if (this.x > 2048 + 50) {
								this.destroy();
							}
						};
						stars.push(spreadStar);
						game.addChild(spreadStar);
					}
				}
				// Play shooting sound
				LK.getSound('shoot').play();
			}
		}
	}
}
// shootTimer already declared earlier in the code
// Start tracking player movement on touch down and shoot on hold
game.down = function (x, y, obj) {
	// Always make the player jump on tap
	player.jump();
	// Start shooting - fire immediately when pressing
	shootTimer = Date.now();
	// Fire initial shot burst
	var initialStar = new Star();
	initialStar.x = player.x + 100;
	initialStar.y = player.y;
	stars.push(initialStar);
	game.addChild(initialStar);
	LK.getSound('shoot').play();
	// If player has power star, add enhanced initial burst
	if (player.hasPowerStar) {
		// Create a burst of 3 stars in a spread pattern
		for (var angle = -0.3; angle <= 0.3; angle += 0.3) {
			if (angle === 0) {
				continue;
			} // Skip center (already created)
			var spreadStar = new Star();
			spreadStar.x = player.x + 100;
			spreadStar.y = player.y;
			spreadStar.speedY = Math.sin(angle) * 8;
			spreadStar.speedX = Math.cos(angle) * spreadStar.speed;
			spreadStar.rotationSpeed = 0.15; // Faster rotation
			stars.push(spreadStar);
			game.addChild(spreadStar);
		}
	}
	// Handle regular movement without repositioning the player at tap position
	dragNode = player;
};
// Update player position during movement
game.move = handleMove;
// Stop tracking player movement and shooting on touch up
game.up = function (x, y, obj) {
	dragNode = null;
	shootTimer = 0; // Reset shoot timer
};
 I need an octopus that looks like bowser. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 Heart illustration red shinny. Single Game Texture. 2d. Blank background. High contrast. No shadows
 Star illustration shinny. Single Game Texture. Blank background. High contrast. No shadows
 Make it more detailed and add flying dinosaurs
 Re imagine
 2d animated character Young ninja chinese qith triangular hat game. Single Game Texture. High contrast. No shadows