User prompt
Move launchestitle left 50 and down 50
User prompt
Replace text that says launches with launchestitle asset
User prompt
Move selectcharactertitle up 50
User prompt
Replace text in select character page with selectcharactertitle asset
User prompt
Remove text that says back in high score screen
User prompt
Replace back button in high score screen with backbutton asset
User prompt
Replace high score button on title screen with hiscorebutton asset
User prompt
Replace start button on title screen with start button asset
User prompt
Make villager character bigger in character select screen
User prompt
Make villager character bigger in character select screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make villager character bigger in character select screen
User prompt
Make spider character a bit bigger in character select screen
User prompt
Make spider character a bit bigger in character select screen
User prompt
Move black background on character select screen left 5
User prompt
Move black background on character select screen left 10
User prompt
Reduce villager size on character select screen to fit inside box
User prompt
Change the colour of the circular button background on the title page to green ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Change the yellow button background to green ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
If steveridingpig character is selected play gamestart sound when selected
User prompt
Play pignoise sound when piglinjockey character is playing and the X5 bonus is reached
User prompt
If piglinjockey character is selected play pignoise sound when selected
User prompt
When character is selected replace chicken with selected character
User prompt
When you click start on title page it enters a character select scene
User prompt
return to title screen straight after game over
User prompt
create a high score tally page and link it to title page ↪💡 Consider importing and using the following plugins: @upit/storage.v1 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScores: [] }); /**** * Classes ****/ var ChickenJockey = Container.expand(function () { var self = Container.call(this); // Create and attach chicken asset 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; }; 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 var titleText = new Text2("HIGH SCORES", { size: 100, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.x = 1024; titleText.y = 600; self.addChild(titleText); // 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 background var buttonBackground = self.backButton.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 5, scaleY: 2, alpha: 0.8 }); // Back text var backText = new Text2("BACK", { size: 80, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); self.backButton.addChild(backText); // 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 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 background var buttonBackground = self.startButton.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 5, scaleY: 2, alpha: 0.8 }); // Start text var startText = new Text2("START", { size: 80, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); self.startButton.addChild(startText); // Create high scores button (positioned below start button) self.highScoresButton = new Container(); self.highScoresButton.x = 1024; self.highScoresButton.y = 1900; // Button background var hsButtonBackground = self.highScoresButton.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 5, scaleY: 2, alpha: 0.8 }); // High Scores text var hsText = new Text2("HIGH SCORES", { size: 70, fill: 0xFFFFFF }); hsText.anchor.set(0.5, 0.5); self.highScoresButton.addChild(hsText); // 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, ready, aiming, launched, gameOver, highScores var score = 0; var launches = 0; var maxLaunches = 10; var popcorns = []; var superPopcorns = []; var ropes = []; var bonusApplied = false; var bonusAnimation = null; var titlePage = null; var highScorePage = null; // 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 scoreText = new Text2("Score: 0", { size: 70, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var launchesText = new Text2("Launches: 0/" + maxLaunches, { size: 50, fill: 0xFFFFFF }); launchesText.anchor.set(0, 0); launchesText.x = 120; // Avoid top-left corner launchesText.y = 140; // Moved down by 120 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 = 100; 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: " + score); scoreText.alpha = 0; launchesText.setText("Launches: " + 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; // 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 } // 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 game elements tween(arena, { alpha: 1 }, { duration: 300 }); tween(backdrop, { alpha: 1 }, { duration: 300 }); tween(chickenJockey, { alpha: 1 }, { duration: 300 }); scoreText.alpha = 1; launchesText.alpha = 1; instructionText.alpha = 1; // Start the actual game startGamePlay(); } }); }; // 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"; } }); }; } // 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 })); // Play gamestart sound when Steve appears LK.getSound('Gamestart').play(); // Remove Steve after 2 seconds LK.setTimeout(function () { if (steve && steve.parent) { steve.parent.removeChild(steve); } }, 2000); } function resetChickenJockey() { chickenJockey.reset(); // Position chicken 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 chicken is reset instructionText.setText("Draw a path to launch the chicken!"); } 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(); }, 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") { // Title page and high scores 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") { // Title page and high scores 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") { // Title page and high scores 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: " + 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: " + 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: " + 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 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 moment then fade out LK.setTimeout(function () { tween(bonusAnimation, { alpha: 0, scaleX: 3.0, scaleY: 3.0 }, { duration: 1500, easing: tween.easeOut }); }, 2000); } }); // 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: " + 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(); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScores: []
});
/****
* Classes
****/
var ChickenJockey = Container.expand(function () {
var self = Container.call(this);
// Create and attach chicken asset
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;
};
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
var titleText = new Text2("HIGH SCORES", {
size: 100,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.x = 1024;
titleText.y = 600;
self.addChild(titleText);
// 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 background
var buttonBackground = self.backButton.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5,
scaleY: 2,
alpha: 0.8
});
// Back text
var backText = new Text2("BACK", {
size: 80,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
self.backButton.addChild(backText);
// 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 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 background
var buttonBackground = self.startButton.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5,
scaleY: 2,
alpha: 0.8
});
// Start text
var startText = new Text2("START", {
size: 80,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
self.startButton.addChild(startText);
// Create high scores button (positioned below start button)
self.highScoresButton = new Container();
self.highScoresButton.x = 1024;
self.highScoresButton.y = 1900;
// Button background
var hsButtonBackground = self.highScoresButton.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5,
scaleY: 2,
alpha: 0.8
});
// High Scores text
var hsText = new Text2("HIGH SCORES", {
size: 70,
fill: 0xFFFFFF
});
hsText.anchor.set(0.5, 0.5);
self.highScoresButton.addChild(hsText);
// 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, ready, aiming, launched, gameOver, highScores
var score = 0;
var launches = 0;
var maxLaunches = 10;
var popcorns = [];
var superPopcorns = [];
var ropes = [];
var bonusApplied = false;
var bonusAnimation = null;
var titlePage = null;
var highScorePage = null;
// 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 scoreText = new Text2("Score: 0", {
size: 70,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var launchesText = new Text2("Launches: 0/" + maxLaunches, {
size: 50,
fill: 0xFFFFFF
});
launchesText.anchor.set(0, 0);
launchesText.x = 120; // Avoid top-left corner
launchesText.y = 140; // Moved down by 120 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 = 100;
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: " + score);
scoreText.alpha = 0;
launchesText.setText("Launches: " + 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;
// 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
}
// 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 game elements
tween(arena, {
alpha: 1
}, {
duration: 300
});
tween(backdrop, {
alpha: 1
}, {
duration: 300
});
tween(chickenJockey, {
alpha: 1
}, {
duration: 300
});
scoreText.alpha = 1;
launchesText.alpha = 1;
instructionText.alpha = 1;
// Start the actual game
startGamePlay();
}
});
};
// 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";
}
});
};
}
// 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
}));
// Play gamestart sound when Steve appears
LK.getSound('Gamestart').play();
// Remove Steve after 2 seconds
LK.setTimeout(function () {
if (steve && steve.parent) {
steve.parent.removeChild(steve);
}
}, 2000);
}
function resetChickenJockey() {
chickenJockey.reset();
// Position chicken 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 chicken is reset
instructionText.setText("Draw a path to launch the chicken!");
}
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();
}, 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") {
// Title page and high scores 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") {
// Title page and high scores 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") {
// Title page and high scores 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: " + 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: " + 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: " + 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 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 moment then fade out
LK.setTimeout(function () {
tween(bonusAnimation, {
alpha: 0,
scaleX: 3.0,
scaleY: 3.0
}, {
duration: 1500,
easing: tween.easeOut
});
}, 2000);
}
});
// 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: " + 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();
;
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
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