User prompt
Add a reset button to the character select screen that resets all the locked characters
User prompt
Register 5 high scores to unlock piglin character
User prompt
when Steve is selected from character select screen play Steve sound
User prompt
When using Steve character and player achieves X5 bonus play the Steve sound
User prompt
Play game 3 times to unlock Steve character ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Move resetscores left 10
User prompt
Move resetscores right 50
User prompt
Move resetscores left 100
User prompt
Move resetscores right 200
User prompt
Move resetscores left 400
User prompt
Move resetscores down 300
User prompt
Replace reset button in highscore screen with resetscores asset
User prompt
Add reset button to high score screen ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Change the current method so the U shows up at the bottom after you dra a U shape
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'checkUShape')' in or related to this line: 'self.checkUShape = function (points) {' Line Number: 1025
User prompt
Trace a " U " shape on the game arena to collect a U asset on the bottom of the screen
User prompt
Move start button up 50 on title screen
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var i = letters.length - 1; i >= 0; i--) {' Line Number: 1132
User prompt
Add collision detection for letters and trigger collection
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'var nextLetterIndex = collectedLetters.length;' Line Number: 1812
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'var nextLetterIndex = collectedLetters.length;' Line Number: 1812
User prompt
Ensure only one letter is on screen at a time and enforce sequential collection
User prompt
Lock all characters with padlock on them to prevent use untill unlocked
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'push')' in or related to this line: 'letters.push(letter);' Line Number: 1797
User prompt
Please fix the bug: 'letters is not defined' in or related to this line: 'for (var i = letters.length - 1; i >= 0; i--) {' Line Number: 1802
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScores: [],
	unlockedCharacters: ["chicken"]
});
/**** 
* Classes
****/ 
var CharacterSelect = Container.expand(function () {
	var self = Container.call(this);
	// Add backdrop
	var backdrop = self.attachAsset('Backdrop', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 1009,
		y: 1366,
		alpha: 0.8
	});
	// Add title using Selectcharactertitle asset
	var titleImage = self.attachAsset('Selectcharactertitle', {
		anchorX: 0.5,
		anchorY: 0,
		x: 1024,
		y: 350
	});
	// Character options
	self.characters = [{
		name: "Chicken",
		asset: "chicken"
	}, {
		name: "Piglin",
		asset: "piglinjockey"
	}, {
		name: "Spider",
		asset: "spiderjockey"
	}, {
		name: "Steve",
		asset: "steveridingpig"
	}, {
		name: "Villager",
		asset: "vilagerjockey"
	}, {
		name: "Skeleton",
		asset: "skeletonhorse"
	}];
	self.selectedCharacter = "chicken";
	self.characterButtons = new Container();
	self.characterButtons.x = 1024;
	self.characterButtons.y = 800;
	self.addChild(self.characterButtons);
	// Create character selection buttons
	var btnWidth = 300;
	var btnHeight = 300;
	var btnSpacing = 350;
	var buttonsPerRow = 3;
	for (var i = 0; i < self.characters.length; i++) {
		var character = self.characters[i];
		var button = new Container();
		// Calculate position
		var row = Math.floor(i / buttonsPerRow);
		var col = i % buttonsPerRow;
		var xPos = (col - (buttonsPerRow - 1) / 2) * btnSpacing;
		var yPos = row * btnSpacing;
		button.x = xPos;
		button.y = yPos;
		// Create button background
		var buttonBg = button.attachAsset('centerCircle', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 3,
			scaleY: 3,
			alpha: 0.6
		});
		// Add character image
		var charImg = button.attachAsset(character.asset, {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: character.asset === "vilagerjockey" ? 0.45 : character.asset === "spiderjockey" ? 0.7 : character.asset === "chicken" ? 0.6 : 0.4,
			scaleY: character.asset === "vilagerjockey" ? 0.45 : character.asset === "spiderjockey" ? 0.7 : character.asset === "chicken" ? 0.6 : 0.4
		});
		// Check if character is unlocked
		var isUnlocked = storage.unlockedCharacters && storage.unlockedCharacters.indexOf(character.asset) !== -1;
		var lockedImg = null;
		// Add locked overlay for all characters except chicken and unlocked ones
		if (character.asset !== "chicken" && !isUnlocked) {
			lockedImg = button.attachAsset('Locked', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: 1,
				scaleY: 1
			});
			// Optionally, dim the character image to indicate locked
			charImg.alpha = 0.5;
		} else {
			// Unlocked: make sure character is fully visible
			charImg.alpha = 1;
		}
		// Character name text removed
		// Store character data with button
		button.characterData = character;
		button.isUnlocked = isUnlocked;
		// Make button interactive
		button.down = function (x, y, obj) {
			// Only animate if unlocked
			if (this.isUnlocked) {
				tween(this, {
					scaleX: 0.9,
					scaleY: 0.9
				}, {
					duration: 100
				});
			}
		};
		button.up = function (x, y, obj) {
			var btnRef = this;
			// Only allow selection if unlocked
			if (!btnRef.isUnlocked) {
				// Optionally, flash the padlock or shake the button to indicate locked
				if (lockedImg) {
					tween(lockedImg, {
						scaleX: 1.2,
						scaleY: 1.2
					}, {
						duration: 80,
						onFinish: function onFinish() {
							tween(lockedImg, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 80
							});
						}
					});
				}
				return;
			}
			tween(btnRef, {
				scaleX: 1.1,
				scaleY: 1.1
			}, {
				duration: 150,
				onFinish: function onFinish() {
					tween(btnRef, {
						scaleX: 1.0,
						scaleY: 1.0
					}, {
						duration: 100,
						onFinish: function onFinish() {
							// Set selected character
							self.selectedCharacter = btnRef.characterData.asset;
							// Notify game of selection
							if (typeof game.onCharacterSelected === 'function') {
								game.onCharacterSelected(btnRef.characterData.asset);
							}
						}
					});
				}
			});
		};
		self.characterButtons.addChild(button);
	}
	return self;
});
var ChickenJockey = Container.expand(function () {
	var self = Container.call(this);
	// Create and attach character asset (default to chicken but will be updated)
	var chickenGraphics = self.attachAsset('chicken', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Physics properties
	self.vx = 0;
	self.vy = 0;
	self.gravity = 0; // No gravity
	self.bounceDecay = 0.8; // Reduced energy loss per bounce
	self.friction = 0.99; // Reduced friction to maintain horizontal momentum
	self.launched = false;
	self.bounceCount = 0;
	self.maxBounces = 10;
	// Rotation properties
	self.rotationSpeed = 0;
	self.path = [];
	self.currentPathIndex = 0;
	self.pathSpeed = 15; // Speed at which chicken follows the path
	self.launch = function (power, angle, path) {
		// Store the path for later use
		self.path = path || [];
		self.currentPathIndex = 0;
		// Reset values
		self.vx = 0;
		self.vy = 0;
		self.rotationSpeed = power / 50;
		self.launched = true;
		self.bounceCount = 0;
		// Play launch sound
		LK.getSound('launch').play();
	};
	self.reset = function () {
		self.vx = 0;
		self.vy = 0;
		self.rotation = 0;
		self.rotationSpeed = 0;
		self.launched = false;
		self.bounceCount = 0;
	};
	// Update the character asset
	self.updateCharacterAsset = function (assetName) {
		// Remove existing character graphic
		if (chickenGraphics && chickenGraphics.parent) {
			self.removeChild(chickenGraphics);
		}
		// Create and attach new character asset
		chickenGraphics = self.attachAsset(assetName, {
			anchorX: 0.5,
			anchorY: 0.5
		});
	};
	self.update = function () {
		if (!self.launched) {
			return;
		}
		// Follow path if we have one
		if (self.path.length > 0 && self.currentPathIndex < self.path.length) {
			// Get target point
			var targetPoint = self.path[self.currentPathIndex];
			// Calculate direction to target
			var dx = targetPoint.x - self.x;
			var dy = targetPoint.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Move towards target point
			if (distance > self.pathSpeed) {
				self.vx = dx / distance * self.pathSpeed;
				self.vy = dy / distance * self.pathSpeed;
			} else {
				// Reached current target point, move to next
				self.currentPathIndex++;
				if (self.currentPathIndex >= self.path.length) {
					// End of path
					self.vx = 0;
					self.vy = 0;
				}
			}
		} else {
			// Apply friction when not following path
			self.vx *= self.friction;
			self.vy *= self.friction;
		}
		// Update position
		self.x += self.vx;
		self.y += self.vy;
		// Apply rotation based on movement direction
		if (Math.abs(self.vx) > 0.1 || Math.abs(self.vy) > 0.1) {
			var targetRotation = Math.atan2(self.vy, self.vx);
			// Gradually rotate towards movement direction
			var rotDiff = targetRotation - self.rotation;
			// Normalize angle
			while (rotDiff > Math.PI) {
				rotDiff -= Math.PI * 2;
			}
			while (rotDiff < -Math.PI) {
				rotDiff += Math.PI * 2;
			}
			// Apply rotation
			self.rotation += rotDiff * 0.1;
		}
		// Check if stopped
		if (Math.abs(self.vx) < 0.5 && Math.abs(self.vy) < 0.5 && (self.bounceCount > 0 || self.currentPathIndex >= self.path.length)) {
			self.launched = false;
			// Notify game that chicken jockey has stopped
			if (typeof game.onChickenJockeyStop === 'function') {
				game.onChickenJockeyStop();
			}
		}
		// Check if max bounces reached
		if (self.bounceCount >= self.maxBounces) {
			self.launched = false;
			// Notify game that max bounces reached
			if (typeof game.onMaxBouncesReached === 'function') {
				game.onMaxBouncesReached();
			}
		}
	};
	return self;
});
var HighScorePage = Container.expand(function () {
	var self = Container.call(this);
	// Add backdrop for high score page
	var backdrop = self.attachAsset('Hiscorebackdrop', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 1024,
		y: 1366,
		alpha: 0.8,
		scaleX: 1,
		scaleY: 1
	});
	// Add title using Highscorestitle asset
	var titleImage = self.attachAsset('Highscorestitle', {
		anchorX: 0.5,
		anchorY: 0,
		x: 1024,
		y: 550
	});
	// Container for score entries
	self.scoreEntries = new Container();
	self.scoreEntries.x = 1024;
	self.scoreEntries.y = 800;
	self.addChild(self.scoreEntries);
	// Back button
	self.backButton = new Container();
	self.backButton.x = 1024;
	self.backButton.y = 2000;
	// Button using Backbutton asset
	var buttonBackground = self.backButton.attachAsset('Backbutton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// No back text - using only the Backbutton asset
	// Add back button to high score page
	self.addChild(self.backButton);
	// Make back button interactive
	self.backButton.down = function (x, y, obj) {
		// Animate button press
		tween(self.backButton, {
			scaleX: 0.9,
			scaleY: 0.9
		}, {
			duration: 100
		});
	};
	self.backButton.up = function (x, y, obj) {
		// Animate button release
		tween(self.backButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 150,
			onFinish: function onFinish() {
				tween(self.backButton, {
					scaleX: 1.0,
					scaleY: 1.0
				}, {
					duration: 100,
					onFinish: function onFinish() {
						// Notify game that back button was pressed
						if (typeof game.onBackButtonPressed === 'function') {
							game.onBackButtonPressed();
						}
					}
				});
			}
		});
	};
	// Update high scores display
	self.updateScores = function () {
		// Clear existing score entries
		while (self.scoreEntries.children.length > 0) {
			self.scoreEntries.removeChild(self.scoreEntries.children[0]);
		}
		// Get high scores from storage
		var highScores = storage.highScores || [];
		// Sort high scores in descending order
		highScores.sort(function (a, b) {
			return b - a;
		});
		// Keep only top 5 scores
		highScores = highScores.slice(0, 5);
		// Display each score
		var yPos = 0;
		for (var i = 0; i < highScores.length; i++) {
			var scoreText = new Text2(i + 1 + ". " + highScores[i], {
				size: 70,
				fill: 0xFFFFFF
			});
			scoreText.anchor.set(0.5, 0);
			scoreText.y = yPos;
			self.scoreEntries.addChild(scoreText);
			yPos += 100;
		}
		// If no scores yet, show a message
		if (highScores.length === 0) {
			var noScoresText = new Text2("No scores yet!", {
				size: 70,
				fill: 0xFFFFFF
			});
			noScoresText.anchor.set(0.5, 0);
			self.scoreEntries.addChild(noScoresText);
		}
	};
	return self;
});
var Launcher = Container.expand(function () {
	var self = Container.call(this);
	// Create and attach launcher asset with alpha 0 to make it invisible
	var launcherGraphics = self.attachAsset('launcher', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0
	});
	// Create aim line (initially invisible)
	var aimLine = self.attachAsset('aimLine', {
		anchorX: 0,
		anchorY: 0.5,
		alpha: 0
	});
	// Launcher properties
	self.angle = -45; // Starting angle in degrees
	self.power = 20; // Increased starting power
	self.maxPower = 40; // Increased maximum power
	self.aiming = false;
	self.drawingPath = false;
	self.points = [];
	self.startX = 0;
	self.startY = 0;
	self.currentX = 0;
	self.currentY = 0;
	self.lastPointTime = 0;
	self.pathStep = 0;
	// Create trajectory path visualization
	self.trajectoryPath = new TrajectoryPath();
	// Start aim by drawing a path
	self.startAim = function (x, y) {
		self.aiming = true;
		self.drawingPath = true;
		self.startX = x;
		self.startY = y;
		self.currentX = x;
		self.currentY = y;
		self.points = [{
			x: x,
			y: y
		}];
		self.lastPointTime = LK.ticks;
		// Show the trajectory path
		if (self.trajectoryPath.parent) {
			self.trajectoryPath.show();
		}
	};
	// Store for drawing path
	self.pathGraphics = new Container();
	self.addChild(self.pathGraphics);
	self.updateAim = function (x, y) {
		if (!self.aiming) {
			return;
		}
		if (self.drawingPath) {
			// Update current position
			self.currentX = x;
			self.currentY = y;
			// Add a point every few frames to avoid too many points
			if (LK.ticks - self.lastPointTime > 2) {
				self.points.push({
					x: x,
					y: y
				});
				// Visualize the path point
				var pathPoint = LK.getAsset('aimLine', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: x,
					y: y,
					scaleX: 0.3,
					scaleY: 0.3,
					alpha: 0.7
				});
				self.pathGraphics.addChild(pathPoint);
				self.lastPointTime = LK.ticks;
				// Update trajectory path to show the actual path
				if (self.trajectoryPath.parent && self.points.length > 1) {
					self.trajectoryPath.updatePathFromPoints(self.points);
				}
			}
			// Calculate direction vector from start to current position
			var dx = x - self.startX;
			var dy = y - self.startY;
			// Calculate angle in degrees (0 is right, 90 is up)
			self.angle = Math.atan2(dy, dx) * 180 / Math.PI;
			// Calculate power based on path length
			var distance = Math.sqrt(dx * dx + dy * dy);
			self.power = Math.min(distance / 10, self.maxPower);
			// Update launcher rotation
			self.rotation = self.angle * Math.PI / 180;
		}
	};
	self.endAim = function () {
		self.aiming = false;
		self.drawingPath = false;
		// Hide trajectory path
		if (self.trajectoryPath.parent) {
			self.trajectoryPath.hide();
		}
		// Keep a copy of the path points
		var pathPoints = self.points.slice();
		// Clear the path visualization after a delay
		LK.setTimeout(function () {
			// Remove all path point graphics
			while (self.pathGraphics.children.length > 0) {
				self.pathGraphics.removeChild(self.pathGraphics.children[0]);
			}
		}, 500);
		// Calculate final launch parameters
		var finalAngle = self.angle + 180; // Reverse direction
		// Return launch parameters
		return {
			angle: finalAngle,
			power: self.power
		};
	};
	return self;
});
var Letter = Container.expand(function (letterAsset) {
	var self = Container.call(this);
	// Store the letter asset name
	self.letter = letterAsset;
	// Create and attach letter asset
	var letterGraphics = self.attachAsset(letterAsset, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Collect function for when the letter is collected
	self.collect = function () {
		// Play collect sound
		LK.getSound('collect').play();
		// Flash effect
		LK.effects.flashObject(self, 0xFFFFFF, 200);
		// Animate collection with spinning and scaling
		tween(self, {
			y: self.y - 100,
			rotation: Math.PI * 4,
			// Spin multiple times
			scaleX: 1.5,
			// Grow while spinning
			scaleY: 1.5,
			// Grow while spinning
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from parent
				if (self.parent) {
					self.parent.removeChild(self);
				}
			}
		});
	};
	return self;
});
// Create letters scattered around the arena
var NumberPattern = Container.expand(function () {
	var self = Container.call(this);
	// Patterns for numbers 1-9, each represented as a 5x5 grid
	// 1 = popcorn, 0 = empty space
	self.patterns = {
		1: [[0, 0, 1, 0, 0], [0, 1, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 1, 1, 1, 0]],
		2: [[0, 1, 1, 1, 0], [1, 0, 0, 0, 1], [0, 0, 1, 1, 0], [0, 1, 0, 0, 0], [1, 1, 1, 1, 1]],
		3: [[0, 1, 1, 1, 0], [1, 0, 0, 0, 1], [0, 0, 1, 1, 0], [1, 0, 0, 0, 1], [0, 1, 1, 1, 0]],
		4: [[0, 0, 1, 1, 0], [0, 1, 0, 1, 0], [1, 0, 0, 1, 0], [1, 1, 1, 1, 1], [0, 0, 0, 1, 0]],
		5: [[1, 1, 1, 1, 1], [1, 0, 0, 0, 0], [1, 1, 1, 1, 0], [0, 0, 0, 0, 1], [1, 1, 1, 1, 0]],
		6: [[0, 1, 1, 1, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 0], [1, 0, 0, 0, 1], [0, 1, 1, 1, 0]],
		7: [[1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [0, 1, 0, 0, 0]],
		8: [[0, 1, 1, 1, 0], [1, 0, 0, 0, 1], [0, 1, 1, 1, 0], [1, 0, 0, 0, 1], [0, 1, 1, 1, 0]],
		9: [[0, 1, 1, 1, 0], [1, 0, 0, 0, 1], [0, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 1, 1, 1, 0]]
	};
	// Create popcorn in a number pattern
	self.createPattern = function (number, centerX, centerY, spacing) {
		if (number < 1 || number > 9 || !self.patterns[number]) {
			return [];
		}
		var pattern = self.patterns[number];
		var patternHeight = pattern.length;
		var patternWidth = pattern[0].length;
		var createdPopcorns = [];
		// Calculate starting position to center the pattern
		var startX = centerX - patternWidth * spacing / 2;
		var startY = centerY - patternHeight * spacing / 2;
		// Create popcorn for each position in the pattern
		for (var row = 0; row < patternHeight; row++) {
			for (var col = 0; col < patternWidth; col++) {
				if (pattern[row][col] === 1) {
					// Create multiple popcorn in each position to make pattern denser
					var numPopcornPerSpot = 4; // Add 4 popcorn per pattern spot
					var offset = spacing / 5; // Small offset to spread them out
					for (var p = 0; p < numPopcornPerSpot; p++) {
						var popcorn = new Popcorn();
						// Add small random offset for each popcorn to create a cluster
						var offsetX = p % 2 * offset - offset / 2;
						var offsetY = Math.floor(p / 2) * offset - offset / 2;
						popcorn.x = startX + col * spacing + offsetX;
						popcorn.y = startY + row * spacing + offsetY;
						createdPopcorns.push(popcorn);
					}
				}
			}
		}
		return createdPopcorns;
	};
	return self;
});
var Popcorn = Container.expand(function () {
	var self = Container.call(this);
	// Create and attach popcorn asset
	var popcornGraphics = self.attachAsset('popcorn', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add slight animation
	self.animationOffset = Math.random() * Math.PI * 2;
	self.animationSpeed = 0.03 + Math.random() * 0.02;
	self.baseY = 0;
	self.collect = function () {
		// Play collect sound
		LK.getSound('pop').play();
		// Flash effect
		LK.effects.flashObject(self, 0xFFFFFF, 200);
		// Animate collection with spinning and scaling
		tween(self, {
			y: self.y - 100,
			rotation: Math.PI * 4,
			// Spin multiple times
			scaleX: 1.5,
			// Grow while spinning
			scaleY: 1.5,
			// Grow while spinning
			alpha: 0
		}, {
			duration: 800,
			// Longer duration for more visible animation
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from parent
				if (self.parent) {
					self.parent.removeChild(self);
				}
			}
		});
	};
	self.update = function () {
		// Hover animation
		if (self.baseY === 0) {
			self.baseY = self.y;
			self.targetX = self.x;
			self.targetY = self.y;
			self.moveTimer = 0;
			self.moveDuration = 180 + Math.random() * 120; // 3-5 seconds at 60fps
		}
		// Smooth hovering
		self.y = self.baseY + Math.sin(LK.ticks * self.animationSpeed + self.animationOffset) * 5;
		// Random movement
		self.moveTimer++;
		if (self.moveTimer >= self.moveDuration) {
			// Set new random target within arena bounds (with padding)
			var padding = 200;
			var newX = bounds.left + padding + Math.random() * (arena.width - padding * 2);
			var newY = bounds.top + padding + Math.random() * (arena.height - padding * 2);
			// Check distance from ropes
			var validPosition = true;
			for (var j = 0; j < ropes.length; j++) {
				var dx = newX - ropes[j].x;
				var dy = newY - ropes[j].y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 200) {
					validPosition = false;
					break;
				}
			}
			if (validPosition) {
				self.targetX = newX;
				self.targetY = newY;
				self.baseY = newY;
				self.moveTimer = 0;
			}
		}
		// Move toward target with easing
		if (self.targetX !== self.x || self.targetY !== self.y) {
			self.x += (self.targetX - self.x) * 0.01;
			self.y += (self.targetY - self.y) * 0.01;
		}
	};
	return self;
});
var Rope = Container.expand(function () {
	var self = Container.call(this);
	// Create and attach rope asset
	var ropeGraphics = self.attachAsset('rope', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Rope properties
	self.tension = 0; // No tension for no bounce effect
	self.bounce = function (chickenJockey) {
		// No velocity change - completely removed bounce effect
		// Set velocity to zero in the direction of the rope
		if (self.rotation === 0 || self.rotation === Math.PI) {
			// Horizontal rope (top or bottom)
			chickenJockey.vy = 0;
		} else {
			// Vertical rope (left or right)
			chickenJockey.vx = 0;
		}
		// Still increment bounce count for tracking
		chickenJockey.bounceCount++;
		// Play bounce sound
		LK.getSound('bounce').play();
		// Flash rope to indicate contact
		LK.effects.flashObject(self, 0xFFFFFF, 200);
	};
	self.intersectsWithPoint = function (x, y) {
		var halfWidth = ropeGraphics.width / 2;
		var halfHeight = ropeGraphics.height / 2;
		// Check if point is within the rope's bounding box
		return x >= self.x - halfWidth && x <= self.x + halfWidth && y >= self.y - halfHeight && y <= self.y + halfHeight;
	};
	return self;
});
var Superpopcorn = Container.expand(function () {
	var self = Container.call(this);
	// Create and attach Superpopcorn asset
	var superPopcornGraphics = self.attachAsset('Superpopcorn', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add slight animation
	self.animationOffset = Math.random() * Math.PI * 2;
	self.animationSpeed = 0.03 + Math.random() * 0.02;
	self.baseY = 0;
	self.collect = function () {
		// Play collect sound
		LK.getSound('pop').play();
		LK.getSound('collect').play();
		// Flash effect
		LK.effects.flashObject(self, 0xFFFFFF, 200);
		// Animate collection with spinning and scaling
		tween(self, {
			y: self.y - 150,
			// Fly higher for superpopcorn
			rotation: Math.PI * 6,
			// Spin more times for superpopcorn
			scaleX: 2.0,
			// Grow larger while spinning
			scaleY: 2.0,
			// Grow larger while spinning
			alpha: 0
		}, {
			duration: 1000,
			// Longer duration for more visible animation
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from parent
				if (self.parent) {
					self.parent.removeChild(self);
				}
			}
		});
	};
	self.update = function () {
		// Hover animation
		if (self.baseY === 0) {
			self.baseY = self.y;
			self.targetX = self.x;
			self.targetY = self.y;
			self.moveTimer = 0;
			self.moveDuration = 120 + Math.random() * 60; // 2-3 seconds at 60fps (faster than regular popcorn)
		}
		// Smooth hovering with larger amplitude for superpopcorn
		self.y = self.baseY + Math.sin(LK.ticks * self.animationSpeed + self.animationOffset) * 8;
		// Random movement
		self.moveTimer++;
		if (self.moveTimer >= self.moveDuration) {
			// Set new random target within arena bounds (with padding)
			var padding = 200;
			var newX = bounds.left + padding + Math.random() * (arena.width - padding * 2);
			var newY = bounds.top + padding + Math.random() * (arena.height - padding * 2);
			// Check distance from ropes
			var validPosition = true;
			for (var j = 0; j < ropes.length; j++) {
				var dx = newX - ropes[j].x;
				var dy = newY - ropes[j].y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < 200) {
					validPosition = false;
					break;
				}
			}
			if (validPosition) {
				self.targetX = newX;
				self.targetY = newY;
				self.baseY = newY;
				self.moveTimer = 0;
			}
		}
		// Move toward target with easing (slightly faster than regular popcorn)
		if (self.targetX !== self.x || self.targetY !== self.y) {
			self.x += (self.targetX - self.x) * 0.015;
			self.y += (self.targetY - self.y) * 0.015;
		}
	};
	return self;
});
var TitlePage = Container.expand(function () {
	var self = Container.call(this);
	// Add title screen background
	var titleBackground = self.attachAsset('Titlescreen', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 1024,
		y: 1366
	});
	// Create start button
	self.startButton = new Container();
	self.startButton.x = 1024;
	self.startButton.y = 1700;
	// Button using Startbutton asset
	var buttonBackground = self.startButton.attachAsset('Startbutton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Create high scores button (positioned below start button)
	self.highScoresButton = new Container();
	self.highScoresButton.x = 1024;
	self.highScoresButton.y = 1900;
	// Button using Hiscorebutton asset
	var hsButtonBackground = self.highScoresButton.attachAsset('Hiscorebutton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add both buttons to title page
	self.addChild(self.startButton);
	self.addChild(self.highScoresButton);
	// Make start button interactive
	self.startButton.down = function (x, y, obj) {
		// Animate button press
		tween(self.startButton, {
			scaleX: 0.9,
			scaleY: 0.9
		}, {
			duration: 100
		});
	};
	self.startButton.up = function (x, y, obj) {
		// Animate button release
		tween(self.startButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 150,
			onFinish: function onFinish() {
				tween(self.startButton, {
					scaleX: 1.0,
					scaleY: 1.0
				}, {
					duration: 100,
					onFinish: function onFinish() {
						// Notify game that start button was pressed
						if (typeof game.onStartButtonPressed === 'function') {
							game.onStartButtonPressed();
						}
					}
				});
			}
		});
	};
	// Make high scores button interactive
	self.highScoresButton.down = function (x, y, obj) {
		// Animate button press
		tween(self.highScoresButton, {
			scaleX: 0.9,
			scaleY: 0.9
		}, {
			duration: 100
		});
	};
	self.highScoresButton.up = function (x, y, obj) {
		// Animate button release
		tween(self.highScoresButton, {
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 150,
			onFinish: function onFinish() {
				tween(self.highScoresButton, {
					scaleX: 1.0,
					scaleY: 1.0
				}, {
					duration: 100,
					onFinish: function onFinish() {
						// Notify game that high scores button was pressed
						if (typeof game.onHighScoresButtonPressed === 'function') {
							game.onHighScoresButtonPressed();
						}
					}
				});
			}
		});
	};
	return self;
});
var TrajectoryPath = Container.expand(function () {
	var self = Container.call(this);
	// Properties
	self.points = [];
	self.maxPoints = 40; // Increased number of trajectory points for better visualization
	self.visible = false;
	// Create path line graphics
	self.pathLine = new Container();
	self.addChild(self.pathLine);
	// Create trajectory points
	self.createPoints = function () {
		// Clear existing points
		for (var i = 0; i < self.points.length; i++) {
			self.removeChild(self.points[i]);
		}
		self.points = [];
		// Create new points
		for (var i = 0; i < self.maxPoints; i++) {
			var point = new TrajectoryPoint();
			point.alpha = 1 - i / self.maxPoints;
			self.addChild(point);
			self.points.push(point);
		}
	};
	// Update trajectory path based on path points
	self.updatePathFromPoints = function (pathPoints) {
		if (!self.visible || !pathPoints || pathPoints.length < 2) {
			return;
		}
		// Clear existing path visualization
		while (self.pathLine.children.length > 0) {
			self.pathLine.removeChild(self.pathLine.children[0]);
		}
		// Draw path line segments
		for (var i = 0; i < pathPoints.length - 1; i++) {
			self.drawPathSegment(pathPoints[i], pathPoints[i + 1], i, pathPoints.length);
		}
		// Update trajectory points along the path
		for (var i = 0; i < self.points.length; i++) {
			var pointIndex = Math.floor(i * (pathPoints.length - 1) / self.points.length);
			if (pointIndex < pathPoints.length - 1) {
				var percent = i * (pathPoints.length - 1) / self.points.length - pointIndex;
				var p1 = pathPoints[pointIndex];
				var p2 = pathPoints[pointIndex + 1];
				self.points[i].x = p1.x + (p2.x - p1.x) * percent;
				self.points[i].y = p1.y + (p2.y - p1.y) * percent;
				self.points[i].alpha = 0.7 * (1 - i / self.points.length);
			}
		}
	};
	// Draw a segment of the path between two points
	self.drawPathSegment = function (p1, p2, index, total) {
		var segment = LK.getAsset('aimLine', {
			anchorX: 0,
			anchorY: 0.5,
			alpha: 0.6 * (1 - index / total),
			scaleX: 0.5,
			scaleY: 0.3
		});
		// Position at start point
		segment.x = p1.x;
		segment.y = p1.y;
		// Calculate segment length and angle
		var dx = p2.x - p1.x;
		var dy = p2.y - p1.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var angle = Math.atan2(dy, dx);
		// Set length and rotation
		segment.width = distance;
		segment.rotation = angle;
		self.pathLine.addChild(segment);
	};
	// Update trajectory path based on launch parameters
	self.updatePath = function (startX, startY, angle, power) {
		if (!self.visible) {
			return;
		}
		// Convert angle to radians
		var radians = angle * Math.PI / 180;
		// Calculate initial velocity
		var vx = Math.cos(radians) * power;
		var vy = Math.sin(radians) * power;
		// Simulate trajectory for each point
		var x = startX;
		var y = startY;
		var tempVX = vx;
		var tempVY = vy;
		for (var i = 0; i < self.points.length; i++) {
			// Update position based on velocity
			x += tempVX;
			y += tempVY;
			// Apply only friction (no gravity)
			tempVX *= 0.99; // friction
			// Position the trajectory point
			self.points[i].x = x;
			self.points[i].y = y;
		}
	};
	// Show trajectory
	self.show = function () {
		self.visible = true;
		self.pathLine.alpha = 1;
		for (var i = 0; i < self.points.length; i++) {
			self.points[i].alpha = 1 - i / self.maxPoints;
		}
	};
	// Hide trajectory
	self.hide = function () {
		self.visible = false;
		self.pathLine.alpha = 0;
		for (var i = 0; i < self.points.length; i++) {
			self.points[i].alpha = 0;
		}
	};
	// Initialize points on creation
	self.createPoints();
	return self;
});
var TrajectoryPoint = Container.expand(function () {
	var self = Container.call(this);
	// Create and attach point asset
	var pointGraphics = self.attachAsset('centerCircle', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.2,
		scaleY: 0.2,
		alpha: 0.5
	});
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000 // Black background
});
/**** 
* Game Code
****/ 
// Game state
var gameState = "title"; // title, characterSelect, ready, aiming, launched, gameOver, highScores
var score = 0;
var launches = 0;
var maxLaunches = 10;
var collectedLetters = []; // Initialize collected letters array here
var popcorns = [];
var superPopcorns = [];
var ropes = [];
var bonusApplied = false;
var bonusAnimation = null;
var titlePage = null;
var highScorePage = null;
var characterSelectPage = null;
var selectedCharacter = "chicken"; // Default character
// Add backdrop behind arena
var backdrop = game.addChild(LK.getAsset('Backdrop', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2
}));
// Create wrestling arena
var arena = game.addChild(LK.getAsset('arena', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2
}));
// Create chicken jockey
var chickenJockey = game.addChild(new ChickenJockey());
var launcher = game.addChild(new Launcher());
// Game boundaries
var bounds = {
	left: arena.x - arena.width / 2,
	right: arena.x + arena.width / 2,
	top: arena.y - arena.height / 2,
	bottom: arena.y + arena.height / 2
};
// Create GUI elements
var scoreTitleImg = LK.getAsset('Scoretitle', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: -10,
	y: 40
});
LK.gui.top.addChild(scoreTitleImg);
var scoreText = new Text2("0", {
	size: 70,
	fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = -170; // Moved left by 50 pixels
scoreText.y = 70; // Moved down by 70 pixels
LK.gui.top.addChild(scoreText);
// Create launches title using Launchestitle asset
var launchesTitleImg = LK.getAsset('Launchestitle', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 150,
	y: 190 // Moved down by 170 pixels
});
LK.gui.topLeft.addChild(launchesTitleImg);
var launchesText = new Text2("0/" + maxLaunches, {
	size: 50,
	fill: 0xFFFFFF
});
launchesText.anchor.set(0, 0);
launchesText.x = 300; // Positioned after the title image
launchesText.y = 160; // Moved down by 140 pixels
LK.gui.topLeft.addChild(launchesText);
var instructionText = new Text2("Draw a path to launch the chicken!", {
	size: 40,
	fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 180;
LK.gui.top.addChild(instructionText);
// Initialize game
function initGame() {
	// Reset variables
	score = 0;
	launches = 0;
	gameState = "title";
	bonusApplied = false;
	// Remove bonus animation if it exists
	if (bonusAnimation && bonusAnimation.parent) {
		bonusAnimation.parent.removeChild(bonusAnimation);
		bonusAnimation = null;
	}
	// Update UI elements but hide them initially
	scoreText.setText(score);
	scoreText.alpha = 0;
	scoreTitleImg.alpha = 0; // Hide score title image initially
	launchesText.setText(launches + "/" + maxLaunches);
	launchesText.alpha = 0;
	instructionText.setText("Draw a path to launch the chicken!");
	instructionText.alpha = 0;
	// Hide game elements initially
	arena.alpha = 0;
	backdrop.alpha = 0;
	chickenJockey.alpha = 0;
	launchesTitleImg.alpha = 0; // Make sure launchestitle is hidden initially
	// Show title page
	if (!titlePage) {
		titlePage = new TitlePage();
		game.addChild(titlePage);
	} else {
		titlePage.alpha = 1;
	}
	// Initialize high score page if it doesn't exist
	if (!highScorePage) {
		highScorePage = new HighScorePage();
		// Keep it detached until needed
	}
	// Initialize character select page if it doesn't exist
	if (!characterSelectPage) {
		characterSelectPage = new CharacterSelect();
		// Keep it detached until needed
	}
	// Add game start handler
	game.onStartButtonPressed = function () {
		// Hide title page
		tween(titlePage, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				if (titlePage.parent) {
					titlePage.parent.removeChild(titlePage);
				}
				// Show character select page
				game.addChild(characterSelectPage);
				characterSelectPage.alpha = 0;
				tween(characterSelectPage, {
					alpha: 1
				}, {
					duration: 500
				});
				// Set game state
				gameState = "characterSelect";
			}
		});
	};
	// Add high scores button handler
	game.onHighScoresButtonPressed = function () {
		// Hide title page
		tween(titlePage, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				if (titlePage.parent) {
					titlePage.parent.removeChild(titlePage);
				}
				// Update high scores before showing
				highScorePage.updateScores();
				// Show high scores page
				game.addChild(highScorePage);
				highScorePage.alpha = 0;
				tween(highScorePage, {
					alpha: 1
				}, {
					duration: 500
				});
				// Set game state
				gameState = "highScores";
			}
		});
	};
	// Add back button handler
	game.onBackButtonPressed = function () {
		// Hide high scores page
		tween(highScorePage, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				if (highScorePage.parent) {
					highScorePage.parent.removeChild(highScorePage);
				}
				// Show title page
				game.addChild(titlePage);
				titlePage.alpha = 0;
				tween(titlePage, {
					alpha: 1
				}, {
					duration: 500
				});
				// Set game state
				gameState = "title";
			}
		});
	};
	// Add character selected handler
	game.onCharacterSelected = function (characterAsset) {
		// Store selected character
		selectedCharacter = characterAsset;
		// Update chicken jockey with selected character
		chickenJockey.updateCharacterAsset(selectedCharacter);
		// Play Pignoise sound if Piglin is selected
		if (selectedCharacter === "piglinjockey") {
			LK.getSound('Pignoise').play();
		}
		// Hide character select page
		tween(characterSelectPage, {
			alpha: 0
		}, {
			duration: 500,
			onFinish: function onFinish() {
				if (characterSelectPage.parent) {
					characterSelectPage.parent.removeChild(characterSelectPage);
				}
				// Show game elements
				tween(arena, {
					alpha: 1
				}, {
					duration: 300
				});
				tween(backdrop, {
					alpha: 1
				}, {
					duration: 300
				});
				tween(chickenJockey, {
					alpha: 1
				}, {
					duration: 300
				});
				scoreText.alpha = 1;
				scoreTitleImg.alpha = 1; // Show score title when game starts
				launchesText.alpha = 1;
				instructionText.alpha = 1;
				// Start the actual game
				startGamePlay();
			}
		});
	};
}
// New function to start the actual gameplay after title screen
function startGamePlay() {
	// Set game state to ready
	gameState = "ready";
	// Reset chicken jockey
	resetChickenJockey();
	// Update instruction text to show current pattern number
	var currentNumber = launches % 9 + 1;
	instructionText.setText("Collect number " + currentNumber + " pattern!");
	// Clear existing popcorn and ropes
	clearPopcornsAndRopes();
	// Create ropes around the arena
	createRopes();
	// Create popcorn scattered around the arena
	createPopcorn(15);
	// Add trajectory path to game
	game.addChild(launcher.trajectoryPath);
	// Play background music
	LK.playMusic('gameMusic');
	// Add Steve to the top left corner of the arena
	var steve = game.addChild(LK.getAsset('Steve', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: bounds.left + 625,
		y: bounds.top + 325
	}));
	// Initially hide the launchesTitleImg
	launchesTitleImg.alpha = 0;
	// Play gamestart sound when Steve appears
	LK.getSound('Gamestart').play();
	// Remove Steve after 2 seconds and show launchestitle
	LK.setTimeout(function () {
		if (steve && steve.parent) {
			steve.parent.removeChild(steve);
		}
		// Show launchestitle after gamestart sound is played
		tween(launchesTitleImg, {
			alpha: 1
		}, {
			duration: 300
		});
	}, 2000);
}
function resetChickenJockey() {
	chickenJockey.reset();
	// Make sure the right character is displayed
	chickenJockey.updateCharacterAsset(selectedCharacter);
	// Position character in the center of the arena
	chickenJockey.x = arena.x;
	chickenJockey.y = arena.y;
	// Position launcher at the same position
	launcher.x = chickenJockey.x;
	launcher.y = chickenJockey.y;
	launcher.rotation = -Math.PI / 4; // 45 degrees upward
	// Reset instruction text when character is reset
	instructionText.setText("Draw a path to launch your character!");
}
function clearPopcornsAndRopes() {
	// Remove all popcorn
	for (var i = 0; i < popcorns.length; i++) {
		if (popcorns[i].parent) {
			popcorns[i].parent.removeChild(popcorns[i]);
		}
	}
	popcorns = [];
	// Remove all superpopcorn
	for (var i = 0; i < superPopcorns.length; i++) {
		if (superPopcorns[i].parent) {
			superPopcorns[i].parent.removeChild(superPopcorns[i]);
		}
	}
	superPopcorns = [];
	// Remove all ropes
	for (var i = 0; i < ropes.length; i++) {
		if (ropes[i].parent) {
			ropes[i].parent.removeChild(ropes[i]);
		}
	}
	ropes = [];
}
function createRopes() {
	// Create top rope
	var topRope = new Rope();
	topRope.x = arena.x;
	topRope.y = bounds.top + 100;
	game.addChild(topRope);
	ropes.push(topRope);
	// Create right rope
	var rightRope = new Rope();
	rightRope.x = bounds.right - 100;
	rightRope.y = arena.y;
	rightRope.rotation = Math.PI / 2; // Rotate 90 degrees
	game.addChild(rightRope);
	ropes.push(rightRope);
	// Create bottom rope
	var bottomRope = new Rope();
	bottomRope.x = arena.x;
	bottomRope.y = bounds.bottom - 100;
	game.addChild(bottomRope);
	ropes.push(bottomRope);
	// Create left rope
	var leftRope = new Rope();
	leftRope.x = bounds.left + 100;
	leftRope.y = arena.y;
	leftRope.rotation = Math.PI / 2; // Rotate 90 degrees
	game.addChild(leftRope);
	ropes.push(leftRope);
}
function createPopcorn(count) {
	// Create a number pattern generator
	var patternGenerator = new NumberPattern();
	// Calculate spacing based on the arena size
	var spacing = 280; // Double the spacing to make the pattern larger
	// Determine which number to display (1-9)
	var currentNumber = launches % 9 + 1;
	// Create popcorn in the number pattern
	var newPopcorns = patternGenerator.createPattern(currentNumber, arena.x,
	// Center X position
	arena.y,
	// Center Y position
	spacing // Spacing between popcorn
	);
	// Add all created popcorn to the game
	for (var i = 0; i < newPopcorns.length; i++) {
		var popcorn = newPopcorns[i];
		// Verify position is valid (not too close to ropes)
		var validPosition = true;
		for (var j = 0; j < ropes.length; j++) {
			var dx = popcorn.x - ropes[j].x;
			var dy = popcorn.y - ropes[j].y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < 100) {
				validPosition = false;
				break;
			}
		}
		// Only add if position is valid
		if (validPosition) {
			game.addChild(popcorn);
			popcorns.push(popcorn);
		}
	}
	// If we need more popcorn to reach the count, add some randomly
	if (popcorns.length < count) {
		for (var i = popcorns.length; i < count; i++) {
			var popcorn = new Popcorn();
			// Random position within arena bounds
			var validPosition = false;
			var attempts = 0;
			var maxAttempts = 50;
			// Keep trying until we find a valid position
			while (!validPosition && attempts < maxAttempts) {
				// Generate random position within arena bounds
				popcorn.x = bounds.left + 200 + Math.random() * (arena.width - 400);
				popcorn.y = bounds.top + 200 + Math.random() * (arena.height - 400);
				// Check distance from each rope
				validPosition = true;
				for (var j = 0; j < ropes.length; j++) {
					var dx = popcorn.x - ropes[j].x;
					var dy = popcorn.y - ropes[j].y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					// If too close to a rope, try again
					if (distance < 200) {
						validPosition = false;
						break;
					}
				}
				attempts++;
			}
			// Add to game
			game.addChild(popcorn);
			popcorns.push(popcorn);
		}
	}
}
function createSuperPopcorn(count) {
	for (var i = 0; i < count; i++) {
		var superPopcorn = new Superpopcorn();
		// Random position within arena bounds
		var validPosition = false;
		var attempts = 0;
		var maxAttempts = 50;
		// Keep trying until we find a valid position
		while (!validPosition && attempts < maxAttempts) {
			// Generate random position within arena bounds
			superPopcorn.x = bounds.left + 200 + Math.random() * (arena.width - 400);
			superPopcorn.y = bounds.top + 200 + Math.random() * (arena.height - 400);
			// Check distance from each rope
			validPosition = true;
			for (var j = 0; j < ropes.length; j++) {
				var dx = superPopcorn.x - ropes[j].x;
				var dy = superPopcorn.y - ropes[j].y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// If too close to a rope, try again
				if (distance < 200) {
					validPosition = false;
					break;
				}
			}
			attempts++;
		}
		// Add to game
		game.addChild(superPopcorn);
		superPopcorns.push(superPopcorn);
	}
}
// Game events
game.onChickenJockeyStop = function () {
	gameState = "ready";
	// Reset bonus status for next round if all popcorn is collected
	if (popcorns.length === 0 && superPopcorns.length === 0) {
		bonusApplied = false;
	}
	// Check if we need to add more popcorn
	if (popcorns.length < 5) {
		createPopcorn(5);
	}
	// Check if out of launches
	if (launches >= maxLaunches) {
		// Game over
		instructionText.setText("Game Over! Final Score: " + score);
		gameState = "gameOver";
		// Save score to high scores
		var highScores = storage.highScores || [];
		highScores.push(score);
		// Sort in descending order
		highScores.sort(function (a, b) {
			return b - a;
		});
		// Keep only top 10 scores
		if (highScores.length > 10) {
			highScores = highScores.slice(0, 10);
		}
		storage.highScores = highScores;
		// Show game over after a short delay
		LK.setTimeout(function () {
			LK.showGameOver();
			// Return to title screen after game over
			LK.setTimeout(function () {
				// Set game state back to title
				gameState = "title";
				// Hide game elements
				arena.alpha = 0;
				backdrop.alpha = 0;
				chickenJockey.alpha = 0;
				scoreText.alpha = 0;
				launchesText.alpha = 0;
				instructionText.alpha = 0;
				// Show title page
				if (!titlePage) {
					titlePage = new TitlePage();
				}
				game.addChild(titlePage);
				titlePage.alpha = 0;
				tween(titlePage, {
					alpha: 1
				}, {
					duration: 500
				});
			}, 500); // Short delay after game over is shown
		}, 2000);
	} else {
		// Reset for next launch
		resetChickenJockey();
		// Update the instruction text to show the current number pattern
		var currentNumber = launches % 9 + 1;
		instructionText.setText("Collect number " + currentNumber + " pattern!");
	}
};
game.onMaxBouncesReached = function () {
	// Same as onChickenJockeyStop for now
	game.onChickenJockeyStop();
};
// Input handling
var dragStartX = 0;
var dragStartY = 0;
game.down = function (x, y, obj) {
	if (gameState === "title" || gameState === "highScores" || gameState === "characterSelect") {
		// Title page, high scores and character select interactions are handled by their respective classes
		return;
	}
	if (gameState === "ready") {
		gameState = "aiming";
		dragStartX = x;
		dragStartY = y;
		launcher.startAim(x, y);
	}
};
game.move = function (x, y, obj) {
	if (gameState === "title" || gameState === "highScores" || gameState === "characterSelect") {
		// Title page, high scores and character select interactions are handled by their respective classes
		return;
	}
	if (gameState === "aiming") {
		launcher.updateAim(x, y);
	}
};
game.up = function (x, y, obj) {
	if (gameState === "title" || gameState === "highScores" || gameState === "characterSelect") {
		// Title page, high scores and character select interactions are handled by their respective classes
		return;
	}
	if (gameState === "aiming") {
		// Make sure we have enough points to create a valid path
		if (launcher.points.length < 2) {
			// Not enough points, cancel launch
			launcher.endAim();
			gameState = "ready";
			instructionText.setText("Draw a longer path to launch!");
			return;
		}
		// Get launch parameters
		var launchParams = launcher.endAim();
		// Create a smoothed path if needed
		var pathToDraw = launcher.points;
		if (pathToDraw.length > 20) {
			// Take fewer points if path is very long
			var smoothedPath = [];
			for (var i = 0; i < pathToDraw.length; i += Math.ceil(pathToDraw.length / 20)) {
				smoothedPath.push(pathToDraw[i]);
			}
			// Make sure we include the last point
			if (smoothedPath[smoothedPath.length - 1] !== pathToDraw[pathToDraw.length - 1]) {
				smoothedPath.push(pathToDraw[pathToDraw.length - 1]);
			}
			pathToDraw = smoothedPath;
		}
		// Launch the chicken jockey with the drawn path
		chickenJockey.launch(launchParams.power, launchParams.angle, pathToDraw);
		// Update game state
		gameState = "launched";
		launches++;
		launchesText.setText(launches + "/" + maxLaunches);
		instructionText.setText("Watch the chicken follow your path!");
		// Add 3 superpopcorn after each launch
		createSuperPopcorn(3);
	}
};
// Main game loop
game.update = function () {
	// Update all game objects
	if (gameState === "launched") {
		chickenJockey.update();
		// Check for collisions with arena boundaries
		if (chickenJockey.x < bounds.left) {
			chickenJockey.x = bounds.left;
			chickenJockey.vx = -chickenJockey.vx * chickenJockey.bounceDecay;
			chickenJockey.bounceCount++;
			LK.getSound('bounce').play();
		} else if (chickenJockey.x > bounds.right) {
			chickenJockey.x = bounds.right;
			chickenJockey.vx = -chickenJockey.vx * chickenJockey.bounceDecay;
			chickenJockey.bounceCount++;
			LK.getSound('bounce').play();
		}
		if (chickenJockey.y < bounds.top) {
			chickenJockey.y = bounds.top;
			chickenJockey.vy = -chickenJockey.vy * chickenJockey.bounceDecay;
			chickenJockey.bounceCount++;
			LK.getSound('bounce').play();
		} else if (chickenJockey.y > bounds.bottom) {
			chickenJockey.y = bounds.bottom;
			chickenJockey.vy = -chickenJockey.vy * chickenJockey.bounceDecay;
			chickenJockey.bounceCount++;
			LK.getSound('bounce').play();
		}
		// Check for collisions with ropes
		for (var i = 0; i < ropes.length; i++) {
			if (chickenJockey.intersects(ropes[i])) {
				ropes[i].bounce(chickenJockey);
			}
		}
		// Check for collisions with popcorn
		for (var i = popcorns.length - 1; i >= 0; i--) {
			if (chickenJockey.intersects(popcorns[i])) {
				// Collect popcorn
				popcorns[i].collect();
				// Remove from array
				popcorns.splice(i, 1);
				// Increase score
				score += 10;
				scoreText.setText(score);
				// Save score to LK
				LK.setScore(score);
				// Check if all popcorn has been collected
				if (popcorns.length === 0 && superPopcorns.length === 0 && !bonusApplied) {
					// Apply X5 bonus
					bonusApplied = true;
					score *= 5;
					scoreText.setText(score);
					LK.setScore(score);
					// Create and show X5 bonus animation in the center of the screen
					if (bonusAnimation && bonusAnimation.parent) {
						bonusAnimation.parent.removeChild(bonusAnimation);
					}
					// Play Pignoise sound if Piglin is selected and X5 bonus is applied
					if (selectedCharacter === "piglinjockey") {
						LK.getSound('Pignoise').play();
					} else {
						// Play Bogerk sound first
						LK.getSound('Bogerk').play();
					}
					// Create X5 animation with explicit alpha=1
					bonusAnimation = LK.getAsset('X5', {
						anchorX: 0.5,
						anchorY: 0.5,
						x: 2048 / 2,
						// Center of screen X
						y: 2732 / 2,
						// Center of screen Y
						scaleX: 1.5,
						// Larger initial scale
						scaleY: 1.5,
						alpha: 1 // Explicitly set alpha to make it visible
					});
					game.addChild(bonusAnimation); // Add to game for better visibility
					// Animate the X5 bonus with more dramatic effect
					tween(bonusAnimation, {
						scaleX: 2.5,
						scaleY: 2.5
					}, {
						duration: 700,
						easing: tween.bounceOut,
						onFinish: function onFinish() {
							// Hold for a shorter moment then fade out
							LK.setTimeout(function () {
								tween(bonusAnimation, {
									alpha: 0,
									scaleX: 3.0,
									scaleY: 3.0
								}, {
									duration: 1000,
									easing: tween.easeOut
								});
							}, 500);
						}
					});
					// Play collect sound for bonus emphasis
					LK.getSound('collect').play();
				}
			}
		}
		// Check for collisions with superpopcorn
		for (var i = superPopcorns.length - 1; i >= 0; i--) {
			if (chickenJockey.intersects(superPopcorns[i])) {
				// Collect superpopcorn
				superPopcorns[i].collect();
				// Remove from array
				superPopcorns.splice(i, 1);
				// Increase score
				score += 1000;
				scoreText.setText(score);
				// Save score to LK
				LK.setScore(score);
			}
		}
	}
	// Update popcorn animations
	for (var i = 0; i < popcorns.length; i++) {
		popcorns[i].update();
	}
	// Update superpopcorn animations
	for (var i = 0; i < superPopcorns.length; i++) {
		superPopcorns[i].update();
	}
};
// Initialize the game
initGame();
;
// Create letters scattered around the arena
createLetters();
function createLetters() {
	// Ensure letters array is defined before use
	if (!letters) {
		letters = [];
	}
	// Check if there are any letters currently on screen
	if (letters.length > 0) {
		return; // Don't create a new letter if one is already present
	}
	// Determine the next letter in the sequence
	var unlockWord = "UNLOCK";
	var nextLetterIndex = collectedLetters.length;
	if (nextLetterIndex >= unlockWord.length) {
		return; // All letters collected, no more to create
	}
	var selectedLetter = unlockWord[nextLetterIndex];
	var letter = new Letter(selectedLetter); // Pass the selected letter to the Letter class
	// Random position within arena bounds
	var validPosition = false;
	var attempts = 0;
	var maxAttempts = 50;
	// Keep trying until we find a valid position
	while (!validPosition && attempts < maxAttempts) {
		// Generate random position within arena bounds
		letter.x = bounds.left + 200 + Math.random() * (arena.width - 400);
		letter.y = bounds.top + 200 + Math.random() * (arena.height - 400);
		// Check distance from each rope
		validPosition = true;
		for (var j = 0; j < ropes.length; j++) {
			var dx = letter.x - ropes[j].x;
			var dy = letter.y - ropes[j].y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// If too close to a rope, try again
			if (distance < 200) {
				validPosition = false;
				break;
			}
		}
		attempts++;
	}
	// Add to game
	game.addChild(letter);
	letters.push(letter);
}
// Array to store letter instances
var letters = [];
// Track collected letters
// Check for collisions with letters
for (var i = letters.length - 1; i >= 0; i--) {
	if (chickenJockey.intersects(letters[i])) {
		// Collect letter
		collectedLetters.push(letters[i].letter);
		letters[i].collect();
		// Remove from array
		letters.splice(i, 1);
		// Create the next letter in sequence
		createLetters();
		// Check if 'UNLOCK' is spelled
		if (collectedLetters.sort().join('') === 'CKLNOU') {
			// Unlock a new character
			var newCharacter = "piglinjockey"; // Example character to unlock
			if (!storage.unlockedCharacters.includes(newCharacter)) {
				storage.unlockedCharacters.push(newCharacter);
				// Notify player of new character unlocked
				instructionText.setText("New character unlocked!");
			}
			// Clear collected letters after unlocking
			collectedLetters = [];
			// Create the first letter of the next word
			createLetters();
		}
	}
} ===================================================================
--- original.js
+++ change.js
@@ -1044,8 +1044,9 @@
 var gameState = "title"; // title, characterSelect, ready, aiming, launched, gameOver, highScores
 var score = 0;
 var launches = 0;
 var maxLaunches = 10;
+var collectedLetters = []; // Initialize collected letters array here
 var popcorns = [];
 var superPopcorns = [];
 var ropes = [];
 var bonusApplied = false;
@@ -1795,9 +1796,8 @@
 }
 // Array to store letter instances
 var letters = [];
 // Track collected letters
-var collectedLetters = [];
 // Check for collisions with letters
 for (var i = letters.length - 1; i >= 0; i--) {
 	if (chickenJockey.intersects(letters[i])) {
 		// Collect letter
 
 
 
 X5 symbol. In-Game asset. 2d. High contrast. No shadows
 X2 symbol. In-Game asset. 2d. High contrast. No shadows
 
 Super popcorn yellow. In-Game asset. 2d. High contrast. No shadows
 
 
 
 
 
 
 
 Start button. In-Game asset. 2d. High contrast. No shadows
 High score button. In-Game asset. 2d. High contrast. No shadows
 Back button. In-Game asset. 2d. High contrast. No shadows
 SELECT YOUR CHARACTER button. In-Game asset. 2d. High contrast. No shadows
 Launches button. In-Game asset. 2d. High contrast. No shadows
 How to play button. In-Game asset. 2d. High contrast. No shadows
 Score button. In-Game asset. 2d. High contrast. No shadows
 High Scores button. In-Game asset. 2d. High contrast. No shadows
 Transparent padlock. In-Game asset. 2d. High contrast. No shadows
 Chicken jockey character. In-Game asset. 2d. High contrast. No shadows
 Reset scores button. In-Game asset. 2d. High contrast. No shadows
 
 
 Spider jockey unlocked button. In-Game asset. 2d. High contrast. No shadows
 Minecraft Steve unlocked button. In-Game asset. 2d. High contrast. No shadows
 Piglin unlocked button. In-Game asset. 2d. High contrast. No shadows
 Minecraft skeleton unlocked button. In-Game asset. 2d. High contrast. No shadows
 Minecraft villager unlocked button. In-Game asset. 2d. High contrast. No shadows
 
 Star. In-Game asset. 2d. High contrast. No shadows
 White star. In-Game asset. 2d. High contrast. No shadows
 
 Red heart. In-Game asset. 2d. High contrast. No shadows
 Purple heart. In-Game asset. 2d. High contrast. No shadows
 
 A peanut. In-Game asset. 2d. High contrast. No shadows
 Cashew nut. In-Game asset. 2d. High contrast. No shadows
 
 
 Grimace shake. In-Game asset. 2d. High contrast. No shadows
 MacDonald's fries. In-Game asset. 2d. High contrast. No shadows
 Grimace unlocked button. In-Game asset. 2d. High contrast. No shadows
 Michael Jackson unlocked button. In-Game asset. 2d. High contrast. No shadows
 John Cena unlocked button. In-Game asset. 2d. High contrast. No shadows
 
 Deez nuts unlocked button. In-Game asset. 2d. High contrast. No shadows
 Shooting stars unlocked button. In-Game asset. 2d. High contrast. No shadows
 
 Rick roll unlocked button. In-Game asset. 2d. High contrast. No shadows
 
 
 
 
 
 
 Popcorn chicken. In-Game asset. 2d. High contrast. No shadows
 Fried chicken drumstick. In-Game asset. 2d. High contrast. No shadows
 
 
 
 
 Amazing digital circus button. In-Game asset. 2d. High contrast. No shadows
 
 
 
 
 Select game mode button. In-Game asset. 2d. High contrast. No shadows
 Diamond shaped colourful classic mode button. In-Game asset. 2d. High contrast. No shadows
 Diamond shaped colourful mini games button. In-Game asset. 2d. High contrast. No shadows
 Same picture in high definition
 Diamond shaped colourful button that says sling shot mode. In-Game asset. 2d. High contrast. No shadows
 Make picture transparent
 
 Bullet. In-Game asset. 2d. High contrast. No shadows
 
 Start game button. In-Game asset. 2d. High contrast. No shadows
 
 Shooting gallery button. In-Game asset. 2d. High contrast. No shadows
 Chain reaction button. In-Game asset. 2d. High contrast. No shadows
 Realistic space backdrop. In-Game asset. 2d. High contrast. No shadows
launch
Sound effect
Gamestart
Sound effect
collect
Sound effect
gameMusic
Music
Gamemusic
Sound effect
Bogerk
Sound effect
pop
Sound effect
Pignoise
Sound effect
Steve
Sound effect
Villager
Sound effect
Spider
Sound effect
Skeleton
Sound effect
Shootingstars
Music
Maccas
Sound effect
Grimace
Sound effect
Thriller
Music
MJ
Sound effect
Cenaentrance
Music
Johncena
Sound effect
Chickencluck
Sound effect
Deeznuts
Sound effect
Deeznutstrap
Music
Rickroll
Sound effect
Nevergonna
Music
Starz
Sound effect
Grimaceshake
Music
Joenugget
Sound effect
gegagedi
Music
Shrek
Sound effect
Raveswamp
Music
Pomni
Sound effect
Digcircus
Music
Runandgo
Music
Gunshot
Sound effect
Reelbadman
Sound effect
Tinggoes
Music