User prompt
Make transition between story scenes smooth ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
After tap to start, show first scene
User prompt
Add first and second scene to story class
User prompt
Add how to play asset to top of instructions page
User prompt
Move example images down 200 in instructions page
User prompt
Remove second lot of words that say how to play instructions page
User prompt
Make text bigger in instructions page
User prompt
Remove section 1 in instructions
User prompt
Move images in instructions page down 300
User prompt
Move text down 300 in instructions page
User prompt
Add storyscene class
User prompt
Make text larger in instructions page
User prompt
Change the word dot to question mark in instructions page
User prompt
Change the word dot to question mark
User prompt
Remove the objective section of text from instructions page
User prompt
Remove the understand the categories section in instructions page
User prompt
Remove tips section of text from instructions
User prompt
Make instruction text bigger
User prompt
Use picture clues as visual examples in instruction page
User prompt
Use clue images to give examples in how to screen
User prompt
Add how to play to instructions screen
User prompt
Move text up 400 in instructions page
User prompt
Remove images from instructions scene
User prompt
Add delay on title screen while it loads assets ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove all clues besides the picture clues method used in puzzle scene
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Dot class for interactive dots in the puzzle var Dot = Container.expand(function () { var self = Container.call(this); // Create a visual representation for the dot var dotGraphics = self.attachAsset('Street', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.8, scaleY: 1.8, alpha: 0 }); // Dot properties self.isActive = false; self.gridX = 0; self.gridY = 0; self.instrumentIndex = 0; self.currentInstrument = null; // Array of instrument image IDs for first row (dots 1-5) self.instruments = ['Blank', 'Saxophone', 'Drum', 'Gutair', 'Harp', 'Flute']; // Array of image IDs for dots 21-25 (bottom row) self.specialInstruments = ['Blank', 'PJ', 'KJ', 'Harmony', 'Khalida', 'Sapphire']; // Method to toggle dot state self.toggle = function () { self.isActive = !self.isActive; }; // Method to cycle through instruments for first row (dots 1-5) self.cycleInstrument = function () { // Remove current instrument if it exists and free it from usedInstruments if (self.currentInstrument) { var currentInstrumentId = self.instruments[self.instrumentIndex]; if (currentInstrumentId !== 'Blank' && usedInstruments[currentInstrumentId] === self) { delete usedInstruments[currentInstrumentId]; } self.removeChild(self.currentInstrument); self.currentInstrument = null; } // Find next available instrument var startIndex = self.instrumentIndex; var found = false; do { self.instrumentIndex = (self.instrumentIndex + 1) % self.instruments.length; var instrumentId = self.instruments[self.instrumentIndex]; // Check if instrument is available (Blank is always available) if (instrumentId === 'Blank' || !usedInstruments[instrumentId]) { found = true; // Mark non-blank instruments as used if (instrumentId !== 'Blank') { usedInstruments[instrumentId] = self; } // Create new instrument image self.currentInstrument = self.attachAsset(instrumentId, { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); break; } } while (self.instrumentIndex !== startIndex); // If no available instrument found, stay on current (shouldn't happen with 6 instruments for 5 dots) if (!found) { self.instrumentIndex = startIndex; } }; // Method to cycle through special images for dots 21-25 (bottom row) self.cycleSpecialInstrument = function () { // Remove current instrument if it exists if (self.currentInstrument) { // Remove from usedSpecialInstruments if not Blank if (typeof usedSpecialInstruments !== "undefined" && self.specialInstruments && typeof self.specialInstrumentIndex === "number") { var prevId = self.specialInstruments[self.specialInstrumentIndex]; if (prevId !== 'Blank' && usedSpecialInstruments[prevId] === self) { delete usedSpecialInstruments[prevId]; } } self.removeChild(self.currentInstrument); self.currentInstrument = null; } // Find next available special instrument (no duplicates except Blank) if (typeof usedSpecialInstruments === "undefined") { usedSpecialInstruments = {}; } if (typeof self.specialInstrumentIndex !== "number") self.specialInstrumentIndex = 0; self.specialInstrumentIndex = typeof self.specialInstrumentIndex === "number" ? self.specialInstrumentIndex : 0; var startIndex = self.specialInstrumentIndex; var found = false; do { self.specialInstrumentIndex = (self.specialInstrumentIndex + 1) % self.specialInstruments.length; var instrumentId = self.specialInstruments[self.specialInstrumentIndex]; // Only allow Blank or unused if (instrumentId === 'Blank' || !usedSpecialInstruments[instrumentId]) { found = true; // Mark as used if not Blank if (instrumentId !== 'Blank') { usedSpecialInstruments[instrumentId] = self; } // Slightly decrease the size of all special images for dots 21-25 var scaleX = 0.85; var scaleY = 0.85; if (instrumentId === 'Harmony') { scaleX = 1.45; scaleY = 1.45; } // Move Khalida or Harmony image up by 10 pixels, move KJ down by 5 pixels var extraY = 0; if (instrumentId === 'Khalida' || instrumentId === 'Harmony') { extraY = -10; } if (instrumentId === 'KJ') { extraY = 5; } self.currentInstrument = self.attachAsset(instrumentId, { anchorX: 0.5, anchorY: 0.5, scaleX: scaleX, scaleY: scaleY, y: extraY }); break; } } while (self.specialInstrumentIndex !== startIndex); // If no available instrument found, stay on current (shouldn't happen) if (!found) { self.specialInstrumentIndex = startIndex; } }; // Touch/click handler self.down = function (x, y, obj) { // Only cycle instruments for dots 1-5 (first row) if (self.gridY === 0) { self.cycleInstrument(); } // Dots 21-25 (bottom row, gridY === 4, gridX 0-4) else if (self.gridY === 4) { self.cycleSpecialInstrument(); } // Dots 16-20 (row 4, gridY === 3, gridX 0-4) else if (self.gridY === 3) { // Animal images to cycle through if (!self.animalImages) { self.animalImages = ['Blank', 'Cat', 'Dog', 'Fish', 'Frog', 'Turtle']; self.animalIndex = 0; } // Setup usedAnimalImages global tracker if not present if (typeof usedAnimalImages === "undefined") { usedAnimalImages = {}; } // Remove current animal image if exists and update usedAnimalImages if (self.currentInstrument) { if (typeof self.animalIndex === "number") { var prevAnimalId = self.animalImages[self.animalIndex]; if (prevAnimalId !== 'Blank' && usedAnimalImages[prevAnimalId] === self) { delete usedAnimalImages[prevAnimalId]; } } self.removeChild(self.currentInstrument); self.currentInstrument = null; } // Cycle to next available animal image (no duplicates except Blank) var startIndex = typeof self.animalIndex === "number" ? self.animalIndex : 0; var found = false; var tries = 0; do { self.animalIndex = (typeof self.animalIndex === "number" ? self.animalIndex : 0) + 1; if (self.animalIndex >= self.animalImages.length) self.animalIndex = 0; var animalId = self.animalImages[self.animalIndex]; // Only allow Blank or unused if (animalId === 'Blank' || !usedAnimalImages[animalId]) { found = true; // Mark as used if not Blank if (animalId !== 'Blank') { usedAnimalImages[animalId] = self; } self.currentInstrument = self.attachAsset(animalId, { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); break; } tries++; } while (self.animalIndex !== startIndex && tries < self.animalImages.length + 1); // If no available animal found, stay on current (shouldn't happen) if (!found) { self.animalIndex = startIndex; } } // Dots 6-10 (row 2, gridY === 1, gridX 0-4) else if (self.gridY === 1) { // Food images to cycle through if (!self.foodImages) { self.foodImages = ['Blank', 'Pizza', 'Chips', 'Icecream', 'Donut', 'Spaghetti']; self.foodIndex = 0; } // Setup usedFoodImages global tracker if not present if (typeof usedFoodImages === "undefined") { usedFoodImages = {}; } // Remove current food image if exists and update usedFoodImages if (self.currentInstrument) { if (typeof self.foodIndex === "number") { var prevFoodId = self.foodImages[self.foodIndex]; if (prevFoodId !== 'Blank' && usedFoodImages[prevFoodId] === self) { delete usedFoodImages[prevFoodId]; } } self.removeChild(self.currentInstrument); self.currentInstrument = null; } // Cycle to next available food image (no duplicates except Blank) var startFoodIndex = typeof self.foodIndex === "number" ? self.foodIndex : 0; var foundFood = false; var foodTries = 0; do { self.foodIndex = (typeof self.foodIndex === "number" ? self.foodIndex : 0) + 1; if (self.foodIndex >= self.foodImages.length) self.foodIndex = 0; var foodId = self.foodImages[self.foodIndex]; // Only allow Blank or unused if (foodId === 'Blank' || !usedFoodImages[foodId]) { foundFood = true; // Mark as used if not Blank if (foodId !== 'Blank') { usedFoodImages[foodId] = self; } self.currentInstrument = self.attachAsset(foodId, { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); break; } foodTries++; } while (self.foodIndex !== startFoodIndex && foodTries < self.foodImages.length + 1); // If no available food found, stay on current (shouldn't happen) if (!foundFood) { self.foodIndex = startFoodIndex; } } else if (self.gridY === 2) { // Toy images to cycle through if (!self.toyImages) { self.toyImages = ['Blank', 'Lego', 'Dolls', 'Basketball', 'Videogame', 'Plushtoy']; self.toyIndex = 0; } // Setup usedToyImages global tracker if not present if (typeof usedToyImages === "undefined") { usedToyImages = {}; } // Remove current toy image if exists and update usedToyImages if (self.currentInstrument) { if (typeof self.toyIndex === "number") { var prevToyId = self.toyImages[self.toyIndex]; if (prevToyId !== 'Blank' && usedToyImages[prevToyId] === self) { delete usedToyImages[prevToyId]; } } self.removeChild(self.currentInstrument); self.currentInstrument = null; } // Cycle to next available toy image (no duplicates except Blank) var startToyIndex = typeof self.toyIndex === "number" ? self.toyIndex : 0; var foundToy = false; var toyTries = 0; do { self.toyIndex = (typeof self.toyIndex === "number" ? self.toyIndex : 0) + 1; if (self.toyIndex >= self.toyImages.length) self.toyIndex = 0; var toyId = self.toyImages[self.toyIndex]; // Only allow Blank or unused if (toyId === 'Blank' || !usedToyImages[toyId]) { foundToy = true; // Mark as used if not Blank if (toyId !== 'Blank') { usedToyImages[toyId] = self; } self.currentInstrument = self.attachAsset(toyId, { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); break; } toyTries++; } while (self.toyIndex !== startToyIndex && toyTries < self.toyImages.length + 1); // If no available toy found, stay on current (shouldn't happen) if (!foundToy) { self.toyIndex = startToyIndex; } } self.toggle(); // Update clues with strikethrough after changing dot if (typeof updateCluesWithStrikethrough === 'function') { updateCluesWithStrikethrough(); } }; // Initialize dot as inactive // Initialize with blank instrument self.currentInstrument = self.attachAsset('Blank', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); return self; }); // Puzzle class for managing a puzzle element in the game var Puzzle = Container.expand(function () { var self = Container.call(this); // Add a 4x5 asset to the puzzle and scale it to be exactly 2048 wide var targetWidth = 2048; var assetWidth = 1000; var scale = targetWidth / assetWidth; // Center horizontally, align to top var puzzleImage = self.attachAsset('4x5', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 0, scaleX: scale, scaleY: scale }); // (Story asset removed) // (Clue images and clue text removed) // Create 25 dots in a 5x5 grid self.dots = []; var gridSize = 5; var dotSpacing = targetWidth / (gridSize + 1); // Distribute dots evenly across the width var gridHeight = puzzleImage.height * scale; var verticalSpacing = gridHeight / (gridSize + 1); for (var row = 0; row < gridSize; row++) { for (var col = 0; col < gridSize; col++) { var dot = new Dot(); dot.gridX = col; dot.gridY = row; // Initialize all indices to 0 for consistent reset state dot.instrumentIndex = 0; dot.specialInstrumentIndex = 0; dot.animalIndex = 0; dot.foodIndex = 0; dot.toyIndex = 0; // Position dots over the 4x5 asset dot.x = (col + 1) * dotSpacing; dot.y = (row + 1) * verticalSpacing; self.dots.push(dot); self.addChild(dot); } } // Example: puzzle state self.isSolved = false; // Method to check if puzzle is solved according to target solution self.checkSolved = function () { // Target solution mapping: dot index -> expected image var targetSolution = { 0: 'Drum', // Dot 1 (row 1, col 1) 1: 'Harp', // Dot 2 (row 1, col 2) 2: 'Saxophone', // Dot 3 (row 1, col 3) 3: 'Flute', // Dot 4 (row 1, col 4) 4: 'Gutair', // Dot 5 (row 1, col 5) 5: 'Spaghetti', // Dot 6 (row 2, col 1) 6: 'Donut', // Dot 7 (row 2, col 2) 7: 'Chips', // Dot 8 (row 2, col 3) 8: 'Icecream', // Dot 9 (row 2, col 4) 9: 'Pizza', // Dot 10 (row 2, col 5) 10: 'Basketball', // Dot 11 (row 3, col 1) 11: 'Dolls', // Dot 12 (row 3, col 2) 12: 'Lego', // Dot 13 (row 3, col 3) 13: 'Videogame', // Dot 14 (row 3, col 4) 14: 'Plushtoy', // Dot 15 (row 3, col 5) 15: 'Fish', // Dot 16 (row 4, col 1) 16: 'Turtle', // Dot 17 (row 4, col 2) 17: 'Frog', // Dot 18 (row 4, col 3) 18: 'Cat', // Dot 19 (row 4, col 4) 19: 'Dog', // Dot 20 (row 4, col 5) 20: 'KJ', // Dot 21 (row 5, col 1) 21: 'Khalida', // Dot 22 (row 5, col 2) 22: 'Sapphire', // Dot 23 (row 5, col 3) 23: 'Harmony', // Dot 24 (row 5, col 4) 24: 'PJ' // Dot 25 (row 5, col 5) }; // Check if all dots match the target solution var allCorrect = true; for (var i = 0; i < self.dots.length; i++) { var dot = self.dots[i]; var expectedImage = targetSolution[i]; // Get current image of the dot based on its row and current index var currentImage = 'Blank'; var row = dot.gridY; if (row === 0 && dot.instruments) { // Row 1: Music instruments currentImage = dot.instruments[dot.instrumentIndex]; } else if (row === 1 && dot.foodImages) { // Row 2: Food currentImage = dot.foodImages[dot.foodIndex]; } else if (row === 2 && dot.toyImages) { // Row 3: Toys currentImage = dot.toyImages[dot.toyIndex]; } else if (row === 3 && dot.animalImages) { // Row 4: Animals currentImage = dot.animalImages[dot.animalIndex]; } else if (row === 4 && dot.specialInstruments) { // Row 5: Family currentImage = dot.specialInstruments[dot.specialInstrumentIndex]; } // Check if current image matches expected if (currentImage !== expectedImage) { allCorrect = false; break; } } // Update solved state only - win display handled by green tick if (allCorrect && !self.isSolved) { self.isSolved = true; } else if (!allCorrect && self.isSolved) { self.isSolved = false; } }; // Example: update method for per-frame logic self.update = function () { // Add per-frame puzzle logic here // For example, check for completion self.checkSolved(); }; return self; }); // TitleScreen class for the game's title screen var TitleScreen = Container.expand(function () { var self = Container.call(this); // Add background var bg = self.attachAsset('Street', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 20.48, scaleY: 27.32, alpha: 0.95 }); // Add title image to fill the whole screen var titleImg = self.attachAsset('Title', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 1.0, scaleY: 1.0 }); // Add animated swirl image, centered, IN FRONT of title var swirlImg = self.attachAsset('Swirl', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 1.2, scaleY: 1.2, alpha: 0.45 }); self.swirlImg = swirlImg; // Add heading image above the title image and swirl, so it is in front of both // Start tiny in the center, then tween to large in the center var headingImg = self.attachAsset('Heading', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, // Start in the center scaleX: 0.1, scaleY: 0.1 }); // Animate heading to grow and stay in the center position, but only after fully loaded function startTitleScreenAnimations() { tween(headingImg, { x: 2048 / 2, y: 2732 / 2, scaleX: 1.0, scaleY: 1.0 }, { duration: 5000, easing: tween.cubicOut }); // Animate swirl rotation using tween for infinite smooth rotation function startSwirlTween() { if (!self.swirlImg) return; // Always rotate to the next full circle (-2*PI) from current rotation for opposite direction var startRotation = self.swirlImg.rotation || 0; var endRotation = startRotation - Math.PI * 2; tween(self.swirlImg, { rotation: endRotation }, { duration: 8000, easing: tween.linear, onFinish: function onFinish() { // Reset rotation to avoid overflow and keep animation smooth if (self.swirlImg) self.swirlImg.rotation = self.swirlImg.rotation % (Math.PI * 2); startSwirlTween(); } }); } startSwirlTween(); } // Wait for the next tick to ensure all assets are loaded and the title screen is fully visible LK.setTimeout(function () { if (self && self.parent) { startTitleScreenAnimations(); } }, 0); // Add "Tap to Start" text with pulsing effect var startText = new Text2("TAP TO START", { size: 120, fill: 0xFFFF00, align: 'center', font: "'Times New Roman','Times New Roman Bold','GillSans-Bold',Impact,'Arial Black',Tahoma" }); startText.anchor.set(0.5, 0.5); startText.x = 2048 / 2; startText.y = 2732 - 300; self.addChild(startText); // Pulse the start text var _pulseStartText = function pulseStartText() { tween(startText, { alpha: 0.3 }, { duration: 800, easing: tween.sineInOut, onFinish: function onFinish() { tween(startText, { alpha: 1 }, { duration: 800, easing: tween.sineInOut, onFinish: _pulseStartText }); } }); }; _pulseStartText(); // Handle tap/click to start game self.down = function (x, y, obj) { // Fade out title screen tween(self, { alpha: 0 }, { duration: 500, easing: tween.cubicOut, onFinish: function onFinish() { if (self.parent) { self.parent.removeChild(self); // Start the main game startMainGame(); } } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Global variables that need to be accessible var usedInstruments = {}; var puzzle; var greenTick; var numberImages = []; var allClueAssets = []; var infoButton; var instructionsScreen = null; var clueStrikeStates = [false, false]; var usedSpecialInstruments = {}; var usedAnimalImages = {}; var usedFoodImages = {}; var usedToyImages = {}; // Function to start the main game after title screen function startMainGame() { // Reset global variables usedInstruments = {}; usedSpecialInstruments = {}; usedAnimalImages = {}; usedFoodImages = {}; usedToyImages = {}; numberImages = []; allClueAssets = []; clueStrikeStates = [false, false]; // Add Puzzle to the game when it starts puzzle = new Puzzle(); game.addChild(puzzle); // Add 1 2 3 4 5 number image assets to the top of the screen var numberLabelY = 60; // 60px from top var numberSpacing = 2048 / 6; // 5 numbers, 6 spaces // Track number image assets for later removal var numberImages = []; for (var i = 1; i <= 5; i++) { var numImg = LK.getAsset(i + "", { anchorX: 0.5, anchorY: 0, x: i * numberSpacing, y: numberLabelY, scaleX: 0.7, scaleY: 0.7 }); game.addChild(numImg); numberImages.push(numImg); } // --- CLUE STRIKETHROUGH LOGIC --- // Track strikethrough state for clues (first two clues only for now) var clueStrikeStates = [false, false]; // Helper to apply or remove strikethrough effect (alpha fade) for a group of clue assets function setClueStrikethrough(clueGroup, isStruck) { var alpha = isStruck ? 0.35 : 1.0; for (var i = 0; i < clueGroup.length; i++) { if (clueGroup[i]) clueGroup[i].alpha = alpha; } } // Helper to toggle strikethrough and remember state // Optionally accepts a clueIndex to persist state for first two clues function makeClueStrikeToggle(clueGroup, clueIndex) { var struck = false; // If restoring, use persisted state if (typeof clueIndex === "number" && clueStrikeStates[clueIndex] !== undefined) { struck = clueStrikeStates[clueIndex]; setClueStrikethrough(clueGroup, struck); } for (var i = 0; i < clueGroup.length; i++) { // Attach to all, but only one will handle the toggle clueGroup[i].down = function () { struck = !struck; setClueStrikethrough(clueGroup, struck); if (typeof clueIndex === "number") { clueStrikeStates[clueIndex] = struck; } }; } } // Add sapphire avatar = fries avatar clue to the left side of the puzzle screen var sapphireImg = LK.getAsset('Sapphire', { anchorX: 0.0, anchorY: 1.0, x: 30, y: 2732 - 40 - 500 + 30, scaleX: 0.45, scaleY: 0.45 }); var friesImg = LK.getAsset('Chips', { anchorX: 0.0, anchorY: 1.0, x: 30 + 200 * 0.45 + 20 + 60, // moved right by 60px to reveal equals symbol // Sapphire width * scale + 20px gap + extra space for equals y: 2732 - 40 - 500 + 30, scaleX: 0.45, scaleY: 0.45 }); var eqText = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqText.anchor.set(0.5, 1.0); eqText.x = (sapphireImg.x + friesImg.x) / 2 + 30; // Centered between sapphire and fries, nudged right for balance eqText.y = 2732 - 40 - 500 + 30; game.addChild(sapphireImg); game.addChild(eqText); game.addChild(friesImg); makeClueStrikeToggle([sapphireImg, eqText, friesImg], 0); // Add sapphire avatar < videogame asset as another clue starting the next clues column var sapphireVideogameClueY = sapphireImg.y; // align with first clue row var sapphireVideogameColumnX = friesImg.x + 350 + 600; // start a new column to the right of previous clues var sapphireClueImg = LK.getAsset('Sapphire', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX, y: sapphireVideogameClueY, scaleX: 0.45, scaleY: 0.45 }); var videogameClueImg_sapphire = LK.getAsset('Videogame', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60, y: sapphireVideogameClueY, scaleX: 0.45, scaleY: 0.45 }); var ltTextSapphireVideogame = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltTextSapphireVideogame.anchor.set(0.5, 1.0); ltTextSapphireVideogame.x = (sapphireClueImg.x + videogameClueImg_sapphire.x) / 2 + 30; ltTextSapphireVideogame.y = sapphireVideogameClueY; game.addChild(sapphireClueImg); game.addChild(ltTextSapphireVideogame); game.addChild(videogameClueImg_sapphire); makeClueStrikeToggle([sapphireClueImg, ltTextSapphireVideogame, videogameClueImg_sapphire], 1); // Add guitar avatar > cat asset as another clue under the sapphire < videogame clue var guitarCatClueY = sapphireVideogameClueY + 120; // 120px below the sapphire < videogame clue var guitarImg = LK.getAsset('Gutair', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX, y: guitarCatClueY, scaleX: 0.45, scaleY: 0.45 }); var catImg = LK.getAsset('Cat', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60, y: guitarCatClueY, scaleX: 0.45, scaleY: 0.45 }); var gtTextGuitarCat = new Text2(">", { size: 120, fill: 0xFFFFFF }); gtTextGuitarCat.anchor.set(0.5, 1.0); gtTextGuitarCat.x = (guitarImg.x + catImg.x) / 2 + 30; gtTextGuitarCat.y = guitarCatClueY; game.addChild(guitarImg); game.addChild(gtTextGuitarCat); game.addChild(catImg); makeClueStrikeToggle([guitarImg, gtTextGuitarCat, catImg]); // Add donut avatar < chips asset as another clue under the Gutair cat clue var donutChipsClueY = guitarCatClueY + 120; // 120px below the guitar > cat clue var donutImg = LK.getAsset('Donut', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX, y: donutChipsClueY, scaleX: 0.45, scaleY: 0.45 }); var chipsImg = LK.getAsset('Chips', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60, y: donutChipsClueY, scaleX: 0.45, scaleY: 0.45 }); var ltTextDonutChips = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltTextDonutChips.anchor.set(0.5, 1.0); ltTextDonutChips.x = (donutImg.x + chipsImg.x) / 2 + 30; ltTextDonutChips.y = donutChipsClueY; game.addChild(donutImg); game.addChild(ltTextDonutChips); game.addChild(chipsImg); makeClueStrikeToggle([donutImg, ltTextDonutChips, chipsImg]); // Add plushtoy avatar = dog asset as another clue under donut and chips var plushtoyDogClueY = donutChipsClueY + 120; // 120px below the donut < chips clue var plushtoyImg = LK.getAsset('Plushtoy', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX, y: plushtoyDogClueY, scaleX: 0.45, scaleY: 0.45 }); var dogImg = LK.getAsset('Dog', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60, y: plushtoyDogClueY, scaleX: 0.45, scaleY: 0.45 }); var eqTextPlushtoyDog = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqTextPlushtoyDog.anchor.set(0.5, 1.0); eqTextPlushtoyDog.x = (plushtoyImg.x + dogImg.x) / 2 + 30; eqTextPlushtoyDog.y = plushtoyDogClueY; game.addChild(plushtoyImg); game.addChild(eqTextPlushtoyDog); game.addChild(dogImg); makeClueStrikeToggle([plushtoyImg, eqTextPlushtoyDog, dogImg]); // Add basketball avatar < donut asset as another clue under plushtoy and dog clue var basketballDonutClueY = plushtoyDogClueY + 120; // 120px below the plushtoy = dog clue var basketballImg = LK.getAsset('Basketball', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX, y: basketballDonutClueY, scaleX: 0.45, scaleY: 0.45 }); var donut2Img = LK.getAsset('Donut', { anchorX: 0.0, anchorY: 1.0, x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60, y: basketballDonutClueY, scaleX: 0.45, scaleY: 0.45 }); var ltTextBasketballDonut = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltTextBasketballDonut.anchor.set(0.5, 1.0); ltTextBasketballDonut.x = (basketballImg.x + donut2Img.x) / 2 + 30; ltTextBasketballDonut.y = basketballDonutClueY; game.addChild(basketballImg); game.addChild(ltTextBasketballDonut); game.addChild(donut2Img); makeClueStrikeToggle([basketballImg, ltTextBasketballDonut, donut2Img]); // Add PJ avatar = dog asset as another clue starting a new column var pjDogColumnX = sapphireVideogameColumnX + 2 * (200 * 0.45 + 20 + 60) + 350; // new column to the right var pjDogClueY = sapphireVideogameClueY; // align with top row var pjDogImg = LK.getAsset('PJ', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX - 100, y: pjDogClueY, scaleX: 0.45, scaleY: 0.45 }); var dog2Img = LK.getAsset('Dog', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100, y: pjDogClueY, scaleX: 0.45, scaleY: 0.45 }); var eqTextPjDog = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqTextPjDog.anchor.set(0.5, 1.0); eqTextPjDog.x = (pjDogImg.x + dog2Img.x) / 2 + 30; eqTextPjDog.y = pjDogClueY; game.addChild(pjDogImg); game.addChild(eqTextPjDog); game.addChild(dog2Img); makeClueStrikeToggle([pjDogImg, eqTextPjDog, dog2Img]); // Add spaghetti avatar < turtle asset as another clue under PJ dog clue var spaghettiTurtleClueY = pjDogClueY + 120; // 120px below the PJ = dog clue var spaghettiImg = LK.getAsset('Spaghetti', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX - 100, y: spaghettiTurtleClueY, scaleX: 0.45, scaleY: 0.45 }); var turtleImg = LK.getAsset('Turtle', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100, y: spaghettiTurtleClueY, scaleX: 0.45, scaleY: 0.45 }); var ltTextSpaghettiTurtle = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltTextSpaghettiTurtle.anchor.set(0.5, 1.0); ltTextSpaghettiTurtle.x = (spaghettiImg.x + turtleImg.x) / 2 + 30; ltTextSpaghettiTurtle.y = spaghettiTurtleClueY; game.addChild(spaghettiImg); game.addChild(ltTextSpaghettiTurtle); game.addChild(turtleImg); makeClueStrikeToggle([spaghettiImg, ltTextSpaghettiTurtle, turtleImg]); // Add frog avatar < ice cream asset as another clue under spaghetti turtle clue var frogIcecreamClueY = spaghettiTurtleClueY + 120; // 120px below the spaghetti < turtle clue var frogImg = LK.getAsset('Frog', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX - 100, y: frogIcecreamClueY, scaleX: 0.45, scaleY: 0.45 }); var icecreamImg = LK.getAsset('Icecream', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100, y: frogIcecreamClueY, scaleX: 0.45, scaleY: 0.45 }); var ltTextFrogIcecream = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltTextFrogIcecream.anchor.set(0.5, 1.0); ltTextFrogIcecream.x = (frogImg.x + icecreamImg.x) / 2 + 30; ltTextFrogIcecream.y = frogIcecreamClueY; game.addChild(frogImg); game.addChild(ltTextFrogIcecream); game.addChild(icecreamImg); makeClueStrikeToggle([frogImg, ltTextFrogIcecream, icecreamImg]); // Add fish avatar = spaghetti asset as another clue under frog icecream clue var fishSpaghettiClueY = frogIcecreamClueY + 120; // 120px below the frog < icecream clue var fishImg = LK.getAsset('Fish', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX - 100, y: fishSpaghettiClueY, scaleX: 0.45, scaleY: 0.45 }); var spaghetti2Img = LK.getAsset('Spaghetti', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100, y: fishSpaghettiClueY, scaleX: 0.45, scaleY: 0.45 }); var eqTextFishSpaghetti = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqTextFishSpaghetti.anchor.set(0.5, 1.0); eqTextFishSpaghetti.x = (fishImg.x + spaghetti2Img.x) / 2 + 30; eqTextFishSpaghetti.y = fishSpaghettiClueY; game.addChild(fishImg); game.addChild(eqTextFishSpaghetti); game.addChild(spaghetti2Img); makeClueStrikeToggle([fishImg, eqTextFishSpaghetti, spaghetti2Img]); // Add cat avatar = videogame asset as another clue under fish and spaghetti var catVideogameClueY = fishSpaghettiClueY + 120; // 120px below the fish = spaghetti clue var catClueImg = LK.getAsset('Cat', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX - 100, y: catVideogameClueY, scaleX: 0.45, scaleY: 0.45 }); var videogameClueImg_cat = LK.getAsset('Videogame', { anchorX: 0.0, anchorY: 1.0, x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100, y: catVideogameClueY, scaleX: 0.45, scaleY: 0.45 }); var eqTextCatVideogame = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqTextCatVideogame.anchor.set(0.5, 1.0); eqTextCatVideogame.x = (catClueImg.x + videogameClueImg_cat.x) / 2 + 30; eqTextCatVideogame.y = catVideogameClueY; game.addChild(catClueImg); game.addChild(eqTextCatVideogame); game.addChild(videogameClueImg_cat); makeClueStrikeToggle([catClueImg, eqTextCatVideogame, videogameClueImg_cat]); // Add Khalida avatar > KJ asset as another clue on the right of the first clue (swap with harmony < pizza) var harmonyClueY = sapphireImg.y; // align with first clue var khalidaClueImg = LK.getAsset('Khalida', { anchorX: 0.0, anchorY: 1.0, x: friesImg.x + 350, y: harmonyClueY, scaleX: 0.45, scaleY: 0.45 }); var kjClueImg = LK.getAsset('KJ', { anchorX: 0.0, anchorY: 1.0, x: friesImg.x + 350 + 200 * 0.45 + 20 + 60, y: harmonyClueY, scaleX: 0.45, scaleY: 0.45 }); var gtTextKhalidaKJ = new Text2(">", { size: 120, fill: 0xFFFFFF }); gtTextKhalidaKJ.anchor.set(0.5, 1.0); gtTextKhalidaKJ.x = (khalidaClueImg.x + kjClueImg.x) / 2 + 30; gtTextKhalidaKJ.y = harmonyClueY; game.addChild(khalidaClueImg); game.addChild(gtTextKhalidaKJ); game.addChild(kjClueImg); makeClueStrikeToggle([khalidaClueImg, gtTextKhalidaKJ, kjClueImg]); // Add PJ avatar = 5 asset as another clue under the first clue var pjClueY = sapphireImg.y + 120; // 120px below the first clue var pjImg = LK.getAsset('PJ', { anchorX: 0.0, anchorY: 1.0, x: 30, y: pjClueY, scaleX: 0.45, scaleY: 0.45 }); var fiveImg = LK.getAsset('5', { anchorX: 0.0, anchorY: 1.0, x: 30 + 200 * 0.45 + 20 + 60, // match fries x y: pjClueY, scaleX: 0.45, scaleY: 0.45 }); var eqText2 = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqText2.anchor.set(0.5, 1.0); eqText2.x = (pjImg.x + fiveImg.x) / 2 + 30; eqText2.y = pjClueY; game.addChild(pjImg); game.addChild(eqText2); game.addChild(fiveImg); makeClueStrikeToggle([pjImg, eqText2, fiveImg]); // Add KJ avatar = 1 asset as another clue under the second clue var kjClueY = pjClueY + 120; // 120px below the second clue var kjImg = LK.getAsset('KJ', { anchorX: 0.0, anchorY: 1.0, x: 30, y: kjClueY, scaleX: 0.45, scaleY: 0.45 }); var oneImg = LK.getAsset('1', { anchorX: 0.0, anchorY: 1.0, x: 30 + 200 * 0.45 + 20 + 60, y: kjClueY, scaleX: 0.45, scaleY: 0.45 }); var eqText3 = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqText3.anchor.set(0.5, 1.0); eqText3.x = (kjImg.x + oneImg.x) / 2 + 30; eqText3.y = kjClueY; game.addChild(kjImg); game.addChild(eqText3); game.addChild(oneImg); makeClueStrikeToggle([kjImg, eqText3, oneImg]); // Add Saxophone avatar = 3 asset as another clue under the harmony clue var saxClueY = harmonyClueY + 120; // 120px below the harmony clue // Use the same x as the right column clues (e.g. 30 + 1200) var rightColumnX = friesImg.x + 350; // This matches the x used for right column clues above var saxImg = LK.getAsset('Saxophone', { anchorX: 0.0, anchorY: 1.0, x: rightColumnX, // align left with right column clues y: saxClueY, scaleX: 0.45, scaleY: 0.45 }); var threeImg = LK.getAsset('3', { anchorX: 0.0, anchorY: 1.0, x: rightColumnX + 200 * 0.45 + 20 + 60, // match pizza x offset y: saxClueY, scaleX: 0.45, scaleY: 0.45 }); var eqTextSax = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqTextSax.anchor.set(0.5, 1.0); eqTextSax.x = (saxImg.x + threeImg.x) / 2 + 30; eqTextSax.y = saxClueY; game.addChild(saxImg); game.addChild(eqTextSax); game.addChild(threeImg); makeClueStrikeToggle([saxImg, eqTextSax, threeImg]); // Add Khalida avatar = harp avatar as another clue under the third clue var khalidaClueY = kjClueY + 120; // 120px below the third clue var khalidaImg = LK.getAsset('Khalida', { anchorX: 0.0, anchorY: 1.0, x: 30, y: khalidaClueY, scaleX: 0.45, scaleY: 0.45 }); var harpImg = LK.getAsset('Harp', { anchorX: 0.0, anchorY: 1.0, x: 30 + 200 * 0.45 + 20 + 60, y: khalidaClueY, scaleX: 0.45, scaleY: 0.45 }); var eqText4 = new Text2("=", { size: 120, fill: 0xFFFFFF }); eqText4.anchor.set(0.5, 1.0); eqText4.x = (khalidaImg.x + harpImg.x) / 2 + 30; eqText4.y = khalidaClueY; game.addChild(khalidaImg); game.addChild(eqText4); game.addChild(harpImg); makeClueStrikeToggle([khalidaImg, eqText4, harpImg]); // Add Khalida avatar > KJ asset as another clue under the saxophone clue (right column, below saxophone = 3) var khalidaKJClueY = saxClueY + 120; // 120px below the saxophone clue var drumClueY = khalidaClueY + 120; // 120px below the fourth clue var drumImg = LK.getAsset('Drum', { anchorX: 0.0, anchorY: 1.0, x: 30, y: drumClueY, scaleX: 0.45, scaleY: 0.45 }); var dollsImg = LK.getAsset('Dolls', { anchorX: 0.0, anchorY: 1.0, x: 30 + 200 * 0.45 + 20 + 60, y: drumClueY, scaleX: 0.45, scaleY: 0.45 }); var ltText = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltText.anchor.set(0.5, 1.0); ltText.x = (drumImg.x + dollsImg.x) / 2 + 30; ltText.y = drumClueY; game.addChild(drumImg); game.addChild(ltText); game.addChild(dollsImg); makeClueStrikeToggle([drumImg, ltText, dollsImg]); // Add harmony avatar < pizza asset as another clue under the saxophone clue (right column, below saxophone = 3) var harmonyImg = LK.getAsset('Harmony', { anchorX: 0.0, anchorY: 1.0, x: rightColumnX, // right column, same x as above y: khalidaKJClueY, scaleX: 0.55, scaleY: 0.55 }); var pizzaImgClue = LK.getAsset('Pizza', { anchorX: 0.0, anchorY: 1.0, x: rightColumnX + 200 * 0.45 + 20 + 60, y: khalidaKJClueY, scaleX: 0.45, scaleY: 0.45 }); var ltTextHarmony = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltTextHarmony.anchor.set(0.5, 1.0); ltTextHarmony.x = (harmonyImg.x + pizzaImgClue.x) / 2 + 30; ltTextHarmony.y = khalidaKJClueY; game.addChild(harmonyImg); game.addChild(ltTextHarmony); game.addChild(pizzaImgClue); makeClueStrikeToggle([harmonyImg, ltTextHarmony, pizzaImgClue]); // Add drum avatar < harp avatar as another clue under the KJ Khalida clue var drumHarpClueY = khalidaKJClueY + 120; // 120px below the KJ Khalida clue var drumHarpImg = LK.getAsset('Drum', { anchorX: 0.0, anchorY: 1.0, x: harmonyImg.x, y: drumHarpClueY, scaleX: 0.45, scaleY: 0.45 }); var harpClueImg = LK.getAsset('Harp', { anchorX: 0.0, anchorY: 1.0, x: harmonyImg.x + 200 * 0.45 + 20 + 60, y: drumHarpClueY, scaleX: 0.45, scaleY: 0.45 }); var ltTextDrumHarp = new Text2("<", { size: 120, fill: 0xFFFFFF }); ltTextDrumHarp.anchor.set(0.5, 1.0); ltTextDrumHarp.x = (drumHarpImg.x + harpClueImg.x) / 2 + 30; ltTextDrumHarp.y = drumHarpClueY; game.addChild(drumHarpImg); game.addChild(ltTextDrumHarp); game.addChild(harpClueImg); makeClueStrikeToggle([drumHarpImg, ltTextDrumHarp, harpClueImg]); // Add harmony avatar > saxophone asset as another clue under the drum harp clue (right column, below drum < harp) var harmonySaxClueY = drumHarpClueY + 120; // 120px below the drum harp clue var harmonyAvatarImg = LK.getAsset('Harmony', { anchorX: 0.0, anchorY: 1.0, x: harmonyImg.x, y: harmonySaxClueY, scaleX: 0.55, scaleY: 0.55 }); var saxophoneAvatarImg = LK.getAsset('Saxophone', { anchorX: 0.0, anchorY: 1.0, x: harmonyImg.x + 200 * 0.45 + 20 + 60, y: harmonySaxClueY, scaleX: 0.45, scaleY: 0.45 }); var gtTextHarmonySax = new Text2(">", { size: 120, fill: 0xFFFFFF }); gtTextHarmonySax.anchor.set(0.5, 1.0); gtTextHarmonySax.x = (harmonyAvatarImg.x + saxophoneAvatarImg.x) / 2 + 30; gtTextHarmonySax.y = harmonySaxClueY; game.addChild(harmonyAvatarImg); game.addChild(gtTextHarmonySax); game.addChild(saxophoneAvatarImg); makeClueStrikeToggle([harmonyAvatarImg, gtTextHarmonySax, saxophoneAvatarImg]); // Add green tick to bottom right corner var greenTick = LK.getAsset('Greentick', { anchorX: 1.0, anchorY: 1.0, x: 2048 - 0, //{7i} // moved right by 50px y: 2732 - 50 - 600 - 35, // moved up by 15px (previously 10, now 15) scaleX: 0.8, scaleY: 0.8 }); game.addChild(greenTick); // Add info button to bottom left corner var infoButton = LK.getAsset('Info', { anchorX: 0.0, anchorY: 1.0, x: 0, y: 2732 - 50 - 600 - 30, scaleX: 1.5, scaleY: 1.5 }); game.addChild(infoButton); // Variable to track instructions screen var instructionsScreen = null; // Make info button clickable to show illustrated how-to-play guide infoButton.down = function (x, y, obj) { // If instructions screen is already showing, hide it if (instructionsScreen && instructionsScreen.parent) { instructionsScreen.parent.removeChild(instructionsScreen); instructionsScreen = null; return; } // Create instructions screen container instructionsScreen = new Container(); // Add semi-transparent background var instructionsBg = LK.getAsset('Street', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 20.48, scaleY: 27.32, alpha: 0.92 }); instructionsScreen.addChild(instructionsBg); // Move all images to the top of the instructions overlay var topY = 120 - 300; // Top margin for images, moved up by 300px // Step 1: Show the puzzle board image at the top var boardImg = LK.getAsset('4x5', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: topY, scaleX: 0.7, scaleY: 0.7 }); instructionsScreen.addChild(boardImg); // Calculate the bottom of the board image for next row of images var boardImgBottom = topY + 1000 * 0.7; // 1000 is asset height // Row of sample images just below the board image var rowImgY = boardImgBottom + 40; // 40px padding below board // Step 2: Show a hand icon over a dot to indicate tapping (use 'Greentick' as a hand substitute) var handIcon = LK.getAsset('Greentick', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 350, y: rowImgY + 60, scaleX: 0.7, scaleY: 0.7, alpha: 0.7 }); instructionsScreen.addChild(handIcon); // Step 3: Show a sample instrument image (e.g. Drum) above the dot var drumImg = LK.getAsset('Drum', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 350, y: rowImgY, scaleX: 1.2, scaleY: 1.2 }); instructionsScreen.addChild(drumImg); // Step 4: Show a sample food image (e.g. Pizza) above a dot in row 2 var pizzaImg = LK.getAsset('Pizza', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 100, y: rowImgY, scaleX: 1.2, scaleY: 1.2 }); instructionsScreen.addChild(pizzaImg); // Step 5: Show a sample toy image (e.g. Lego) above a dot in row 3 var legoImg = LK.getAsset('Lego', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 150, y: rowImgY, scaleX: 1.2, scaleY: 1.2 }); instructionsScreen.addChild(legoImg); // Step 6: Show a sample animal image (e.g. Cat) above a dot in row 4 var catImg = LK.getAsset('Cat', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 350, y: rowImgY, scaleX: 1.2, scaleY: 1.2 }); instructionsScreen.addChild(catImg); // Step 7: Show a sample family image (e.g. PJ) to the right of cat in row 5 var pjImg = LK.getAsset('PJ', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 550, y: rowImgY, scaleX: 0.7, scaleY: 0.7 }); instructionsScreen.addChild(pjImg); // Step 8: Show the green tick in the bottom right as the "submit" button var tickIcon = LK.getAsset('Greentick', { anchorX: 1.0, anchorY: 1.0, x: 2048 - 50, y: 2732 - 50, scaleX: 1.2, scaleY: 1.2 }); instructionsScreen.addChild(tickIcon); // Step 9: Add step-by-step text instructions var instructionsText = new Text2("HOW TO PLAY THIS PUZZLE GAME\n" + "Match each dot to the correct picture\n" + "in its row. Each row is a different category.\n\n" + "1. Tap a dot to cycle through the possible items for that row.\n" + " (Each tap changes the picture on that dot)\n\n" + "2. Each row has a different category:\n" + " Row 1: Music\n" + " Row 2: Food\n" + " Row 3: Toys\n" + " Row 4: Animals\n" + " Row 5: Family\n\n" + "3. Use the clues at the bottom of the screen\n" + " to help you match each item to its correct spot.\n\n" + "4. When you think you've solved the puzzle,\n" + " tap the green tick in the bottom right to check your answer!\n\n" + "Tip: Tap the info button any time for help.\n\n" + "Tap anywhere to close this guide.", { size: 70, fill: 0xffffff, align: 'center', font: "'Times New Roman Bold','Times New Roman','GillSans-Bold',Impact,'Arial Black',Tahoma" }); instructionsText.anchor.set(0.5, 0.5); instructionsText.x = 2048 / 2; instructionsText.y = 2732 / 2 + 420; instructionsScreen.addChild(instructionsText); // Make the entire instructions screen clickable to close instructionsScreen.down = function (x, y, obj) { if (instructionsScreen && instructionsScreen.parent) { instructionsScreen.parent.removeChild(instructionsScreen); instructionsScreen = null; } }; // Add instructions screen to game game.addChild(instructionsScreen); }; // Helper to show/hide info button function setInfoButtonVisible(visible) { if (infoButton && infoButton.parent) { infoButton.visible = !!visible; } } // Function to update clues with strikethrough for solved items (picture clues only) function updateCluesWithStrikethrough() { // This function now only handles picture clue strikethrough effects // The picture clues are already implemented with makeClueStrikeToggle // No additional text-based clue processing needed } // Make green tick clickable to enter puzzle attempt greenTick.down = function (x, y, obj) { // Remove all clue assets from game when green tick is clicked if (typeof allClueAssets === "undefined") allClueAssets = []; // If not already collected, collect all clue assets for later restoration if (allClueAssets.length === 0) { // Collect all clue asset instances, including both videogame clue images allClueAssets = [sapphireImg, friesImg, eqText, sapphireClueImg, ltTextSapphireVideogame, videogameClueImg_sapphire, // sapphire < videogame guitarImg, catImg, gtTextGuitarCat, donutImg, chipsImg, ltTextDonutChips, plushtoyImg, dogImg, eqTextPlushtoyDog, basketballImg, donut2Img, ltTextBasketballDonut, pjDogImg, dog2Img, eqTextPjDog, spaghettiImg, turtleImg, ltTextSpaghettiTurtle, frogImg, icecreamImg, ltTextFrogIcecream, fishImg, spaghetti2Img, eqTextFishSpaghetti, catClueImg, eqTextCatVideogame, videogameClueImg_cat, // cat = videogame khalidaClueImg, kjClueImg, gtTextKhalidaKJ, pjImg, fiveImg, eqText2, kjImg, oneImg, eqText3, saxImg, threeImg, eqTextSax, khalidaImg, harpImg, eqText4, drumImg, dollsImg, ltText, harmonyImg, pizzaImgClue, ltTextHarmony, drumHarpImg, harpClueImg, ltTextDrumHarp, harmonyAvatarImg, saxophoneAvatarImg, gtTextHarmonySax]; // Remove duplicates and nulls for safety var seen = []; var filtered = []; for (var i = 0; i < allClueAssets.length; i++) { var asset = allClueAssets[i]; if (asset && seen.indexOf(asset) === -1) { seen.push(asset); filtered.push(asset); } } allClueAssets = filtered; } for (var i = 0; i < allClueAssets.length; i++) { if (allClueAssets[i] && allClueAssets[i].parent) { allClueAssets[i].parent.removeChild(allClueAssets[i]); } } // Remove number image assets from game when green tick is clicked if (typeof numberImages !== "undefined" && numberImages.length) { for (var i = 0; i < numberImages.length; i++) { if (numberImages[i] && numberImages[i].parent) numberImages[i].parent.removeChild(numberImages[i]); } } if (puzzle && typeof puzzle.checkSolved === "function") { // Run the check puzzle.checkSolved(); // If solved, show endpuzzletwo scene if (puzzle.isSolved) { // Remove the puzzle and green tick from the game if (puzzle.parent) puzzle.parent.removeChild(puzzle); if (greenTick.parent) greenTick.parent.removeChild(greenTick); // Hide info button when showing endpuzzletwo setInfoButtonVisible(false); // Show endpuzzletwo asset centered on screen var endpuzzletwo = LK.getAsset('Endpuzzletwo', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 2.2, scaleY: 2.2, alpha: 0 }); game.addChild(endpuzzletwo); // Fade in endpuzzletwo tween(endpuzzletwo, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); // After 2 seconds, fade out and swap to correct scene with correct word under the correct image LK.setTimeout(function () { tween(endpuzzletwo, { alpha: 0 }, { duration: 350, easing: tween.cubicIn, onFinish: function onFinish() { if (endpuzzletwo.parent) endpuzzletwo.parent.removeChild(endpuzzletwo); // Show Correct scene (centered) var correctScene = LK.getAsset('Correct', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 2.2, scaleY: 2.2, alpha: 0 }); game.addChild(correctScene); // Fade in correctScene tween(correctScene, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); // No winning image displayed - just show the correct word // Show the correct word asset at the bottom of the screen var correctWord = LK.getAsset('Correctword', { anchorX: 0.5, anchorY: 1.0, x: 2048 / 2, y: 2732 - 50, scaleX: 2.2, scaleY: 2.2, alpha: 0 }); game.addChild(correctWord); tween(correctWord, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); } }); }, 2000); } else { // If not solved, show endgame1 scene if (puzzle.parent) puzzle.parent.removeChild(puzzle); if (greenTick.parent) greenTick.parent.removeChild(greenTick); // Hide info button when showing endgame1 setInfoButtonVisible(false); // Show endgame1 asset centered on screen var endgame1 = LK.getAsset('Endpuzzleone', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 2.2, scaleY: 2.2, alpha: 0 }); game.addChild(endgame1); tween(endgame1, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); // After 2 seconds, fade out and swap to incorrect scene with incorrect word under the incorrect image LK.setTimeout(function () { tween(endgame1, { alpha: 0 }, { duration: 350, easing: tween.cubicIn, onFinish: function onFinish() { if (endgame1.parent) endgame1.parent.removeChild(endgame1); // Show Incorrect scene (centered) var incorrectScene = LK.getAsset('Incorrect', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 2.2, scaleY: 2.2, alpha: 0 }); game.addChild(incorrectScene); tween(incorrectScene, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); // Find the first incorrect dot and its expected word var targetSolution = { 0: 'Drum', 1: 'Harp', 2: 'Saxophone', 3: 'Flute', 4: 'Gutair', 5: 'Spaghetti', 6: 'Donut', 7: 'Chips', 8: 'Icecream', 9: 'Pizza', 10: 'Basketball', 11: 'Dolls', 12: 'Lego', 13: 'Videogame', 14: 'Plushtoy', 15: 'Fish', 16: 'Turtle', 17: 'Frog', 18: 'Cat', 19: 'Dog', 20: 'KJ', 21: 'Khalida', 22: 'Sapphire', 23: 'Harmony', 24: 'PJ' }; var firstWrongIdx = -1; var wrongActual = ''; var wrongExpected = ''; for (var i = 0; i < puzzle.dots.length; i++) { var dot = puzzle.dots[i]; var expected = targetSolution[i]; var actual = 'Blank'; var row = dot.gridY; // Get current image based on row and index if (row === 0 && dot.instruments) { actual = dot.instruments[dot.instrumentIndex]; } else if (row === 1 && dot.foodImages) { actual = dot.foodImages[dot.foodIndex]; } else if (row === 2 && dot.toyImages) { actual = dot.toyImages[dot.toyIndex]; } else if (row === 3 && dot.animalImages) { actual = dot.animalImages[dot.animalIndex]; } else if (row === 4 && dot.specialInstruments) { actual = dot.specialInstruments[dot.specialInstrumentIndex]; } if (actual !== expected) { firstWrongIdx = i; wrongActual = actual; wrongExpected = expected; break; } } // If found, show the incorrect image and word under it if (firstWrongIdx !== -1) { var wrongImg = null; var imgY = 2732 / 2 + 100; var wordY = imgY; // Only show the image if it's not 'Blank' if (wrongActual !== 'Blank') { wrongImg = LK.getAsset(wrongActual, { anchorX: 0.5, anchorY: 1.0, x: 2048 / 2, y: imgY, alpha: 0 }); game.addChild(wrongImg); tween(wrongImg, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); wordY = 2732 / 2 + 120 + (wrongImg.height || 100); // 20px below image } else { // If blank, just show the word lower down wordY = 2732 / 2 + 120; } // Show the incorrect word asset at the bottom of the screen var incorrectWord = LK.getAsset('Incorrectword', { anchorX: 0.5, anchorY: 1.0, x: 2048 / 2, y: 2732 - 50, // 50px padding from bottom scaleX: 2.2, scaleY: 2.2, alpha: 0 }); game.addChild(incorrectWord); tween(incorrectWord, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); // Add retry button below the incorrect image/word var retryBtnY = 2732 - 50 - incorrectWord.height * 2.2 - 40; // 40px above incorrect word var retryBtn = LK.getAsset('Retry', { anchorX: 0.5, anchorY: 1.0, x: 2048 / 2, y: retryBtnY, scaleX: 1.8, scaleY: 1.8, alpha: 0 }); game.addChild(retryBtn); tween(retryBtn, { alpha: 1 }, { duration: 350, easing: tween.cubicOut }); // Retry button handler: remove incorrect scene and restart puzzle retryBtn.down = function (x, y, obj) { // Fade out all incorrect scene assets, then remove and reset var fadeOuts = [incorrectScene, wrongImg, incorrectWord, retryBtn]; var fadeCount = 0; var fadeDone = function fadeDone() { fadeCount++; if (fadeCount === fadeOuts.length) { // Remove all incorrect scene assets if (incorrectScene && incorrectScene.parent) incorrectScene.parent.removeChild(incorrectScene); if (wrongImg && wrongImg.parent) wrongImg.parent.removeChild(wrongImg); if (incorrectWord && incorrectWord.parent) incorrectWord.parent.removeChild(incorrectWord); if (retryBtn && retryBtn.parent) retryBtn.parent.removeChild(retryBtn); // Reset all used image trackers so dots can be reused usedInstruments = {}; usedSpecialInstruments = {}; usedAnimalImages = {}; usedFoodImages = {}; usedToyImages = {}; // Re-add puzzle and green tick puzzle = new Puzzle(); game.addChild(puzzle); game.addChild(greenTick); // Re-add number image assets to the top of the screen numberImages = []; for (var i = 1; i <= 5; i++) { var numImg = LK.getAsset(i + "", { anchorX: 0.5, anchorY: 0, x: i * (2048 / 6), y: 60, scaleX: 0.7, scaleY: 0.7 }); game.addChild(numImg); numberImages.push(numImg); } // Restore all clue assets when retry is clicked if (typeof allClueAssets !== "undefined" && allClueAssets.length) { for (var i = 0; i < allClueAssets.length; i++) { if (allClueAssets[i] && !allClueAssets[i].parent) { game.addChild(allClueAssets[i]); } } // Remove all strikethrough from clues when retry is clicked for (var i = 0; i < allClueAssets.length; i++) { if (allClueAssets[i]) allClueAssets[i].alpha = 1.0; } // Reset strikethrough state for all clues for (var i = 0; i < clueStrikeStates.length; i++) { clueStrikeStates[i] = false; } } // Re-add info button after story asset if (infoButton && infoButton.parent) { infoButton.parent.removeChild(infoButton); } // Find the story asset in the puzzle and add infoButton after it var storyAssetIdx = -1; for (var i = 0; i < puzzle.children.length; i++) { var child = puzzle.children[i]; if (child && child.assetId === 'Story') { storyAssetIdx = i; break; } } if (storyAssetIdx !== -1) { // Insert infoButton after story asset if (puzzle.children.length > storyAssetIdx + 1) { puzzle.addChildAt(infoButton, storyAssetIdx + 1); } else { puzzle.addChild(infoButton); } } else { // Fallback: add to puzzle if not found puzzle.addChild(infoButton); } // Show info button again after retry setInfoButtonVisible(true); } }; for (var i = 0; i < fadeOuts.length; i++) { if (fadeOuts[i]) { tween(fadeOuts[i], { alpha: 0 }, { duration: 250, easing: tween.cubicIn, onFinish: fadeDone }); } else { fadeDone(); } } }; } } }); }, 2000); } } }; // Update global references that might be needed window.puzzle = puzzle; window.greenTick = greenTick; window.numberImages = numberImages; window.allClueAssets = allClueAssets; window.infoButton = infoButton; } // Initialize the game with title screen var titleScreen = new TitleScreen(); game.addChild(titleScreen);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Dot class for interactive dots in the puzzle
var Dot = Container.expand(function () {
var self = Container.call(this);
// Create a visual representation for the dot
var dotGraphics = self.attachAsset('Street', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8,
alpha: 0
});
// Dot properties
self.isActive = false;
self.gridX = 0;
self.gridY = 0;
self.instrumentIndex = 0;
self.currentInstrument = null;
// Array of instrument image IDs for first row (dots 1-5)
self.instruments = ['Blank', 'Saxophone', 'Drum', 'Gutair', 'Harp', 'Flute'];
// Array of image IDs for dots 21-25 (bottom row)
self.specialInstruments = ['Blank', 'PJ', 'KJ', 'Harmony', 'Khalida', 'Sapphire'];
// Method to toggle dot state
self.toggle = function () {
self.isActive = !self.isActive;
};
// Method to cycle through instruments for first row (dots 1-5)
self.cycleInstrument = function () {
// Remove current instrument if it exists and free it from usedInstruments
if (self.currentInstrument) {
var currentInstrumentId = self.instruments[self.instrumentIndex];
if (currentInstrumentId !== 'Blank' && usedInstruments[currentInstrumentId] === self) {
delete usedInstruments[currentInstrumentId];
}
self.removeChild(self.currentInstrument);
self.currentInstrument = null;
}
// Find next available instrument
var startIndex = self.instrumentIndex;
var found = false;
do {
self.instrumentIndex = (self.instrumentIndex + 1) % self.instruments.length;
var instrumentId = self.instruments[self.instrumentIndex];
// Check if instrument is available (Blank is always available)
if (instrumentId === 'Blank' || !usedInstruments[instrumentId]) {
found = true;
// Mark non-blank instruments as used
if (instrumentId !== 'Blank') {
usedInstruments[instrumentId] = self;
}
// Create new instrument image
self.currentInstrument = self.attachAsset(instrumentId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
break;
}
} while (self.instrumentIndex !== startIndex);
// If no available instrument found, stay on current (shouldn't happen with 6 instruments for 5 dots)
if (!found) {
self.instrumentIndex = startIndex;
}
};
// Method to cycle through special images for dots 21-25 (bottom row)
self.cycleSpecialInstrument = function () {
// Remove current instrument if it exists
if (self.currentInstrument) {
// Remove from usedSpecialInstruments if not Blank
if (typeof usedSpecialInstruments !== "undefined" && self.specialInstruments && typeof self.specialInstrumentIndex === "number") {
var prevId = self.specialInstruments[self.specialInstrumentIndex];
if (prevId !== 'Blank' && usedSpecialInstruments[prevId] === self) {
delete usedSpecialInstruments[prevId];
}
}
self.removeChild(self.currentInstrument);
self.currentInstrument = null;
}
// Find next available special instrument (no duplicates except Blank)
if (typeof usedSpecialInstruments === "undefined") {
usedSpecialInstruments = {};
}
if (typeof self.specialInstrumentIndex !== "number") self.specialInstrumentIndex = 0;
self.specialInstrumentIndex = typeof self.specialInstrumentIndex === "number" ? self.specialInstrumentIndex : 0;
var startIndex = self.specialInstrumentIndex;
var found = false;
do {
self.specialInstrumentIndex = (self.specialInstrumentIndex + 1) % self.specialInstruments.length;
var instrumentId = self.specialInstruments[self.specialInstrumentIndex];
// Only allow Blank or unused
if (instrumentId === 'Blank' || !usedSpecialInstruments[instrumentId]) {
found = true;
// Mark as used if not Blank
if (instrumentId !== 'Blank') {
usedSpecialInstruments[instrumentId] = self;
}
// Slightly decrease the size of all special images for dots 21-25
var scaleX = 0.85;
var scaleY = 0.85;
if (instrumentId === 'Harmony') {
scaleX = 1.45;
scaleY = 1.45;
}
// Move Khalida or Harmony image up by 10 pixels, move KJ down by 5 pixels
var extraY = 0;
if (instrumentId === 'Khalida' || instrumentId === 'Harmony') {
extraY = -10;
}
if (instrumentId === 'KJ') {
extraY = 5;
}
self.currentInstrument = self.attachAsset(instrumentId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: scaleX,
scaleY: scaleY,
y: extraY
});
break;
}
} while (self.specialInstrumentIndex !== startIndex);
// If no available instrument found, stay on current (shouldn't happen)
if (!found) {
self.specialInstrumentIndex = startIndex;
}
};
// Touch/click handler
self.down = function (x, y, obj) {
// Only cycle instruments for dots 1-5 (first row)
if (self.gridY === 0) {
self.cycleInstrument();
}
// Dots 21-25 (bottom row, gridY === 4, gridX 0-4)
else if (self.gridY === 4) {
self.cycleSpecialInstrument();
}
// Dots 16-20 (row 4, gridY === 3, gridX 0-4)
else if (self.gridY === 3) {
// Animal images to cycle through
if (!self.animalImages) {
self.animalImages = ['Blank', 'Cat', 'Dog', 'Fish', 'Frog', 'Turtle'];
self.animalIndex = 0;
}
// Setup usedAnimalImages global tracker if not present
if (typeof usedAnimalImages === "undefined") {
usedAnimalImages = {};
}
// Remove current animal image if exists and update usedAnimalImages
if (self.currentInstrument) {
if (typeof self.animalIndex === "number") {
var prevAnimalId = self.animalImages[self.animalIndex];
if (prevAnimalId !== 'Blank' && usedAnimalImages[prevAnimalId] === self) {
delete usedAnimalImages[prevAnimalId];
}
}
self.removeChild(self.currentInstrument);
self.currentInstrument = null;
}
// Cycle to next available animal image (no duplicates except Blank)
var startIndex = typeof self.animalIndex === "number" ? self.animalIndex : 0;
var found = false;
var tries = 0;
do {
self.animalIndex = (typeof self.animalIndex === "number" ? self.animalIndex : 0) + 1;
if (self.animalIndex >= self.animalImages.length) self.animalIndex = 0;
var animalId = self.animalImages[self.animalIndex];
// Only allow Blank or unused
if (animalId === 'Blank' || !usedAnimalImages[animalId]) {
found = true;
// Mark as used if not Blank
if (animalId !== 'Blank') {
usedAnimalImages[animalId] = self;
}
self.currentInstrument = self.attachAsset(animalId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
break;
}
tries++;
} while (self.animalIndex !== startIndex && tries < self.animalImages.length + 1);
// If no available animal found, stay on current (shouldn't happen)
if (!found) {
self.animalIndex = startIndex;
}
}
// Dots 6-10 (row 2, gridY === 1, gridX 0-4)
else if (self.gridY === 1) {
// Food images to cycle through
if (!self.foodImages) {
self.foodImages = ['Blank', 'Pizza', 'Chips', 'Icecream', 'Donut', 'Spaghetti'];
self.foodIndex = 0;
}
// Setup usedFoodImages global tracker if not present
if (typeof usedFoodImages === "undefined") {
usedFoodImages = {};
}
// Remove current food image if exists and update usedFoodImages
if (self.currentInstrument) {
if (typeof self.foodIndex === "number") {
var prevFoodId = self.foodImages[self.foodIndex];
if (prevFoodId !== 'Blank' && usedFoodImages[prevFoodId] === self) {
delete usedFoodImages[prevFoodId];
}
}
self.removeChild(self.currentInstrument);
self.currentInstrument = null;
}
// Cycle to next available food image (no duplicates except Blank)
var startFoodIndex = typeof self.foodIndex === "number" ? self.foodIndex : 0;
var foundFood = false;
var foodTries = 0;
do {
self.foodIndex = (typeof self.foodIndex === "number" ? self.foodIndex : 0) + 1;
if (self.foodIndex >= self.foodImages.length) self.foodIndex = 0;
var foodId = self.foodImages[self.foodIndex];
// Only allow Blank or unused
if (foodId === 'Blank' || !usedFoodImages[foodId]) {
foundFood = true;
// Mark as used if not Blank
if (foodId !== 'Blank') {
usedFoodImages[foodId] = self;
}
self.currentInstrument = self.attachAsset(foodId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
break;
}
foodTries++;
} while (self.foodIndex !== startFoodIndex && foodTries < self.foodImages.length + 1);
// If no available food found, stay on current (shouldn't happen)
if (!foundFood) {
self.foodIndex = startFoodIndex;
}
} else if (self.gridY === 2) {
// Toy images to cycle through
if (!self.toyImages) {
self.toyImages = ['Blank', 'Lego', 'Dolls', 'Basketball', 'Videogame', 'Plushtoy'];
self.toyIndex = 0;
}
// Setup usedToyImages global tracker if not present
if (typeof usedToyImages === "undefined") {
usedToyImages = {};
}
// Remove current toy image if exists and update usedToyImages
if (self.currentInstrument) {
if (typeof self.toyIndex === "number") {
var prevToyId = self.toyImages[self.toyIndex];
if (prevToyId !== 'Blank' && usedToyImages[prevToyId] === self) {
delete usedToyImages[prevToyId];
}
}
self.removeChild(self.currentInstrument);
self.currentInstrument = null;
}
// Cycle to next available toy image (no duplicates except Blank)
var startToyIndex = typeof self.toyIndex === "number" ? self.toyIndex : 0;
var foundToy = false;
var toyTries = 0;
do {
self.toyIndex = (typeof self.toyIndex === "number" ? self.toyIndex : 0) + 1;
if (self.toyIndex >= self.toyImages.length) self.toyIndex = 0;
var toyId = self.toyImages[self.toyIndex];
// Only allow Blank or unused
if (toyId === 'Blank' || !usedToyImages[toyId]) {
foundToy = true;
// Mark as used if not Blank
if (toyId !== 'Blank') {
usedToyImages[toyId] = self;
}
self.currentInstrument = self.attachAsset(toyId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
break;
}
toyTries++;
} while (self.toyIndex !== startToyIndex && toyTries < self.toyImages.length + 1);
// If no available toy found, stay on current (shouldn't happen)
if (!foundToy) {
self.toyIndex = startToyIndex;
}
}
self.toggle();
// Update clues with strikethrough after changing dot
if (typeof updateCluesWithStrikethrough === 'function') {
updateCluesWithStrikethrough();
}
};
// Initialize dot as inactive
// Initialize with blank instrument
self.currentInstrument = self.attachAsset('Blank', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
return self;
});
// Puzzle class for managing a puzzle element in the game
var Puzzle = Container.expand(function () {
var self = Container.call(this);
// Add a 4x5 asset to the puzzle and scale it to be exactly 2048 wide
var targetWidth = 2048;
var assetWidth = 1000;
var scale = targetWidth / assetWidth;
// Center horizontally, align to top
var puzzleImage = self.attachAsset('4x5', {
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: 0,
scaleX: scale,
scaleY: scale
});
// (Story asset removed)
// (Clue images and clue text removed)
// Create 25 dots in a 5x5 grid
self.dots = [];
var gridSize = 5;
var dotSpacing = targetWidth / (gridSize + 1); // Distribute dots evenly across the width
var gridHeight = puzzleImage.height * scale;
var verticalSpacing = gridHeight / (gridSize + 1);
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
var dot = new Dot();
dot.gridX = col;
dot.gridY = row;
// Initialize all indices to 0 for consistent reset state
dot.instrumentIndex = 0;
dot.specialInstrumentIndex = 0;
dot.animalIndex = 0;
dot.foodIndex = 0;
dot.toyIndex = 0;
// Position dots over the 4x5 asset
dot.x = (col + 1) * dotSpacing;
dot.y = (row + 1) * verticalSpacing;
self.dots.push(dot);
self.addChild(dot);
}
}
// Example: puzzle state
self.isSolved = false;
// Method to check if puzzle is solved according to target solution
self.checkSolved = function () {
// Target solution mapping: dot index -> expected image
var targetSolution = {
0: 'Drum',
// Dot 1 (row 1, col 1)
1: 'Harp',
// Dot 2 (row 1, col 2)
2: 'Saxophone',
// Dot 3 (row 1, col 3)
3: 'Flute',
// Dot 4 (row 1, col 4)
4: 'Gutair',
// Dot 5 (row 1, col 5)
5: 'Spaghetti',
// Dot 6 (row 2, col 1)
6: 'Donut',
// Dot 7 (row 2, col 2)
7: 'Chips',
// Dot 8 (row 2, col 3)
8: 'Icecream',
// Dot 9 (row 2, col 4)
9: 'Pizza',
// Dot 10 (row 2, col 5)
10: 'Basketball',
// Dot 11 (row 3, col 1)
11: 'Dolls',
// Dot 12 (row 3, col 2)
12: 'Lego',
// Dot 13 (row 3, col 3)
13: 'Videogame',
// Dot 14 (row 3, col 4)
14: 'Plushtoy',
// Dot 15 (row 3, col 5)
15: 'Fish',
// Dot 16 (row 4, col 1)
16: 'Turtle',
// Dot 17 (row 4, col 2)
17: 'Frog',
// Dot 18 (row 4, col 3)
18: 'Cat',
// Dot 19 (row 4, col 4)
19: 'Dog',
// Dot 20 (row 4, col 5)
20: 'KJ',
// Dot 21 (row 5, col 1)
21: 'Khalida',
// Dot 22 (row 5, col 2)
22: 'Sapphire',
// Dot 23 (row 5, col 3)
23: 'Harmony',
// Dot 24 (row 5, col 4)
24: 'PJ' // Dot 25 (row 5, col 5)
};
// Check if all dots match the target solution
var allCorrect = true;
for (var i = 0; i < self.dots.length; i++) {
var dot = self.dots[i];
var expectedImage = targetSolution[i];
// Get current image of the dot based on its row and current index
var currentImage = 'Blank';
var row = dot.gridY;
if (row === 0 && dot.instruments) {
// Row 1: Music instruments
currentImage = dot.instruments[dot.instrumentIndex];
} else if (row === 1 && dot.foodImages) {
// Row 2: Food
currentImage = dot.foodImages[dot.foodIndex];
} else if (row === 2 && dot.toyImages) {
// Row 3: Toys
currentImage = dot.toyImages[dot.toyIndex];
} else if (row === 3 && dot.animalImages) {
// Row 4: Animals
currentImage = dot.animalImages[dot.animalIndex];
} else if (row === 4 && dot.specialInstruments) {
// Row 5: Family
currentImage = dot.specialInstruments[dot.specialInstrumentIndex];
}
// Check if current image matches expected
if (currentImage !== expectedImage) {
allCorrect = false;
break;
}
}
// Update solved state only - win display handled by green tick
if (allCorrect && !self.isSolved) {
self.isSolved = true;
} else if (!allCorrect && self.isSolved) {
self.isSolved = false;
}
};
// Example: update method for per-frame logic
self.update = function () {
// Add per-frame puzzle logic here
// For example, check for completion
self.checkSolved();
};
return self;
});
// TitleScreen class for the game's title screen
var TitleScreen = Container.expand(function () {
var self = Container.call(this);
// Add background
var bg = self.attachAsset('Street', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 20.48,
scaleY: 27.32,
alpha: 0.95
});
// Add title image to fill the whole screen
var titleImg = self.attachAsset('Title', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1.0,
scaleY: 1.0
});
// Add animated swirl image, centered, IN FRONT of title
var swirlImg = self.attachAsset('Swirl', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.45
});
self.swirlImg = swirlImg;
// Add heading image above the title image and swirl, so it is in front of both
// Start tiny in the center, then tween to large in the center
var headingImg = self.attachAsset('Heading', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
// Start in the center
scaleX: 0.1,
scaleY: 0.1
});
// Animate heading to grow and stay in the center position, but only after fully loaded
function startTitleScreenAnimations() {
tween(headingImg, {
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 5000,
easing: tween.cubicOut
});
// Animate swirl rotation using tween for infinite smooth rotation
function startSwirlTween() {
if (!self.swirlImg) return;
// Always rotate to the next full circle (-2*PI) from current rotation for opposite direction
var startRotation = self.swirlImg.rotation || 0;
var endRotation = startRotation - Math.PI * 2;
tween(self.swirlImg, {
rotation: endRotation
}, {
duration: 8000,
easing: tween.linear,
onFinish: function onFinish() {
// Reset rotation to avoid overflow and keep animation smooth
if (self.swirlImg) self.swirlImg.rotation = self.swirlImg.rotation % (Math.PI * 2);
startSwirlTween();
}
});
}
startSwirlTween();
}
// Wait for the next tick to ensure all assets are loaded and the title screen is fully visible
LK.setTimeout(function () {
if (self && self.parent) {
startTitleScreenAnimations();
}
}, 0);
// Add "Tap to Start" text with pulsing effect
var startText = new Text2("TAP TO START", {
size: 120,
fill: 0xFFFF00,
align: 'center',
font: "'Times New Roman','Times New Roman Bold','GillSans-Bold',Impact,'Arial Black',Tahoma"
});
startText.anchor.set(0.5, 0.5);
startText.x = 2048 / 2;
startText.y = 2732 - 300;
self.addChild(startText);
// Pulse the start text
var _pulseStartText = function pulseStartText() {
tween(startText, {
alpha: 0.3
}, {
duration: 800,
easing: tween.sineInOut,
onFinish: function onFinish() {
tween(startText, {
alpha: 1
}, {
duration: 800,
easing: tween.sineInOut,
onFinish: _pulseStartText
});
}
});
};
_pulseStartText();
// Handle tap/click to start game
self.down = function (x, y, obj) {
// Fade out title screen
tween(self, {
alpha: 0
}, {
duration: 500,
easing: tween.cubicOut,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
// Start the main game
startMainGame();
}
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Global variables that need to be accessible
var usedInstruments = {};
var puzzle;
var greenTick;
var numberImages = [];
var allClueAssets = [];
var infoButton;
var instructionsScreen = null;
var clueStrikeStates = [false, false];
var usedSpecialInstruments = {};
var usedAnimalImages = {};
var usedFoodImages = {};
var usedToyImages = {};
// Function to start the main game after title screen
function startMainGame() {
// Reset global variables
usedInstruments = {};
usedSpecialInstruments = {};
usedAnimalImages = {};
usedFoodImages = {};
usedToyImages = {};
numberImages = [];
allClueAssets = [];
clueStrikeStates = [false, false];
// Add Puzzle to the game when it starts
puzzle = new Puzzle();
game.addChild(puzzle);
// Add 1 2 3 4 5 number image assets to the top of the screen
var numberLabelY = 60; // 60px from top
var numberSpacing = 2048 / 6; // 5 numbers, 6 spaces
// Track number image assets for later removal
var numberImages = [];
for (var i = 1; i <= 5; i++) {
var numImg = LK.getAsset(i + "", {
anchorX: 0.5,
anchorY: 0,
x: i * numberSpacing,
y: numberLabelY,
scaleX: 0.7,
scaleY: 0.7
});
game.addChild(numImg);
numberImages.push(numImg);
}
// --- CLUE STRIKETHROUGH LOGIC ---
// Track strikethrough state for clues (first two clues only for now)
var clueStrikeStates = [false, false];
// Helper to apply or remove strikethrough effect (alpha fade) for a group of clue assets
function setClueStrikethrough(clueGroup, isStruck) {
var alpha = isStruck ? 0.35 : 1.0;
for (var i = 0; i < clueGroup.length; i++) {
if (clueGroup[i]) clueGroup[i].alpha = alpha;
}
}
// Helper to toggle strikethrough and remember state
// Optionally accepts a clueIndex to persist state for first two clues
function makeClueStrikeToggle(clueGroup, clueIndex) {
var struck = false;
// If restoring, use persisted state
if (typeof clueIndex === "number" && clueStrikeStates[clueIndex] !== undefined) {
struck = clueStrikeStates[clueIndex];
setClueStrikethrough(clueGroup, struck);
}
for (var i = 0; i < clueGroup.length; i++) {
// Attach to all, but only one will handle the toggle
clueGroup[i].down = function () {
struck = !struck;
setClueStrikethrough(clueGroup, struck);
if (typeof clueIndex === "number") {
clueStrikeStates[clueIndex] = struck;
}
};
}
}
// Add sapphire avatar = fries avatar clue to the left side of the puzzle screen
var sapphireImg = LK.getAsset('Sapphire', {
anchorX: 0.0,
anchorY: 1.0,
x: 30,
y: 2732 - 40 - 500 + 30,
scaleX: 0.45,
scaleY: 0.45
});
var friesImg = LK.getAsset('Chips', {
anchorX: 0.0,
anchorY: 1.0,
x: 30 + 200 * 0.45 + 20 + 60,
// moved right by 60px to reveal equals symbol
// Sapphire width * scale + 20px gap + extra space for equals
y: 2732 - 40 - 500 + 30,
scaleX: 0.45,
scaleY: 0.45
});
var eqText = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqText.anchor.set(0.5, 1.0);
eqText.x = (sapphireImg.x + friesImg.x) / 2 + 30; // Centered between sapphire and fries, nudged right for balance
eqText.y = 2732 - 40 - 500 + 30;
game.addChild(sapphireImg);
game.addChild(eqText);
game.addChild(friesImg);
makeClueStrikeToggle([sapphireImg, eqText, friesImg], 0);
// Add sapphire avatar < videogame asset as another clue starting the next clues column
var sapphireVideogameClueY = sapphireImg.y; // align with first clue row
var sapphireVideogameColumnX = friesImg.x + 350 + 600; // start a new column to the right of previous clues
var sapphireClueImg = LK.getAsset('Sapphire', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX,
y: sapphireVideogameClueY,
scaleX: 0.45,
scaleY: 0.45
});
var videogameClueImg_sapphire = LK.getAsset('Videogame', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60,
y: sapphireVideogameClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltTextSapphireVideogame = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltTextSapphireVideogame.anchor.set(0.5, 1.0);
ltTextSapphireVideogame.x = (sapphireClueImg.x + videogameClueImg_sapphire.x) / 2 + 30;
ltTextSapphireVideogame.y = sapphireVideogameClueY;
game.addChild(sapphireClueImg);
game.addChild(ltTextSapphireVideogame);
game.addChild(videogameClueImg_sapphire);
makeClueStrikeToggle([sapphireClueImg, ltTextSapphireVideogame, videogameClueImg_sapphire], 1);
// Add guitar avatar > cat asset as another clue under the sapphire < videogame clue
var guitarCatClueY = sapphireVideogameClueY + 120; // 120px below the sapphire < videogame clue
var guitarImg = LK.getAsset('Gutair', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX,
y: guitarCatClueY,
scaleX: 0.45,
scaleY: 0.45
});
var catImg = LK.getAsset('Cat', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60,
y: guitarCatClueY,
scaleX: 0.45,
scaleY: 0.45
});
var gtTextGuitarCat = new Text2(">", {
size: 120,
fill: 0xFFFFFF
});
gtTextGuitarCat.anchor.set(0.5, 1.0);
gtTextGuitarCat.x = (guitarImg.x + catImg.x) / 2 + 30;
gtTextGuitarCat.y = guitarCatClueY;
game.addChild(guitarImg);
game.addChild(gtTextGuitarCat);
game.addChild(catImg);
makeClueStrikeToggle([guitarImg, gtTextGuitarCat, catImg]);
// Add donut avatar < chips asset as another clue under the Gutair cat clue
var donutChipsClueY = guitarCatClueY + 120; // 120px below the guitar > cat clue
var donutImg = LK.getAsset('Donut', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX,
y: donutChipsClueY,
scaleX: 0.45,
scaleY: 0.45
});
var chipsImg = LK.getAsset('Chips', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60,
y: donutChipsClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltTextDonutChips = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltTextDonutChips.anchor.set(0.5, 1.0);
ltTextDonutChips.x = (donutImg.x + chipsImg.x) / 2 + 30;
ltTextDonutChips.y = donutChipsClueY;
game.addChild(donutImg);
game.addChild(ltTextDonutChips);
game.addChild(chipsImg);
makeClueStrikeToggle([donutImg, ltTextDonutChips, chipsImg]);
// Add plushtoy avatar = dog asset as another clue under donut and chips
var plushtoyDogClueY = donutChipsClueY + 120; // 120px below the donut < chips clue
var plushtoyImg = LK.getAsset('Plushtoy', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX,
y: plushtoyDogClueY,
scaleX: 0.45,
scaleY: 0.45
});
var dogImg = LK.getAsset('Dog', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60,
y: plushtoyDogClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqTextPlushtoyDog = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqTextPlushtoyDog.anchor.set(0.5, 1.0);
eqTextPlushtoyDog.x = (plushtoyImg.x + dogImg.x) / 2 + 30;
eqTextPlushtoyDog.y = plushtoyDogClueY;
game.addChild(plushtoyImg);
game.addChild(eqTextPlushtoyDog);
game.addChild(dogImg);
makeClueStrikeToggle([plushtoyImg, eqTextPlushtoyDog, dogImg]);
// Add basketball avatar < donut asset as another clue under plushtoy and dog clue
var basketballDonutClueY = plushtoyDogClueY + 120; // 120px below the plushtoy = dog clue
var basketballImg = LK.getAsset('Basketball', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX,
y: basketballDonutClueY,
scaleX: 0.45,
scaleY: 0.45
});
var donut2Img = LK.getAsset('Donut', {
anchorX: 0.0,
anchorY: 1.0,
x: sapphireVideogameColumnX + 200 * 0.45 + 20 + 60,
y: basketballDonutClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltTextBasketballDonut = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltTextBasketballDonut.anchor.set(0.5, 1.0);
ltTextBasketballDonut.x = (basketballImg.x + donut2Img.x) / 2 + 30;
ltTextBasketballDonut.y = basketballDonutClueY;
game.addChild(basketballImg);
game.addChild(ltTextBasketballDonut);
game.addChild(donut2Img);
makeClueStrikeToggle([basketballImg, ltTextBasketballDonut, donut2Img]);
// Add PJ avatar = dog asset as another clue starting a new column
var pjDogColumnX = sapphireVideogameColumnX + 2 * (200 * 0.45 + 20 + 60) + 350; // new column to the right
var pjDogClueY = sapphireVideogameClueY; // align with top row
var pjDogImg = LK.getAsset('PJ', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX - 100,
y: pjDogClueY,
scaleX: 0.45,
scaleY: 0.45
});
var dog2Img = LK.getAsset('Dog', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100,
y: pjDogClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqTextPjDog = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqTextPjDog.anchor.set(0.5, 1.0);
eqTextPjDog.x = (pjDogImg.x + dog2Img.x) / 2 + 30;
eqTextPjDog.y = pjDogClueY;
game.addChild(pjDogImg);
game.addChild(eqTextPjDog);
game.addChild(dog2Img);
makeClueStrikeToggle([pjDogImg, eqTextPjDog, dog2Img]);
// Add spaghetti avatar < turtle asset as another clue under PJ dog clue
var spaghettiTurtleClueY = pjDogClueY + 120; // 120px below the PJ = dog clue
var spaghettiImg = LK.getAsset('Spaghetti', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX - 100,
y: spaghettiTurtleClueY,
scaleX: 0.45,
scaleY: 0.45
});
var turtleImg = LK.getAsset('Turtle', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100,
y: spaghettiTurtleClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltTextSpaghettiTurtle = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltTextSpaghettiTurtle.anchor.set(0.5, 1.0);
ltTextSpaghettiTurtle.x = (spaghettiImg.x + turtleImg.x) / 2 + 30;
ltTextSpaghettiTurtle.y = spaghettiTurtleClueY;
game.addChild(spaghettiImg);
game.addChild(ltTextSpaghettiTurtle);
game.addChild(turtleImg);
makeClueStrikeToggle([spaghettiImg, ltTextSpaghettiTurtle, turtleImg]);
// Add frog avatar < ice cream asset as another clue under spaghetti turtle clue
var frogIcecreamClueY = spaghettiTurtleClueY + 120; // 120px below the spaghetti < turtle clue
var frogImg = LK.getAsset('Frog', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX - 100,
y: frogIcecreamClueY,
scaleX: 0.45,
scaleY: 0.45
});
var icecreamImg = LK.getAsset('Icecream', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100,
y: frogIcecreamClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltTextFrogIcecream = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltTextFrogIcecream.anchor.set(0.5, 1.0);
ltTextFrogIcecream.x = (frogImg.x + icecreamImg.x) / 2 + 30;
ltTextFrogIcecream.y = frogIcecreamClueY;
game.addChild(frogImg);
game.addChild(ltTextFrogIcecream);
game.addChild(icecreamImg);
makeClueStrikeToggle([frogImg, ltTextFrogIcecream, icecreamImg]);
// Add fish avatar = spaghetti asset as another clue under frog icecream clue
var fishSpaghettiClueY = frogIcecreamClueY + 120; // 120px below the frog < icecream clue
var fishImg = LK.getAsset('Fish', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX - 100,
y: fishSpaghettiClueY,
scaleX: 0.45,
scaleY: 0.45
});
var spaghetti2Img = LK.getAsset('Spaghetti', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100,
y: fishSpaghettiClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqTextFishSpaghetti = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqTextFishSpaghetti.anchor.set(0.5, 1.0);
eqTextFishSpaghetti.x = (fishImg.x + spaghetti2Img.x) / 2 + 30;
eqTextFishSpaghetti.y = fishSpaghettiClueY;
game.addChild(fishImg);
game.addChild(eqTextFishSpaghetti);
game.addChild(spaghetti2Img);
makeClueStrikeToggle([fishImg, eqTextFishSpaghetti, spaghetti2Img]);
// Add cat avatar = videogame asset as another clue under fish and spaghetti
var catVideogameClueY = fishSpaghettiClueY + 120; // 120px below the fish = spaghetti clue
var catClueImg = LK.getAsset('Cat', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX - 100,
y: catVideogameClueY,
scaleX: 0.45,
scaleY: 0.45
});
var videogameClueImg_cat = LK.getAsset('Videogame', {
anchorX: 0.0,
anchorY: 1.0,
x: pjDogColumnX + 200 * 0.45 + 20 + 60 - 100,
y: catVideogameClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqTextCatVideogame = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqTextCatVideogame.anchor.set(0.5, 1.0);
eqTextCatVideogame.x = (catClueImg.x + videogameClueImg_cat.x) / 2 + 30;
eqTextCatVideogame.y = catVideogameClueY;
game.addChild(catClueImg);
game.addChild(eqTextCatVideogame);
game.addChild(videogameClueImg_cat);
makeClueStrikeToggle([catClueImg, eqTextCatVideogame, videogameClueImg_cat]);
// Add Khalida avatar > KJ asset as another clue on the right of the first clue (swap with harmony < pizza)
var harmonyClueY = sapphireImg.y; // align with first clue
var khalidaClueImg = LK.getAsset('Khalida', {
anchorX: 0.0,
anchorY: 1.0,
x: friesImg.x + 350,
y: harmonyClueY,
scaleX: 0.45,
scaleY: 0.45
});
var kjClueImg = LK.getAsset('KJ', {
anchorX: 0.0,
anchorY: 1.0,
x: friesImg.x + 350 + 200 * 0.45 + 20 + 60,
y: harmonyClueY,
scaleX: 0.45,
scaleY: 0.45
});
var gtTextKhalidaKJ = new Text2(">", {
size: 120,
fill: 0xFFFFFF
});
gtTextKhalidaKJ.anchor.set(0.5, 1.0);
gtTextKhalidaKJ.x = (khalidaClueImg.x + kjClueImg.x) / 2 + 30;
gtTextKhalidaKJ.y = harmonyClueY;
game.addChild(khalidaClueImg);
game.addChild(gtTextKhalidaKJ);
game.addChild(kjClueImg);
makeClueStrikeToggle([khalidaClueImg, gtTextKhalidaKJ, kjClueImg]);
// Add PJ avatar = 5 asset as another clue under the first clue
var pjClueY = sapphireImg.y + 120; // 120px below the first clue
var pjImg = LK.getAsset('PJ', {
anchorX: 0.0,
anchorY: 1.0,
x: 30,
y: pjClueY,
scaleX: 0.45,
scaleY: 0.45
});
var fiveImg = LK.getAsset('5', {
anchorX: 0.0,
anchorY: 1.0,
x: 30 + 200 * 0.45 + 20 + 60,
// match fries x
y: pjClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqText2 = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqText2.anchor.set(0.5, 1.0);
eqText2.x = (pjImg.x + fiveImg.x) / 2 + 30;
eqText2.y = pjClueY;
game.addChild(pjImg);
game.addChild(eqText2);
game.addChild(fiveImg);
makeClueStrikeToggle([pjImg, eqText2, fiveImg]);
// Add KJ avatar = 1 asset as another clue under the second clue
var kjClueY = pjClueY + 120; // 120px below the second clue
var kjImg = LK.getAsset('KJ', {
anchorX: 0.0,
anchorY: 1.0,
x: 30,
y: kjClueY,
scaleX: 0.45,
scaleY: 0.45
});
var oneImg = LK.getAsset('1', {
anchorX: 0.0,
anchorY: 1.0,
x: 30 + 200 * 0.45 + 20 + 60,
y: kjClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqText3 = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqText3.anchor.set(0.5, 1.0);
eqText3.x = (kjImg.x + oneImg.x) / 2 + 30;
eqText3.y = kjClueY;
game.addChild(kjImg);
game.addChild(eqText3);
game.addChild(oneImg);
makeClueStrikeToggle([kjImg, eqText3, oneImg]);
// Add Saxophone avatar = 3 asset as another clue under the harmony clue
var saxClueY = harmonyClueY + 120; // 120px below the harmony clue
// Use the same x as the right column clues (e.g. 30 + 1200)
var rightColumnX = friesImg.x + 350; // This matches the x used for right column clues above
var saxImg = LK.getAsset('Saxophone', {
anchorX: 0.0,
anchorY: 1.0,
x: rightColumnX,
// align left with right column clues
y: saxClueY,
scaleX: 0.45,
scaleY: 0.45
});
var threeImg = LK.getAsset('3', {
anchorX: 0.0,
anchorY: 1.0,
x: rightColumnX + 200 * 0.45 + 20 + 60,
// match pizza x offset
y: saxClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqTextSax = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqTextSax.anchor.set(0.5, 1.0);
eqTextSax.x = (saxImg.x + threeImg.x) / 2 + 30;
eqTextSax.y = saxClueY;
game.addChild(saxImg);
game.addChild(eqTextSax);
game.addChild(threeImg);
makeClueStrikeToggle([saxImg, eqTextSax, threeImg]);
// Add Khalida avatar = harp avatar as another clue under the third clue
var khalidaClueY = kjClueY + 120; // 120px below the third clue
var khalidaImg = LK.getAsset('Khalida', {
anchorX: 0.0,
anchorY: 1.0,
x: 30,
y: khalidaClueY,
scaleX: 0.45,
scaleY: 0.45
});
var harpImg = LK.getAsset('Harp', {
anchorX: 0.0,
anchorY: 1.0,
x: 30 + 200 * 0.45 + 20 + 60,
y: khalidaClueY,
scaleX: 0.45,
scaleY: 0.45
});
var eqText4 = new Text2("=", {
size: 120,
fill: 0xFFFFFF
});
eqText4.anchor.set(0.5, 1.0);
eqText4.x = (khalidaImg.x + harpImg.x) / 2 + 30;
eqText4.y = khalidaClueY;
game.addChild(khalidaImg);
game.addChild(eqText4);
game.addChild(harpImg);
makeClueStrikeToggle([khalidaImg, eqText4, harpImg]);
// Add Khalida avatar > KJ asset as another clue under the saxophone clue (right column, below saxophone = 3)
var khalidaKJClueY = saxClueY + 120; // 120px below the saxophone clue
var drumClueY = khalidaClueY + 120; // 120px below the fourth clue
var drumImg = LK.getAsset('Drum', {
anchorX: 0.0,
anchorY: 1.0,
x: 30,
y: drumClueY,
scaleX: 0.45,
scaleY: 0.45
});
var dollsImg = LK.getAsset('Dolls', {
anchorX: 0.0,
anchorY: 1.0,
x: 30 + 200 * 0.45 + 20 + 60,
y: drumClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltText = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltText.anchor.set(0.5, 1.0);
ltText.x = (drumImg.x + dollsImg.x) / 2 + 30;
ltText.y = drumClueY;
game.addChild(drumImg);
game.addChild(ltText);
game.addChild(dollsImg);
makeClueStrikeToggle([drumImg, ltText, dollsImg]);
// Add harmony avatar < pizza asset as another clue under the saxophone clue (right column, below saxophone = 3)
var harmonyImg = LK.getAsset('Harmony', {
anchorX: 0.0,
anchorY: 1.0,
x: rightColumnX,
// right column, same x as above
y: khalidaKJClueY,
scaleX: 0.55,
scaleY: 0.55
});
var pizzaImgClue = LK.getAsset('Pizza', {
anchorX: 0.0,
anchorY: 1.0,
x: rightColumnX + 200 * 0.45 + 20 + 60,
y: khalidaKJClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltTextHarmony = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltTextHarmony.anchor.set(0.5, 1.0);
ltTextHarmony.x = (harmonyImg.x + pizzaImgClue.x) / 2 + 30;
ltTextHarmony.y = khalidaKJClueY;
game.addChild(harmonyImg);
game.addChild(ltTextHarmony);
game.addChild(pizzaImgClue);
makeClueStrikeToggle([harmonyImg, ltTextHarmony, pizzaImgClue]);
// Add drum avatar < harp avatar as another clue under the KJ Khalida clue
var drumHarpClueY = khalidaKJClueY + 120; // 120px below the KJ Khalida clue
var drumHarpImg = LK.getAsset('Drum', {
anchorX: 0.0,
anchorY: 1.0,
x: harmonyImg.x,
y: drumHarpClueY,
scaleX: 0.45,
scaleY: 0.45
});
var harpClueImg = LK.getAsset('Harp', {
anchorX: 0.0,
anchorY: 1.0,
x: harmonyImg.x + 200 * 0.45 + 20 + 60,
y: drumHarpClueY,
scaleX: 0.45,
scaleY: 0.45
});
var ltTextDrumHarp = new Text2("<", {
size: 120,
fill: 0xFFFFFF
});
ltTextDrumHarp.anchor.set(0.5, 1.0);
ltTextDrumHarp.x = (drumHarpImg.x + harpClueImg.x) / 2 + 30;
ltTextDrumHarp.y = drumHarpClueY;
game.addChild(drumHarpImg);
game.addChild(ltTextDrumHarp);
game.addChild(harpClueImg);
makeClueStrikeToggle([drumHarpImg, ltTextDrumHarp, harpClueImg]);
// Add harmony avatar > saxophone asset as another clue under the drum harp clue (right column, below drum < harp)
var harmonySaxClueY = drumHarpClueY + 120; // 120px below the drum harp clue
var harmonyAvatarImg = LK.getAsset('Harmony', {
anchorX: 0.0,
anchorY: 1.0,
x: harmonyImg.x,
y: harmonySaxClueY,
scaleX: 0.55,
scaleY: 0.55
});
var saxophoneAvatarImg = LK.getAsset('Saxophone', {
anchorX: 0.0,
anchorY: 1.0,
x: harmonyImg.x + 200 * 0.45 + 20 + 60,
y: harmonySaxClueY,
scaleX: 0.45,
scaleY: 0.45
});
var gtTextHarmonySax = new Text2(">", {
size: 120,
fill: 0xFFFFFF
});
gtTextHarmonySax.anchor.set(0.5, 1.0);
gtTextHarmonySax.x = (harmonyAvatarImg.x + saxophoneAvatarImg.x) / 2 + 30;
gtTextHarmonySax.y = harmonySaxClueY;
game.addChild(harmonyAvatarImg);
game.addChild(gtTextHarmonySax);
game.addChild(saxophoneAvatarImg);
makeClueStrikeToggle([harmonyAvatarImg, gtTextHarmonySax, saxophoneAvatarImg]);
// Add green tick to bottom right corner
var greenTick = LK.getAsset('Greentick', {
anchorX: 1.0,
anchorY: 1.0,
x: 2048 - 0,
//{7i} // moved right by 50px
y: 2732 - 50 - 600 - 35,
// moved up by 15px (previously 10, now 15)
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(greenTick);
// Add info button to bottom left corner
var infoButton = LK.getAsset('Info', {
anchorX: 0.0,
anchorY: 1.0,
x: 0,
y: 2732 - 50 - 600 - 30,
scaleX: 1.5,
scaleY: 1.5
});
game.addChild(infoButton);
// Variable to track instructions screen
var instructionsScreen = null;
// Make info button clickable to show illustrated how-to-play guide
infoButton.down = function (x, y, obj) {
// If instructions screen is already showing, hide it
if (instructionsScreen && instructionsScreen.parent) {
instructionsScreen.parent.removeChild(instructionsScreen);
instructionsScreen = null;
return;
}
// Create instructions screen container
instructionsScreen = new Container();
// Add semi-transparent background
var instructionsBg = LK.getAsset('Street', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 20.48,
scaleY: 27.32,
alpha: 0.92
});
instructionsScreen.addChild(instructionsBg);
// Move all images to the top of the instructions overlay
var topY = 120 - 300; // Top margin for images, moved up by 300px
// Step 1: Show the puzzle board image at the top
var boardImg = LK.getAsset('4x5', {
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: topY,
scaleX: 0.7,
scaleY: 0.7
});
instructionsScreen.addChild(boardImg);
// Calculate the bottom of the board image for next row of images
var boardImgBottom = topY + 1000 * 0.7; // 1000 is asset height
// Row of sample images just below the board image
var rowImgY = boardImgBottom + 40; // 40px padding below board
// Step 2: Show a hand icon over a dot to indicate tapping (use 'Greentick' as a hand substitute)
var handIcon = LK.getAsset('Greentick', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 350,
y: rowImgY + 60,
scaleX: 0.7,
scaleY: 0.7,
alpha: 0.7
});
instructionsScreen.addChild(handIcon);
// Step 3: Show a sample instrument image (e.g. Drum) above the dot
var drumImg = LK.getAsset('Drum', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 350,
y: rowImgY,
scaleX: 1.2,
scaleY: 1.2
});
instructionsScreen.addChild(drumImg);
// Step 4: Show a sample food image (e.g. Pizza) above a dot in row 2
var pizzaImg = LK.getAsset('Pizza', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 100,
y: rowImgY,
scaleX: 1.2,
scaleY: 1.2
});
instructionsScreen.addChild(pizzaImg);
// Step 5: Show a sample toy image (e.g. Lego) above a dot in row 3
var legoImg = LK.getAsset('Lego', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 150,
y: rowImgY,
scaleX: 1.2,
scaleY: 1.2
});
instructionsScreen.addChild(legoImg);
// Step 6: Show a sample animal image (e.g. Cat) above a dot in row 4
var catImg = LK.getAsset('Cat', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 350,
y: rowImgY,
scaleX: 1.2,
scaleY: 1.2
});
instructionsScreen.addChild(catImg);
// Step 7: Show a sample family image (e.g. PJ) to the right of cat in row 5
var pjImg = LK.getAsset('PJ', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 550,
y: rowImgY,
scaleX: 0.7,
scaleY: 0.7
});
instructionsScreen.addChild(pjImg);
// Step 8: Show the green tick in the bottom right as the "submit" button
var tickIcon = LK.getAsset('Greentick', {
anchorX: 1.0,
anchorY: 1.0,
x: 2048 - 50,
y: 2732 - 50,
scaleX: 1.2,
scaleY: 1.2
});
instructionsScreen.addChild(tickIcon);
// Step 9: Add step-by-step text instructions
var instructionsText = new Text2("HOW TO PLAY THIS PUZZLE GAME\n" + "Match each dot to the correct picture\n" + "in its row. Each row is a different category.\n\n" + "1. Tap a dot to cycle through the possible items for that row.\n" + " (Each tap changes the picture on that dot)\n\n" + "2. Each row has a different category:\n" + " Row 1: Music\n" + " Row 2: Food\n" + " Row 3: Toys\n" + " Row 4: Animals\n" + " Row 5: Family\n\n" + "3. Use the clues at the bottom of the screen\n" + " to help you match each item to its correct spot.\n\n" + "4. When you think you've solved the puzzle,\n" + " tap the green tick in the bottom right to check your answer!\n\n" + "Tip: Tap the info button any time for help.\n\n" + "Tap anywhere to close this guide.", {
size: 70,
fill: 0xffffff,
align: 'center',
font: "'Times New Roman Bold','Times New Roman','GillSans-Bold',Impact,'Arial Black',Tahoma"
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 2048 / 2;
instructionsText.y = 2732 / 2 + 420;
instructionsScreen.addChild(instructionsText);
// Make the entire instructions screen clickable to close
instructionsScreen.down = function (x, y, obj) {
if (instructionsScreen && instructionsScreen.parent) {
instructionsScreen.parent.removeChild(instructionsScreen);
instructionsScreen = null;
}
};
// Add instructions screen to game
game.addChild(instructionsScreen);
};
// Helper to show/hide info button
function setInfoButtonVisible(visible) {
if (infoButton && infoButton.parent) {
infoButton.visible = !!visible;
}
}
// Function to update clues with strikethrough for solved items (picture clues only)
function updateCluesWithStrikethrough() {
// This function now only handles picture clue strikethrough effects
// The picture clues are already implemented with makeClueStrikeToggle
// No additional text-based clue processing needed
}
// Make green tick clickable to enter puzzle attempt
greenTick.down = function (x, y, obj) {
// Remove all clue assets from game when green tick is clicked
if (typeof allClueAssets === "undefined") allClueAssets = [];
// If not already collected, collect all clue assets for later restoration
if (allClueAssets.length === 0) {
// Collect all clue asset instances, including both videogame clue images
allClueAssets = [sapphireImg, friesImg, eqText, sapphireClueImg, ltTextSapphireVideogame, videogameClueImg_sapphire,
// sapphire < videogame
guitarImg, catImg, gtTextGuitarCat, donutImg, chipsImg, ltTextDonutChips, plushtoyImg, dogImg, eqTextPlushtoyDog, basketballImg, donut2Img, ltTextBasketballDonut, pjDogImg, dog2Img, eqTextPjDog, spaghettiImg, turtleImg, ltTextSpaghettiTurtle, frogImg, icecreamImg, ltTextFrogIcecream, fishImg, spaghetti2Img, eqTextFishSpaghetti, catClueImg, eqTextCatVideogame, videogameClueImg_cat,
// cat = videogame
khalidaClueImg, kjClueImg, gtTextKhalidaKJ, pjImg, fiveImg, eqText2, kjImg, oneImg, eqText3, saxImg, threeImg, eqTextSax, khalidaImg, harpImg, eqText4, drumImg, dollsImg, ltText, harmonyImg, pizzaImgClue, ltTextHarmony, drumHarpImg, harpClueImg, ltTextDrumHarp, harmonyAvatarImg, saxophoneAvatarImg, gtTextHarmonySax];
// Remove duplicates and nulls for safety
var seen = [];
var filtered = [];
for (var i = 0; i < allClueAssets.length; i++) {
var asset = allClueAssets[i];
if (asset && seen.indexOf(asset) === -1) {
seen.push(asset);
filtered.push(asset);
}
}
allClueAssets = filtered;
}
for (var i = 0; i < allClueAssets.length; i++) {
if (allClueAssets[i] && allClueAssets[i].parent) {
allClueAssets[i].parent.removeChild(allClueAssets[i]);
}
}
// Remove number image assets from game when green tick is clicked
if (typeof numberImages !== "undefined" && numberImages.length) {
for (var i = 0; i < numberImages.length; i++) {
if (numberImages[i] && numberImages[i].parent) numberImages[i].parent.removeChild(numberImages[i]);
}
}
if (puzzle && typeof puzzle.checkSolved === "function") {
// Run the check
puzzle.checkSolved();
// If solved, show endpuzzletwo scene
if (puzzle.isSolved) {
// Remove the puzzle and green tick from the game
if (puzzle.parent) puzzle.parent.removeChild(puzzle);
if (greenTick.parent) greenTick.parent.removeChild(greenTick);
// Hide info button when showing endpuzzletwo
setInfoButtonVisible(false);
// Show endpuzzletwo asset centered on screen
var endpuzzletwo = LK.getAsset('Endpuzzletwo', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
});
game.addChild(endpuzzletwo);
// Fade in endpuzzletwo
tween(endpuzzletwo, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
// After 2 seconds, fade out and swap to correct scene with correct word under the correct image
LK.setTimeout(function () {
tween(endpuzzletwo, {
alpha: 0
}, {
duration: 350,
easing: tween.cubicIn,
onFinish: function onFinish() {
if (endpuzzletwo.parent) endpuzzletwo.parent.removeChild(endpuzzletwo);
// Show Correct scene (centered)
var correctScene = LK.getAsset('Correct', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
});
game.addChild(correctScene);
// Fade in correctScene
tween(correctScene, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
// No winning image displayed - just show the correct word
// Show the correct word asset at the bottom of the screen
var correctWord = LK.getAsset('Correctword', {
anchorX: 0.5,
anchorY: 1.0,
x: 2048 / 2,
y: 2732 - 50,
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
});
game.addChild(correctWord);
tween(correctWord, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
}
});
}, 2000);
} else {
// If not solved, show endgame1 scene
if (puzzle.parent) puzzle.parent.removeChild(puzzle);
if (greenTick.parent) greenTick.parent.removeChild(greenTick);
// Hide info button when showing endgame1
setInfoButtonVisible(false);
// Show endgame1 asset centered on screen
var endgame1 = LK.getAsset('Endpuzzleone', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
});
game.addChild(endgame1);
tween(endgame1, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
// After 2 seconds, fade out and swap to incorrect scene with incorrect word under the incorrect image
LK.setTimeout(function () {
tween(endgame1, {
alpha: 0
}, {
duration: 350,
easing: tween.cubicIn,
onFinish: function onFinish() {
if (endgame1.parent) endgame1.parent.removeChild(endgame1);
// Show Incorrect scene (centered)
var incorrectScene = LK.getAsset('Incorrect', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
});
game.addChild(incorrectScene);
tween(incorrectScene, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
// Find the first incorrect dot and its expected word
var targetSolution = {
0: 'Drum',
1: 'Harp',
2: 'Saxophone',
3: 'Flute',
4: 'Gutair',
5: 'Spaghetti',
6: 'Donut',
7: 'Chips',
8: 'Icecream',
9: 'Pizza',
10: 'Basketball',
11: 'Dolls',
12: 'Lego',
13: 'Videogame',
14: 'Plushtoy',
15: 'Fish',
16: 'Turtle',
17: 'Frog',
18: 'Cat',
19: 'Dog',
20: 'KJ',
21: 'Khalida',
22: 'Sapphire',
23: 'Harmony',
24: 'PJ'
};
var firstWrongIdx = -1;
var wrongActual = '';
var wrongExpected = '';
for (var i = 0; i < puzzle.dots.length; i++) {
var dot = puzzle.dots[i];
var expected = targetSolution[i];
var actual = 'Blank';
var row = dot.gridY;
// Get current image based on row and index
if (row === 0 && dot.instruments) {
actual = dot.instruments[dot.instrumentIndex];
} else if (row === 1 && dot.foodImages) {
actual = dot.foodImages[dot.foodIndex];
} else if (row === 2 && dot.toyImages) {
actual = dot.toyImages[dot.toyIndex];
} else if (row === 3 && dot.animalImages) {
actual = dot.animalImages[dot.animalIndex];
} else if (row === 4 && dot.specialInstruments) {
actual = dot.specialInstruments[dot.specialInstrumentIndex];
}
if (actual !== expected) {
firstWrongIdx = i;
wrongActual = actual;
wrongExpected = expected;
break;
}
}
// If found, show the incorrect image and word under it
if (firstWrongIdx !== -1) {
var wrongImg = null;
var imgY = 2732 / 2 + 100;
var wordY = imgY;
// Only show the image if it's not 'Blank'
if (wrongActual !== 'Blank') {
wrongImg = LK.getAsset(wrongActual, {
anchorX: 0.5,
anchorY: 1.0,
x: 2048 / 2,
y: imgY,
alpha: 0
});
game.addChild(wrongImg);
tween(wrongImg, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
wordY = 2732 / 2 + 120 + (wrongImg.height || 100); // 20px below image
} else {
// If blank, just show the word lower down
wordY = 2732 / 2 + 120;
}
// Show the incorrect word asset at the bottom of the screen
var incorrectWord = LK.getAsset('Incorrectword', {
anchorX: 0.5,
anchorY: 1.0,
x: 2048 / 2,
y: 2732 - 50,
// 50px padding from bottom
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
});
game.addChild(incorrectWord);
tween(incorrectWord, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
// Add retry button below the incorrect image/word
var retryBtnY = 2732 - 50 - incorrectWord.height * 2.2 - 40; // 40px above incorrect word
var retryBtn = LK.getAsset('Retry', {
anchorX: 0.5,
anchorY: 1.0,
x: 2048 / 2,
y: retryBtnY,
scaleX: 1.8,
scaleY: 1.8,
alpha: 0
});
game.addChild(retryBtn);
tween(retryBtn, {
alpha: 1
}, {
duration: 350,
easing: tween.cubicOut
});
// Retry button handler: remove incorrect scene and restart puzzle
retryBtn.down = function (x, y, obj) {
// Fade out all incorrect scene assets, then remove and reset
var fadeOuts = [incorrectScene, wrongImg, incorrectWord, retryBtn];
var fadeCount = 0;
var fadeDone = function fadeDone() {
fadeCount++;
if (fadeCount === fadeOuts.length) {
// Remove all incorrect scene assets
if (incorrectScene && incorrectScene.parent) incorrectScene.parent.removeChild(incorrectScene);
if (wrongImg && wrongImg.parent) wrongImg.parent.removeChild(wrongImg);
if (incorrectWord && incorrectWord.parent) incorrectWord.parent.removeChild(incorrectWord);
if (retryBtn && retryBtn.parent) retryBtn.parent.removeChild(retryBtn);
// Reset all used image trackers so dots can be reused
usedInstruments = {};
usedSpecialInstruments = {};
usedAnimalImages = {};
usedFoodImages = {};
usedToyImages = {};
// Re-add puzzle and green tick
puzzle = new Puzzle();
game.addChild(puzzle);
game.addChild(greenTick);
// Re-add number image assets to the top of the screen
numberImages = [];
for (var i = 1; i <= 5; i++) {
var numImg = LK.getAsset(i + "", {
anchorX: 0.5,
anchorY: 0,
x: i * (2048 / 6),
y: 60,
scaleX: 0.7,
scaleY: 0.7
});
game.addChild(numImg);
numberImages.push(numImg);
}
// Restore all clue assets when retry is clicked
if (typeof allClueAssets !== "undefined" && allClueAssets.length) {
for (var i = 0; i < allClueAssets.length; i++) {
if (allClueAssets[i] && !allClueAssets[i].parent) {
game.addChild(allClueAssets[i]);
}
}
// Remove all strikethrough from clues when retry is clicked
for (var i = 0; i < allClueAssets.length; i++) {
if (allClueAssets[i]) allClueAssets[i].alpha = 1.0;
}
// Reset strikethrough state for all clues
for (var i = 0; i < clueStrikeStates.length; i++) {
clueStrikeStates[i] = false;
}
}
// Re-add info button after story asset
if (infoButton && infoButton.parent) {
infoButton.parent.removeChild(infoButton);
}
// Find the story asset in the puzzle and add infoButton after it
var storyAssetIdx = -1;
for (var i = 0; i < puzzle.children.length; i++) {
var child = puzzle.children[i];
if (child && child.assetId === 'Story') {
storyAssetIdx = i;
break;
}
}
if (storyAssetIdx !== -1) {
// Insert infoButton after story asset
if (puzzle.children.length > storyAssetIdx + 1) {
puzzle.addChildAt(infoButton, storyAssetIdx + 1);
} else {
puzzle.addChild(infoButton);
}
} else {
// Fallback: add to puzzle if not found
puzzle.addChild(infoButton);
}
// Show info button again after retry
setInfoButtonVisible(true);
}
};
for (var i = 0; i < fadeOuts.length; i++) {
if (fadeOuts[i]) {
tween(fadeOuts[i], {
alpha: 0
}, {
duration: 250,
easing: tween.cubicIn,
onFinish: fadeDone
});
} else {
fadeDone();
}
}
};
}
}
});
}, 2000);
}
}
};
// Update global references that might be needed
window.puzzle = puzzle;
window.greenTick = greenTick;
window.numberImages = numberImages;
window.allClueAssets = allClueAssets;
window.infoButton = infoButton;
}
// Initialize the game with title screen
var titleScreen = new TitleScreen();
game.addChild(titleScreen);
Add more vibrant colours to picture
Make this scene more modern like in the present
A 4x5 grid in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Remove man
Saxophone in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Harp in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Drum in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Flute in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Question mark professor Layton game style. In-Game asset. 2d. High contrast. No shadows
12yo blonde girl in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Cute little10yo girl brown hair in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Cute little 7yo girl with blonde curly hair. Professor Layton game style In-Game asset. 2d. High contrast. No shadows
15 yo boy with short scruffy blonde hair professor Layton game style. In-Game asset. 2d. High contrast. No shadows
18yo girl with short brown hair professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Cat in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
White dog with brown patch on eyes professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Turtle in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Frog in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Goldfish in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Basketball ball professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Lego bricks professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Video game console professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Teddy bear professor Layton game style. In-Game asset. 2d. High contrast. No shadows
These dolls in professor Layton game art style
Hot chips or fries in professor Layton game style artwork. In-Game asset. 2d. High contrast. No shadows
Bowl of spaghetti in professor Layton game style artwork. In-Game asset. 2d. High contrast. No shadows
Pizza in professor Layton game style artwork. In-Game asset. 2d. High contrast. No shadows
Chocolate donut in professor Layton game style artwork. In-Game asset. 2d. High contrast. No shadows
Ice cream cone in professor Layton game style artwork. In-Game asset. 2d. High contrast. No shadows
Make her crack a small smile
The word "correct" in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
The word " incorrect" in professor Layton game style. In-Game asset. 2d. High contrast. No shadows
Green tick in professor Layton gamestyle. In-Game asset. 2d. High contrast. No shadows
Button with RETRY PUZZLE on it in professor Layton game style artwork In-Game asset. 2d. High contrast. No shadows
Information symbol in professor Layton game style artwork. In-Game asset. 2d. High contrast. No shadows
Number 1 button professor Layton game style artwork. In-Game asset. 2d. High contrast. No shadows
Number 2
Number 3
Number 4
Number 5
Remove clock
Make sure J and Y is not cut off
How to play button in professor Layton game style font. In-Game asset. 2d. High contrast. No shadows
Make robe hang lower so you can't see it's feet
Make it say play new puzzle
A 16:9 title banner