User prompt
Make grimacejockey move in a walking up and down motion
User prompt
Make skeleton horse walk right across the scene with a walking up and down motion
User prompt
Move skeletonhorse character down 150 and left 400 from the middle of minigame scene
User prompt
Move skeletonhorse character down 150 from the middle of minigame scene
User prompt
Move skeletonhorse character to the middle of minigame scene
User prompt
Add zigzag motion to piglinjockey character in minigame
User prompt
Move piglinjockey character up 600 in minigame
User prompt
Make shootingstars character move from left to right and going in circles up the top of minigame scene
User prompt
Make shootingstars character move from right to left up the top of minigame scene
User prompt
Make chicken character walk right across screen in minigame
User prompt
Move chicken character down 500 and left 400
User prompt
Make chicken character bigger in minigame scene
User prompt
Move chicken character to middle of minigame scene as starting position
User prompt
Reduce deeznuts size in minigame
User prompt
Move deeznuts to 400 px right from middle of minigame screen as starting position
User prompt
Move deeznuts to 600 left and 400 down from middle of minigame screen as starting position
User prompt
Move deeznuts to middle of minigame screen as starting position
User prompt
Move deeznuts to middle of minigame screen as starting position
User prompt
Reduce Steveridingpig size in minigame
User prompt
Reduce Steveridingpig size in minigame
User prompt
Shrink Steveridingpig character to as small as possible ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make Steveridingpig half the size in minigame
User prompt
Make Steveridingpig smaller in minigame ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move Steveridingpig character to 500px up from centre of minigame screen as starting position
User prompt
Move Steveridingpig character to centre of minigame screen as starting position
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScores: [], gamePlays: 0, steveUnlocked: false, piglinUnlocked: false, villagerUnlocked: false, spiderUnlocked: false, registeredScores: 0, skeletonUnlocked: false, grimaceUnlocked: false, mjUnlocked: false, johnCenaUnlocked: false, shootingStarsUnlocked: false, deezNutsUnlocked: false, rickrollUnlocked: false, selectedCharacter: "chicken", bonusAnimation: "undefined", titlePage: "undefined", highScorePage: "undefined", characterSelectPage: "undefined", arena: "undefined", backdrop: "undefined", chickenJockey: "undefined", launcher: "undefined", scoreText: "undefined", scoreTitleImg: "undefined", launchesText: "undefined", instructionText: "undefined", launchesTitleImg: "undefined", steve: "undefined", bonusApplied: false, pathTracker: "undefined", popcorns: [], superPopcorns: [], ropes: [], bounds: {}, grimaceTaps: 0, gameState: "title", score: 0, launches: 0, maxLaunches: 10, dragStartX: 0, dragStartY: 0, allCharactersUnlocked: false }); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); // Create bullet visuals using Bullet asset var bulletGraphics = self.attachAsset('Bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); // Bullet properties self.speed = 20; self.angle = 0; self.maxDistance = 2000; self.distanceTraveled = 0; self.startX = 0; self.startY = 0; // Initialize bullet with angle and starting position self.init = function (startX, startY, angle) { self.x = startX; self.y = startY; self.startX = startX; self.startY = startY; self.angle = angle; // Convert angle to radians var radians = angle * Math.PI / 180; // Calculate velocity components self.vx = Math.cos(radians) * self.speed; self.vy = Math.sin(radians) * self.speed; // Set rotation to match direction bulletGraphics.rotation = radians; }; // Update bullet position self.update = function () { // Move bullet self.x += self.vx; self.y += self.vy; // Calculate distance traveled var dx = self.x - self.startX; var dy = self.y - self.startY; self.distanceTraveled = Math.sqrt(dx * dx + dy * dy); // Check if bullet has traveled too far if (self.distanceTraveled > self.maxDistance) { if (self.parent) { self.parent.removeChild(self); } return; } // Check for hits with targets if (typeof game.targets !== 'undefined') { for (var i = 0; i < game.targets.length; i++) { if (game.targets[i].active && self.intersects(game.targets[i])) { // Hit target game.targets[i].hit(); // Remove bullet if (self.parent) { self.parent.removeChild(self); } return; } } } // Check for hits with characters in the target container if (typeof game.miniGamesPage !== 'undefined' && typeof game.miniGamesPage.targetContainer !== 'undefined') { var chars = game.miniGamesPage.targetContainer.children; for (var i = 0; i < chars.length; i++) { if (chars[i].active && self.intersects(chars[i])) { // Hit character if (typeof chars[i].hit === 'function') { chars[i].hit(); } else { // If character doesn't have a hit method, remove it if (chars[i].parent) { chars[i].parent.removeChild(chars[i]); } } // Remove bullet if (self.parent) { self.parent.removeChild(self); } return; } } } }; return self; }); 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 }); // Create a container for the character instead of attaching directly to allow better Z-order control var walkingCharacterContainer = new Container(); walkingCharacterContainer.x = 2048 + 300; // Start off-screen to the right walkingCharacterContainer.y = 1300; // Centered vertically but lower on screen self.addChild(walkingCharacterContainer); // Add walking character to the container to control visibility separately var walkingCharacter = walkingCharacterContainer.attachAsset('Gunslinger', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); // Animate character walking in tween(walkingCharacter, { x: 1024 // Move to center of screen }, { duration: 2000, easing: tween.easeOut, onFinish: function onFinish() { // Add slight idle animation tween(walkingCharacter, { y: walkingCharacter.y - 20 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(walkingCharacter, { y: walkingCharacter.y + 20 }, { duration: 1000, easing: tween.easeInOut, repeat: -1, yoyo: true }); } }); } }); // Add title using Selectcharactertitle asset var titleImage = self.attachAsset('Selectcharactertitle', { anchorX: 0.5, anchorY: 0, x: 1024, y: 150 }); // Add back button self.backButton = new Container(); self.backButton.x = 150; // Position at top left, but not in the 0-100px reserved area self.backButton.y = 350; // Align vertically with reset button // Create back button using the Backbutton asset var backButtonImage = self.backButton.attachAsset('Backbutton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, alpha: 1.0 }); self.addChild(self.backButton); // Add reset button self.resetButton = new Container(); self.resetButton.x = 1900; // Position at top right of screen self.resetButton.y = 350; // Position at top right of screen // Create reset button using the Resetcharacter asset var resetButtonImage = self.resetButton.attachAsset('Resetcharacter', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, alpha: 1.0 }); // Add reset button to character select page self.addChild(self.resetButton); // 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" }, { name: "Grimace", asset: "Grimacejockey" }, { name: "MJ", asset: "Michaeljackson" }, { name: "John Cena", asset: "Johncena" }, { name: "Shooting Stars", asset: "Shootingstars" }, { name: "DeezNuts", asset: "Deeznuts" }, { name: "Rickroll", asset: "Rickroll" }, { name: "Joe Nugget", asset: "Joenugget" }, { name: "Shrekwizowski", asset: "Shrekwizowski" }, { name: "Pomni", asset: "Pomni" }]; self.selectedCharacter = "chicken"; self.characterButtons = new Container(); self.characterButtons.x = 1024; self.characterButtons.y = 700; 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 + 10; // Move right 10 pixels 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 }); // Add locked overlay for all characters except chicken, Steve (if unlocked), Piglin (if unlocked), Villager (if unlocked), Spider (if unlocked), Skeleton (if unlocked by S pattern), Grimace (if unlocked), MJ (if unlocked), and SpongeBob if (character.asset !== "chicken" && !(character.asset === "steveridingpig" && storage.steveUnlocked === true) && !(character.asset === "piglinjockey" && storage.piglinUnlocked === true) && !(character.asset === "vilagerjockey" && storage.villagerUnlocked === true) && !(character.asset === "spiderjockey" && storage.spiderUnlocked === true) && !(character.asset === "skeletonhorse" && storage.skeletonUnlocked === true) && !(character.asset === "Grimacejockey" && storage.grimaceUnlocked === true) && !(character.asset === "Michaeljackson" && storage.mjUnlocked === true) && !(character.asset === "Johncena" && storage.johnCenaUnlocked === true) && !(character.asset === "Shootingstars" && storage.shootingStarsUnlocked === true) && !(character.asset === "Deeznuts") && !(character.asset === "Rickroll") && !(character.asset === "Joenugget") && !(character.asset === "SpongeBob") && !(character.asset === "Shrekwizowski") && !(character.asset === "Pomni")) { var lockedImg = button.attachAsset('Locked', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); button.lockedImg = lockedImg; // Store reference to locked image } else { if (button.lockedImg && button.lockedImg.parent) { button.lockedImg.parent.removeChild(button.lockedImg); // Remove padlock if character is unlocked } } // Character name text removed // Store character data with button button.characterData = character; // Make button interactive button.down = function (x, y, obj) { tween(this, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; button.up = function (x, y, obj) { var btnRef = this; // Check if character is unlocked before allowing selection var isUnlocked = btnRef.characterData.asset === "chicken" || btnRef.characterData.asset === "steveridingpig" && storage.steveUnlocked === true || btnRef.characterData.asset === "piglinjockey" && storage.piglinUnlocked === true || btnRef.characterData.asset === "vilagerjockey" && storage.villagerUnlocked === true || btnRef.characterData.asset === "spiderjockey" && storage.spiderUnlocked === true || btnRef.characterData.asset === "skeletonhorse" && storage.skeletonUnlocked === true || btnRef.characterData.asset === "Grimacejockey" && storage.grimaceUnlocked === true || btnRef.characterData.asset === "Michaeljackson" && storage.mjUnlocked === true || btnRef.characterData.asset === "Johncena" && storage.johnCenaUnlocked === true || btnRef.characterData.asset === "Shootingstars" && storage.shootingStarsUnlocked === true || btnRef.characterData.asset === "Deeznuts" && storage.deezNutsUnlocked === true || btnRef.characterData.asset === "Rickroll" || btnRef.characterData.asset === "Joenugget" || btnRef.characterData.asset === "SpongeBob" || btnRef.characterData.asset === "Shrekwizowski" || btnRef.characterData.asset === "Pomni"; if (!isUnlocked) { // Show unlock message based on character if (btnRef.characterData.asset === "Michaeljackson") { var playCount = storage.gamePlays || 0; var playsRemaining = Math.max(0, 20 - playCount); var unlockText = new Text2("Play " + playsRemaining + " more time" + (playsRemaining !== 1 ? "s" : "") + " to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } else if (btnRef.characterData.asset === "steveridingpig") { var playCount = storage.gamePlays || 0; var playsRemaining = Math.max(0, 3 - playCount); var unlockText = new Text2("Play " + playsRemaining + " more time" + (playsRemaining !== 1 ? "s" : "") + " to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } else if (btnRef.characterData.asset === "piglinjockey") { var scoresRegistered = storage.registeredScores || 0; var scoresRemaining = Math.max(0, 5 - scoresRegistered); var unlockText = new Text2("Register " + scoresRemaining + " more high score" + (scoresRemaining !== 1 ? "s" : "") + " to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } else if (btnRef.characterData.asset === "vilagerjockey") { var unlockText = new Text2("Score 1,000,000 points to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } else if (btnRef.characterData.asset === "spiderjockey") { var unlockText = new Text2("Score 10,000,000 points to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } else if (btnRef.characterData.asset === "skeletonhorse") { var unlockText = new Text2("Trace an 'S' on the arena to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } else if (btnRef.characterData.asset === "Johncena") { var playCount = storage.gamePlays || 0; var playsRemaining = Math.max(0, 30 - playCount); var unlockText = new Text2("Play " + playsRemaining + " more time" + (playsRemaining !== 1 ? "s" : "") + " to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } else if (btnRef.characterData.asset === "Shootingstars") { var unlockText = new Text2("Trace a star in arena to unlock", { size: 40, fill: 0xFFFFFF }); unlockText.anchor.set(0.5, 0.5); unlockText.x = 0; unlockText.y = 150; btnRef.addChild(unlockText); // Fade out the text after 2 seconds tween(unlockText, { alpha: 0 }, { delay: 2000, duration: 500, onFinish: function onFinish() { if (unlockText.parent) { unlockText.parent.removeChild(unlockText); } } }); } // Animate button but don't select locked character tween(btnRef, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, onFinish: function onFinish() { tween(btnRef, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); 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; // Update popcorn asset to 'Belt' if Johncena is selected if (btnRef.characterData.asset === "Johncena") { var popcornAsset = 'Belt'; for (var i = 0; i < popcorns.length; i++) { if (typeof popcorns[i].updateAsset === "function") { popcorns[i].updateAsset(popcornAsset); } } } // Notify game of selection if (typeof game.onCharacterSelected === 'function') { game.onCharacterSelected(btnRef.characterData.asset); } } }); } }); }; self.characterButtons.addChild(button); } // Make reset button interactive self.resetButton.down = function (x, y, obj) { // Animate button press tween(self.resetButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.resetButton.up = function (x, y, obj) { // Play pop sound LK.getSound('pop').play(); // Animate button release tween(self.resetButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, onFinish: function onFinish() { tween(self.resetButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { // Reset unlock status for all characters storage.steveUnlocked = false; storage.piglinUnlocked = false; storage.villagerUnlocked = false; storage.spiderUnlocked = false; storage.gamePlays = 0; storage.registeredScores = 0; skeletonUnlocked = false; // Reset skeleton unlock state storage.skeletonUnlocked = false; // Persist reset state grimaceUnlocked = false; // Reset grimace unlock state storage.grimaceUnlocked = false; // Persist reset state storage.mjUnlocked = false; // Reset MJ unlock state storage.johnCenaUnlocked = false; // Reset John Cena unlock state storage.rickrollUnlocked = false; // Reset Rickroll unlock state storage.shootingStarsUnlocked = false; // Reset Shooting Stars unlock state storage.deezNutsUnlocked = false; // Reset DeezNuts unlock state storage.allCharactersUnlocked = false; // Reset all characters unlocked state // Flash confirmation message var confirmationMsg = new Text2("Characters reset!", { size: 70, fill: 0xFF0000 }); confirmationMsg.anchor.set(0.5, 0.5); confirmationMsg.x = 0; confirmationMsg.y = -400; // Position above characters self.characterButtons.addChild(confirmationMsg); // Fade out confirmation message tween(confirmationMsg, { alpha: 0 }, { delay: 1500, duration: 500, onFinish: function onFinish() { if (confirmationMsg.parent) { confirmationMsg.parent.removeChild(confirmationMsg); } // Force refresh the character selection screen if (typeof game.onCharacterSelectReset === 'function') { game.onCharacterSelectReset(); } } }); } }); } }); }; // 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) { // Play pop sound LK.getSound('pop').play(); // 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() { // Hide character select page and show title page if (self.parent) { self.parent.removeChild(self); } if (typeof game !== "undefined" && typeof titlePage !== "undefined") { game.addChild(titlePage); titlePage.alpha = 0; tween(titlePage, { alpha: 1 }, { duration: 500 }); // Set game state to title if (typeof gameState !== "undefined") { gameState = "title"; } } } }); } }); }; 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; // If no path is provided, use direct velocity based on angle and power if (!path || path.length === 0) { // Convert angle from degrees to radians var radians = angle * Math.PI / 180; // Calculate initial velocity components self.vx = Math.cos(radians) * power; self.vy = Math.sin(radians) * power; } // 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 GameModeSelect = Container.expand(function () { var self = Container.call(this); // Add backdrop var backdrop = self.attachAsset('Commandblock', { anchorX: 0.5, anchorY: 0.5, x: 1009, y: 1366, alpha: 0.8 }); // Add title var titleImage = self.attachAsset('Selectgame', { anchorX: 0.5, anchorY: 0, x: 1024, y: 650 }); // No title text needed as we use the Selectgame image instead // Create classic mode button self.classicModeButton = new Container(); self.classicModeButton.x = 614; self.classicModeButton.y = 1450; // No background needed for classic mode button // Use Classic asset instead of text var classicImg = self.classicModeButton.attachAsset('Classic', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); // Create bonus mode button self.bonusModeButton = new Container(); self.bonusModeButton.x = 1059; self.bonusModeButton.y = 1450; // Use Bonusgame asset instead of text var bonusImg = self.bonusModeButton.attachAsset('Bonusgame', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, alpha: 1.0 }); // Create shooting gallery button (replaces mini games button) self.miniGamesButton = new Container(); self.miniGamesButton.x = 1509; self.miniGamesButton.y = 1450; // Shooting gallery button has no background // Use Shootinggallery asset instead of text var miniGamesImg = self.miniGamesButton.attachAsset('Shootinggallery', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, alpha: 1.0 }); // Add back button self.backButton = new Container(); self.backButton.x = 150; self.backButton.y = 350; var backButtonImage = self.backButton.attachAsset('Backbutton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, alpha: 1.0 }); self.addChild(self.classicModeButton); self.addChild(self.bonusModeButton); self.addChild(self.miniGamesButton); self.addChild(self.backButton); // Make classic mode button interactive self.classicModeButton.down = function (x, y, obj) { tween(this, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.classicModeButton.up = function (x, y, obj) { // Play pop sound LK.getSound('pop').play(); tween(this, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, onFinish: function onFinish() { tween(this, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { // Notify game of mode selection if (typeof game.onGameModeSelected === 'function') { game.onGameModeSelected("classic"); } } }); } }); }; // Make bonus mode button interactive self.bonusModeButton.down = function (x, y, obj) { tween(this, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.bonusModeButton.up = function (x, y, obj) { // Play pop sound LK.getSound('pop').play(); tween(this, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, onFinish: function onFinish() { tween(this, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { // Notify game of mode selection if (typeof game.onGameModeSelected === 'function') { game.onGameModeSelected("bonus", true); // Pass true to indicate only background change } } }); } }); }; // Make mini games button interactive self.miniGamesButton.down = function (x, y, obj) { tween(this, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.miniGamesButton.up = function (x, y, obj) { // Play pop sound LK.getSound('pop').play(); tween(this, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, onFinish: function onFinish() { tween(this, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { // Notify game of mode selection if (typeof game.onGameModeSelected === 'function') { game.onGameModeSelected("minigames"); } } }); } }); }; // Make back button interactive self.backButton.down = function (x, y, obj) { tween(self.backButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.backButton.up = function (x, y, obj) { // Play pop sound LK.getSound('pop').play(); 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() { // Hide game mode select page and show title page if (self.parent) { self.parent.removeChild(self); } if (typeof game !== "undefined" && typeof titlePage !== "undefined") { game.addChild(titlePage); titlePage.alpha = 0; tween(titlePage, { alpha: 1 }, { duration: 500 }); // Set game state to title if (typeof gameState !== "undefined") { gameState = "title"; } } } }); } }); }; 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); // Reset button - positioned to the right of back button self.resetButton = new Container(); self.resetButton.x = 1040; // Moved right 40 pixels self.resetButton.y = 2300; // Moved down 300 pixels // Create reset button using the Resetscores asset var resetButtonImage = self.resetButton.attachAsset('Resetscores', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, alpha: 1.0 }); // Add reset button to high score page self.addChild(self.resetButton); // 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) { // Play pop sound LK.getSound('pop').play(); // 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(); } } }); } }); }; // Make reset button interactive self.resetButton.down = function (x, y, obj) { // Animate button press tween(self.resetButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.resetButton.up = function (x, y, obj) { // Play pop sound LK.getSound('pop').play(); // Animate button release tween(self.resetButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, onFinish: function onFinish() { tween(self.resetButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { // Clear high scores and update display storage.highScores = []; self.updateScores(); // Flash confirmation message var confirmationMsg = new Text2("High scores reset!", { size: 70, fill: 0xFF0000 }); confirmationMsg.anchor.set(0.5, 0.5); confirmationMsg.x = 0; confirmationMsg.y = -200; // Position above scores self.scoreEntries.addChild(confirmationMsg); // Fade out confirmation message tween(confirmationMsg, { alpha: 0 }, { delay: 1500, duration: 500, onFinish: function onFinish() { if (confirmationMsg.parent) { confirmationMsg.parent.removeChild(confirmationMsg); } } }); } }); } }); }; // 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); // Track number of registered high scores storage.registeredScores = highScores.length; // Check if Piglin should be unlocked (after 5 high scores) if (storage.registeredScores >= 5 && storage.piglinUnlocked !== true) { // Removed unlock condition for Shooting Stars based on high score // DeezNuts character is automatically unlocked (removed condition check) storage.deezNutsUnlocked = true; storage.piglinUnlocked = true; // Create unlocked notification using piglinunlocked asset instead of text var unlockedMsg = LK.getAsset('Piglinunlocked', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -300 }); self.scoreEntries.addChild(unlockedMsg); // Immediately remove padlock for Piglin if (characterSelectPage) { for (var i = 0; i < characterSelectPage.characters.length; i++) { var character = characterSelectPage.characters[i]; if (character.asset === "piglinjockey" && characterSelectPage.characterButtons.children[i].lockedImg) { characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg); } } } // Animate and remove the notification tween(unlockedMsg, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { // Play Piglin sound to acknowledge unlock LK.getSound('Pignoise').play(); // Hold for a moment then fade out LK.setTimeout(function () { tween(unlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (unlockedMsg.parent) { unlockedMsg.parent.removeChild(unlockedMsg); } } }); }, 500); } }); } // 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); } // Show progress towards unlocking Piglin if (!storage.piglinUnlocked) { var scoresRemaining = Math.max(0, 5 - storage.registeredScores); var progressText = new Text2("Register " + scoresRemaining + " more high score" + (scoresRemaining !== 1 ? "s" : "") + " to unlock Piglin", { size: 40, fill: 0xFFFFFF }); progressText.anchor.set(0.5, 0.5); progressText.x = 0; progressText.y = 600; self.scoreEntries.addChild(progressText); } }; 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(); } // Start path tracking for S detection if (pathTracker) { pathTracker.startTracking(); pathTracker.addPoint(x, y); } }; // 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 }); // Track point for S detection if (pathTracker) { pathTracker.addPoint(x, 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); // Check if an S pattern or star pattern was detected if (pathTracker) { var patternDetected = pathTracker.stopTracking(); if (patternDetected) { // Check which pattern was detected if (pathTracker.sDetected && !skeletonUnlocked) { // Unlock skeleton character skeletonUnlocked = true; storage.skeletonUnlocked = true; // Play skeleton sound LK.getSound('Skeleton').play(); // Create and show unlock message using skeletonunlocked asset var unlockMsg = LK.getAsset('Skeletonunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(unlockMsg); // Animate and remove the notification tween(unlockMsg, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(unlockMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (unlockMsg.parent) { unlockMsg.parent.removeChild(unlockMsg); } } }); }, 500); } }); } else if (pathTracker.starDetected && !storage.shootingStarsUnlocked) { // Unlock Shooting Stars character storage.shootingStarsUnlocked = true; // Play Starz sound when Shooting Stars is unlocked LK.getSound('Starz').play(); // Play Shooting Stars sound LK.getSound('Shootingstars').play(); // Create and show unlock message using Shootingstarsunlocked asset var starsUnlockMsg = LK.getAsset('Shootingstarsunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(starsUnlockMsg); // Immediately remove padlock for Shooting Stars if on character select screen if (characterSelectPage) { for (var i = 0; i < characterSelectPage.characters.length; i++) { var character = characterSelectPage.characters[i]; if (character.asset === "Shootingstars" && characterSelectPage.characterButtons.children[i].lockedImg) { characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg); } } } // Animate and remove the notification tween(starsUnlockMsg, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(starsUnlockMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (starsUnlockMsg.parent) { starsUnlockMsg.parent.removeChild(starsUnlockMsg); } } }); }, 500); } }); } } } // Calculate final launch parameters var finalAngle = self.angle + 180; // Reverse direction // Return launch parameters return { angle: finalAngle, power: self.power }; }; return self; }); var MiniGamesPage = Container.expand(function () { var self = Container.call(this); // Add backdrop using Jnugbackdrop var backdrop = self.attachAsset('Jnugbackdrop', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, alpha: 1.0 }); // Game state and properties self.gameActive = false; self.score = 0; self.targets = []; self.bullets = []; self.targetTimer = 0; self.targetSpawnRate = 120; // Frames between spawns // Add score display self.scoreText = new Text2("Score: 0", { size: 60, fill: 0xFFFFFF }); self.scoreText.anchor.set(0.5, 0); self.scoreText.x = 1024; self.scoreText.y = 100; self.addChild(self.scoreText); // Create a container for gunslinger for better swipe handling self.gunslingerContainer = new Container(); self.gunslingerContainer.x = 394; self.gunslingerContainer.y = 1370; self.addChild(self.gunslingerContainer); // Add gunslinger to scene var gunslinger = self.gunslingerContainer.attachAsset('Gunslinger', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.98, alpha: 1.0 }); // Variables for tracking swipe self.gunslingerContainer.isGunDrawn = false; self.gunslingerContainer.swipeStartY = 0; self.gunslingerContainer.swipeThreshold = 100; // Minimum distance for a swipe // Add container for targets self.targetContainer = new Container(); self.addChild(self.targetContainer); // We will add targets one at a time later - not now // Add start game button self.startButton = new Container(); self.startButton.x = 1024; self.startButton.y = 800; var startButtonImage = self.startButton.attachAsset('Startgame', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); self.addChild(self.startButton); // Make start button interactive self.startButton.down = function (x, y, obj) { tween(self.startButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.startButton.up = function (x, y, obj) { 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() { // Start the game self.startGame(); } }); } }); }; // Start the shooting game self.startGame = function () { // Hide start button if (self.startButton.parent) { self.startButton.parent.removeChild(self.startButton); } // Don't draw gun automatically - player will need to swipe up to draw gun self.gunslingerContainer.isGunDrawn = false; LK.getSound('pop').play(); // Set game as active self.gameActive = true; self.score = 0; self.scoreText.setText("Score: 0"); // Add Joe Nugget to the scene var joeTarget = new Target(); joeTarget.character = 'Joenugget'; joeTarget.updateCharacterAsset(); self.targetContainer.addChild(joeTarget); self.targets.push(joeTarget); // Play Joe Nugget sound when he appears LK.getSound('Joenugget').play(); }; // Handle target hit self.onTargetHit = function (target) { // Increase score self.score += 100; self.scoreText.setText("Score: " + self.score); // Play sound LK.getSound('pop').play(); // Win condition: if player reaches 5000 points without missing a shot if (self.score >= 5000 && self.gameActive) { self.gameActive = false; LK.setTimeout(function () { LK.showYouWin(); }, 500); return; } // Spawn next target after a short delay LK.setTimeout(function () { self.spawnNextTarget(); }, 1000); }; // Add function to spawn next target self.spawnNextTarget = function () { // Create a new target with the next character in sequence var newTarget = new Target(); // Target will automatically use next character thanks to Target.currentCharacterIndex newTarget.updateCharacterAsset(); self.targetContainer.addChild(newTarget); self.targets.push(newTarget); // Play sound based on new character if (newTarget.character === 'chicken') { LK.getSound('Chickencluck').play(); } else if (newTarget.character === 'piglinjockey') { LK.getSound('Pignoise').play(); } else if (newTarget.character === 'spiderjockey') { LK.getSound('Spider').play(); } else if (newTarget.character === 'steveridingpig') { LK.getSound('Steve').play(); } else if (newTarget.character === 'vilagerjockey') { LK.getSound('Villager').play(); } else if (newTarget.character === 'skeletonhorse') { LK.getSound('Skeleton').play(); } else if (newTarget.character === 'Grimacejockey') { LK.getSound('Grimace').play(); } else if (newTarget.character === 'Michaeljackson') { LK.getSound('MJ').play(); } else if (newTarget.character === 'Johncena') { LK.getSound('Johncena').play(); } else if (newTarget.character === 'Shootingstars') { LK.getSound('Starz').play(); } else if (newTarget.character === 'Deeznuts') { LK.getSound('Deeznuts').play(); } else if (newTarget.character === 'Rickroll') { LK.getSound('Rickroll').play(); } else if (newTarget.character === 'Joenugget') { LK.getSound('Joenugget').play(); } else if (newTarget.character === 'Shrekwizowski') { LK.getSound('Shrek').play(); } else if (newTarget.character === 'Pomni') { LK.getSound('Pomni').play(); } }; // Spawn a new target at random position self.spawnTarget = function () { // Check if there's already an active target var hasActiveTarget = false; for (var i = 0; i < self.targets.length; i++) { if (self.targets[i].active) { hasActiveTarget = true; break; } } // Targets will be added one at a time from elsewhere, not automatically here }; // Fire a bullet from gunslinger toward tap location self.fireBullet = function (targetX, targetY) { // Only fire if gun is drawn if (!self.gunslingerContainer.isGunDrawn) return; // Calculate firing position (top of gun) var fireX = self.gunslingerContainer.x + 350; // Move right 350 var fireY = self.gunslingerContainer.y - 350; // Offset to top of gun, moved down 150 (-500 + 150 = -350) // Calculate angle to target var dx = targetX - fireX; var dy = targetY - fireY; var angle = Math.atan2(dy, dx) * 180 / Math.PI; // Create bullet var bullet = new Bullet(); bullet.init(fireX, fireY, angle); self.addChild(bullet); self.bullets.push(bullet); // Show gunfire effect var gunfire = LK.getAsset('Gunfire', { anchorX: 0.5, anchorY: 0.5, x: fireX, y: fireY, alpha: 1.0, scaleX: 0.8, scaleY: 0.8 }); self.addChild(gunfire); // Position gunfire at tip of gun and rotate to match bullet direction gunfire.rotation = Math.atan2(dy, dx); // Animate gunfire effect tween(gunfire, { alpha: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { if (gunfire.parent) { gunfire.parent.removeChild(gunfire); } } }); // Play gunshot sound LK.getSound('Gunshot').play(); }; // Touch/mouse down on gunslinger self.gunslingerContainer.down = function (x, y, obj) { // Record starting position for swipe detection self.gunslingerContainer.swipeStartY = y; }; // Touch/mouse up on gunslinger self.gunslingerContainer.up = function (x, y, obj) { var swipeDistance = self.gunslingerContainer.swipeStartY - y; // Check if swipe up and gun not drawn if (swipeDistance > self.gunslingerContainer.swipeThreshold && !self.gunslingerContainer.isGunDrawn) { // Switch to gundrawn asset if (gunslinger && gunslinger.parent) { gunslinger.parent.removeChild(gunslinger); } gunslinger = self.gunslingerContainer.attachAsset('Gundrawn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.98, alpha: 1.0 }); self.gunslingerContainer.isGunDrawn = true; LK.getSound('pop').play(); } // Check if swipe down and gun is drawn else if (swipeDistance < -self.gunslingerContainer.swipeThreshold && self.gunslingerContainer.isGunDrawn) { // Switch back to gunslinger asset if (gunslinger && gunslinger.parent) { gunslinger.parent.removeChild(gunslinger); } gunslinger = self.gunslingerContainer.attachAsset('Gunslinger', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.98, alpha: 1.0 }); self.gunslingerContainer.isGunDrawn = false; LK.getSound('pop').play(); } }; // Screen taps for shooting targets self.down = function (x, y, obj) { // Only process if game is active if (!self.gameActive) return; // Only fire if gun is drawn if (!self.gunslingerContainer.isGunDrawn) return; // Allow shooting anywhere on the screen self.fireBullet(x, y); }; // Update function self.update = function () { if (self.gameActive) { // No automatic spawning of targets - we'll add them one at a time externally // Update targets for (var i = self.targets.length - 1; i >= 0; i--) { self.targets[i].update(); // Remove expired targets if (!self.targets[i].active && self.targets[i].alpha <= 0) { if (self.targets[i].parent) { self.targets[i].parent.removeChild(self.targets[i]); } self.targets.splice(i, 1); } } // Update bullets for (var i = self.bullets.length - 1; i >= 0; i--) { self.bullets[i].update(); // Remove bullets that have traveled too far if (self.bullets[i].distanceTraveled > self.bullets[i].maxDistance) { if (self.bullets[i].parent) { self.bullets[i].parent.removeChild(self.bullets[i]); } self.bullets.splice(i, 1); } } } }; // Back button implementation removed from minigame scene 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 PathTracker = Container.expand(function () { var self = Container.call(this); // Path tracking properties self.isTracking = false; self.pathPoints = []; self.sDetected = false; self.starDetected = false; // Track if star pattern is detected // Start tracking a new path self.startTracking = function () { self.isTracking = true; self.pathPoints = []; self.sDetected = false; self.starDetected = false; // Reset star pattern detection }; // Add a point to the tracking path self.addPoint = function (x, y) { if (!self.isTracking) { return; } // Add point to path self.pathPoints.push({ x: x, y: y }); // Check for patterns if we have enough points if (self.pathPoints.length > 20) { self.checkForSPattern(); self.checkForStarPattern(); // Also check for star pattern } }; // Stop tracking self.stopTracking = function () { self.isTracking = false; // Return true if either S or star pattern was detected return self.sDetected || self.starDetected; }; // Check if the path forms an S pattern self.checkForSPattern = function () { if (self.pathPoints.length < 20) { return false; } // Analyze path for S shape // An S shape should go from top to bottom with two major direction changes // Find bounding box of the path var minX = self.pathPoints[0].x; var maxX = self.pathPoints[0].x; var minY = self.pathPoints[0].y; var maxY = self.pathPoints[0].y; for (var i = 1; i < self.pathPoints.length; i++) { minX = Math.min(minX, self.pathPoints[i].x); maxX = Math.max(maxX, self.pathPoints[i].x); minY = Math.min(minY, self.pathPoints[i].y); maxY = Math.max(maxY, self.pathPoints[i].y); } // Check if path has enough height and width to be an S var width = maxX - minX; var height = maxY - minY; if (height < 300 || width < 200) { return false; } // Divide path into vertical thirds var topThird = minY + height / 3; var bottomThird = maxY - height / 3; // Count direction changes (left/right) in top, middle and bottom sections var topSection = self.analyzeSection(self.pathPoints, minY, topThird); var middleSection = self.analyzeSection(self.pathPoints, topThird, bottomThird); var bottomSection = self.analyzeSection(self.pathPoints, bottomThird, maxY); // For an S pattern, typically: // - Top section has rightward movement // - Middle section has leftward movement // - Bottom section has rightward movement if (topSection.direction === "right" && middleSection.direction === "left" && bottomSection.direction === "right") { self.sDetected = true; return true; } // Also check reverse S pattern if (topSection.direction === "left" && middleSection.direction === "right" && bottomSection.direction === "left") { self.sDetected = true; return true; } return false; }; // Check if the path forms a star pattern self.checkForStarPattern = function () { if (self.pathPoints.length < 20) { return false; } // Analyze path for star shape // Find the center point of all path points var centerX = 0; var centerY = 0; for (var i = 0; i < self.pathPoints.length; i++) { centerX += self.pathPoints[i].x; centerY += self.pathPoints[i].y; } centerX /= self.pathPoints.length; centerY /= self.pathPoints.length; // A star pattern should have at least 5 peaks (points extending outward) // and 5 valleys (points returning inward) var peaks = []; var valleys = []; var distanceThreshold = 100; // Minimum peak distance from center var minPeaks = 5; // Minimum number of peaks to be considered a star // Calculate distance from center for each point var distances = []; for (var i = 0; i < self.pathPoints.length; i++) { var dx = self.pathPoints[i].x - centerX; var dy = self.pathPoints[i].y - centerY; var distance = Math.sqrt(dx * dx + dy * dy); distances.push(distance); } // Find peaks (local maxima) in the distance function for (var i = 5; i < self.pathPoints.length - 5; i++) { var isPeak = true; var isValley = true; // Check if this is a peak for (var j = i - 5; j <= i + 5; j++) { if (j === i) { continue; } if (distances[j] > distances[i]) { isPeak = false; } if (distances[j] < distances[i]) { isValley = false; } } // Add to peaks if it's far enough from center if (isPeak && distances[i] > distanceThreshold) { peaks.push(i); } // Add to valleys if (isValley) { valleys.push(i); } } // For a star pattern, we need at least 5 peaks if (peaks.length >= minPeaks) { // Check that peaks are somewhat evenly distributed around the center var angles = []; for (var i = 0; i < peaks.length; i++) { var idx = peaks[i]; var dx = self.pathPoints[idx].x - centerX; var dy = self.pathPoints[idx].y - centerY; var angle = Math.atan2(dy, dx); if (angle < 0) { angle += 2 * Math.PI; } // Normalize to [0, 2π] angles.push(angle); } // Sort angles angles.sort(function (a, b) { return a - b; }); // Check for relatively even spacing between peaks var isEvenlySpaced = true; var idealSpacing = 2 * Math.PI / angles.length; var spacingTolerance = idealSpacing * 0.5; // 50% tolerance for (var i = 0; i < angles.length; i++) { var nextIdx = (i + 1) % angles.length; var spacing = angles[nextIdx] - angles[i]; if (spacing < 0) { spacing += 2 * Math.PI; } if (Math.abs(spacing - idealSpacing) > spacingTolerance) { isEvenlySpaced = false; break; } } // If we have enough peaks and they're evenly spaced, it's a star if (isEvenlySpaced) { self.starDetected = true; return true; } } return false; }; // Analyze a section of the path for predominant horizontal direction self.analyzeSection = function (points, minY, maxY) { var leftwardMovement = 0; var rightwardMovement = 0; // Find points in this vertical section var sectionPoints = []; for (var i = 0; i < points.length; i++) { if (points[i].y >= minY && points[i].y <= maxY) { sectionPoints.push(points[i]); } } // Sort points by y-coordinate sectionPoints.sort(function (a, b) { return a.y - b.y; }); // Calculate horizontal movement through the section for (var i = 1; i < sectionPoints.length; i++) { var dx = sectionPoints[i].x - sectionPoints[i - 1].x; if (dx > 0) { rightwardMovement += dx; } else if (dx < 0) { leftwardMovement += Math.abs(dx); } } return { direction: rightwardMovement > leftwardMovement ? "right" : "left", rightwardMovement: rightwardMovement, leftwardMovement: leftwardMovement }; }; return self; }); var Popcorn = Container.expand(function () { var self = Container.call(this); // Create and attach popcorn asset // Create and attach popcorn asset based on selected character var popcornGraphics = self.attachAsset(selectedCharacter === "Joenugget" ? 'Drumstick' : selectedCharacter === "Grimacejockey" ? 'Shakes' : selectedCharacter === "Johncena" ? 'Belt' : selectedCharacter === "Shootingstars" ? 'Stars' : selectedCharacter === "Deeznuts" ? 'Nuts' : selectedCharacter === "Rickroll" ? 'Hearts' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Circuspop' : '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.updateAsset = function (assetName) { if (popcornGraphics && popcornGraphics.parent) { self.removeChild(popcornGraphics); } popcornGraphics = self.attachAsset(selectedCharacter === "Joenugget" ? 'Drumstick' : selectedCharacter === "Grimacejockey" ? 'Shakes' : selectedCharacter === "Johncena" ? 'Belt' : selectedCharacter === "Pomni" ? 'Circuspop' : assetName, { anchorX: 0.5, anchorY: 0.5 }); }; 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; } // Ensure popcorn stays within the rope boundaries var padding = 150; // Minimum distance from ropes if (self.x < bounds.left + padding) { self.x = bounds.left + padding; self.targetX = self.x; } else if (self.x > bounds.right - padding) { self.x = bounds.right - padding; self.targetX = self.x; } if (self.y < bounds.top + padding) { self.y = bounds.top + padding; self.targetY = self.y; self.baseY = self.y; } else if (self.y > bounds.bottom - padding) { self.y = bounds.bottom - padding; self.targetY = self.y; self.baseY = self.y; } }; 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 SlingshotLauncher = Container.expand(function () { var self = Container.call(this); // Create slingshot elements var basePoint = self.attachAsset('launcher', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7, scaleX: 1.5, scaleY: 1.5 }); // Create elastic bands var leftBand = self.attachAsset('aimLine', { anchorX: 0, anchorY: 0.5, alpha: 0.8, scaleY: 0.5, tint: 0xFF0000 }); var rightBand = self.attachAsset('aimLine', { anchorX: 0, anchorY: 0.5, alpha: 0.8, scaleY: 0.5, tint: 0xFF0000 }); // Hide bands initially leftBand.alpha = 0; rightBand.alpha = 0; // Properties self.aiming = false; self.pullbackX = 0; self.pullbackY = 0; self.maxPullback = 300; self.power = 0; // Start aiming self.startAim = function (x, y) { self.aiming = true; self.pullbackX = x; self.pullbackY = y; // Show elastic bands leftBand.alpha = 0.8; rightBand.alpha = 0.8; // Update bands self.updateBands(x, y); }; // Update during aiming self.updateAim = function (x, y) { if (!self.aiming) return; // Calculate distance from start point var dx = x - self.x; var dy = y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Limit pullback distance if (distance > self.maxPullback) { var ratio = self.maxPullback / distance; dx *= ratio; dy *= ratio; x = self.x + dx; y = self.y + dy; } // Save pullback position self.pullbackX = x; self.pullbackY = y; // Calculate power based on distance self.power = distance / 5; // Update bands self.updateBands(x, y); }; // Update elastic bands self.updateBands = function (x, y) { // Position and angle for left band leftBand.x = self.x - 25; leftBand.y = self.y; var dx1 = x - leftBand.x; var dy1 = y - leftBand.y; var angle1 = Math.atan2(dy1, dx1); var dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1); leftBand.rotation = angle1; leftBand.width = dist1; // Position and angle for right band rightBand.x = self.x + 25; rightBand.y = self.y; var dx2 = x - rightBand.x; var dy2 = y - rightBand.y; var angle2 = Math.atan2(dy2, dx2); var dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2); rightBand.rotation = angle2; rightBand.width = dist2; }; // End aiming and launch self.endAim = function () { if (!self.aiming) return null; self.aiming = false; // Hide bands after launch tween(leftBand, { alpha: 0 }, { duration: 200 }); tween(rightBand, { alpha: 0 }, { duration: 200 }); // Calculate launch vector - opposite of pullback var dx = self.x - self.pullbackX; var dy = self.y - self.pullbackY; var angle = Math.atan2(dy, dx) * 180 / Math.PI; // Return launch parameters return { angle: angle, power: self.power, path: null // No predefined path for slingshot mode }; }; return self; }); var Superpopcorn = Container.expand(function () { var self = Container.call(this); // Create and attach Superpopcorn asset // Create and attach Superpopcorn asset based on selected character var superPopcornGraphics = self.attachAsset(selectedCharacter === "Shootingstars" ? 'Whitestars' : selectedCharacter === "Deeznuts" ? 'Cashew' : selectedCharacter === "Rickroll" ? 'Purpleheart' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Digpop' : '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.updateAsset = function (assetName) { if (superPopcornGraphics && superPopcornGraphics.parent) { self.removeChild(superPopcornGraphics); } superPopcornGraphics = self.attachAsset(selectedCharacter === "Joenugget" ? 'Popchicken' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Digpop' : assetName, { anchorX: 0.5, anchorY: 0.5 }); }; 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; } // Ensure superpopcorn stays within the rope boundaries var padding = 150; // Minimum distance from ropes if (self.x < bounds.left + padding) { self.x = bounds.left + padding; self.targetX = self.x; } else if (self.x > bounds.right - padding) { self.x = bounds.right - padding; self.targetX = self.x; } if (self.y < bounds.top + padding) { self.y = bounds.top + padding; self.targetY = self.y; self.baseY = self.y; } else if (self.y > bounds.bottom - padding) { self.y = bounds.bottom - padding; self.targetY = self.y; self.baseY = self.y; } }; return self; }); var Target = Container.expand(function () { var self = Container.call(this); // Array of characters to use as targets in order of appearance var characters = ['chicken', 'piglinjockey', 'spiderjockey', 'steveridingpig', 'vilagerjockey', 'skeletonhorse', 'Grimacejockey', 'Michaeljackson', 'Johncena', 'Shootingstars', 'Deeznuts', 'Rickroll', 'Joenugget', 'Shrekwizowski', 'Pomni']; // Use a static counter to cycle through characters in sequence rather than randomly if (typeof Target.currentCharacterIndex === 'undefined') { Target.currentCharacterIndex = 0; } // Get the next character in sequence and increment counter var characterToUse = characters[Target.currentCharacterIndex]; Target.currentCharacterIndex = (Target.currentCharacterIndex + 1) % characters.length; // Create character graphics as a placeholder (will be updated in updateCharacterAsset) var characterGraphics; // Properties self.active = true; self.lifespan = 3000; // 3 seconds self.created = LK.ticks; self.character = characterToUse; self.movementSpeed = 5; self.startPosition = { x: 0, y: 0 }; self.targetPosition = { x: 0, y: 0 }; self.isMoving = false; // Function to update character asset with appropriate behavior self.updateCharacterAsset = function () { // Remove existing character graphic if it exists if (characterGraphics && characterGraphics.parent) { self.removeChild(characterGraphics); } // Attach new asset with different properties based on character characterGraphics = self.attachAsset(self.character, { anchorX: 0.5, anchorY: 0.5, scaleX: self.character === 'Joenugget' ? 0.8 : 0.5, scaleY: self.character === 'Joenugget' ? 0.8 : 0.5 }); // Set up character appearance based on character type if (self.character === 'Joenugget') { // Joe Nugget starts from right side in middle and walks to center self.x = 2048 + 250; // Start off-screen to the right self.y = 1650; // 50px higher than before (from 1700 to 1650) self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: 1024, y: self.y }; // Move to center self.isMoving = true; self.movementSpeed = 1; // Even slower movement speed for Joe Nugget // Add bob animation for Joe Nugget to make it look like walking var originalY = self.y; tween(characterGraphics, { y: -20 // Move up more for more visible bobbing }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(characterGraphics, { y: 10 // Move down below center point for more natural walking motion }, { duration: 500, easing: tween.easeInOut, repeat: -1, yoyo: true // Continuously bob up and down }); } }); } else if (self.character === 'spiderjockey') { // Spider jockey appears in middle of screen and moves downwards self.x = 1024; // Center of screen horizontally self.y = 1024; // Start higher on screen self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, // Stay centered horizontally y: 1800 // Move down to lower part of screen }; self.isMoving = true; self.movementSpeed = 2; // Slow movement speed // Add slight animation for spider to make it look like moving tween(characterGraphics, { y: -10 // Bobbing up }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(characterGraphics, { y: 10 // Bobbing down }, { duration: 600, easing: tween.easeInOut, repeat: -1, yoyo: true // Continuously bob up and down }); } }); } else if (self.character === 'Grimacejockey') { // Grimace jockey starts from 300px right and 200px down of left centre of screen and walks right across self.x = 300; // Start 300px right of the left edge self.y = 1366 + 200; // 200px down from middle of screen vertically self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: 2048 - 400, // Move to 400px from right of screen instead of off-screen y: self.y }; self.isMoving = true; self.movementSpeed = 3; // Moderate movement speed // Add bob animation for Grimace to make it look like walking tween(characterGraphics, { y: -15 // Bobbing up }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(characterGraphics, { y: 15 // Bobbing down }, { duration: 500, easing: tween.easeInOut, repeat: -1, yoyo: true // Continuously bob up and down }); } }); } else if (self.character === 'chicken') { // Chicken flies from top of screen to random lower position self.x = Math.random() * 1600 + 224; // Random x between 224-1824 self.y = -100; // Start above screen self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: Math.random() * 500 + 400 }; // Random y between 400-900 self.isMoving = true; self.movementSpeed = 8; // Faster movement } else if (self.character === 'piglinjockey') { // Piglin jockey appears at left bottom of screen and move right slowly across the screen self.x = 200; // Start at left side of screen self.y = 2200; // Bottom of screen self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: 2048 - 200, // Move to right side of screen (with small margin) y: self.y // Stay at the same height }; // Move across screen self.isMoving = true; self.movementSpeed = 3; // Slower movement speed } else if (self.character === 'Michaeljackson') { // MJ appears slightly left of center of screen self.x = 1024 - 150; // 150 left from center of screen self.y = 1366; // Middle of screen self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: self.y }; // Stay at the offset position self.isMoving = false; self.movementSpeed = 0; // Not moving // Make MJ head smaller by using a smaller scale characterGraphics.scaleX = 0.35; characterGraphics.scaleY = 0.35; } else if (self.character === 'Rickroll') { // Add rickroll appears at offset from center of screen self.x = 1024 + 600; // 600 pixels right from center of screen horizontally self.y = 1366 + 100; // 100 pixels down from middle of screen self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: self.y }; // Stay at offset position self.isMoving = false; self.movementSpeed = 0; // Not moving // Make Rickroll character smaller characterGraphics.scaleX = 0.25; characterGraphics.scaleY = 0.25; } else if (self.character === 'steveridingpig') { // Steveridingpig appears at center of the screen self.x = 1024; // Center of screen horizontally self.y = 1366; // Center of screen vertically self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: self.y }; // Stay at center position self.isMoving = false; self.movementSpeed = 0; // Not moving // Set appropriate scale for steveridingpig characterGraphics.scaleX = 0.5; characterGraphics.scaleY = 0.5; } else if (self.character === 'Pomni') { // Pomni appears at center of the screen and 150 down self.x = 1024; // Center of screen horizontally self.y = 1366 + 150; // 150 down from center of screen vertically self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: self.y }; // Stay at offset position self.isMoving = false; self.movementSpeed = 0; // Not moving // Set appropriate scale for Pomni characterGraphics.scaleX = 0.4; characterGraphics.scaleY = 0.4; } else if (self.character === 'Shootingstars') { // Shootingstars starts at the top of the minigame scene self.centerX = Math.random() * 1200 + 424; // Center of circle, avoid edges self.centerY = Math.random() * 400 + 700; // Center of circle, mid screen self.radius = 250 + Math.random() * 100; // Circle radius self.angle = 0; // Current angle in radians self.angularSpeed = 0.035 + Math.random() * 0.01; // Radians per frame self.x = self.centerX + self.radius * Math.cos(self.angle); self.y = self.centerY + self.radius * Math.sin(self.angle); self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: self.y }; self.isMoving = true; self.movementSpeed = 0; // Not used for circular movement } else if (self.character === 'Shrekwizowski') { // Shrek appears in center and grows self.x = 1024; // Center x self.y = 1366; // Center y self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: self.y }; // Doesn't move characterGraphics.scaleX = 0.1; characterGraphics.scaleY = 0.1; // Grow animation tween(characterGraphics, { scaleX: 0.5, scaleY: 0.5 }, { duration: 500, easing: tween.easeOut }); self.isMoving = false; } else { // Default: appear at random position on screen self.x = Math.random() * 1600 + 224; // Random x between 224-1824 self.y = Math.random() * 1200 + 500; // Random y between 500-1700 self.startPosition = { x: self.x, y: self.y }; self.targetPosition = { x: self.x, y: self.y }; // Doesn't move self.isMoving = false; // Add a small zoom-in animation for appearance characterGraphics.scaleX = 0.3; characterGraphics.scaleY = 0.3; tween(characterGraphics, { scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); } }; // Initialize with the chosen character self.updateCharacterAsset(); // Hit function - called when target is hit by a bullet self.hit = function () { if (!self.active) return; self.active = false; // Animate hit tween(self, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (self.parent) { self.parent.removeChild(self); } } }); // Notify game of hit if (typeof game.onTargetHit === 'function') { game.onTargetHit(self); } }; // Update function self.update = function () { // Move character if it's still moving if (self.isMoving && self.active) { if (self.character === 'Shootingstars') { // Move in a circle self.angle += self.angularSpeed; if (self.angle > Math.PI * 2) self.angle -= Math.PI * 2; self.x = self.centerX + self.radius * Math.cos(self.angle); self.y = self.centerY + self.radius * Math.sin(self.angle); } else { // Calculate direction to target var dx = self.targetPosition.x - self.x; var dy = self.targetPosition.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Move towards target if (distance > self.movementSpeed) { self.x += dx / distance * self.movementSpeed; self.y += dy / distance * self.movementSpeed; } else { // Reached destination self.x = self.targetPosition.x; self.y = self.targetPosition.y; self.isMoving = false; } } } // Check if lifetime expired if (LK.ticks - self.created > self.lifespan && self.active) { // Disappear tween(self, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (self.parent) { self.parent.removeChild(self); } } }); self.active = false; } }; 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 }); // Make title screen tappable to unlock Grimace titleBackground.down = function (x, y, obj) { grimaceTaps++; if (grimaceTaps === 5 && !grimaceUnlocked) { grimaceUnlocked = true; storage.grimaceUnlocked = true; // Play Maccas sound when Grimace is unlocked LK.getSound('Maccas').play(); // Update character buttons to remove padlock from Grimace and MJ if unlocked updateCharacterButtons(); // Create unlocked notification using grimaceunlocked asset var grimaceUnlockedMsg = LK.getAsset('Grimaceunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 0.8, scaleY: 0.8 }); // Replace grimacejockey with grimaceunlocked asset when unlocked if (characterSelectPage) { for (var i = 0; i < characterSelectPage.characters.length; i++) { var character = characterSelectPage.characters[i]; if (character.asset === "Grimacejockey" && characterSelectPage.characterButtons.children[i]) { var button = characterSelectPage.characterButtons.children[i]; // Remove existing character image for (var j = 0; j < button.children.length; j++) { if (button.children[j].assetId === "Grimacejockey") { button.removeChild(button.children[j]); break; } } // Add grimaceunlocked asset instead var grimaceImg = button.attachAsset('Grimaceunlocked', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); } } } game.addChild(grimaceUnlockedMsg); // Animate and remove the notification tween(grimaceUnlockedMsg, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(grimaceUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (grimaceUnlockedMsg.parent) { grimaceUnlockedMsg.parent.removeChild(grimaceUnlockedMsg); } } }); }, 500); } }); } }; // Add unlock progress text // Create start button self.startButton = new Container(); self.startButton.x = 1024; self.startButton.y = 1650; // 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) { // Play pop sound LK.getSound('pop').play(); // 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) { // Play pop sound LK.getSound('pop').play(); // 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, gameModeSelect, characterSelect, ready, aiming, launched, gameOver, highScores, minigames var gameMode = "classic"; // classic or bonus 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; var gameModeSelectPage = null; var characterSelectPage = null; var miniGamesPage = null; var selectedCharacter = "chicken"; // Default character var pathTracker = new PathTracker(); // Add path tracker for S detection var skeletonUnlocked = false; // Track if skeleton has been unlocked through S pattern var grimaceTaps = 0; // Counter for taps on title screen var grimaceUnlocked = false; // Track if Grimace character is unlocked // Function to update character buttons when a character is unlocked function updateCharacterButtons() { if (characterSelectPage) { for (var i = 0; i < characterSelectPage.characters.length; i++) { var character = characterSelectPage.characters[i]; if (character.asset === "Grimacejockey" && grimaceUnlocked && characterSelectPage.characterButtons.children[i].lockedImg) { characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg); } if (character.asset === "Michaeljackson" && storage.mjUnlocked && characterSelectPage.characterButtons.children[i].lockedImg) { characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg); // Show MJ unlocked asset when MJ is unlocked var mjUnlockedMsg = LK.getAsset('MJunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(mjUnlockedMsg); // Animate and remove the notification tween(mjUnlockedMsg, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(mjUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (mjUnlockedMsg.parent) { mjUnlockedMsg.parent.removeChild(mjUnlockedMsg); } } }); }, 500); } }); } if (character.asset === "Johncena" && storage.johnCenaUnlocked && characterSelectPage.characterButtons.children[i].lockedImg) { characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg); // Show John Cena unlocked asset when John Cena is unlocked var johncenaUnlockedMsg = LK.getAsset('Johncenaunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(johncenaUnlockedMsg); // Animate and remove the notification tween(johncenaUnlockedMsg, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(johncenaUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (johncenaUnlockedMsg.parent) { johncenaUnlockedMsg.parent.removeChild(johncenaUnlockedMsg); } } }); }, 500); } }); } } } // Check if Rickroll should be unlocked (when all other characters are unlocked) if (!storage.rickrollUnlocked) { // Check if all other characters are unlocked, excluding Joe Nugget var allCharactersUnlocked = storage.steveUnlocked && storage.piglinUnlocked && storage.villagerUnlocked && storage.spiderUnlocked && storage.skeletonUnlocked && storage.grimaceUnlocked && storage.mjUnlocked && storage.johnCenaUnlocked && storage.shootingStarsUnlocked && storage.deezNutsUnlocked; storage.allCharactersUnlocked = allCharactersUnlocked; if (allCharactersUnlocked) { storage.rickrollUnlocked = true; // Play rickroll sound when rickroll character is unlocked LK.getSound('Rickroll').play(); // Create unlocked notification using Rickroll unlocked asset var rickrollUnlockedMsg = LK.getAsset('Rickrollunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(rickrollUnlockedMsg); // If character select page exists, remove padlock from Rickroll character if (characterSelectPage) { for (var i = 0; i < characterSelectPage.characters.length; i++) { var character = characterSelectPage.characters[i]; if (character.asset === "Rickroll" && characterSelectPage.characterButtons.children[i].lockedImg) { characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg); } } } // Animate and remove the notification tween(rickrollUnlockedMsg, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(rickrollUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (rickrollUnlockedMsg.parent) { rickrollUnlockedMsg.parent.removeChild(rickrollUnlockedMsg); } } }); }, 500); } }); } } } // 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 arenaAsset = selectedCharacter === "Shootingstars" ? 'Space' : 'arena'; if (arena && arena.parent) { arena.parent.removeChild(arena); } var arenaAsset = selectedCharacter === "Joenugget" ? 'Jnugbackdrop' : selectedCharacter === "Shootingstars" ? 'Space' : 'arena'; var arena = game.addChild(LK.getAsset(arenaAsset, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: selectedCharacter === "Shootingstars" ? 1 : 1, scaleY: selectedCharacter === "Shootingstars" ? 1 : 1 })); // Add slow rotation to hyperspace when in bonus mode if (gameMode === "bonus") { tween(arena, { rotation: Math.PI * 2 }, { duration: 60000, // Complete one full rotation in 60 seconds repeat: -1, // Infinite repetition onRepeat: function onRepeat() { // Reset rotation to avoid potential issues after multiple rotations arena.rotation = 0; } }); } // 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.x = 100; // Move text right 50 more pixels instructionText.y = 180; LK.gui.top.addChild(instructionText); // Initialize game function initGame() { // Check if MJ should be unlocked when played 20 times if (!storage.mjUnlocked && storage.gamePlays >= 20) { storage.mjUnlocked = true; // Play MJ sound when MJ is unlocked LK.getSound('MJ').play(); // Show MJ unlocked asset when MJ is unlocked var mjUnlockedMsg = LK.getAsset('MJunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(mjUnlockedMsg); // Animate and remove the notification tween(mjUnlockedMsg, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(mjUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (mjUnlockedMsg.parent) { mjUnlockedMsg.parent.removeChild(mjUnlockedMsg); } } }); }, 500); } }); } // Check if John Cena should be unlocked when played 30 times if (!storage.johnCenaUnlocked && storage.gamePlays >= 30) { storage.johnCenaUnlocked = true; // Play John Cena entrance sound when John Cena is unlocked LK.getSound('Johncena').play(); // Create unlocked notification using John Cena unlocked asset var cenaUnlockedMsg = LK.getAsset('Johncenaunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(cenaUnlockedMsg); // Animate and remove the notification tween(cenaUnlockedMsg, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(cenaUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (cenaUnlockedMsg.parent) { cenaUnlockedMsg.parent.removeChild(cenaUnlockedMsg); } } }); }, 500); } }); } // Reset variables score = 0; launches = 0; gameState = "title"; bonusApplied = false; skeletonUnlocked = storage.skeletonUnlocked || false; storage.deezNutsUnlocked = true; grimaceUnlocked = storage.grimaceUnlocked || 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 your character!"); 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 game mode select page if it doesn't exist if (!gameModeSelectPage) { gameModeSelectPage = new GameModeSelect(); // Keep it detached until needed } // Initialize mini games page if it doesn't exist if (!miniGamesPage) { miniGamesPage = new MiniGamesPage(); // 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 () { // Track game plays in storage storage.gamePlays = (storage.gamePlays || 0) + 1; // Check if Steve should be unlocked (after 3 plays) if (storage.gamePlays >= 3 && storage.steveUnlocked !== true) { storage.steveUnlocked = true; // Play Steve sound when Steve is unlocked LK.getSound('Steve').play(); // Immediately remove padlock for Steve if (characterSelectPage) { for (var i = 0; i < characterSelectPage.characters.length; i++) { var character = characterSelectPage.characters[i]; if (character.asset === "steveridingpig" && characterSelectPage.characterButtons.children[i].lockedImg) { characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg); } } } // Create unlocked notification using steveunlocked asset instead of text var unlockedMsg = LK.getAsset('Steveunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(unlockedMsg); // Animate and remove the notification tween(unlockedMsg, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { tween(unlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (unlockedMsg.parent) { unlockedMsg.parent.removeChild(unlockedMsg); } } }); } }); } // Hide title page tween(titlePage, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { if (titlePage.parent) { titlePage.parent.removeChild(titlePage); } // Show game mode selection page instead of character select game.addChild(gameModeSelectPage); gameModeSelectPage.alpha = 0; tween(gameModeSelectPage, { alpha: 1 }, { duration: 500 }); // Set game state gameState = "gameModeSelect"; } }); }; // 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 game mode selection handler game.onGameModeSelected = function (mode, backgroundOnly) { // Store selected game mode gameMode = mode; // Hide game mode select page tween(gameModeSelectPage, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { if (gameModeSelectPage.parent) { gameModeSelectPage.parent.removeChild(gameModeSelectPage); } // Check if minigames mode was selected if (mode === "minigames") { // Set game state to minigames gameState = "minigames"; // Show mini games page game.addChild(miniGamesPage); miniGamesPage.alpha = 0; tween(miniGamesPage, { alpha: 1 }, { duration: 500, onFinish: function onFinish() { // Store reference to targets and update handler for bullet-target collision game.targets = miniGamesPage.targets; game.onTargetHit = function (target) { miniGamesPage.onTargetHit(target); }; } }); return; } // Set game state gameState = "characterSelect"; // Update instruction text based on selected mode if (mode === "bonus") { // Change background for bonus mode if (arena && arena.parent) { arena.parent.removeChild(arena); } arena = game.addChild(LK.getAsset('Hyperspace', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 1, scaleY: 1 })); // Add slow rotation to hyperspace tween(arena, { rotation: Math.PI * 2 }, { duration: 60000, repeat: -1, onRepeat: function onRepeat() { arena.rotation = 0; } }); // Ensure arena is behind other elements if (chickenJockey.parent) { chickenJockey.parent.removeChild(chickenJockey); } game.addChild(chickenJockey); } // Only show character select page after bonus mode setup is complete LK.setTimeout(function () { game.addChild(characterSelectPage); characterSelectPage.alpha = 0; tween(characterSelectPage, { alpha: 1 }, { duration: 500 }); }, 100); // Short delay to ensure background is properly applied } }); }; // Add handler for character selected handler game.onCharacterSelected = function (characterAsset) { // Store selected character selectedCharacter = characterAsset; // Replace arena with space asset when Shooting Stars character is selected or in bonus mode if (arena && arena.parent) { arena.parent.removeChild(arena); } var arenaAsset; if (gameMode === "bonus") { // Use Hyperspace in bonus mode regardless of character arenaAsset = 'Hyperspace'; } else { arenaAsset = selectedCharacter === "Joenugget" ? 'Jnugbackdrop' : selectedCharacter === "Shootingstars" || selectedCharacter === "Deeznuts" ? 'Space' : selectedCharacter === "Shrekwizowski" ? 'Swamp' : selectedCharacter === "Pomni" ? 'Digcircus' : selectedCharacter === "Michaeljackson" ? 'MJbackground' : 'arena'; } arena = game.addChild(LK.getAsset(arenaAsset, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 1, scaleY: 1 })); // Start slow rotation if in bonus mode if (gameMode === "bonus") { tween(arena, { rotation: Math.PI * 2 }, { duration: 60000, repeat: -1, onRepeat: function onRepeat() { arena.rotation = 0; } }); // Ensure that 5 superpopcorn are immediately created for the first launch in bonus mode createSuperPopcorn(5); } // Update chicken jockey with selected character and make sure it's in front chickenJockey.updateCharacterAsset(selectedCharacter); // Ensure chicken jockey is on top by removing and re-adding it if (chickenJockey.parent) { chickenJockey.parent.removeChild(chickenJockey); } game.addChild(chickenJockey); // Only add character-specific backdrops in non-bonus mode if (gameMode !== "bonus") { if (selectedCharacter === "Deeznuts") { var spaceLevel = LK.getAsset('Spacelevel', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(spaceLevel); game.addChild(chickenJockey); // Ensure DeezNuts character is on top } // Add rickbackdrop when Rickroll character is selected if (selectedCharacter === "Rickroll") { var rickbackdrop = LK.getAsset('Rickbackdrop', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(rickbackdrop); // Make sure it's behind the chicken jockey if (chickenJockey.parent) { chickenJockey.parent.removeChild(chickenJockey); } game.addChild(chickenJockey); } } // Update popcorn asset for existing popcorns var popcornAsset = selectedCharacter === "Grimacejockey" ? 'Shakes' : selectedCharacter === "Johncena" ? 'Belt' : selectedCharacter === "Shootingstars" ? 'Stars' : selectedCharacter === "Deeznuts" ? 'Nuts' : selectedCharacter === "Rickroll" ? 'Hearts' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Circuspop' : 'popcorn'; for (var i = 0; i < popcorns.length; i++) { popcorns[i].updateAsset(popcornAsset); } var superPopcornAsset = selectedCharacter === "Shootingstars" ? 'Whitestars' : selectedCharacter === "Deeznuts" ? 'Cashew' : selectedCharacter === "Rickroll" ? 'Purpleheart' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Popshrek' : selectedCharacter === "Pomni" ? 'Digpop' : 'Superpopcorn'; for (var i = 0; i < superPopcorns.length; i++) { superPopcorns[i].updateAsset(superPopcornAsset); } // Play character-specific sounds if (selectedCharacter === "piglinjockey") { LK.getSound('Pignoise').play(); } else if (selectedCharacter === "steveridingpig") { LK.getSound('Steve').play(); } else if (selectedCharacter === "vilagerjockey") { LK.getSound('Villager').play(); } else if (selectedCharacter === "spiderjockey") { LK.getSound('Spider').play(); } else if (selectedCharacter === "skeletonhorse") { LK.getSound('Skeleton').play(); } else if (selectedCharacter === "Grimacejockey") { LK.getSound('Grimace').play(); } else if (selectedCharacter === "Michaeljackson") { LK.getSound('MJ').play(); // Thriller music will be played in startGamePlay() function //Removed duplicate music initialization here } else if (selectedCharacter === "Johncena") { LK.getSound('Johncena').play(); // Play John Cena entrance music during gameplay when John Cena character is selected LK.playMusic('Cenaentrance'); } else if (selectedCharacter === "Deeznuts") { LK.getSound('Deeznuts').play(); LK.playMusic('Deeznutstrap'); } else if (selectedCharacter === "Shootingstars") { LK.playMusic('Shootingstars'); } else if (selectedCharacter === "Joenugget") { LK.getSound('Joenugget').play(); } else if (selectedCharacter === "Rickroll") { LK.getSound('Rickroll').play(); } else if (selectedCharacter === "Shrekwizowski") { LK.getSound('Shrek').play(); } else if (selectedCharacter === "Pomni") { LK.getSound('Pomni').play(); } else { // Play default game music for other characters LK.playMusic('gameMusic'); } // Add handler for character select reset game.onCharacterSelectReset = function () { // Remove current character select page if (characterSelectPage && characterSelectPage.parent) { characterSelectPage.parent.removeChild(characterSelectPage); } // Create new character select page with reset unlocks characterSelectPage = new CharacterSelect(); game.addChild(characterSelectPage); }; // 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; // Update instructions based on game mode if (gameMode === "bonus") { instructionText.setText("Pull back and release to slingshot your character!"); // Replace path launcher with slingshot launcher in bonus mode if (launcher && launcher.parent) { launcher.parent.removeChild(launcher); } launcher = game.addChild(new SlingshotLauncher()); launcher.x = chickenJockey.x; launcher.y = chickenJockey.y; launcher.alpha = 0; // Make launcher invisible in bonus mode } else { instructionText.setText("**Hidden character** Tap 5 popcorn in title screen to unlock."); } // Clear existing popcorn and ropes clearPopcornsAndRopes(); // Create ropes around the arena createRopes(); // Create popcorn scattered around the arena - only in classic mode if (gameMode !== "bonus") { createPopcorn(15); // Regular amount in classic mode } // Add trajectory path to game if not in bonus mode if (gameMode !== "bonus" && launcher.trajectoryPath) { game.addChild(launcher.trajectoryPath); } // Play background music based on selected character if (selectedCharacter === "Michaeljackson") { LK.playMusic('Thriller'); } else if (selectedCharacter === "Johncena") { LK.playMusic('Cenaentrance'); } else if (selectedCharacter === "Shootingstars") { LK.playMusic('Shootingstars'); } else if (selectedCharacter === "Rickroll") { LK.playMusic('Nevergonna'); } else if (selectedCharacter === "Grimacejockey") { LK.playMusic('Grimaceshake'); } else if (selectedCharacter === "Joenugget") { LK.playMusic('gegagedi'); } else if (selectedCharacter === "Shrekwizowski") { LK.playMusic('Raveswamp'); } else if (selectedCharacter === "Pomni") { LK.playMusic('Digcircus'); } else if (selectedCharacter !== "Deeznuts") { 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 - (selectedCharacter === "Michaeljackson" ? 150 : 0) + (selectedCharacter === "Michaeljackson" ? 300 : 0); chickenJockey.y = selectedCharacter === "Michaeljackson" ? arena.y - 670 : arena.y - 400; // 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() { // Skip rope creation in bonus mode if (gameMode === "bonus") { return; } // Position ropes at edge of screen if using MJBackground var isMJBackground = selectedCharacter === "Michaeljackson"; var edgeOffset = isMJBackground ? 0 : 100; // Create top rope var topRope = new Rope(); topRope.x = arena.x; topRope.y = bounds.top + edgeOffset; game.addChild(topRope); ropes.push(topRope); // Create right rope var rightRope = new Rope(); rightRope.x = bounds.right - edgeOffset; 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 - edgeOffset; game.addChild(bottomRope); ropes.push(bottomRope); // Create left rope var leftRope = new Rope(); leftRope.x = bounds.left + edgeOffset; leftRope.y = arena.y; leftRope.rotation = Math.PI / 2; // Rotate 90 degrees game.addChild(leftRope); ropes.push(leftRope); // If MJ background, animate ropes to make them more visible if (isMJBackground) { for (var i = 0; i < ropes.length; i++) { // Flash the ropes slightly to make them more visible against MJ background tween(ropes[i], { alpha: 0.7 }, { duration: 300, onFinish: function onFinish() { tween(this, { alpha: 1 }, { duration: 300 }); } }); } } } 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 // Determine the correct popcorn asset based on the selected character var popcornAsset = selectedCharacter === "Joenugget" ? 'Drumstick' : 'popcorn'; // Default asset if (selectedCharacter === "Grimacejockey") { popcornAsset = 'Shakes'; } else if (selectedCharacter === "Johncena") { popcornAsset = 'Belt'; // Ensure Belt is used for John Cena } else if (selectedCharacter === "Shootingstars") { popcornAsset = 'Stars'; } else if (selectedCharacter === "Deeznuts") { popcornAsset = 'Nuts'; } else if (selectedCharacter === "Rickroll") { popcornAsset = 'Hearts'; } 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(); // Update asset based on selected character popcorn.updateAsset(popcornAsset); // 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(); // Update asset based on selected character var superPopcornAsset = selectedCharacter === "Joenugget" ? 'Popchicken' : selectedCharacter === "Shootingstars" ? 'Whitestars' : selectedCharacter === "Deeznuts" ? 'Cashew' : selectedCharacter === "Rickroll" ? 'Purpleheart' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : 'Superpopcorn'; superPopcorn.updateAsset(superPopcornAsset); // 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"; // Check if all popcorn is collected to apply X5 bonus // Make sure we check for empty popcorns array at the exact moment the chicken stops 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 character-specific sounds for X5 bonus if (selectedCharacter === "Shootingstars") { // No sound for Shooting Stars } else if (selectedCharacter === "piglinjockey") { LK.getSound('Pignoise').play(); } else if (selectedCharacter === "steveridingpig") { LK.getSound('Steve').play(); } else if (selectedCharacter === "vilagerjockey") { LK.getSound('Villager').play(); } else if (selectedCharacter === "spiderjockey") { LK.getSound('Spider').play(); } else if (selectedCharacter === "skeletonhorse") { LK.getSound('Skeleton').play(); } else if (selectedCharacter === "Grimacejockey") { LK.getSound('Grimace').play(); } else if (selectedCharacter === "Michaeljackson") { LK.getSound('MJ').play(); } else if (selectedCharacter === "Deeznuts") { LK.getSound('Deeznuts').play(); } else if (selectedCharacter === "Rickroll") { LK.getSound('Rickroll').play(); } else if (selectedCharacter === "Joenugget") { LK.getSound('Joenugget').play(); } else if (selectedCharacter === "Johncena") { LK.getSound('Johncena').play(); } else if (selectedCharacter === "Shrekwizowski") { LK.getSound('Shrek').play(); } else if (selectedCharacter === "Pomni") { LK.getSound('Pomni').play(); } else { LK.getSound('Bogerk').play(); } // Create X5 animation bonusAnimation = LK.getAsset('X5', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 1.5, scaleY: 1.5, alpha: 1 }); game.addChild(bonusAnimation); // Animate the X5 bonus tween(bonusAnimation, { scaleX: 2.5, scaleY: 2.5 }, { duration: 700, easing: tween.bounceOut, onFinish: function onFinish() { 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(); } else if (popcorns.length === 0 && superPopcorns.length === 0) { // Reset bonus status for next round if all popcorn is collected but bonus was already applied bonusApplied = false; } // Check if score has reached 1000000 to unlock villager character if (score >= 1000000 && !storage.villagerUnlocked) { storage.villagerUnlocked = true; // Play Villager sound when Villager is unlocked LK.getSound('Villager').play(); // Create unlocked notification using villagerunlocked asset instead of text var villagerUnlockedMsg = LK.getAsset('Villagerunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(villagerUnlockedMsg); // Animate and remove the notification tween(villagerUnlockedMsg, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { // Play Chicken sound to acknowledge unlock LK.getSound('Chickencluck').play(); // Hold for a moment then fade out LK.setTimeout(function () { tween(villagerUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (villagerUnlockedMsg.parent) { villagerUnlockedMsg.parent.removeChild(villagerUnlockedMsg); } } }); }, 500); } }); } // Check if score has reached 10,000,000 to unlock spider character if (score >= 10000000 && !storage.spiderUnlocked) { storage.spiderUnlocked = true; // Play Spider sound to acknowledge unlock LK.getSound('Spider').play(); // Create unlocked notification using spiderjockeyunlocked asset instead of text var spiderUnlockedMsg = LK.getAsset('Spiderjockeyunlocked', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(spiderUnlockedMsg); // Animate and remove the notification tween(spiderUnlockedMsg, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { // Play Chicken sound to acknowledge unlock LK.getSound('Chickencluck').play(); // Hold for a moment then fade out LK.setTimeout(function () { tween(spiderUnlockedMsg, { alpha: 0 }, { delay: 1000, duration: 500, onFinish: function onFinish() { if (spiderUnlockedMsg.parent) { spiderUnlockedMsg.parent.removeChild(spiderUnlockedMsg); } } }); }, 500); } }); } // 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 all popcorn for a X5 bonus!"); } }; 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" || gameState === "gameModeSelect" || gameState === "minigames") { // Title page, high scores, game mode select, mini games and character select interactions are handled by their respective classes return; } if (gameState === "ready") { gameState = "aiming"; dragStartX = x; dragStartY = y; // Use appropriate aiming method based on game mode if (gameMode === "bonus") { // In bonus mode, aim from character position launcher.startAim(chickenJockey.x, chickenJockey.y); } else { // In classic mode, use path drawing launcher.startAim(x, y); } } }; game.move = function (x, y, obj) { if (gameState === "title" || gameState === "highScores" || gameState === "characterSelect" || gameState === "gameModeSelect" || gameState === "minigames") { // Title page, high scores, game mode select, mini games and character select interactions are handled by their respective classes return; } if (gameState === "aiming") { // Use appropriate aiming method based on game mode launcher.updateAim(x, y); // In bonus mode, move the character to the slingshot pullback position if (gameMode === "bonus" && launcher.aiming) { chickenJockey.x = launcher.pullbackX; chickenJockey.y = launcher.pullbackY; } } }; game.up = function (x, y, obj) { if (gameState === "title" || gameState === "highScores" || gameState === "characterSelect" || gameState === "gameModeSelect" || gameState === "minigames") { // Title page, high scores, game mode select, mini games and character select interactions are handled by their respective classes return; } if (gameState === "aiming") { if (gameMode === "bonus") { // Handle slingshot launch in bonus mode var launchParams = launcher.endAim(); // Only launch if there's enough power if (!launchParams || launchParams.power < 5) { gameState = "ready"; instructionText.setText("Pull back more to launch your character!"); return; } // Launch the chicken jockey with direct parameters chickenJockey.launch(launchParams.power, launchParams.angle); // Update game state gameState = "launched"; launches++; launchesText.setText(launches + "/" + maxLaunches); instructionText.setText("Watch your character fly through space!"); // Add 5 superpopcorn in bonus mode after each launch createSuperPopcorn(5); } else { // Classic mode path-based launch // 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 your character!"); 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 character follow your path!"); // Add 3 superpopcorn after each launch createSuperPopcorn(3); } } }; // Main game loop game.update = function () { // Update minigames if (gameState === "minigames" && miniGamesPage && typeof miniGamesPage.update === "function") { miniGamesPage.update(); } // Update all game objects else 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 different sounds based on selected character if (selectedCharacter === "Shootingstars") { // No sound for Shooting Stars } else if (selectedCharacter === "piglinjockey") { LK.getSound('Pignoise').play(); } else if (selectedCharacter === "steveridingpig") { // Play Steve sound when Steve character is used and X5 bonus is achieved LK.getSound('Steve').play(); } else if (selectedCharacter === "vilagerjockey") { LK.getSound('Villager').play(); } else if (selectedCharacter === "spiderjockey") { LK.getSound('Spider').play(); } else if (selectedCharacter === "skeletonhorse") { // Play Skeleton sound when Skeleton character is used and X5 bonus is achieved LK.getSound('Skeleton').play(); } else if (selectedCharacter === "Grimacejockey") { // Play Grimace sound when Grimace character is used and X5 bonus is achieved LK.getSound('Grimace').play(); } else if (selectedCharacter === "Michaeljackson") { // Play MJ sound when MJ character is used and X5 bonus is achieved LK.getSound('MJ').play(); } else if (selectedCharacter === "Deeznuts") { // Play Deeznuts sound when DeezNuts character is used and X5 bonus is achieved LK.getSound('Deeznuts').play(); } else if (selectedCharacter === "Rickroll") { LK.getSound('Rickroll').play(); } else if (selectedCharacter === "Joenugget") { // Play Joenugget sound when Joe Nugget character is used and X5 bonus is achieved LK.getSound('Joenugget').play(); } else if (selectedCharacter === "Johncena") { // Play John Cena sound when John Cena character is used and X5 bonus is achieved LK.getSound('Johncena').play(); } else if (selectedCharacter === "Shrekwizowski") { LK.getSound('Shrek').play(); } else if (selectedCharacter === "Pomni") { LK.getSound('Pomni').play(); } else { // Play Bogerk sound for other characters 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(); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScores: [],
gamePlays: 0,
steveUnlocked: false,
piglinUnlocked: false,
villagerUnlocked: false,
spiderUnlocked: false,
registeredScores: 0,
skeletonUnlocked: false,
grimaceUnlocked: false,
mjUnlocked: false,
johnCenaUnlocked: false,
shootingStarsUnlocked: false,
deezNutsUnlocked: false,
rickrollUnlocked: false,
selectedCharacter: "chicken",
bonusAnimation: "undefined",
titlePage: "undefined",
highScorePage: "undefined",
characterSelectPage: "undefined",
arena: "undefined",
backdrop: "undefined",
chickenJockey: "undefined",
launcher: "undefined",
scoreText: "undefined",
scoreTitleImg: "undefined",
launchesText: "undefined",
instructionText: "undefined",
launchesTitleImg: "undefined",
steve: "undefined",
bonusApplied: false,
pathTracker: "undefined",
popcorns: [],
superPopcorns: [],
ropes: [],
bounds: {},
grimaceTaps: 0,
gameState: "title",
score: 0,
launches: 0,
maxLaunches: 10,
dragStartX: 0,
dragStartY: 0,
allCharactersUnlocked: false
});
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
// Create bullet visuals using Bullet asset
var bulletGraphics = self.attachAsset('Bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
// Bullet properties
self.speed = 20;
self.angle = 0;
self.maxDistance = 2000;
self.distanceTraveled = 0;
self.startX = 0;
self.startY = 0;
// Initialize bullet with angle and starting position
self.init = function (startX, startY, angle) {
self.x = startX;
self.y = startY;
self.startX = startX;
self.startY = startY;
self.angle = angle;
// Convert angle to radians
var radians = angle * Math.PI / 180;
// Calculate velocity components
self.vx = Math.cos(radians) * self.speed;
self.vy = Math.sin(radians) * self.speed;
// Set rotation to match direction
bulletGraphics.rotation = radians;
};
// Update bullet position
self.update = function () {
// Move bullet
self.x += self.vx;
self.y += self.vy;
// Calculate distance traveled
var dx = self.x - self.startX;
var dy = self.y - self.startY;
self.distanceTraveled = Math.sqrt(dx * dx + dy * dy);
// Check if bullet has traveled too far
if (self.distanceTraveled > self.maxDistance) {
if (self.parent) {
self.parent.removeChild(self);
}
return;
}
// Check for hits with targets
if (typeof game.targets !== 'undefined') {
for (var i = 0; i < game.targets.length; i++) {
if (game.targets[i].active && self.intersects(game.targets[i])) {
// Hit target
game.targets[i].hit();
// Remove bullet
if (self.parent) {
self.parent.removeChild(self);
}
return;
}
}
}
// Check for hits with characters in the target container
if (typeof game.miniGamesPage !== 'undefined' && typeof game.miniGamesPage.targetContainer !== 'undefined') {
var chars = game.miniGamesPage.targetContainer.children;
for (var i = 0; i < chars.length; i++) {
if (chars[i].active && self.intersects(chars[i])) {
// Hit character
if (typeof chars[i].hit === 'function') {
chars[i].hit();
} else {
// If character doesn't have a hit method, remove it
if (chars[i].parent) {
chars[i].parent.removeChild(chars[i]);
}
}
// Remove bullet
if (self.parent) {
self.parent.removeChild(self);
}
return;
}
}
}
};
return self;
});
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
});
// Create a container for the character instead of attaching directly to allow better Z-order control
var walkingCharacterContainer = new Container();
walkingCharacterContainer.x = 2048 + 300; // Start off-screen to the right
walkingCharacterContainer.y = 1300; // Centered vertically but lower on screen
self.addChild(walkingCharacterContainer);
// Add walking character to the container to control visibility separately
var walkingCharacter = walkingCharacterContainer.attachAsset('Gunslinger', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
// Animate character walking in
tween(walkingCharacter, {
x: 1024 // Move to center of screen
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Add slight idle animation
tween(walkingCharacter, {
y: walkingCharacter.y - 20
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(walkingCharacter, {
y: walkingCharacter.y + 20
}, {
duration: 1000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
});
}
});
// Add title using Selectcharactertitle asset
var titleImage = self.attachAsset('Selectcharactertitle', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: 150
});
// Add back button
self.backButton = new Container();
self.backButton.x = 150; // Position at top left, but not in the 0-100px reserved area
self.backButton.y = 350; // Align vertically with reset button
// Create back button using the Backbutton asset
var backButtonImage = self.backButton.attachAsset('Backbutton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
});
self.addChild(self.backButton);
// Add reset button
self.resetButton = new Container();
self.resetButton.x = 1900; // Position at top right of screen
self.resetButton.y = 350; // Position at top right of screen
// Create reset button using the Resetcharacter asset
var resetButtonImage = self.resetButton.attachAsset('Resetcharacter', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
});
// Add reset button to character select page
self.addChild(self.resetButton);
// 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"
}, {
name: "Grimace",
asset: "Grimacejockey"
}, {
name: "MJ",
asset: "Michaeljackson"
}, {
name: "John Cena",
asset: "Johncena"
}, {
name: "Shooting Stars",
asset: "Shootingstars"
}, {
name: "DeezNuts",
asset: "Deeznuts"
}, {
name: "Rickroll",
asset: "Rickroll"
}, {
name: "Joe Nugget",
asset: "Joenugget"
}, {
name: "Shrekwizowski",
asset: "Shrekwizowski"
}, {
name: "Pomni",
asset: "Pomni"
}];
self.selectedCharacter = "chicken";
self.characterButtons = new Container();
self.characterButtons.x = 1024;
self.characterButtons.y = 700;
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 + 10; // Move right 10 pixels
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
});
// Add locked overlay for all characters except chicken, Steve (if unlocked), Piglin (if unlocked), Villager (if unlocked), Spider (if unlocked), Skeleton (if unlocked by S pattern), Grimace (if unlocked), MJ (if unlocked), and SpongeBob
if (character.asset !== "chicken" && !(character.asset === "steveridingpig" && storage.steveUnlocked === true) && !(character.asset === "piglinjockey" && storage.piglinUnlocked === true) && !(character.asset === "vilagerjockey" && storage.villagerUnlocked === true) && !(character.asset === "spiderjockey" && storage.spiderUnlocked === true) && !(character.asset === "skeletonhorse" && storage.skeletonUnlocked === true) && !(character.asset === "Grimacejockey" && storage.grimaceUnlocked === true) && !(character.asset === "Michaeljackson" && storage.mjUnlocked === true) && !(character.asset === "Johncena" && storage.johnCenaUnlocked === true) && !(character.asset === "Shootingstars" && storage.shootingStarsUnlocked === true) && !(character.asset === "Deeznuts") && !(character.asset === "Rickroll") && !(character.asset === "Joenugget") && !(character.asset === "SpongeBob") && !(character.asset === "Shrekwizowski") && !(character.asset === "Pomni")) {
var lockedImg = button.attachAsset('Locked', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
button.lockedImg = lockedImg; // Store reference to locked image
} else {
if (button.lockedImg && button.lockedImg.parent) {
button.lockedImg.parent.removeChild(button.lockedImg); // Remove padlock if character is unlocked
}
}
// Character name text removed
// Store character data with button
button.characterData = character;
// Make button interactive
button.down = function (x, y, obj) {
tween(this, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
button.up = function (x, y, obj) {
var btnRef = this;
// Check if character is unlocked before allowing selection
var isUnlocked = btnRef.characterData.asset === "chicken" || btnRef.characterData.asset === "steveridingpig" && storage.steveUnlocked === true || btnRef.characterData.asset === "piglinjockey" && storage.piglinUnlocked === true || btnRef.characterData.asset === "vilagerjockey" && storage.villagerUnlocked === true || btnRef.characterData.asset === "spiderjockey" && storage.spiderUnlocked === true || btnRef.characterData.asset === "skeletonhorse" && storage.skeletonUnlocked === true || btnRef.characterData.asset === "Grimacejockey" && storage.grimaceUnlocked === true || btnRef.characterData.asset === "Michaeljackson" && storage.mjUnlocked === true || btnRef.characterData.asset === "Johncena" && storage.johnCenaUnlocked === true || btnRef.characterData.asset === "Shootingstars" && storage.shootingStarsUnlocked === true || btnRef.characterData.asset === "Deeznuts" && storage.deezNutsUnlocked === true || btnRef.characterData.asset === "Rickroll" || btnRef.characterData.asset === "Joenugget" || btnRef.characterData.asset === "SpongeBob" || btnRef.characterData.asset === "Shrekwizowski" || btnRef.characterData.asset === "Pomni";
if (!isUnlocked) {
// Show unlock message based on character
if (btnRef.characterData.asset === "Michaeljackson") {
var playCount = storage.gamePlays || 0;
var playsRemaining = Math.max(0, 20 - playCount);
var unlockText = new Text2("Play " + playsRemaining + " more time" + (playsRemaining !== 1 ? "s" : "") + " to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
} else if (btnRef.characterData.asset === "steveridingpig") {
var playCount = storage.gamePlays || 0;
var playsRemaining = Math.max(0, 3 - playCount);
var unlockText = new Text2("Play " + playsRemaining + " more time" + (playsRemaining !== 1 ? "s" : "") + " to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
} else if (btnRef.characterData.asset === "piglinjockey") {
var scoresRegistered = storage.registeredScores || 0;
var scoresRemaining = Math.max(0, 5 - scoresRegistered);
var unlockText = new Text2("Register " + scoresRemaining + " more high score" + (scoresRemaining !== 1 ? "s" : "") + " to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
} else if (btnRef.characterData.asset === "vilagerjockey") {
var unlockText = new Text2("Score 1,000,000 points to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
} else if (btnRef.characterData.asset === "spiderjockey") {
var unlockText = new Text2("Score 10,000,000 points to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
} else if (btnRef.characterData.asset === "skeletonhorse") {
var unlockText = new Text2("Trace an 'S' on the arena to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
} else if (btnRef.characterData.asset === "Johncena") {
var playCount = storage.gamePlays || 0;
var playsRemaining = Math.max(0, 30 - playCount);
var unlockText = new Text2("Play " + playsRemaining + " more time" + (playsRemaining !== 1 ? "s" : "") + " to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
} else if (btnRef.characterData.asset === "Shootingstars") {
var unlockText = new Text2("Trace a star in arena to unlock", {
size: 40,
fill: 0xFFFFFF
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 0;
unlockText.y = 150;
btnRef.addChild(unlockText);
// Fade out the text after 2 seconds
tween(unlockText, {
alpha: 0
}, {
delay: 2000,
duration: 500,
onFinish: function onFinish() {
if (unlockText.parent) {
unlockText.parent.removeChild(unlockText);
}
}
});
}
// Animate button but don't select locked character
tween(btnRef, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(btnRef, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
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;
// Update popcorn asset to 'Belt' if Johncena is selected
if (btnRef.characterData.asset === "Johncena") {
var popcornAsset = 'Belt';
for (var i = 0; i < popcorns.length; i++) {
if (typeof popcorns[i].updateAsset === "function") {
popcorns[i].updateAsset(popcornAsset);
}
}
}
// Notify game of selection
if (typeof game.onCharacterSelected === 'function') {
game.onCharacterSelected(btnRef.characterData.asset);
}
}
});
}
});
};
self.characterButtons.addChild(button);
}
// Make reset button interactive
self.resetButton.down = function (x, y, obj) {
// Animate button press
tween(self.resetButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.resetButton.up = function (x, y, obj) {
// Play pop sound
LK.getSound('pop').play();
// Animate button release
tween(self.resetButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(self.resetButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
// Reset unlock status for all characters
storage.steveUnlocked = false;
storage.piglinUnlocked = false;
storage.villagerUnlocked = false;
storage.spiderUnlocked = false;
storage.gamePlays = 0;
storage.registeredScores = 0;
skeletonUnlocked = false; // Reset skeleton unlock state
storage.skeletonUnlocked = false; // Persist reset state
grimaceUnlocked = false; // Reset grimace unlock state
storage.grimaceUnlocked = false; // Persist reset state
storage.mjUnlocked = false; // Reset MJ unlock state
storage.johnCenaUnlocked = false; // Reset John Cena unlock state
storage.rickrollUnlocked = false; // Reset Rickroll unlock state
storage.shootingStarsUnlocked = false; // Reset Shooting Stars unlock state
storage.deezNutsUnlocked = false; // Reset DeezNuts unlock state
storage.allCharactersUnlocked = false; // Reset all characters unlocked state
// Flash confirmation message
var confirmationMsg = new Text2("Characters reset!", {
size: 70,
fill: 0xFF0000
});
confirmationMsg.anchor.set(0.5, 0.5);
confirmationMsg.x = 0;
confirmationMsg.y = -400; // Position above characters
self.characterButtons.addChild(confirmationMsg);
// Fade out confirmation message
tween(confirmationMsg, {
alpha: 0
}, {
delay: 1500,
duration: 500,
onFinish: function onFinish() {
if (confirmationMsg.parent) {
confirmationMsg.parent.removeChild(confirmationMsg);
}
// Force refresh the character selection screen
if (typeof game.onCharacterSelectReset === 'function') {
game.onCharacterSelectReset();
}
}
});
}
});
}
});
};
// 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) {
// Play pop sound
LK.getSound('pop').play();
// 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() {
// Hide character select page and show title page
if (self.parent) {
self.parent.removeChild(self);
}
if (typeof game !== "undefined" && typeof titlePage !== "undefined") {
game.addChild(titlePage);
titlePage.alpha = 0;
tween(titlePage, {
alpha: 1
}, {
duration: 500
});
// Set game state to title
if (typeof gameState !== "undefined") {
gameState = "title";
}
}
}
});
}
});
};
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;
// If no path is provided, use direct velocity based on angle and power
if (!path || path.length === 0) {
// Convert angle from degrees to radians
var radians = angle * Math.PI / 180;
// Calculate initial velocity components
self.vx = Math.cos(radians) * power;
self.vy = Math.sin(radians) * power;
}
// 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 GameModeSelect = Container.expand(function () {
var self = Container.call(this);
// Add backdrop
var backdrop = self.attachAsset('Commandblock', {
anchorX: 0.5,
anchorY: 0.5,
x: 1009,
y: 1366,
alpha: 0.8
});
// Add title
var titleImage = self.attachAsset('Selectgame', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: 650
});
// No title text needed as we use the Selectgame image instead
// Create classic mode button
self.classicModeButton = new Container();
self.classicModeButton.x = 614;
self.classicModeButton.y = 1450;
// No background needed for classic mode button
// Use Classic asset instead of text
var classicImg = self.classicModeButton.attachAsset('Classic', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Create bonus mode button
self.bonusModeButton = new Container();
self.bonusModeButton.x = 1059;
self.bonusModeButton.y = 1450;
// Use Bonusgame asset instead of text
var bonusImg = self.bonusModeButton.attachAsset('Bonusgame', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 1.0
});
// Create shooting gallery button (replaces mini games button)
self.miniGamesButton = new Container();
self.miniGamesButton.x = 1509;
self.miniGamesButton.y = 1450;
// Shooting gallery button has no background
// Use Shootinggallery asset instead of text
var miniGamesImg = self.miniGamesButton.attachAsset('Shootinggallery', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 1.0
});
// Add back button
self.backButton = new Container();
self.backButton.x = 150;
self.backButton.y = 350;
var backButtonImage = self.backButton.attachAsset('Backbutton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
});
self.addChild(self.classicModeButton);
self.addChild(self.bonusModeButton);
self.addChild(self.miniGamesButton);
self.addChild(self.backButton);
// Make classic mode button interactive
self.classicModeButton.down = function (x, y, obj) {
tween(this, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.classicModeButton.up = function (x, y, obj) {
// Play pop sound
LK.getSound('pop').play();
tween(this, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(this, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
// Notify game of mode selection
if (typeof game.onGameModeSelected === 'function') {
game.onGameModeSelected("classic");
}
}
});
}
});
};
// Make bonus mode button interactive
self.bonusModeButton.down = function (x, y, obj) {
tween(this, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.bonusModeButton.up = function (x, y, obj) {
// Play pop sound
LK.getSound('pop').play();
tween(this, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(this, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
// Notify game of mode selection
if (typeof game.onGameModeSelected === 'function') {
game.onGameModeSelected("bonus", true); // Pass true to indicate only background change
}
}
});
}
});
};
// Make mini games button interactive
self.miniGamesButton.down = function (x, y, obj) {
tween(this, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.miniGamesButton.up = function (x, y, obj) {
// Play pop sound
LK.getSound('pop').play();
tween(this, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(this, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
// Notify game of mode selection
if (typeof game.onGameModeSelected === 'function') {
game.onGameModeSelected("minigames");
}
}
});
}
});
};
// Make back button interactive
self.backButton.down = function (x, y, obj) {
tween(self.backButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.backButton.up = function (x, y, obj) {
// Play pop sound
LK.getSound('pop').play();
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() {
// Hide game mode select page and show title page
if (self.parent) {
self.parent.removeChild(self);
}
if (typeof game !== "undefined" && typeof titlePage !== "undefined") {
game.addChild(titlePage);
titlePage.alpha = 0;
tween(titlePage, {
alpha: 1
}, {
duration: 500
});
// Set game state to title
if (typeof gameState !== "undefined") {
gameState = "title";
}
}
}
});
}
});
};
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);
// Reset button - positioned to the right of back button
self.resetButton = new Container();
self.resetButton.x = 1040; // Moved right 40 pixels
self.resetButton.y = 2300; // Moved down 300 pixels
// Create reset button using the Resetscores asset
var resetButtonImage = self.resetButton.attachAsset('Resetscores', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
});
// Add reset button to high score page
self.addChild(self.resetButton);
// 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) {
// Play pop sound
LK.getSound('pop').play();
// 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();
}
}
});
}
});
};
// Make reset button interactive
self.resetButton.down = function (x, y, obj) {
// Animate button press
tween(self.resetButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.resetButton.up = function (x, y, obj) {
// Play pop sound
LK.getSound('pop').play();
// Animate button release
tween(self.resetButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(self.resetButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
// Clear high scores and update display
storage.highScores = [];
self.updateScores();
// Flash confirmation message
var confirmationMsg = new Text2("High scores reset!", {
size: 70,
fill: 0xFF0000
});
confirmationMsg.anchor.set(0.5, 0.5);
confirmationMsg.x = 0;
confirmationMsg.y = -200; // Position above scores
self.scoreEntries.addChild(confirmationMsg);
// Fade out confirmation message
tween(confirmationMsg, {
alpha: 0
}, {
delay: 1500,
duration: 500,
onFinish: function onFinish() {
if (confirmationMsg.parent) {
confirmationMsg.parent.removeChild(confirmationMsg);
}
}
});
}
});
}
});
};
// 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);
// Track number of registered high scores
storage.registeredScores = highScores.length;
// Check if Piglin should be unlocked (after 5 high scores)
if (storage.registeredScores >= 5 && storage.piglinUnlocked !== true) {
// Removed unlock condition for Shooting Stars based on high score
// DeezNuts character is automatically unlocked (removed condition check)
storage.deezNutsUnlocked = true;
storage.piglinUnlocked = true;
// Create unlocked notification using piglinunlocked asset instead of text
var unlockedMsg = LK.getAsset('Piglinunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -300
});
self.scoreEntries.addChild(unlockedMsg);
// Immediately remove padlock for Piglin
if (characterSelectPage) {
for (var i = 0; i < characterSelectPage.characters.length; i++) {
var character = characterSelectPage.characters[i];
if (character.asset === "piglinjockey" && characterSelectPage.characterButtons.children[i].lockedImg) {
characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg);
}
}
}
// Animate and remove the notification
tween(unlockedMsg, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
// Play Piglin sound to acknowledge unlock
LK.getSound('Pignoise').play();
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(unlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (unlockedMsg.parent) {
unlockedMsg.parent.removeChild(unlockedMsg);
}
}
});
}, 500);
}
});
}
// 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);
}
// Show progress towards unlocking Piglin
if (!storage.piglinUnlocked) {
var scoresRemaining = Math.max(0, 5 - storage.registeredScores);
var progressText = new Text2("Register " + scoresRemaining + " more high score" + (scoresRemaining !== 1 ? "s" : "") + " to unlock Piglin", {
size: 40,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 0.5);
progressText.x = 0;
progressText.y = 600;
self.scoreEntries.addChild(progressText);
}
};
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();
}
// Start path tracking for S detection
if (pathTracker) {
pathTracker.startTracking();
pathTracker.addPoint(x, y);
}
};
// 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
});
// Track point for S detection
if (pathTracker) {
pathTracker.addPoint(x, 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);
// Check if an S pattern or star pattern was detected
if (pathTracker) {
var patternDetected = pathTracker.stopTracking();
if (patternDetected) {
// Check which pattern was detected
if (pathTracker.sDetected && !skeletonUnlocked) {
// Unlock skeleton character
skeletonUnlocked = true;
storage.skeletonUnlocked = true;
// Play skeleton sound
LK.getSound('Skeleton').play();
// Create and show unlock message using skeletonunlocked asset
var unlockMsg = LK.getAsset('Skeletonunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(unlockMsg);
// Animate and remove the notification
tween(unlockMsg, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(unlockMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (unlockMsg.parent) {
unlockMsg.parent.removeChild(unlockMsg);
}
}
});
}, 500);
}
});
} else if (pathTracker.starDetected && !storage.shootingStarsUnlocked) {
// Unlock Shooting Stars character
storage.shootingStarsUnlocked = true;
// Play Starz sound when Shooting Stars is unlocked
LK.getSound('Starz').play();
// Play Shooting Stars sound
LK.getSound('Shootingstars').play();
// Create and show unlock message using Shootingstarsunlocked asset
var starsUnlockMsg = LK.getAsset('Shootingstarsunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(starsUnlockMsg);
// Immediately remove padlock for Shooting Stars if on character select screen
if (characterSelectPage) {
for (var i = 0; i < characterSelectPage.characters.length; i++) {
var character = characterSelectPage.characters[i];
if (character.asset === "Shootingstars" && characterSelectPage.characterButtons.children[i].lockedImg) {
characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg);
}
}
}
// Animate and remove the notification
tween(starsUnlockMsg, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(starsUnlockMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (starsUnlockMsg.parent) {
starsUnlockMsg.parent.removeChild(starsUnlockMsg);
}
}
});
}, 500);
}
});
}
}
}
// Calculate final launch parameters
var finalAngle = self.angle + 180; // Reverse direction
// Return launch parameters
return {
angle: finalAngle,
power: self.power
};
};
return self;
});
var MiniGamesPage = Container.expand(function () {
var self = Container.call(this);
// Add backdrop using Jnugbackdrop
var backdrop = self.attachAsset('Jnugbackdrop', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
alpha: 1.0
});
// Game state and properties
self.gameActive = false;
self.score = 0;
self.targets = [];
self.bullets = [];
self.targetTimer = 0;
self.targetSpawnRate = 120; // Frames between spawns
// Add score display
self.scoreText = new Text2("Score: 0", {
size: 60,
fill: 0xFFFFFF
});
self.scoreText.anchor.set(0.5, 0);
self.scoreText.x = 1024;
self.scoreText.y = 100;
self.addChild(self.scoreText);
// Create a container for gunslinger for better swipe handling
self.gunslingerContainer = new Container();
self.gunslingerContainer.x = 394;
self.gunslingerContainer.y = 1370;
self.addChild(self.gunslingerContainer);
// Add gunslinger to scene
var gunslinger = self.gunslingerContainer.attachAsset('Gunslinger', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.98,
alpha: 1.0
});
// Variables for tracking swipe
self.gunslingerContainer.isGunDrawn = false;
self.gunslingerContainer.swipeStartY = 0;
self.gunslingerContainer.swipeThreshold = 100; // Minimum distance for a swipe
// Add container for targets
self.targetContainer = new Container();
self.addChild(self.targetContainer);
// We will add targets one at a time later - not now
// Add start game button
self.startButton = new Container();
self.startButton.x = 1024;
self.startButton.y = 800;
var startButtonImage = self.startButton.attachAsset('Startgame', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
self.addChild(self.startButton);
// Make start button interactive
self.startButton.down = function (x, y, obj) {
tween(self.startButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.startButton.up = function (x, y, obj) {
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() {
// Start the game
self.startGame();
}
});
}
});
};
// Start the shooting game
self.startGame = function () {
// Hide start button
if (self.startButton.parent) {
self.startButton.parent.removeChild(self.startButton);
}
// Don't draw gun automatically - player will need to swipe up to draw gun
self.gunslingerContainer.isGunDrawn = false;
LK.getSound('pop').play();
// Set game as active
self.gameActive = true;
self.score = 0;
self.scoreText.setText("Score: 0");
// Add Joe Nugget to the scene
var joeTarget = new Target();
joeTarget.character = 'Joenugget';
joeTarget.updateCharacterAsset();
self.targetContainer.addChild(joeTarget);
self.targets.push(joeTarget);
// Play Joe Nugget sound when he appears
LK.getSound('Joenugget').play();
};
// Handle target hit
self.onTargetHit = function (target) {
// Increase score
self.score += 100;
self.scoreText.setText("Score: " + self.score);
// Play sound
LK.getSound('pop').play();
// Win condition: if player reaches 5000 points without missing a shot
if (self.score >= 5000 && self.gameActive) {
self.gameActive = false;
LK.setTimeout(function () {
LK.showYouWin();
}, 500);
return;
}
// Spawn next target after a short delay
LK.setTimeout(function () {
self.spawnNextTarget();
}, 1000);
};
// Add function to spawn next target
self.spawnNextTarget = function () {
// Create a new target with the next character in sequence
var newTarget = new Target();
// Target will automatically use next character thanks to Target.currentCharacterIndex
newTarget.updateCharacterAsset();
self.targetContainer.addChild(newTarget);
self.targets.push(newTarget);
// Play sound based on new character
if (newTarget.character === 'chicken') {
LK.getSound('Chickencluck').play();
} else if (newTarget.character === 'piglinjockey') {
LK.getSound('Pignoise').play();
} else if (newTarget.character === 'spiderjockey') {
LK.getSound('Spider').play();
} else if (newTarget.character === 'steveridingpig') {
LK.getSound('Steve').play();
} else if (newTarget.character === 'vilagerjockey') {
LK.getSound('Villager').play();
} else if (newTarget.character === 'skeletonhorse') {
LK.getSound('Skeleton').play();
} else if (newTarget.character === 'Grimacejockey') {
LK.getSound('Grimace').play();
} else if (newTarget.character === 'Michaeljackson') {
LK.getSound('MJ').play();
} else if (newTarget.character === 'Johncena') {
LK.getSound('Johncena').play();
} else if (newTarget.character === 'Shootingstars') {
LK.getSound('Starz').play();
} else if (newTarget.character === 'Deeznuts') {
LK.getSound('Deeznuts').play();
} else if (newTarget.character === 'Rickroll') {
LK.getSound('Rickroll').play();
} else if (newTarget.character === 'Joenugget') {
LK.getSound('Joenugget').play();
} else if (newTarget.character === 'Shrekwizowski') {
LK.getSound('Shrek').play();
} else if (newTarget.character === 'Pomni') {
LK.getSound('Pomni').play();
}
};
// Spawn a new target at random position
self.spawnTarget = function () {
// Check if there's already an active target
var hasActiveTarget = false;
for (var i = 0; i < self.targets.length; i++) {
if (self.targets[i].active) {
hasActiveTarget = true;
break;
}
}
// Targets will be added one at a time from elsewhere, not automatically here
};
// Fire a bullet from gunslinger toward tap location
self.fireBullet = function (targetX, targetY) {
// Only fire if gun is drawn
if (!self.gunslingerContainer.isGunDrawn) return;
// Calculate firing position (top of gun)
var fireX = self.gunslingerContainer.x + 350; // Move right 350
var fireY = self.gunslingerContainer.y - 350; // Offset to top of gun, moved down 150 (-500 + 150 = -350)
// Calculate angle to target
var dx = targetX - fireX;
var dy = targetY - fireY;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
// Create bullet
var bullet = new Bullet();
bullet.init(fireX, fireY, angle);
self.addChild(bullet);
self.bullets.push(bullet);
// Show gunfire effect
var gunfire = LK.getAsset('Gunfire', {
anchorX: 0.5,
anchorY: 0.5,
x: fireX,
y: fireY,
alpha: 1.0,
scaleX: 0.8,
scaleY: 0.8
});
self.addChild(gunfire);
// Position gunfire at tip of gun and rotate to match bullet direction
gunfire.rotation = Math.atan2(dy, dx);
// Animate gunfire effect
tween(gunfire, {
alpha: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
if (gunfire.parent) {
gunfire.parent.removeChild(gunfire);
}
}
});
// Play gunshot sound
LK.getSound('Gunshot').play();
};
// Touch/mouse down on gunslinger
self.gunslingerContainer.down = function (x, y, obj) {
// Record starting position for swipe detection
self.gunslingerContainer.swipeStartY = y;
};
// Touch/mouse up on gunslinger
self.gunslingerContainer.up = function (x, y, obj) {
var swipeDistance = self.gunslingerContainer.swipeStartY - y;
// Check if swipe up and gun not drawn
if (swipeDistance > self.gunslingerContainer.swipeThreshold && !self.gunslingerContainer.isGunDrawn) {
// Switch to gundrawn asset
if (gunslinger && gunslinger.parent) {
gunslinger.parent.removeChild(gunslinger);
}
gunslinger = self.gunslingerContainer.attachAsset('Gundrawn', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.98,
alpha: 1.0
});
self.gunslingerContainer.isGunDrawn = true;
LK.getSound('pop').play();
}
// Check if swipe down and gun is drawn
else if (swipeDistance < -self.gunslingerContainer.swipeThreshold && self.gunslingerContainer.isGunDrawn) {
// Switch back to gunslinger asset
if (gunslinger && gunslinger.parent) {
gunslinger.parent.removeChild(gunslinger);
}
gunslinger = self.gunslingerContainer.attachAsset('Gunslinger', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.98,
alpha: 1.0
});
self.gunslingerContainer.isGunDrawn = false;
LK.getSound('pop').play();
}
};
// Screen taps for shooting targets
self.down = function (x, y, obj) {
// Only process if game is active
if (!self.gameActive) return;
// Only fire if gun is drawn
if (!self.gunslingerContainer.isGunDrawn) return;
// Allow shooting anywhere on the screen
self.fireBullet(x, y);
};
// Update function
self.update = function () {
if (self.gameActive) {
// No automatic spawning of targets - we'll add them one at a time externally
// Update targets
for (var i = self.targets.length - 1; i >= 0; i--) {
self.targets[i].update();
// Remove expired targets
if (!self.targets[i].active && self.targets[i].alpha <= 0) {
if (self.targets[i].parent) {
self.targets[i].parent.removeChild(self.targets[i]);
}
self.targets.splice(i, 1);
}
}
// Update bullets
for (var i = self.bullets.length - 1; i >= 0; i--) {
self.bullets[i].update();
// Remove bullets that have traveled too far
if (self.bullets[i].distanceTraveled > self.bullets[i].maxDistance) {
if (self.bullets[i].parent) {
self.bullets[i].parent.removeChild(self.bullets[i]);
}
self.bullets.splice(i, 1);
}
}
}
};
// Back button implementation removed from minigame scene
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 PathTracker = Container.expand(function () {
var self = Container.call(this);
// Path tracking properties
self.isTracking = false;
self.pathPoints = [];
self.sDetected = false;
self.starDetected = false; // Track if star pattern is detected
// Start tracking a new path
self.startTracking = function () {
self.isTracking = true;
self.pathPoints = [];
self.sDetected = false;
self.starDetected = false; // Reset star pattern detection
};
// Add a point to the tracking path
self.addPoint = function (x, y) {
if (!self.isTracking) {
return;
}
// Add point to path
self.pathPoints.push({
x: x,
y: y
});
// Check for patterns if we have enough points
if (self.pathPoints.length > 20) {
self.checkForSPattern();
self.checkForStarPattern(); // Also check for star pattern
}
};
// Stop tracking
self.stopTracking = function () {
self.isTracking = false;
// Return true if either S or star pattern was detected
return self.sDetected || self.starDetected;
};
// Check if the path forms an S pattern
self.checkForSPattern = function () {
if (self.pathPoints.length < 20) {
return false;
}
// Analyze path for S shape
// An S shape should go from top to bottom with two major direction changes
// Find bounding box of the path
var minX = self.pathPoints[0].x;
var maxX = self.pathPoints[0].x;
var minY = self.pathPoints[0].y;
var maxY = self.pathPoints[0].y;
for (var i = 1; i < self.pathPoints.length; i++) {
minX = Math.min(minX, self.pathPoints[i].x);
maxX = Math.max(maxX, self.pathPoints[i].x);
minY = Math.min(minY, self.pathPoints[i].y);
maxY = Math.max(maxY, self.pathPoints[i].y);
}
// Check if path has enough height and width to be an S
var width = maxX - minX;
var height = maxY - minY;
if (height < 300 || width < 200) {
return false;
}
// Divide path into vertical thirds
var topThird = minY + height / 3;
var bottomThird = maxY - height / 3;
// Count direction changes (left/right) in top, middle and bottom sections
var topSection = self.analyzeSection(self.pathPoints, minY, topThird);
var middleSection = self.analyzeSection(self.pathPoints, topThird, bottomThird);
var bottomSection = self.analyzeSection(self.pathPoints, bottomThird, maxY);
// For an S pattern, typically:
// - Top section has rightward movement
// - Middle section has leftward movement
// - Bottom section has rightward movement
if (topSection.direction === "right" && middleSection.direction === "left" && bottomSection.direction === "right") {
self.sDetected = true;
return true;
}
// Also check reverse S pattern
if (topSection.direction === "left" && middleSection.direction === "right" && bottomSection.direction === "left") {
self.sDetected = true;
return true;
}
return false;
};
// Check if the path forms a star pattern
self.checkForStarPattern = function () {
if (self.pathPoints.length < 20) {
return false;
}
// Analyze path for star shape
// Find the center point of all path points
var centerX = 0;
var centerY = 0;
for (var i = 0; i < self.pathPoints.length; i++) {
centerX += self.pathPoints[i].x;
centerY += self.pathPoints[i].y;
}
centerX /= self.pathPoints.length;
centerY /= self.pathPoints.length;
// A star pattern should have at least 5 peaks (points extending outward)
// and 5 valleys (points returning inward)
var peaks = [];
var valleys = [];
var distanceThreshold = 100; // Minimum peak distance from center
var minPeaks = 5; // Minimum number of peaks to be considered a star
// Calculate distance from center for each point
var distances = [];
for (var i = 0; i < self.pathPoints.length; i++) {
var dx = self.pathPoints[i].x - centerX;
var dy = self.pathPoints[i].y - centerY;
var distance = Math.sqrt(dx * dx + dy * dy);
distances.push(distance);
}
// Find peaks (local maxima) in the distance function
for (var i = 5; i < self.pathPoints.length - 5; i++) {
var isPeak = true;
var isValley = true;
// Check if this is a peak
for (var j = i - 5; j <= i + 5; j++) {
if (j === i) {
continue;
}
if (distances[j] > distances[i]) {
isPeak = false;
}
if (distances[j] < distances[i]) {
isValley = false;
}
}
// Add to peaks if it's far enough from center
if (isPeak && distances[i] > distanceThreshold) {
peaks.push(i);
}
// Add to valleys
if (isValley) {
valleys.push(i);
}
}
// For a star pattern, we need at least 5 peaks
if (peaks.length >= minPeaks) {
// Check that peaks are somewhat evenly distributed around the center
var angles = [];
for (var i = 0; i < peaks.length; i++) {
var idx = peaks[i];
var dx = self.pathPoints[idx].x - centerX;
var dy = self.pathPoints[idx].y - centerY;
var angle = Math.atan2(dy, dx);
if (angle < 0) {
angle += 2 * Math.PI;
} // Normalize to [0, 2π]
angles.push(angle);
}
// Sort angles
angles.sort(function (a, b) {
return a - b;
});
// Check for relatively even spacing between peaks
var isEvenlySpaced = true;
var idealSpacing = 2 * Math.PI / angles.length;
var spacingTolerance = idealSpacing * 0.5; // 50% tolerance
for (var i = 0; i < angles.length; i++) {
var nextIdx = (i + 1) % angles.length;
var spacing = angles[nextIdx] - angles[i];
if (spacing < 0) {
spacing += 2 * Math.PI;
}
if (Math.abs(spacing - idealSpacing) > spacingTolerance) {
isEvenlySpaced = false;
break;
}
}
// If we have enough peaks and they're evenly spaced, it's a star
if (isEvenlySpaced) {
self.starDetected = true;
return true;
}
}
return false;
};
// Analyze a section of the path for predominant horizontal direction
self.analyzeSection = function (points, minY, maxY) {
var leftwardMovement = 0;
var rightwardMovement = 0;
// Find points in this vertical section
var sectionPoints = [];
for (var i = 0; i < points.length; i++) {
if (points[i].y >= minY && points[i].y <= maxY) {
sectionPoints.push(points[i]);
}
}
// Sort points by y-coordinate
sectionPoints.sort(function (a, b) {
return a.y - b.y;
});
// Calculate horizontal movement through the section
for (var i = 1; i < sectionPoints.length; i++) {
var dx = sectionPoints[i].x - sectionPoints[i - 1].x;
if (dx > 0) {
rightwardMovement += dx;
} else if (dx < 0) {
leftwardMovement += Math.abs(dx);
}
}
return {
direction: rightwardMovement > leftwardMovement ? "right" : "left",
rightwardMovement: rightwardMovement,
leftwardMovement: leftwardMovement
};
};
return self;
});
var Popcorn = Container.expand(function () {
var self = Container.call(this);
// Create and attach popcorn asset
// Create and attach popcorn asset based on selected character
var popcornGraphics = self.attachAsset(selectedCharacter === "Joenugget" ? 'Drumstick' : selectedCharacter === "Grimacejockey" ? 'Shakes' : selectedCharacter === "Johncena" ? 'Belt' : selectedCharacter === "Shootingstars" ? 'Stars' : selectedCharacter === "Deeznuts" ? 'Nuts' : selectedCharacter === "Rickroll" ? 'Hearts' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Circuspop' : '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.updateAsset = function (assetName) {
if (popcornGraphics && popcornGraphics.parent) {
self.removeChild(popcornGraphics);
}
popcornGraphics = self.attachAsset(selectedCharacter === "Joenugget" ? 'Drumstick' : selectedCharacter === "Grimacejockey" ? 'Shakes' : selectedCharacter === "Johncena" ? 'Belt' : selectedCharacter === "Pomni" ? 'Circuspop' : assetName, {
anchorX: 0.5,
anchorY: 0.5
});
};
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;
}
// Ensure popcorn stays within the rope boundaries
var padding = 150; // Minimum distance from ropes
if (self.x < bounds.left + padding) {
self.x = bounds.left + padding;
self.targetX = self.x;
} else if (self.x > bounds.right - padding) {
self.x = bounds.right - padding;
self.targetX = self.x;
}
if (self.y < bounds.top + padding) {
self.y = bounds.top + padding;
self.targetY = self.y;
self.baseY = self.y;
} else if (self.y > bounds.bottom - padding) {
self.y = bounds.bottom - padding;
self.targetY = self.y;
self.baseY = self.y;
}
};
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 SlingshotLauncher = Container.expand(function () {
var self = Container.call(this);
// Create slingshot elements
var basePoint = self.attachAsset('launcher', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7,
scaleX: 1.5,
scaleY: 1.5
});
// Create elastic bands
var leftBand = self.attachAsset('aimLine', {
anchorX: 0,
anchorY: 0.5,
alpha: 0.8,
scaleY: 0.5,
tint: 0xFF0000
});
var rightBand = self.attachAsset('aimLine', {
anchorX: 0,
anchorY: 0.5,
alpha: 0.8,
scaleY: 0.5,
tint: 0xFF0000
});
// Hide bands initially
leftBand.alpha = 0;
rightBand.alpha = 0;
// Properties
self.aiming = false;
self.pullbackX = 0;
self.pullbackY = 0;
self.maxPullback = 300;
self.power = 0;
// Start aiming
self.startAim = function (x, y) {
self.aiming = true;
self.pullbackX = x;
self.pullbackY = y;
// Show elastic bands
leftBand.alpha = 0.8;
rightBand.alpha = 0.8;
// Update bands
self.updateBands(x, y);
};
// Update during aiming
self.updateAim = function (x, y) {
if (!self.aiming) return;
// Calculate distance from start point
var dx = x - self.x;
var dy = y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Limit pullback distance
if (distance > self.maxPullback) {
var ratio = self.maxPullback / distance;
dx *= ratio;
dy *= ratio;
x = self.x + dx;
y = self.y + dy;
}
// Save pullback position
self.pullbackX = x;
self.pullbackY = y;
// Calculate power based on distance
self.power = distance / 5;
// Update bands
self.updateBands(x, y);
};
// Update elastic bands
self.updateBands = function (x, y) {
// Position and angle for left band
leftBand.x = self.x - 25;
leftBand.y = self.y;
var dx1 = x - leftBand.x;
var dy1 = y - leftBand.y;
var angle1 = Math.atan2(dy1, dx1);
var dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
leftBand.rotation = angle1;
leftBand.width = dist1;
// Position and angle for right band
rightBand.x = self.x + 25;
rightBand.y = self.y;
var dx2 = x - rightBand.x;
var dy2 = y - rightBand.y;
var angle2 = Math.atan2(dy2, dx2);
var dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
rightBand.rotation = angle2;
rightBand.width = dist2;
};
// End aiming and launch
self.endAim = function () {
if (!self.aiming) return null;
self.aiming = false;
// Hide bands after launch
tween(leftBand, {
alpha: 0
}, {
duration: 200
});
tween(rightBand, {
alpha: 0
}, {
duration: 200
});
// Calculate launch vector - opposite of pullback
var dx = self.x - self.pullbackX;
var dy = self.y - self.pullbackY;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
// Return launch parameters
return {
angle: angle,
power: self.power,
path: null // No predefined path for slingshot mode
};
};
return self;
});
var Superpopcorn = Container.expand(function () {
var self = Container.call(this);
// Create and attach Superpopcorn asset
// Create and attach Superpopcorn asset based on selected character
var superPopcornGraphics = self.attachAsset(selectedCharacter === "Shootingstars" ? 'Whitestars' : selectedCharacter === "Deeznuts" ? 'Cashew' : selectedCharacter === "Rickroll" ? 'Purpleheart' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Digpop' : '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.updateAsset = function (assetName) {
if (superPopcornGraphics && superPopcornGraphics.parent) {
self.removeChild(superPopcornGraphics);
}
superPopcornGraphics = self.attachAsset(selectedCharacter === "Joenugget" ? 'Popchicken' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Digpop' : assetName, {
anchorX: 0.5,
anchorY: 0.5
});
};
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;
}
// Ensure superpopcorn stays within the rope boundaries
var padding = 150; // Minimum distance from ropes
if (self.x < bounds.left + padding) {
self.x = bounds.left + padding;
self.targetX = self.x;
} else if (self.x > bounds.right - padding) {
self.x = bounds.right - padding;
self.targetX = self.x;
}
if (self.y < bounds.top + padding) {
self.y = bounds.top + padding;
self.targetY = self.y;
self.baseY = self.y;
} else if (self.y > bounds.bottom - padding) {
self.y = bounds.bottom - padding;
self.targetY = self.y;
self.baseY = self.y;
}
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
// Array of characters to use as targets in order of appearance
var characters = ['chicken', 'piglinjockey', 'spiderjockey', 'steveridingpig', 'vilagerjockey', 'skeletonhorse', 'Grimacejockey', 'Michaeljackson', 'Johncena', 'Shootingstars', 'Deeznuts', 'Rickroll', 'Joenugget', 'Shrekwizowski', 'Pomni'];
// Use a static counter to cycle through characters in sequence rather than randomly
if (typeof Target.currentCharacterIndex === 'undefined') {
Target.currentCharacterIndex = 0;
}
// Get the next character in sequence and increment counter
var characterToUse = characters[Target.currentCharacterIndex];
Target.currentCharacterIndex = (Target.currentCharacterIndex + 1) % characters.length;
// Create character graphics as a placeholder (will be updated in updateCharacterAsset)
var characterGraphics;
// Properties
self.active = true;
self.lifespan = 3000; // 3 seconds
self.created = LK.ticks;
self.character = characterToUse;
self.movementSpeed = 5;
self.startPosition = {
x: 0,
y: 0
};
self.targetPosition = {
x: 0,
y: 0
};
self.isMoving = false;
// Function to update character asset with appropriate behavior
self.updateCharacterAsset = function () {
// Remove existing character graphic if it exists
if (characterGraphics && characterGraphics.parent) {
self.removeChild(characterGraphics);
}
// Attach new asset with different properties based on character
characterGraphics = self.attachAsset(self.character, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: self.character === 'Joenugget' ? 0.8 : 0.5,
scaleY: self.character === 'Joenugget' ? 0.8 : 0.5
});
// Set up character appearance based on character type
if (self.character === 'Joenugget') {
// Joe Nugget starts from right side in middle and walks to center
self.x = 2048 + 250; // Start off-screen to the right
self.y = 1650; // 50px higher than before (from 1700 to 1650)
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: 1024,
y: self.y
}; // Move to center
self.isMoving = true;
self.movementSpeed = 1; // Even slower movement speed for Joe Nugget
// Add bob animation for Joe Nugget to make it look like walking
var originalY = self.y;
tween(characterGraphics, {
y: -20 // Move up more for more visible bobbing
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(characterGraphics, {
y: 10 // Move down below center point for more natural walking motion
}, {
duration: 500,
easing: tween.easeInOut,
repeat: -1,
yoyo: true // Continuously bob up and down
});
}
});
} else if (self.character === 'spiderjockey') {
// Spider jockey appears in middle of screen and moves downwards
self.x = 1024; // Center of screen horizontally
self.y = 1024; // Start higher on screen
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
// Stay centered horizontally
y: 1800 // Move down to lower part of screen
};
self.isMoving = true;
self.movementSpeed = 2; // Slow movement speed
// Add slight animation for spider to make it look like moving
tween(characterGraphics, {
y: -10 // Bobbing up
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(characterGraphics, {
y: 10 // Bobbing down
}, {
duration: 600,
easing: tween.easeInOut,
repeat: -1,
yoyo: true // Continuously bob up and down
});
}
});
} else if (self.character === 'Grimacejockey') {
// Grimace jockey starts from 300px right and 200px down of left centre of screen and walks right across
self.x = 300; // Start 300px right of the left edge
self.y = 1366 + 200; // 200px down from middle of screen vertically
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: 2048 - 400,
// Move to 400px from right of screen instead of off-screen
y: self.y
};
self.isMoving = true;
self.movementSpeed = 3; // Moderate movement speed
// Add bob animation for Grimace to make it look like walking
tween(characterGraphics, {
y: -15 // Bobbing up
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(characterGraphics, {
y: 15 // Bobbing down
}, {
duration: 500,
easing: tween.easeInOut,
repeat: -1,
yoyo: true // Continuously bob up and down
});
}
});
} else if (self.character === 'chicken') {
// Chicken flies from top of screen to random lower position
self.x = Math.random() * 1600 + 224; // Random x between 224-1824
self.y = -100; // Start above screen
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: Math.random() * 500 + 400
}; // Random y between 400-900
self.isMoving = true;
self.movementSpeed = 8; // Faster movement
} else if (self.character === 'piglinjockey') {
// Piglin jockey appears at left bottom of screen and move right slowly across the screen
self.x = 200; // Start at left side of screen
self.y = 2200; // Bottom of screen
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: 2048 - 200,
// Move to right side of screen (with small margin)
y: self.y // Stay at the same height
}; // Move across screen
self.isMoving = true;
self.movementSpeed = 3; // Slower movement speed
} else if (self.character === 'Michaeljackson') {
// MJ appears slightly left of center of screen
self.x = 1024 - 150; // 150 left from center of screen
self.y = 1366; // Middle of screen
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: self.y
}; // Stay at the offset position
self.isMoving = false;
self.movementSpeed = 0; // Not moving
// Make MJ head smaller by using a smaller scale
characterGraphics.scaleX = 0.35;
characterGraphics.scaleY = 0.35;
} else if (self.character === 'Rickroll') {
// Add rickroll appears at offset from center of screen
self.x = 1024 + 600; // 600 pixels right from center of screen horizontally
self.y = 1366 + 100; // 100 pixels down from middle of screen
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: self.y
}; // Stay at offset position
self.isMoving = false;
self.movementSpeed = 0; // Not moving
// Make Rickroll character smaller
characterGraphics.scaleX = 0.25;
characterGraphics.scaleY = 0.25;
} else if (self.character === 'steveridingpig') {
// Steveridingpig appears at center of the screen
self.x = 1024; // Center of screen horizontally
self.y = 1366; // Center of screen vertically
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: self.y
}; // Stay at center position
self.isMoving = false;
self.movementSpeed = 0; // Not moving
// Set appropriate scale for steveridingpig
characterGraphics.scaleX = 0.5;
characterGraphics.scaleY = 0.5;
} else if (self.character === 'Pomni') {
// Pomni appears at center of the screen and 150 down
self.x = 1024; // Center of screen horizontally
self.y = 1366 + 150; // 150 down from center of screen vertically
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: self.y
}; // Stay at offset position
self.isMoving = false;
self.movementSpeed = 0; // Not moving
// Set appropriate scale for Pomni
characterGraphics.scaleX = 0.4;
characterGraphics.scaleY = 0.4;
} else if (self.character === 'Shootingstars') {
// Shootingstars starts at the top of the minigame scene
self.centerX = Math.random() * 1200 + 424; // Center of circle, avoid edges
self.centerY = Math.random() * 400 + 700; // Center of circle, mid screen
self.radius = 250 + Math.random() * 100; // Circle radius
self.angle = 0; // Current angle in radians
self.angularSpeed = 0.035 + Math.random() * 0.01; // Radians per frame
self.x = self.centerX + self.radius * Math.cos(self.angle);
self.y = self.centerY + self.radius * Math.sin(self.angle);
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: self.y
};
self.isMoving = true;
self.movementSpeed = 0; // Not used for circular movement
} else if (self.character === 'Shrekwizowski') {
// Shrek appears in center and grows
self.x = 1024; // Center x
self.y = 1366; // Center y
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: self.y
}; // Doesn't move
characterGraphics.scaleX = 0.1;
characterGraphics.scaleY = 0.1;
// Grow animation
tween(characterGraphics, {
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
easing: tween.easeOut
});
self.isMoving = false;
} else {
// Default: appear at random position on screen
self.x = Math.random() * 1600 + 224; // Random x between 224-1824
self.y = Math.random() * 1200 + 500; // Random y between 500-1700
self.startPosition = {
x: self.x,
y: self.y
};
self.targetPosition = {
x: self.x,
y: self.y
}; // Doesn't move
self.isMoving = false;
// Add a small zoom-in animation for appearance
characterGraphics.scaleX = 0.3;
characterGraphics.scaleY = 0.3;
tween(characterGraphics, {
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
easing: tween.easeOut
});
}
};
// Initialize with the chosen character
self.updateCharacterAsset();
// Hit function - called when target is hit by a bullet
self.hit = function () {
if (!self.active) return;
self.active = false;
// Animate hit
tween(self, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
// Notify game of hit
if (typeof game.onTargetHit === 'function') {
game.onTargetHit(self);
}
};
// Update function
self.update = function () {
// Move character if it's still moving
if (self.isMoving && self.active) {
if (self.character === 'Shootingstars') {
// Move in a circle
self.angle += self.angularSpeed;
if (self.angle > Math.PI * 2) self.angle -= Math.PI * 2;
self.x = self.centerX + self.radius * Math.cos(self.angle);
self.y = self.centerY + self.radius * Math.sin(self.angle);
} else {
// Calculate direction to target
var dx = self.targetPosition.x - self.x;
var dy = self.targetPosition.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Move towards target
if (distance > self.movementSpeed) {
self.x += dx / distance * self.movementSpeed;
self.y += dy / distance * self.movementSpeed;
} else {
// Reached destination
self.x = self.targetPosition.x;
self.y = self.targetPosition.y;
self.isMoving = false;
}
}
}
// Check if lifetime expired
if (LK.ticks - self.created > self.lifespan && self.active) {
// Disappear
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
self.active = false;
}
};
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
});
// Make title screen tappable to unlock Grimace
titleBackground.down = function (x, y, obj) {
grimaceTaps++;
if (grimaceTaps === 5 && !grimaceUnlocked) {
grimaceUnlocked = true;
storage.grimaceUnlocked = true;
// Play Maccas sound when Grimace is unlocked
LK.getSound('Maccas').play();
// Update character buttons to remove padlock from Grimace and MJ if unlocked
updateCharacterButtons();
// Create unlocked notification using grimaceunlocked asset
var grimaceUnlockedMsg = LK.getAsset('Grimaceunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 0.8,
scaleY: 0.8
});
// Replace grimacejockey with grimaceunlocked asset when unlocked
if (characterSelectPage) {
for (var i = 0; i < characterSelectPage.characters.length; i++) {
var character = characterSelectPage.characters[i];
if (character.asset === "Grimacejockey" && characterSelectPage.characterButtons.children[i]) {
var button = characterSelectPage.characterButtons.children[i];
// Remove existing character image
for (var j = 0; j < button.children.length; j++) {
if (button.children[j].assetId === "Grimacejockey") {
button.removeChild(button.children[j]);
break;
}
}
// Add grimaceunlocked asset instead
var grimaceImg = button.attachAsset('Grimaceunlocked', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
}
}
}
game.addChild(grimaceUnlockedMsg);
// Animate and remove the notification
tween(grimaceUnlockedMsg, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(grimaceUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (grimaceUnlockedMsg.parent) {
grimaceUnlockedMsg.parent.removeChild(grimaceUnlockedMsg);
}
}
});
}, 500);
}
});
}
};
// Add unlock progress text
// Create start button
self.startButton = new Container();
self.startButton.x = 1024;
self.startButton.y = 1650;
// 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) {
// Play pop sound
LK.getSound('pop').play();
// 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) {
// Play pop sound
LK.getSound('pop').play();
// 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, gameModeSelect, characterSelect, ready, aiming, launched, gameOver, highScores, minigames
var gameMode = "classic"; // classic or bonus
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;
var gameModeSelectPage = null;
var characterSelectPage = null;
var miniGamesPage = null;
var selectedCharacter = "chicken"; // Default character
var pathTracker = new PathTracker(); // Add path tracker for S detection
var skeletonUnlocked = false; // Track if skeleton has been unlocked through S pattern
var grimaceTaps = 0; // Counter for taps on title screen
var grimaceUnlocked = false; // Track if Grimace character is unlocked
// Function to update character buttons when a character is unlocked
function updateCharacterButtons() {
if (characterSelectPage) {
for (var i = 0; i < characterSelectPage.characters.length; i++) {
var character = characterSelectPage.characters[i];
if (character.asset === "Grimacejockey" && grimaceUnlocked && characterSelectPage.characterButtons.children[i].lockedImg) {
characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg);
}
if (character.asset === "Michaeljackson" && storage.mjUnlocked && characterSelectPage.characterButtons.children[i].lockedImg) {
characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg);
// Show MJ unlocked asset when MJ is unlocked
var mjUnlockedMsg = LK.getAsset('MJunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(mjUnlockedMsg);
// Animate and remove the notification
tween(mjUnlockedMsg, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(mjUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (mjUnlockedMsg.parent) {
mjUnlockedMsg.parent.removeChild(mjUnlockedMsg);
}
}
});
}, 500);
}
});
}
if (character.asset === "Johncena" && storage.johnCenaUnlocked && characterSelectPage.characterButtons.children[i].lockedImg) {
characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg);
// Show John Cena unlocked asset when John Cena is unlocked
var johncenaUnlockedMsg = LK.getAsset('Johncenaunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(johncenaUnlockedMsg);
// Animate and remove the notification
tween(johncenaUnlockedMsg, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(johncenaUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (johncenaUnlockedMsg.parent) {
johncenaUnlockedMsg.parent.removeChild(johncenaUnlockedMsg);
}
}
});
}, 500);
}
});
}
}
}
// Check if Rickroll should be unlocked (when all other characters are unlocked)
if (!storage.rickrollUnlocked) {
// Check if all other characters are unlocked, excluding Joe Nugget
var allCharactersUnlocked = storage.steveUnlocked && storage.piglinUnlocked && storage.villagerUnlocked && storage.spiderUnlocked && storage.skeletonUnlocked && storage.grimaceUnlocked && storage.mjUnlocked && storage.johnCenaUnlocked && storage.shootingStarsUnlocked && storage.deezNutsUnlocked;
storage.allCharactersUnlocked = allCharactersUnlocked;
if (allCharactersUnlocked) {
storage.rickrollUnlocked = true;
// Play rickroll sound when rickroll character is unlocked
LK.getSound('Rickroll').play();
// Create unlocked notification using Rickroll unlocked asset
var rickrollUnlockedMsg = LK.getAsset('Rickrollunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(rickrollUnlockedMsg);
// If character select page exists, remove padlock from Rickroll character
if (characterSelectPage) {
for (var i = 0; i < characterSelectPage.characters.length; i++) {
var character = characterSelectPage.characters[i];
if (character.asset === "Rickroll" && characterSelectPage.characterButtons.children[i].lockedImg) {
characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg);
}
}
}
// Animate and remove the notification
tween(rickrollUnlockedMsg, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(rickrollUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (rickrollUnlockedMsg.parent) {
rickrollUnlockedMsg.parent.removeChild(rickrollUnlockedMsg);
}
}
});
}, 500);
}
});
}
}
}
// 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 arenaAsset = selectedCharacter === "Shootingstars" ? 'Space' : 'arena';
if (arena && arena.parent) {
arena.parent.removeChild(arena);
}
var arenaAsset = selectedCharacter === "Joenugget" ? 'Jnugbackdrop' : selectedCharacter === "Shootingstars" ? 'Space' : 'arena';
var arena = game.addChild(LK.getAsset(arenaAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: selectedCharacter === "Shootingstars" ? 1 : 1,
scaleY: selectedCharacter === "Shootingstars" ? 1 : 1
}));
// Add slow rotation to hyperspace when in bonus mode
if (gameMode === "bonus") {
tween(arena, {
rotation: Math.PI * 2
}, {
duration: 60000,
// Complete one full rotation in 60 seconds
repeat: -1,
// Infinite repetition
onRepeat: function onRepeat() {
// Reset rotation to avoid potential issues after multiple rotations
arena.rotation = 0;
}
});
}
// 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.x = 100; // Move text right 50 more pixels
instructionText.y = 180;
LK.gui.top.addChild(instructionText);
// Initialize game
function initGame() {
// Check if MJ should be unlocked when played 20 times
if (!storage.mjUnlocked && storage.gamePlays >= 20) {
storage.mjUnlocked = true;
// Play MJ sound when MJ is unlocked
LK.getSound('MJ').play();
// Show MJ unlocked asset when MJ is unlocked
var mjUnlockedMsg = LK.getAsset('MJunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(mjUnlockedMsg);
// Animate and remove the notification
tween(mjUnlockedMsg, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(mjUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (mjUnlockedMsg.parent) {
mjUnlockedMsg.parent.removeChild(mjUnlockedMsg);
}
}
});
}, 500);
}
});
}
// Check if John Cena should be unlocked when played 30 times
if (!storage.johnCenaUnlocked && storage.gamePlays >= 30) {
storage.johnCenaUnlocked = true;
// Play John Cena entrance sound when John Cena is unlocked
LK.getSound('Johncena').play();
// Create unlocked notification using John Cena unlocked asset
var cenaUnlockedMsg = LK.getAsset('Johncenaunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(cenaUnlockedMsg);
// Animate and remove the notification
tween(cenaUnlockedMsg, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(cenaUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (cenaUnlockedMsg.parent) {
cenaUnlockedMsg.parent.removeChild(cenaUnlockedMsg);
}
}
});
}, 500);
}
});
}
// Reset variables
score = 0;
launches = 0;
gameState = "title";
bonusApplied = false;
skeletonUnlocked = storage.skeletonUnlocked || false;
storage.deezNutsUnlocked = true;
grimaceUnlocked = storage.grimaceUnlocked || 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 your character!");
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 game mode select page if it doesn't exist
if (!gameModeSelectPage) {
gameModeSelectPage = new GameModeSelect();
// Keep it detached until needed
}
// Initialize mini games page if it doesn't exist
if (!miniGamesPage) {
miniGamesPage = new MiniGamesPage();
// 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 () {
// Track game plays in storage
storage.gamePlays = (storage.gamePlays || 0) + 1;
// Check if Steve should be unlocked (after 3 plays)
if (storage.gamePlays >= 3 && storage.steveUnlocked !== true) {
storage.steveUnlocked = true;
// Play Steve sound when Steve is unlocked
LK.getSound('Steve').play();
// Immediately remove padlock for Steve
if (characterSelectPage) {
for (var i = 0; i < characterSelectPage.characters.length; i++) {
var character = characterSelectPage.characters[i];
if (character.asset === "steveridingpig" && characterSelectPage.characterButtons.children[i].lockedImg) {
characterSelectPage.characterButtons.children[i].lockedImg.parent.removeChild(characterSelectPage.characterButtons.children[i].lockedImg);
}
}
}
// Create unlocked notification using steveunlocked asset instead of text
var unlockedMsg = LK.getAsset('Steveunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(unlockedMsg);
// Animate and remove the notification
tween(unlockedMsg, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
tween(unlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (unlockedMsg.parent) {
unlockedMsg.parent.removeChild(unlockedMsg);
}
}
});
}
});
}
// Hide title page
tween(titlePage, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (titlePage.parent) {
titlePage.parent.removeChild(titlePage);
}
// Show game mode selection page instead of character select
game.addChild(gameModeSelectPage);
gameModeSelectPage.alpha = 0;
tween(gameModeSelectPage, {
alpha: 1
}, {
duration: 500
});
// Set game state
gameState = "gameModeSelect";
}
});
};
// 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 game mode selection handler
game.onGameModeSelected = function (mode, backgroundOnly) {
// Store selected game mode
gameMode = mode;
// Hide game mode select page
tween(gameModeSelectPage, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
if (gameModeSelectPage.parent) {
gameModeSelectPage.parent.removeChild(gameModeSelectPage);
}
// Check if minigames mode was selected
if (mode === "minigames") {
// Set game state to minigames
gameState = "minigames";
// Show mini games page
game.addChild(miniGamesPage);
miniGamesPage.alpha = 0;
tween(miniGamesPage, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
// Store reference to targets and update handler for bullet-target collision
game.targets = miniGamesPage.targets;
game.onTargetHit = function (target) {
miniGamesPage.onTargetHit(target);
};
}
});
return;
}
// Set game state
gameState = "characterSelect";
// Update instruction text based on selected mode
if (mode === "bonus") {
// Change background for bonus mode
if (arena && arena.parent) {
arena.parent.removeChild(arena);
}
arena = game.addChild(LK.getAsset('Hyperspace', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1,
scaleY: 1
}));
// Add slow rotation to hyperspace
tween(arena, {
rotation: Math.PI * 2
}, {
duration: 60000,
repeat: -1,
onRepeat: function onRepeat() {
arena.rotation = 0;
}
});
// Ensure arena is behind other elements
if (chickenJockey.parent) {
chickenJockey.parent.removeChild(chickenJockey);
}
game.addChild(chickenJockey);
}
// Only show character select page after bonus mode setup is complete
LK.setTimeout(function () {
game.addChild(characterSelectPage);
characterSelectPage.alpha = 0;
tween(characterSelectPage, {
alpha: 1
}, {
duration: 500
});
}, 100); // Short delay to ensure background is properly applied
}
});
};
// Add handler for character selected handler
game.onCharacterSelected = function (characterAsset) {
// Store selected character
selectedCharacter = characterAsset;
// Replace arena with space asset when Shooting Stars character is selected or in bonus mode
if (arena && arena.parent) {
arena.parent.removeChild(arena);
}
var arenaAsset;
if (gameMode === "bonus") {
// Use Hyperspace in bonus mode regardless of character
arenaAsset = 'Hyperspace';
} else {
arenaAsset = selectedCharacter === "Joenugget" ? 'Jnugbackdrop' : selectedCharacter === "Shootingstars" || selectedCharacter === "Deeznuts" ? 'Space' : selectedCharacter === "Shrekwizowski" ? 'Swamp' : selectedCharacter === "Pomni" ? 'Digcircus' : selectedCharacter === "Michaeljackson" ? 'MJbackground' : 'arena';
}
arena = game.addChild(LK.getAsset(arenaAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1,
scaleY: 1
}));
// Start slow rotation if in bonus mode
if (gameMode === "bonus") {
tween(arena, {
rotation: Math.PI * 2
}, {
duration: 60000,
repeat: -1,
onRepeat: function onRepeat() {
arena.rotation = 0;
}
});
// Ensure that 5 superpopcorn are immediately created for the first launch in bonus mode
createSuperPopcorn(5);
}
// Update chicken jockey with selected character and make sure it's in front
chickenJockey.updateCharacterAsset(selectedCharacter);
// Ensure chicken jockey is on top by removing and re-adding it
if (chickenJockey.parent) {
chickenJockey.parent.removeChild(chickenJockey);
}
game.addChild(chickenJockey);
// Only add character-specific backdrops in non-bonus mode
if (gameMode !== "bonus") {
if (selectedCharacter === "Deeznuts") {
var spaceLevel = LK.getAsset('Spacelevel', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(spaceLevel);
game.addChild(chickenJockey); // Ensure DeezNuts character is on top
}
// Add rickbackdrop when Rickroll character is selected
if (selectedCharacter === "Rickroll") {
var rickbackdrop = LK.getAsset('Rickbackdrop', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(rickbackdrop);
// Make sure it's behind the chicken jockey
if (chickenJockey.parent) {
chickenJockey.parent.removeChild(chickenJockey);
}
game.addChild(chickenJockey);
}
}
// Update popcorn asset for existing popcorns
var popcornAsset = selectedCharacter === "Grimacejockey" ? 'Shakes' : selectedCharacter === "Johncena" ? 'Belt' : selectedCharacter === "Shootingstars" ? 'Stars' : selectedCharacter === "Deeznuts" ? 'Nuts' : selectedCharacter === "Rickroll" ? 'Hearts' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : selectedCharacter === "Pomni" ? 'Circuspop' : 'popcorn';
for (var i = 0; i < popcorns.length; i++) {
popcorns[i].updateAsset(popcornAsset);
}
var superPopcornAsset = selectedCharacter === "Shootingstars" ? 'Whitestars' : selectedCharacter === "Deeznuts" ? 'Cashew' : selectedCharacter === "Rickroll" ? 'Purpleheart' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Popshrek' : selectedCharacter === "Pomni" ? 'Digpop' : 'Superpopcorn';
for (var i = 0; i < superPopcorns.length; i++) {
superPopcorns[i].updateAsset(superPopcornAsset);
}
// Play character-specific sounds
if (selectedCharacter === "piglinjockey") {
LK.getSound('Pignoise').play();
} else if (selectedCharacter === "steveridingpig") {
LK.getSound('Steve').play();
} else if (selectedCharacter === "vilagerjockey") {
LK.getSound('Villager').play();
} else if (selectedCharacter === "spiderjockey") {
LK.getSound('Spider').play();
} else if (selectedCharacter === "skeletonhorse") {
LK.getSound('Skeleton').play();
} else if (selectedCharacter === "Grimacejockey") {
LK.getSound('Grimace').play();
} else if (selectedCharacter === "Michaeljackson") {
LK.getSound('MJ').play();
// Thriller music will be played in startGamePlay() function
//Removed duplicate music initialization here
} else if (selectedCharacter === "Johncena") {
LK.getSound('Johncena').play();
// Play John Cena entrance music during gameplay when John Cena character is selected
LK.playMusic('Cenaentrance');
} else if (selectedCharacter === "Deeznuts") {
LK.getSound('Deeznuts').play();
LK.playMusic('Deeznutstrap');
} else if (selectedCharacter === "Shootingstars") {
LK.playMusic('Shootingstars');
} else if (selectedCharacter === "Joenugget") {
LK.getSound('Joenugget').play();
} else if (selectedCharacter === "Rickroll") {
LK.getSound('Rickroll').play();
} else if (selectedCharacter === "Shrekwizowski") {
LK.getSound('Shrek').play();
} else if (selectedCharacter === "Pomni") {
LK.getSound('Pomni').play();
} else {
// Play default game music for other characters
LK.playMusic('gameMusic');
}
// Add handler for character select reset
game.onCharacterSelectReset = function () {
// Remove current character select page
if (characterSelectPage && characterSelectPage.parent) {
characterSelectPage.parent.removeChild(characterSelectPage);
}
// Create new character select page with reset unlocks
characterSelectPage = new CharacterSelect();
game.addChild(characterSelectPage);
};
// 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;
// Update instructions based on game mode
if (gameMode === "bonus") {
instructionText.setText("Pull back and release to slingshot your character!");
// Replace path launcher with slingshot launcher in bonus mode
if (launcher && launcher.parent) {
launcher.parent.removeChild(launcher);
}
launcher = game.addChild(new SlingshotLauncher());
launcher.x = chickenJockey.x;
launcher.y = chickenJockey.y;
launcher.alpha = 0; // Make launcher invisible in bonus mode
} else {
instructionText.setText("**Hidden character** Tap 5 popcorn in title screen to unlock.");
}
// Clear existing popcorn and ropes
clearPopcornsAndRopes();
// Create ropes around the arena
createRopes();
// Create popcorn scattered around the arena - only in classic mode
if (gameMode !== "bonus") {
createPopcorn(15); // Regular amount in classic mode
}
// Add trajectory path to game if not in bonus mode
if (gameMode !== "bonus" && launcher.trajectoryPath) {
game.addChild(launcher.trajectoryPath);
}
// Play background music based on selected character
if (selectedCharacter === "Michaeljackson") {
LK.playMusic('Thriller');
} else if (selectedCharacter === "Johncena") {
LK.playMusic('Cenaentrance');
} else if (selectedCharacter === "Shootingstars") {
LK.playMusic('Shootingstars');
} else if (selectedCharacter === "Rickroll") {
LK.playMusic('Nevergonna');
} else if (selectedCharacter === "Grimacejockey") {
LK.playMusic('Grimaceshake');
} else if (selectedCharacter === "Joenugget") {
LK.playMusic('gegagedi');
} else if (selectedCharacter === "Shrekwizowski") {
LK.playMusic('Raveswamp');
} else if (selectedCharacter === "Pomni") {
LK.playMusic('Digcircus');
} else if (selectedCharacter !== "Deeznuts") {
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 - (selectedCharacter === "Michaeljackson" ? 150 : 0) + (selectedCharacter === "Michaeljackson" ? 300 : 0);
chickenJockey.y = selectedCharacter === "Michaeljackson" ? arena.y - 670 : arena.y - 400;
// 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() {
// Skip rope creation in bonus mode
if (gameMode === "bonus") {
return;
}
// Position ropes at edge of screen if using MJBackground
var isMJBackground = selectedCharacter === "Michaeljackson";
var edgeOffset = isMJBackground ? 0 : 100;
// Create top rope
var topRope = new Rope();
topRope.x = arena.x;
topRope.y = bounds.top + edgeOffset;
game.addChild(topRope);
ropes.push(topRope);
// Create right rope
var rightRope = new Rope();
rightRope.x = bounds.right - edgeOffset;
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 - edgeOffset;
game.addChild(bottomRope);
ropes.push(bottomRope);
// Create left rope
var leftRope = new Rope();
leftRope.x = bounds.left + edgeOffset;
leftRope.y = arena.y;
leftRope.rotation = Math.PI / 2; // Rotate 90 degrees
game.addChild(leftRope);
ropes.push(leftRope);
// If MJ background, animate ropes to make them more visible
if (isMJBackground) {
for (var i = 0; i < ropes.length; i++) {
// Flash the ropes slightly to make them more visible against MJ background
tween(ropes[i], {
alpha: 0.7
}, {
duration: 300,
onFinish: function onFinish() {
tween(this, {
alpha: 1
}, {
duration: 300
});
}
});
}
}
}
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
// Determine the correct popcorn asset based on the selected character
var popcornAsset = selectedCharacter === "Joenugget" ? 'Drumstick' : 'popcorn'; // Default asset
if (selectedCharacter === "Grimacejockey") {
popcornAsset = 'Shakes';
} else if (selectedCharacter === "Johncena") {
popcornAsset = 'Belt'; // Ensure Belt is used for John Cena
} else if (selectedCharacter === "Shootingstars") {
popcornAsset = 'Stars';
} else if (selectedCharacter === "Deeznuts") {
popcornAsset = 'Nuts';
} else if (selectedCharacter === "Rickroll") {
popcornAsset = 'Hearts';
}
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();
// Update asset based on selected character
popcorn.updateAsset(popcornAsset);
// 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();
// Update asset based on selected character
var superPopcornAsset = selectedCharacter === "Joenugget" ? 'Popchicken' : selectedCharacter === "Shootingstars" ? 'Whitestars' : selectedCharacter === "Deeznuts" ? 'Cashew' : selectedCharacter === "Rickroll" ? 'Purpleheart' : selectedCharacter === "Grimacejockey" ? 'Fries' : selectedCharacter === "Johncena" ? 'Wwe' : selectedCharacter === "Shrekwizowski" ? 'Shrekcorn' : 'Superpopcorn';
superPopcorn.updateAsset(superPopcornAsset);
// 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";
// Check if all popcorn is collected to apply X5 bonus
// Make sure we check for empty popcorns array at the exact moment the chicken stops
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 character-specific sounds for X5 bonus
if (selectedCharacter === "Shootingstars") {
// No sound for Shooting Stars
} else if (selectedCharacter === "piglinjockey") {
LK.getSound('Pignoise').play();
} else if (selectedCharacter === "steveridingpig") {
LK.getSound('Steve').play();
} else if (selectedCharacter === "vilagerjockey") {
LK.getSound('Villager').play();
} else if (selectedCharacter === "spiderjockey") {
LK.getSound('Spider').play();
} else if (selectedCharacter === "skeletonhorse") {
LK.getSound('Skeleton').play();
} else if (selectedCharacter === "Grimacejockey") {
LK.getSound('Grimace').play();
} else if (selectedCharacter === "Michaeljackson") {
LK.getSound('MJ').play();
} else if (selectedCharacter === "Deeznuts") {
LK.getSound('Deeznuts').play();
} else if (selectedCharacter === "Rickroll") {
LK.getSound('Rickroll').play();
} else if (selectedCharacter === "Joenugget") {
LK.getSound('Joenugget').play();
} else if (selectedCharacter === "Johncena") {
LK.getSound('Johncena').play();
} else if (selectedCharacter === "Shrekwizowski") {
LK.getSound('Shrek').play();
} else if (selectedCharacter === "Pomni") {
LK.getSound('Pomni').play();
} else {
LK.getSound('Bogerk').play();
}
// Create X5 animation
bonusAnimation = LK.getAsset('X5', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1.5,
scaleY: 1.5,
alpha: 1
});
game.addChild(bonusAnimation);
// Animate the X5 bonus
tween(bonusAnimation, {
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 700,
easing: tween.bounceOut,
onFinish: function onFinish() {
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();
} else if (popcorns.length === 0 && superPopcorns.length === 0) {
// Reset bonus status for next round if all popcorn is collected but bonus was already applied
bonusApplied = false;
}
// Check if score has reached 1000000 to unlock villager character
if (score >= 1000000 && !storage.villagerUnlocked) {
storage.villagerUnlocked = true;
// Play Villager sound when Villager is unlocked
LK.getSound('Villager').play();
// Create unlocked notification using villagerunlocked asset instead of text
var villagerUnlockedMsg = LK.getAsset('Villagerunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(villagerUnlockedMsg);
// Animate and remove the notification
tween(villagerUnlockedMsg, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
// Play Chicken sound to acknowledge unlock
LK.getSound('Chickencluck').play();
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(villagerUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (villagerUnlockedMsg.parent) {
villagerUnlockedMsg.parent.removeChild(villagerUnlockedMsg);
}
}
});
}, 500);
}
});
}
// Check if score has reached 10,000,000 to unlock spider character
if (score >= 10000000 && !storage.spiderUnlocked) {
storage.spiderUnlocked = true;
// Play Spider sound to acknowledge unlock
LK.getSound('Spider').play();
// Create unlocked notification using spiderjockeyunlocked asset instead of text
var spiderUnlockedMsg = LK.getAsset('Spiderjockeyunlocked', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(spiderUnlockedMsg);
// Animate and remove the notification
tween(spiderUnlockedMsg, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
// Play Chicken sound to acknowledge unlock
LK.getSound('Chickencluck').play();
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(spiderUnlockedMsg, {
alpha: 0
}, {
delay: 1000,
duration: 500,
onFinish: function onFinish() {
if (spiderUnlockedMsg.parent) {
spiderUnlockedMsg.parent.removeChild(spiderUnlockedMsg);
}
}
});
}, 500);
}
});
}
// 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 all popcorn for a X5 bonus!");
}
};
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" || gameState === "gameModeSelect" || gameState === "minigames") {
// Title page, high scores, game mode select, mini games and character select interactions are handled by their respective classes
return;
}
if (gameState === "ready") {
gameState = "aiming";
dragStartX = x;
dragStartY = y;
// Use appropriate aiming method based on game mode
if (gameMode === "bonus") {
// In bonus mode, aim from character position
launcher.startAim(chickenJockey.x, chickenJockey.y);
} else {
// In classic mode, use path drawing
launcher.startAim(x, y);
}
}
};
game.move = function (x, y, obj) {
if (gameState === "title" || gameState === "highScores" || gameState === "characterSelect" || gameState === "gameModeSelect" || gameState === "minigames") {
// Title page, high scores, game mode select, mini games and character select interactions are handled by their respective classes
return;
}
if (gameState === "aiming") {
// Use appropriate aiming method based on game mode
launcher.updateAim(x, y);
// In bonus mode, move the character to the slingshot pullback position
if (gameMode === "bonus" && launcher.aiming) {
chickenJockey.x = launcher.pullbackX;
chickenJockey.y = launcher.pullbackY;
}
}
};
game.up = function (x, y, obj) {
if (gameState === "title" || gameState === "highScores" || gameState === "characterSelect" || gameState === "gameModeSelect" || gameState === "minigames") {
// Title page, high scores, game mode select, mini games and character select interactions are handled by their respective classes
return;
}
if (gameState === "aiming") {
if (gameMode === "bonus") {
// Handle slingshot launch in bonus mode
var launchParams = launcher.endAim();
// Only launch if there's enough power
if (!launchParams || launchParams.power < 5) {
gameState = "ready";
instructionText.setText("Pull back more to launch your character!");
return;
}
// Launch the chicken jockey with direct parameters
chickenJockey.launch(launchParams.power, launchParams.angle);
// Update game state
gameState = "launched";
launches++;
launchesText.setText(launches + "/" + maxLaunches);
instructionText.setText("Watch your character fly through space!");
// Add 5 superpopcorn in bonus mode after each launch
createSuperPopcorn(5);
} else {
// Classic mode path-based launch
// 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 your character!");
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 character follow your path!");
// Add 3 superpopcorn after each launch
createSuperPopcorn(3);
}
}
};
// Main game loop
game.update = function () {
// Update minigames
if (gameState === "minigames" && miniGamesPage && typeof miniGamesPage.update === "function") {
miniGamesPage.update();
}
// Update all game objects
else 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 different sounds based on selected character
if (selectedCharacter === "Shootingstars") {
// No sound for Shooting Stars
} else if (selectedCharacter === "piglinjockey") {
LK.getSound('Pignoise').play();
} else if (selectedCharacter === "steveridingpig") {
// Play Steve sound when Steve character is used and X5 bonus is achieved
LK.getSound('Steve').play();
} else if (selectedCharacter === "vilagerjockey") {
LK.getSound('Villager').play();
} else if (selectedCharacter === "spiderjockey") {
LK.getSound('Spider').play();
} else if (selectedCharacter === "skeletonhorse") {
// Play Skeleton sound when Skeleton character is used and X5 bonus is achieved
LK.getSound('Skeleton').play();
} else if (selectedCharacter === "Grimacejockey") {
// Play Grimace sound when Grimace character is used and X5 bonus is achieved
LK.getSound('Grimace').play();
} else if (selectedCharacter === "Michaeljackson") {
// Play MJ sound when MJ character is used and X5 bonus is achieved
LK.getSound('MJ').play();
} else if (selectedCharacter === "Deeznuts") {
// Play Deeznuts sound when DeezNuts character is used and X5 bonus is achieved
LK.getSound('Deeznuts').play();
} else if (selectedCharacter === "Rickroll") {
LK.getSound('Rickroll').play();
} else if (selectedCharacter === "Joenugget") {
// Play Joenugget sound when Joe Nugget character is used and X5 bonus is achieved
LK.getSound('Joenugget').play();
} else if (selectedCharacter === "Johncena") {
// Play John Cena sound when John Cena character is used and X5 bonus is achieved
LK.getSound('Johncena').play();
} else if (selectedCharacter === "Shrekwizowski") {
LK.getSound('Shrek').play();
} else if (selectedCharacter === "Pomni") {
LK.getSound('Pomni').play();
} else {
// Play Bogerk sound for other characters
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();
;
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