User prompt
In how to tutorial show a list of matching items and tags so people know what to look for
User prompt
Change how to page to have a detailed tutorial with images
User prompt
If you make a mistake with the button sequence reset sequence so player can try again
User prompt
Ensure saxophone button sounds play even if pressed quickly
User prompt
Change how to play instructions to say discounted tags are green instead of yellow
User prompt
Add detailed instructions for the game on the how to play screen
User prompt
Click on instructions button to enter how to screen
User prompt
When instructions button is clicked bring up new page with detailed instructions using pictures
User prompt
When how to play button is clicked give detailed explanation with pictures as examples
User prompt
Add instructions button to bottom left corner of title screen
User prompt
Move saxbutton2 down 500
User prompt
Add player asset to bottom of title screen
User prompt
Please fix the bug: 'TypeError: LK.musicBeat is not a function' in or related to this line: 'LK.musicBeat(function () {' Line Number: 895
User prompt
Make tags stay in sync with the beat
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'onSpectrum')' in or related to this line: 'facekit.music.onSpectrum(function (spectrum) {' Line Number: 930
User prompt
Flash tags on high notes:** Detect spikes in high frequencies and trigger flashes only then. - **Respond to harmony:** Vary the number or style of flashes based on how many frequency bands are active. - **Stay in sync with the beat:** Use beat detection for timing, but only flash on high notes or harmonically rich moments for more musical responsiveness.
User prompt
Please fix the bug: 'TypeError: facekit.listenMicVolume is not a function' in or related to this line: 'facekit.listenMicVolume(function (vol) {' Line Number: 929 ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Make tags jump on high notes
User prompt
Make tags pulsate to the beat frequency
User prompt
Please fix the bug: 'TypeError: LK.setMusicInterval is not a function' in or related to this line: 'LK.setMusicInterval(function () {' Line Number: 896
User prompt
Please fix the bug: 'TypeError: LK.musicBeat is not a function' in or related to this line: 'LK.musicBeat(function () {' Line Number: 895
User prompt
Keep the flashes time with the beat
User prompt
Decrease tag flash and randomly flash 3 tags at a time to the rhythm
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Discount class to handle discounted item prices var Discount = Container.expand(function () { var self = Container.call(this); // Set the discount tag asset self.setDiscountTag = function (assetId, options) { if (self.discountTagAsset) { self.removeChild(self.discountTagAsset); } options = options || {}; if (options.anchorX === undefined) options.anchorX = 0.5; if (options.anchorY === undefined) options.anchorY = 0.5; if (options.x === undefined) options.x = 0; if (options.y === undefined) options.y = 0; self.discountTagAsset = self.attachAsset(assetId, {}); }; // Set the discounted price text self.setDiscountPrice = function (discountPrice, options) { if (self.discountPriceText) { self.removeChild(self.discountPriceText); } options = options || {}; var size = options.size || 40; var fill = options.fill || "#ff0"; self.discountPriceText = new Text2('$' + discountPrice.toFixed(2), { size: size, fill: fill }); self.discountPriceText.anchor.set(0.5, 0.5); self.discountPriceText.x = options.x !== undefined ? options.x : 0; self.discountPriceText.y = options.y !== undefined ? options.y : 0; self.addChild(self.discountPriceText); }; return self; }); // Pricetag class to organize pricetag assets var Pricetag = Container.expand(function () { var self = Container.call(this); // Add a pricetag asset (default is the generic 'pricetag' shape, can be replaced with a specific asset) self.setTag = function (assetId, options) { // Remove previous tag if any if (self.tagAsset) { self.removeChild(self.tagAsset); } // Default options options = options || {}; if (options.anchorX === undefined) options.anchorX = 0.5; if (options.anchorY === undefined) options.anchorY = 0.5; if (options.x === undefined) options.x = 0; if (options.y === undefined) options.y = 0; self.tagAsset = self.attachAsset(assetId, {}); }; // Optionally, add price text self.setPrice = function (price, options) { if (self.priceText) { self.removeChild(self.priceText); } options = options || {}; var size = options.size || 40; var fill = options.fill || "#fff"; self.priceText = new Text2('$' + price.toFixed(2), { size: size, fill: fill }); self.priceText.anchor.set(0.5, 0.5); self.priceText.x = options.x !== undefined ? options.x : 0; self.priceText.y = options.y !== undefined ? options.y : 0; self.addChild(self.priceText); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // --- Begin floating price tag and click-to-buy system --- // List of items and their price tag asset/image IDs and prices var titlePage = game.addChild(new Container()); titlePage.addChild(LK.getAsset('titlescreen', { anchorX: 0.5, anchorY: 0.5, x: 1124, y: 1366 })); // Add saxbutton2 image to the title screen, centered horizontally, below the title var saxbutton2 = titlePage.addChild(LK.getAsset('Saxbutton2', { anchorX: 0.5, anchorY: 0.5, x: 1124 + 600, y: 1800 })); // --- Add 8 interactive dots in front of saxbutton2 on the title screen --- // Build dotPositions step by step to avoid referencing undefined array elements var dotPositions = []; // Dot 1 dotPositions.push({ x: 1600, y: saxbutton2.y - 320 - 50 // Move dot 1 up by 50 pixels }); // Dot 2 dotPositions.push({ x: 1000 + 400 + 250 - 50, y: saxbutton2.y - 200 + 50 + 20 }); // Dot 3 (now dotPositions[1] is defined) dotPositions.push({ x: dotPositions[1].x, y: dotPositions[1].y + 150 + 100 - 20 // Move dot 3 down by 100 pixels, then up by 20 }); // Dot 4 dotPositions.push({ x: dotPositions[2].x, y: dotPositions[2].y + 150 + 50 // Place dot 4 directly under dot 3, then move down by 50 }); // Dot 5 dotPositions.push({ x: dotPositions[0].x + 250 + 20, // Move dot 5 to the right of dot 1 (250px + 20px to the right) y: dotPositions[0].y + 50 // Move dot 5 down by 50 pixels }); // Dot 6 dotPositions.push({ x: dotPositions[4].x, y: dotPositions[4].y + 200 + 50 // Move dot 6 down by 50 pixels }); // Dot 7 dotPositions.push({ x: dotPositions[5].x, y: dotPositions[5].y + 200 + 50 // Move dot 7 under dot 6, then down by 50 }); // Dot 8 dotPositions.push({ x: dotPositions[3].x + 250 + 20 - 50 - 50, // Move dot8 to the right of dot4 (dotPositions[3]), then left by 50, then left by 50 again y: dotPositions[3].y + 50 // Move dot8 down by 50 pixels }); var titleDots = []; for (var i = 0; i < 8; ++i) { var dot = titlePage.addChild(LK.getAsset('saleTag', { anchorX: 0.5, anchorY: 0.5, x: dotPositions[i].x, y: dotPositions[i].y, scaleX: i === 0 || i === 1 || i === 2 || i === 3 || i === 4 || i === 5 || i === 6 || i === 7 ? 3.0 : 1.2, scaleY: i === 0 || i === 1 || i === 2 || i === 3 || i === 4 || i === 5 || i === 6 || i === 7 ? 3.0 : 1.2, alpha: 0.0 })); dot.interactive = true; // Simple interaction: pulse the dot on tap dot.on('down', function (dotRef, dotIndex) { return function () { // --- Begin dot order logic --- if (typeof window.dotOrderState === "undefined") { window.dotOrderState = { current: 0, triggered: false }; } if (!window.dotOrderState.triggered) { if (dotIndex === window.dotOrderState.current) { window.dotOrderState.current++; // Play sound for this dot if (dotIndex === 0) LK.getSound('1').play(); if (dotIndex === 1) LK.getSound('2').play(); if (dotIndex === 2) LK.getSound('3').play(); if (dotIndex === 3) LK.getSound('4').play(); if (dotIndex === 4) LK.getSound('5').play(); if (dotIndex === 5) LK.getSound('6').play(); if (dotIndex === 6) LK.getSound('7').play(); if (dotIndex === 7) LK.getSound('8').play(); if (window.dotOrderState.current === 8) { window.dotOrderState.triggered = true; // Simulate start button press if (typeof startButton !== "undefined" && startButton && startButton.emit) { startButton.emit('down'); } } } else { // Reset if wrong order window.dotOrderState.current = 0; } } else { // Play sound for this dot (after triggered) if (dotIndex === 0) LK.getSound('1').play(); if (dotIndex === 1) LK.getSound('2').play(); if (dotIndex === 2) LK.getSound('3').play(); if (dotIndex === 3) LK.getSound('4').play(); if (dotIndex === 4) LK.getSound('5').play(); if (dotIndex === 5) LK.getSound('6').play(); if (dotIndex === 6) LK.getSound('7').play(); if (dotIndex === 7) LK.getSound('8').play(); } // --- End dot order logic --- tween(dotRef, { scaleX: 1.7, scaleY: 1.7 }, { duration: 120, easing: tween.easeInOut, onFinish: function onFinish() { tween(dotRef, { scaleX: 1.2, scaleY: 1.2 }, { duration: 120, easing: tween.easeInOut }); } }); }; }(dot, i)); titleDots.push(dot); } // Play heymacklemore sound when title screen first appears LK.getSound('Heymacklemore').play(); // Create a start button using the Startbutton asset var startButton = titlePage.addChild(LK.getAsset('Startbutton', { anchorX: 0.5, anchorY: 0.5, // Centered horizontally, positioned near the bottom of the screen, moved up by 50, then down by 500 x: 1024 + 100, y: 2732 - 200 - 200 - 50 + 500, alpha: 0 // Make the start button invisible })); startButton.interactive = true; startButton.on('down', function () { // Play instrumental music when the start button is pressed LK.playMusic('instrumentalMusic'); // Remove the title page when the start button is clicked titlePage.destroy(); // Add the thrift background when the start button is clicked game.addChild(LK.getAsset('thriftBackground', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 })); // Initialize inventory bar without background var inventoryBar = new Container(); inventoryBar.y += 300; // Extend inventory bar on top screen by 300 pixels game.addChild(inventoryBar); // Initialize bottom inventory bar without background var bottomInventoryBar = new Container(); game.addChild(bottomInventoryBar); // Add shopkeeper to the game screen var shopkeeper = game.addChild(LK.getAsset('shopkeeper', { anchorX: 0.5, anchorY: 0.5, x: 1224, y: 1430 })); // --- Shopkeeper dialogue logic --- var shopkeeperDialogue = null; shopkeeper.interactive = true; shopkeeper.on('down', function () { // Play heymacklemore sound when shopkeeper is clicked LK.getSound('Heymacklemore').play(); // If dialogue is already showing, do nothing if (shopkeeperDialogue) return; // Create dialogue container shopkeeperDialogue = game.addChild(new Container()); shopkeeperDialogue.x = 1024; shopkeeperDialogue.y = 900; // Add background for dialogue (bigger and transparent) var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 // semi-transparent })); // Add dialogue text var dialogueText = shopkeeperDialogue.addChild(new Text2("Welcome to the Thrift Shop!\n\nCan I help you with anything?", { size: 90, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 0; dialogueText.y = -120; // Add Yes and No buttons var buttonWidth = 350; var buttonHeight = 120; var buttonSpacing = 80; var buttonY = 180; // Yes button var yesButtonBg = shopkeeperDialogue.addChild(LK.getAsset('categoryButton', { anchorX: 0.5, anchorY: 0.5, x: -buttonWidth / 2 - buttonSpacing / 2, y: buttonY, scaleX: buttonWidth / 200, scaleY: buttonHeight / 80, alpha: 0.85 })); var yesButtonText = shopkeeperDialogue.addChild(new Text2("Yes", { size: 70, fill: "#fff" })); yesButtonText.anchor.set(0.5, 0.5); yesButtonText.x = yesButtonBg.x; yesButtonText.y = yesButtonBg.y; yesButtonBg.interactive = true; yesButtonBg.on('down', function () { // Dismiss dialogue on Yes if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } // Show instructions about shopping list and price matching shopkeeperDialogue = game.addChild(new Container()); shopkeeperDialogue.x = 1024; shopkeeperDialogue.y = 900; // Add background for dialogue (bigger and transparent) var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 // semi-transparent })); // Add instruction text var dialogueText = shopkeeperDialogue.addChild(new Text2("Check the shopping list to see what yo need to buy then match a price with an item to check it off the list. Pop all them tags for the ultimate come up.", { size: 90, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 0; dialogueText.y = 0; // Make the instruction message dismissible on tap shopkeeperDialogue.interactive = true; shopkeeperDialogue.on('down', function () { if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } }); }); // No button var noButtonBg = shopkeeperDialogue.addChild(LK.getAsset('categoryButton', { anchorX: 0.5, anchorY: 0.5, x: buttonWidth / 2 + buttonSpacing / 2, y: buttonY, scaleX: buttonWidth / 200, scaleY: buttonHeight / 80, alpha: 0.85 })); var noButtonText = shopkeeperDialogue.addChild(new Text2("No", { size: 70, fill: "#fff" })); noButtonText.anchor.set(0.5, 0.5); noButtonText.x = noButtonBg.x; noButtonText.y = noButtonBg.y; noButtonBg.interactive = true; noButtonBg.on('down', function () { // Dismiss dialogue on No if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } // Show follow-up message shopkeeperDialogue = game.addChild(new Container()); shopkeeperDialogue.x = 1024; shopkeeperDialogue.y = 900; // Add background for dialogue (bigger and transparent) var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 // semi-transparent })); // Add follow-up text var dialogueText = shopkeeperDialogue.addChild(new Text2("One man's trash is another man's come up!", { size: 90, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 0; dialogueText.y = 0; // Make the follow-up message dismissible on tap shopkeeperDialogue.interactive = true; shopkeeperDialogue.on('down', function () { if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } }); }); // Remove old tap-to-dismiss logic (dialogue is now dismissed by Yes/No buttons only) }); // --- Begin floating price tag and click-to-buy system --- // List of items and their price tag asset/image IDs and prices var itemData = [{ name: 'Big Ass Coat', asset: 'bigAssCoat', price: 4.00, pricetagAsset: 'Pricetagbigasscoat', x: 1524, y: 2040 }, { name: 'Dookie Brown Leather Jacket', asset: 'dookieBrownLeatherJacket', price: 3.50, pricetagAsset: 'pricetagdookiebrownjacket', x: 2004, y: 2040 }, { name: 'Grandma\'s Coat', asset: 'granddadsClothes', price: 2.50, pricetagAsset: 'pricetaggrandadscoat', x: 1769, y: 2020 }, { name: 'Pink Leopard Mink', asset: 'pinkLeopardMink', price: 5.00, pricetagAsset: 'pricetagpinkleaperdmink', x: 300, y: 2100 }, { name: 'Plaid Button-Up Shirt', asset: 'plaidButtonUpShirt', price: 2.00, pricetagAsset: 'pricetagpladbuttonupshirt', x: 550, y: 1620 }, { name: 'Velour Jumpsuit', asset: 'velourJumpsuit', price: 3.00, pricetagAsset: 'Pricetagvelourjumpsuit', x: 100, y: 2120 }, { name: 'Built-In Onesie With Socks', asset: 'builtInOnesieWithSocks', price: 2.00, pricetagAsset: 'Pricetagbuiltinonesiewithsocks', discountTagAsset: 'Discountbuiltinonesiewithsocks', x: 820, y: 1600 }, { name: 'Zebra Pajamas', asset: 'flannelZebraPyjamas', price: 2.50, pricetagAsset: 'Pricetagzebrapyjamas', x: 750, y: 2020 }, { name: 'Fox Skin', asset: 'furFoxSkin', price: 4.50, pricetagAsset: 'pricetagfoxskin', x: 970, y: 2000 }, { name: 'Skeet Blanket', asset: 'skeetBlanket', price: 2.00, pricetagAsset: 'Pricetagskeetblanket', x: 1200, y: 2000 }, { name: 'House Slippers', asset: 'houseSlippers', price: 1.50, pricetagAsset: 'pricetaghouseslippers', x: 1700, y: 1320 }, { name: 'Wolf Skin Hat', asset: 'wolfSkinHat', price: 2.00, pricetagAsset: 'pricetagwolfskinhat', x: 520, y: 1290 }, { name: 'Gator Shoes', asset: 'gatorShoes', price: 3.00, pricetagAsset: 'Pricetaggatorshoes', x: 1800, y: 1430 }, { name: 'Velcro Sneakers', asset: 'velcroSneakers', price: 2.00, pricetagAsset: 'Pricetagvelcrosneakers', x: 1900, y: 1310 }, { name: 'Telescope', asset: 'telescope', price: 3.00, pricetagAsset: 'Pricetagtelescope', x: 900, y: 1030 }, { name: 'Kneeboard', asset: 'kneeBoard', price: 4.00, pricetagAsset: 'Pricetagkneeboard', x: 1500, y: 2200 }, { name: 'Broken Keyboard', asset: 'brokenKeyboard', price: 2.00, pricetagAsset: 'pricetagbrokenkeybord', x: 1770, y: 970 }]; // Store references to item containers and price tags var itemObjects = []; var priceTagObjects = []; // Import tween plugin for animating price tags // Helper to get a random position within the game area (not overlapping items and not too close to other tags) function getRandomTagPosition(existingTags) { var margin = 60; var minDistance = 350; // Increased minimum distance between tags (in px) var maxAttempts = 60; var attempt = 0; var x, y, valid; do { x = Math.random() * (2048 - 2 * margin) + margin; y = Math.random() * (2732 - 2 * margin) + margin; valid = true; if (existingTags && existingTags.length) { for (var i = 0; i < existingTags.length; ++i) { var tag = existingTags[i]; // Use tag.x/tag.y if set, else skip if (typeof tag.x === "number" && typeof tag.y === "number") { var dx = tag.x - x; var dy = tag.y - y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < minDistance) { valid = false; break; } } } } attempt++; } while (!valid && attempt < maxAttempts); return { x: x, y: y }; } // Create items (static, not interactive for buying) for (var i = 0; i < itemData.length; ++i) { var data = itemData[i]; var item = game.addChild(LK.getAsset(data.asset, { anchorX: 0.5, anchorY: 0.5, x: data.x, y: data.y })); item.itemName = data.name; item.itemPrice = data.price; item.pricetagAsset = data.pricetagAsset; itemObjects.push(item); } // Create floating price tags for (var i = 0; i < itemData.length; ++i) { var data = itemData[i]; var tag = new Pricetag(); tag.setTag(data.pricetagAsset, { anchorX: 0.5, anchorY: 0.5 }); tag.setPrice(data.price, { size: 36, fill: "#fff", x: 0, y: 60 }); if (tag.priceText) tag.priceText.alpha = 0; // Make small text invisible // Set tag's starting position to match the item's position tag.x = data.x; tag.y = data.y; tag.anchorX = 0.5; tag.anchorY = 0.5; tag.itemName = data.name; tag.itemPrice = data.price; tag.pricetagAsset = data.pricetagAsset; tag.interactive = true; priceTagObjects.push(tag); game.addChild(tag); } // Animate price tags to randomly move around the game scene using tweens function moveTagRandomly(tag) { var margin = 60; var tagWidth = tag.width || 100; var tagHeight = tag.height || 100; // Calculate random position within bounds, avoiding bunching with other tags var minDistance = 350; var maxAttempts = 60; var attempt = 0; var newX, newY, valid; do { var minX = margin + tagWidth / 2; var maxX = 2048 - margin - tagWidth / 2; var minY = margin + tagHeight / 2; var maxY = 2732 - margin - tagHeight / 2; newX = Math.random() * (maxX - minX) + minX; newY = Math.random() * (maxY - minY) + minY; valid = true; // Check against all other tags (except self) for (var i = 0; i < priceTagObjects.length; ++i) { var other = priceTagObjects[i]; if (other !== tag && typeof other.x === "number" && typeof other.y === "number") { var dx = other.x - newX; var dy = other.y - newY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < minDistance) { valid = false; break; } } } attempt++; } while (!valid && attempt < maxAttempts); var duration = 12000 + Math.random() * 5000; // 12s to 17s (much slower movement) tween(tag, { x: newX, y: newY }, { duration: duration, easing: tween.easeInOut, onFinish: function onFinish() { // After reaching the new position, check for overlap and nudge if needed var overlapFound = false; for (var i = 0; i < priceTagObjects.length; ++i) { var other = priceTagObjects[i]; if (other !== tag && typeof other.x === "number" && typeof other.y === "number") { var dx = other.x - tag.x; var dy = other.y - tag.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < minDistance) { // Nudge this tag away from the overlapping tag var angle = Math.atan2(dy, dx); tag.x = other.x + Math.cos(angle) * minDistance; tag.y = other.y + Math.sin(angle) * minDistance; overlapFound = true; } } } // After resolving, move again moveTagRandomly(tag); } }); } // Start random movement for all price tags for (var i = 0; i < priceTagObjects.length; ++i) { moveTagRandomly(priceTagObjects[i]); } // --- Flash tags to the music beat and harmony --- // Beat pattern in ms (simulate a 4/4 beat, e.g. 900ms per beat for less frequent flashes) var tagFlashBeatPattern = [900, 900, 900, 1100, 900, 900, 1200]; // slower, less frequent flashes var tagFlashBeatIndex = 0; // Helper to get N unique random indices from 0..max-1 function getNUniqueRandomIndices(n, max) { var indices = []; var available = []; for (var i = 0; i < max; ++i) available.push(i); for (var j = 0; j < n && available.length > 0; ++j) { var pick = Math.floor(Math.random() * available.length); indices.push(available[pick]); available.splice(pick, 1); } return indices; } function flashRandomTags() { // Pick 3 unique random tags to flash var numToFlash = Math.min(3, priceTagObjects.length); var indices = getNUniqueRandomIndices(numToFlash, priceTagObjects.length); for (var i = 0; i < indices.length; ++i) { (function (tag) { // Pulse up tween(tag, { scaleX: 1.5, scaleY: 1.5 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { // Pulse down tween(tag, { scaleX: 1.2, scaleY: 1.2 }, { duration: 180, easing: tween.easeIn }); } }); })(priceTagObjects[indices[i]]); } // Schedule next flash based on beat pattern tagFlashBeatIndex = (tagFlashBeatIndex + 1) % tagFlashBeatPattern.length; LK.setTimeout(flashRandomTags, tagFlashBeatPattern[tagFlashBeatIndex]); } // Start flashing random tags to the beat LK.setTimeout(flashRandomTags, tagFlashBeatPattern[0]); // No need for per-frame update for tag movement anymore game.update = function () {}; // --- Discount price tag swap logic --- // Map of itemName to discount assetId (if available) var discountTagMap = { "Big Ass Coat": "discountbigasscoat", "Dookie Brown Leather Jacket": "discountleatherjacket", "Grandma's Coat": "discountgrandadscoat", "Pink Leopard Mink": "discountpinkleoperdmink", "Plaid Button-Up Shirt": "discountplaidbuttonupshirt", "Velour Jumpsuit": "discountvelourjumpsuit", "Built-In Onesie With Socks": "Discountbuiltinonesiewithsocks", "Zebra Pajamas": "discountzebrapajamas", "Fox Skin": "discountfoxskin", "Skeet Blanket": "discountskeetblanket", "House Slippers": "discounthouseslippers", "Wolf Skin Hat": "discountwolfskinhat", "Gator Shoes": "Discountgatorshoes", "Velcro Sneakers": "Discountvelcrosneakers", "Telescope": "Discounttelescope", "Kneeboard": "Discountkneeboard", "Broken Keyboard": "Discountbrokenkeyboard" }; // Track which tags are currently discounted var discountedTagIndices = []; // Helper to swap a price tag to its discount version function swapToDiscount(tag, itemName) { var discountAsset = discountTagMap[itemName]; if (discountAsset) { tag.setTag(discountAsset, { anchorX: 0.5, anchorY: 0.5 }); // Find the discounted price from the original itemData array var discountPrice = null; for (var i = 0; i < itemData.length; ++i) { if (itemData[i].name === itemName) { // Special discount price for Fox Skin if (itemName === "Fox Skin") { discountPrice = 2.00; } else if (itemName === "Pink Leopard Mink") { discountPrice = 0.99; } else if (itemName === "Skeet Blanket") { discountPrice = 0.50; } else if (itemName === "Broken Keyboard") { discountPrice = 1.00; } else if (typeof itemData[i].price === "number" && itemData[i].price < tag.itemPrice) { discountPrice = itemData[i].price; } else { discountPrice = tag.itemPrice * 0.7; // Default: 30% off if not specified } break; } } // Always force Fox Skin discount price to $2.00 if (itemName === "Fox Skin") { discountPrice = 2.00; } // Always force Pink Leopard Mink discount price to $0.99 if (itemName === "Pink Leopard Mink") { discountPrice = 0.99; } // Always force Skeet Blanket discount price to $0.50 if (itemName === "Skeet Blanket") { discountPrice = 0.50; } // Always force Broken Keyboard discount price to $1.00 if (itemName === "Broken Keyboard") { discountPrice = 1.00; } if (discountPrice === null) discountPrice = tag.itemPrice * 0.7; tag.setPrice(discountPrice, { size: 36, fill: "#ff0", x: 0, y: 60 }); if (tag.priceText) tag.priceText.alpha = 0; // Make discount price text invisible tag.itemPrice = discountPrice; tag.isDiscounted = true; } } // Helper to swap a price tag back to its original version function swapToOriginal(tag, itemName) { // Find the original asset and price from itemData for (var i = 0; i < itemData.length; ++i) { if (itemData[i].name === itemName) { tag.setTag(itemData[i].pricetagAsset, { anchorX: 0.5, anchorY: 0.5 }); tag.setPrice(itemData[i].price, { size: 36, fill: "#fff", x: 0, y: 60 }); if (tag.priceText) tag.priceText.alpha = 0; // Make original price text invisible tag.itemPrice = itemData[i].price; tag.isDiscounted = false; break; } } } // Timer to randomly swap price tags with discount assets every 10 seconds LK.setInterval(function () { // First, revert any currently discounted tags to original for (var i = 0; i < discountedTagIndices.length; ++i) { var idx = discountedTagIndices[i]; if (priceTagObjects[idx]) { swapToOriginal(priceTagObjects[idx], priceTagObjects[idx].itemName); } } discountedTagIndices = []; // Pick a random number of tags to discount (at least 1, up to 1/3 of tags) var numToDiscount = 1 + Math.floor(Math.random() * Math.max(1, Math.floor(priceTagObjects.length / 3))); var availableIndices = []; for (var i = 0; i < priceTagObjects.length; ++i) { // Only allow discount if a discount asset exists for this item if (discountTagMap[priceTagObjects[i].itemName]) { availableIndices.push(i); } } // Shuffle availableIndices for (var i = availableIndices.length - 1; i > 0; --i) { var j = Math.floor(Math.random() * (i + 1)); var temp = availableIndices[i]; availableIndices[i] = availableIndices[j]; availableIndices[j] = temp; } // Apply discount to the first numToDiscount tags for (var i = 0; i < numToDiscount && i < availableIndices.length; ++i) { var idx = availableIndices[i]; swapToDiscount(priceTagObjects[idx], priceTagObjects[idx].itemName); discountedTagIndices.push(idx); } }, 10000); // --- Click-to-buy logic --- // Track selection state var selectedTag = null; var selectedItem = null; // Track purchased items globally var purchasedItems = []; // Track which checklist we're on (1 or 2) and purchased count for current list var currentChecklistNumber = 1; var currentChecklistPurchaseCount = 0; // Store shopping list items globally so they persist var shoppingListItems = []; // Helper function to generate new shopping list function generateNewShoppingList() { var usedIndices = []; // Get remaining unpurchased items var availableItems = []; for (var i = 0; i < itemData.length; i++) { if (purchasedItems.indexOf(itemData[i].name) === -1) { availableItems.push(i); } } // If we have enough unpurchased items for a full list, use them if (availableItems.length >= 5) { // Shuffle available items for (var i = availableItems.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = availableItems[i]; availableItems[i] = availableItems[j]; availableItems[j] = temp; } // Add first 5 items from shuffled available pool for (var i = 0; i < 5; i++) { shoppingListItems.push(itemData[availableItems[i]]); } } else if (availableItems.length > 0) { // Add all remaining unpurchased items for (var i = 0; i < availableItems.length; i++) { shoppingListItems.push(itemData[availableItems[i]]); } // Fill remaining slots with random items from full pool while (shoppingListItems.length < 5 && usedIndices.length < itemData.length) { var randomIndex = Math.floor(Math.random() * itemData.length); if (usedIndices.indexOf(randomIndex) === -1) { var alreadyInList = false; for (var j = 0; j < shoppingListItems.length; j++) { if (shoppingListItems[j].name === itemData[randomIndex].name) { alreadyInList = true; break; } } if (!alreadyInList) { shoppingListItems.push(itemData[randomIndex]); usedIndices.push(randomIndex); } } } } else { // All items purchased - create random list from all items while (shoppingListItems.length < 5 && usedIndices.length < itemData.length) { var randomIndex = Math.floor(Math.random() * itemData.length); if (usedIndices.indexOf(randomIndex) === -1) { shoppingListItems.push(itemData[randomIndex]); usedIndices.push(randomIndex); } } } } // Helper: highlight a tag or item function highlight(obj, on) { if (!obj) return; if (on) { obj.alpha = 0.7; } else { obj.alpha = 1.0; } } // Price tag click handler function onTagDown(tag) { return function () { // If already selected, deselect if (selectedTag === tag) { highlight(selectedTag, false); selectedTag = null; return; } // If an item is already selected, try to buy if (selectedItem && selectedItem.itemName === tag.itemName) { // Calculate price - apply 20% discount if tag is discounted var finalPrice = tag.itemPrice; if (tag.isDiscounted) { // Special case: Pink Leopard Mink discount price is always $0.99, do not apply 20% off logic if (tag.itemName === "Pink Leopard Mink") { finalPrice = 0.99; } else if (tag.itemName === "Fox Skin") { finalPrice = 2.00; } else if (tag.itemName === "Skeet Blanket") { finalPrice = 0.50; } else if (tag.itemName === "Broken Keyboard") { finalPrice = 1.00; } else { // Find original price from itemData var originalPrice = null; for (var i = 0; i < itemData.length; ++i) { if (itemData[i].name === tag.itemName) { originalPrice = itemData[i].price; break; } } if (originalPrice) { finalPrice = originalPrice * 0.8; // 20% off original price } } } // Check if player can afford the item, show game over if not if (shoppingCart.getBudget() < finalPrice) { // Check if player can afford ANYTHING on the current shopping list var canAffordSomething = false; for (var i = 0; i < shoppingListItems.length; i++) { // Only check unpurchased items if (purchasedItems.indexOf(shoppingListItems[i].name) === -1) { // Find the tag for this item for (var j = 0; j < priceTagObjects.length; j++) { if (priceTagObjects[j].itemName === shoppingListItems[i].name) { var tagPrice = priceTagObjects[j].itemPrice; // If discounted, check for special prices if (priceTagObjects[j].isDiscounted) { if (priceTagObjects[j].itemName === "Pink Leopard Mink") tagPrice = 0.99;else if (priceTagObjects[j].itemName === "Fox Skin") tagPrice = 2.00;else if (priceTagObjects[j].itemName === "Skeet Blanket") tagPrice = 0.50;else if (priceTagObjects[j].itemName === "Broken Keyboard") tagPrice = 1.00;else { // Find original price for (var k = 0; k < itemData.length; ++k) { if (itemData[k].name === priceTagObjects[j].itemName) { tagPrice = itemData[k].price * 0.8; break; } } } } if (shoppingCart.getBudget() >= tagPrice) { canAffordSomething = true; break; } } } } if (canAffordSomething) break; } if (!canAffordSomething) { // Show dialogue explaining can't afford anything else if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } shopkeeperDialogue = game.addChild(new Container()); shopkeeperDialogue.x = 1024; shopkeeperDialogue.y = 900; var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 })); var dialogueText = shopkeeperDialogue.addChild(new Text2("Looks like you can't afford anything else on your list!\n\nBetter luck next time!", { size: 90, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 0; dialogueText.y = 0; // Play probsshoulda sound when this text is being displayed LK.getSound('Probsshoulda').play(); // Make dialogue dismissible on tap, then go to game over shopkeeperDialogue.interactive = true; shopkeeperDialogue.on('down', function () { if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } LK.showGameOver(); }); } else { LK.showGameOver(); } return; } // Attempt to buy if (shoppingCart.addItem(tag.itemName, finalPrice)) { // Play leopard mink sound if Pink Leopard Mink is purchased if (tag.itemName === "Pink Leopard Mink") { LK.getSound('Leopardmink').play(); } // Play bigasscoat sound if Big Ass Coat is purchased if (tag.itemName === "Big Ass Coat") { LK.getSound('Bigasscoat').play(); } // Play builtinonesie sound if Built-In Onesie With Socks is purchased if (tag.itemName === "Built-In Onesie With Socks") { LK.getSound('Builtinonesie').play(); } // Play gatorshoes sound if Gator Shoes is purchased if (tag.itemName === "Gator Shoes") { LK.getSound('Gatorshoes').play(); } // Play velcros sound if Velcro Sneakers is purchased if (tag.itemName === "Velcro Sneakers") { LK.getSound('Velcros').play(); } // Play houseslippers sound if House Slippers is purchased if (tag.itemName === "House Slippers") { LK.getSound('Houseslippers').play(); } // Play skeetblanket sound if Skeet Blanket is purchased if (tag.itemName === "Skeet Blanket") { LK.getSound('Skeetblanket').play(); } // Play velourjumpsuit sound if Velour Jumpsuit is purchased if (tag.itemName === "Velour Jumpsuit") { LK.getSound('Velourjumpsuit').play(); } // Play plaidshirt sound if Plaid Button-Up Shirt is purchased if (tag.itemName === "Plaid Button-Up Shirt") { LK.getSound('Plaidshirt').play(); } // Play grandmascoat sound if Grandma's Coat is purchased if (tag.itemName === "Grandma's Coat") { LK.getSound('Grandmascoat').play(); } // Play foxfur sound if Fox Skin is purchased if (tag.itemName === "Fox Skin") { LK.getSound('Foxfur').play(); } // Play wolfhat sound if Wolf Skin Hat is purchased if (tag.itemName === "Wolf Skin Hat") { LK.getSound('Wolfhat').play(); } // Play zebrajamies sound if Zebra Pajamas is purchased if (tag.itemName === "Zebra Pajamas") { LK.getSound('Zebrajamies').play(); } // Play dookiebrown sound if Dookie Brown Leather Jacket is purchased if (tag.itemName === "Dookie Brown Leather Jacket") { LK.getSound('Dookiebrown').play(); } budgetText.setText('$' + shoppingCart.getBudget()); // Play kneeboard sound if Kneeboard is purchased if (tag.itemName === "Kneeboard") { LK.getSound('Kneeboard').play(); } // Play brokenkeyboard sound if Broken Keyboard is purchased if (tag.itemName === "Broken Keyboard") { LK.getSound('Brokenkeyboard').play(); } // Play telescope sound if Telescope is purchased if (tag.itemName === "Telescope") { LK.getSound('Telescope').play(); } // Track purchased item if (purchasedItems.indexOf(tag.itemName) === -1) { purchasedItems.push(tag.itemName); // Check if this item is on the current shopping list var isOnCurrentList = false; for (var j = 0; j < shoppingListItems.length; j++) { if (shoppingListItems[j].name === tag.itemName) { isOnCurrentList = true; break; } } if (isOnCurrentList) { currentChecklistPurchaseCount++; // Check if we've purchased 5 items from current list if (currentChecklistPurchaseCount >= 5) { // Calculate voucher amount based on checklist number var voucherAmount = currentChecklistNumber === 1 ? 3.00 : currentChecklistNumber === 2 ? 5.00 : 5.00; shoppingCart.budget = Math.round((shoppingCart.budget + voucherAmount) * 100) / 100; LK.getSound('Cash').play(); budgetText.setText('$' + shoppingCart.getBudget()); // Show shopkeeper dialogue about voucher if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } shopkeeperDialogue = game.addChild(new Container()); shopkeeperDialogue.x = 1024; shopkeeperDialogue.y = 900; // Add background for dialogue var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 })); // Add voucher dialogue text var dialogueText = shopkeeperDialogue.addChild(new Text2("Congratulations!\n\nYou completed your shopping list!\nHere's a $" + voucherAmount.toFixed(2) + " voucher for your next purchase.", { size: 80, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 0; dialogueText.y = 0; // Make dialogue dismissible on tap shopkeeperDialogue.interactive = true; shopkeeperDialogue.on('down', function () { if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } }); // Generate new checklist currentChecklistNumber++; currentChecklistPurchaseCount = 0; // Clear current shopping list and generate new one shoppingListItems = []; generateNewShoppingList(); } } } // Remove both tag and item from scene tag.destroy(); selectedItem.destroy(); // Add to inventory bar var targetBar = inventoryBar.children.length < 10 ? inventoryBar : bottomInventoryBar; var itemSlot = targetBar.addChild(LK.getAsset('itemSlot', { anchorX: 0.5, anchorY: 0.5, x: targetBar.children.length * 180 + 90, y: 125 })); itemSlot.addChild(LK.getAsset(selectedItem.assetId || tag.assetId || tag.itemName, { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 0.5, scaleY: 0.5 })); } highlight(selectedTag, false); highlight(selectedItem, false); selectedTag = null; selectedItem = null; return; } // Otherwise, select this tag if (selectedTag) highlight(selectedTag, false); selectedTag = tag; highlight(selectedTag, true); }; } // Item click handler function onItemDown(item) { return function () { // If already selected, deselect if (selectedItem === item) { highlight(selectedItem, false); selectedItem = null; return; } // If a tag is already selected, try to buy if (selectedTag && selectedTag.itemName === item.itemName) { // Calculate price - apply 20% discount if tag is discounted var finalPrice = selectedTag.itemPrice; if (selectedTag.isDiscounted) { // Special case: Pink Leopard Mink discount price is always $0.99, do not apply 20% off logic if (selectedTag.itemName === "Pink Leopard Mink") { finalPrice = 0.99; } else if (selectedTag.itemName === "Fox Skin") { finalPrice = 2.00; } else if (selectedTag.itemName === "Skeet Blanket") { finalPrice = 0.50; } else if (selectedTag.itemName === "Broken Keyboard") { finalPrice = 1.00; } else { // Find original price from itemData var originalPrice = null; for (var i = 0; i < itemData.length; ++i) { if (itemData[i].name === selectedTag.itemName) { originalPrice = itemData[i].price; break; } } if (originalPrice) { finalPrice = originalPrice * 0.8; // 20% off original price } } } // Check if player can afford the item, show game over if not if (shoppingCart.getBudget() < finalPrice) { // Check if player can afford ANYTHING on the current shopping list var canAffordSomething = false; for (var i = 0; i < shoppingListItems.length; i++) { // Only check unpurchased items if (purchasedItems.indexOf(shoppingListItems[i].name) === -1) { // Find the tag for this item for (var j = 0; j < priceTagObjects.length; j++) { if (priceTagObjects[j].itemName === shoppingListItems[i].name) { var tagPrice = priceTagObjects[j].itemPrice; // If discounted, check for special prices if (priceTagObjects[j].isDiscounted) { if (priceTagObjects[j].itemName === "Pink Leopard Mink") tagPrice = 0.99;else if (priceTagObjects[j].itemName === "Fox Skin") tagPrice = 2.00;else if (priceTagObjects[j].itemName === "Skeet Blanket") tagPrice = 0.50;else if (priceTagObjects[j].itemName === "Broken Keyboard") tagPrice = 1.00;else { // Find original price for (var k = 0; k < itemData.length; ++k) { if (itemData[k].name === priceTagObjects[j].itemName) { tagPrice = itemData[k].price * 0.8; break; } } } } if (shoppingCart.getBudget() >= tagPrice) { canAffordSomething = true; break; } } } } if (canAffordSomething) break; } if (!canAffordSomething) { // Show dialogue explaining can't afford anything else if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } shopkeeperDialogue = game.addChild(new Container()); shopkeeperDialogue.x = 1024; shopkeeperDialogue.y = 900; var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 })); var dialogueText = shopkeeperDialogue.addChild(new Text2("Looks like you can't afford anything else on your list!\n\nBetter luck next time!", { size: 90, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 0; dialogueText.y = 0; // Play probsshoulda sound when this text is being displayed LK.getSound('Probsshoulda').play(); // Make dialogue dismissible on tap, then go to game over shopkeeperDialogue.interactive = true; shopkeeperDialogue.on('down', function () { if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } LK.showGameOver(); }); } else { LK.showGameOver(); } return; } // Attempt to buy if (shoppingCart.addItem(item.itemName, finalPrice)) { // Play leopard mink sound if Pink Leopard Mink is purchased if (item.itemName === "Pink Leopard Mink") { LK.getSound('Leopardmink').play(); } // Play bigasscoat sound if Big Ass Coat is purchased if (item.itemName === "Big Ass Coat") { LK.getSound('Bigasscoat').play(); } // Play builtinonesie sound if Built-In Onesie With Socks is purchased if (item.itemName === "Built-In Onesie With Socks") { LK.getSound('Builtinonesie').play(); } // Play gatorshoes sound if Gator Shoes is purchased if (item.itemName === "Gator Shoes") { LK.getSound('Gatorshoes').play(); } // Play velcros sound if Velcro Sneakers is purchased if (item.itemName === "Velcro Sneakers") { LK.getSound('Velcros').play(); } // Play houseslippers sound if House Slippers is purchased if (item.itemName === "House Slippers") { LK.getSound('Houseslippers').play(); } // Play skeetblanket sound if Skeet Blanket is purchased if (item.itemName === "Skeet Blanket") { LK.getSound('Skeetblanket').play(); } // Play velourjumpsuit sound if Velour Jumpsuit is purchased if (item.itemName === "Velour Jumpsuit") { LK.getSound('Velourjumpsuit').play(); } // Play plaidshirt sound if Plaid Button-Up Shirt is purchased if (item.itemName === "Plaid Button-Up Shirt") { LK.getSound('Plaidshirt').play(); } // Play grandmascoat sound if Grandma's Coat is purchased if (item.itemName === "Grandma's Coat") { LK.getSound('Grandmascoat').play(); } // Play foxfur sound if Fox Skin is purchased if (item.itemName === "Fox Skin") { LK.getSound('Foxfur').play(); } // Play wolfhat sound if Wolf Skin Hat is purchased if (item.itemName === "Wolf Skin Hat") { LK.getSound('Wolfhat').play(); } // Play zebrajamies sound if Zebra Pajamas is purchased if (item.itemName === "Zebra Pajamas") { LK.getSound('Zebrajamies').play(); } // Play dookiebrown sound if Dookie Brown Leather Jacket is purchased if (item.itemName === "Dookie Brown Leather Jacket") { LK.getSound('Dookiebrown').play(); } budgetText.setText('$' + shoppingCart.getBudget()); // Play kneeboard sound if Kneeboard is purchased if (item.itemName === "Kneeboard") { LK.getSound('Kneeboard').play(); } // Play brokenkeyboard sound if Broken Keyboard is purchased if (item.itemName === "Broken Keyboard") { LK.getSound('Brokenkeyboard').play(); } // Play telescope sound if Telescope is purchased if (item.itemName === "Telescope") { LK.getSound('Telescope').play(); } // Track purchased item if (purchasedItems.indexOf(item.itemName) === -1) { purchasedItems.push(item.itemName); // Check if this item is on the current shopping list var isOnCurrentList = false; for (var j = 0; j < shoppingListItems.length; j++) { if (shoppingListItems[j].name === item.itemName) { isOnCurrentList = true; break; } } if (isOnCurrentList) { currentChecklistPurchaseCount++; // Check if we've purchased 5 items from current list if (currentChecklistPurchaseCount >= 5) { // Calculate voucher amount based on checklist number var voucherAmount = currentChecklistNumber === 1 ? 3.00 : currentChecklistNumber === 2 ? 5.00 : 5.00; shoppingCart.budget = Math.round((shoppingCart.budget + voucherAmount) * 100) / 100; LK.getSound('Cash').play(); budgetText.setText('$' + shoppingCart.getBudget()); // Show shopkeeper dialogue about voucher if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } shopkeeperDialogue = game.addChild(new Container()); shopkeeperDialogue.x = 1024; shopkeeperDialogue.y = 900; // Add background for dialogue var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 })); // Add voucher dialogue text var dialogueText = shopkeeperDialogue.addChild(new Text2("Congratulations!\n\nYou completed your shopping list!\nHere's a $" + voucherAmount.toFixed(2) + " voucher for your next purchase.", { size: 80, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); dialogueText.anchor.set(0.5, 0.5); dialogueText.x = 0; dialogueText.y = 0; // Make dialogue dismissible on tap shopkeeperDialogue.interactive = true; shopkeeperDialogue.on('down', function () { if (shopkeeperDialogue) { shopkeeperDialogue.destroy(); shopkeeperDialogue = null; } }); // Generate new checklist currentChecklistNumber++; currentChecklistPurchaseCount = 0; // Clear current shopping list and generate new one shoppingListItems = []; generateNewShoppingList(); } } } // Remove both tag and item from scene selectedTag.destroy(); item.destroy(); // Add to inventory bar var targetBar = inventoryBar.children.length < 10 ? inventoryBar : bottomInventoryBar; var itemSlot = targetBar.addChild(LK.getAsset('itemSlot', { anchorX: 0.5, anchorY: 0.5, x: targetBar.children.length * 180 + 90, y: 125 })); itemSlot.addChild(LK.getAsset(item.assetId || selectedTag.assetId || item.itemName, { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 0.5, scaleY: 0.5 })); } highlight(selectedTag, false); highlight(selectedItem, false); selectedTag = null; selectedItem = null; return; } // Otherwise, select this item if (selectedItem) highlight(selectedItem, false); selectedItem = item; highlight(selectedItem, true); }; } // Attach click handlers for (var i = 0; i < priceTagObjects.length; ++i) { var tag = priceTagObjects[i]; tag.on('down', onTagDown(tag)); } for (var i = 0; i < itemObjects.length; ++i) { var item = itemObjects[i]; item.interactive = true; item.assetId = itemData[i].asset; item.on('down', onItemDown(item)); } // --- End floating price tag and click-to-buy system --- // Add instruction box with black background to the middle of the screen var instructionBox = game.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 1.5, scaleY: 1.5 })); var shoppingCart = new ShoppingCart(20); // Initialize shoppingCart with $20 in budget var budgetText = new Text2('$' + shoppingCart.getBudget(), { size: 50, fill: 0xFFFFFF }); budgetText.anchor.set(0.5, 0.5); budgetText.zIndex = 2; // Increase zIndex to place text in front of shopping cart var instructionText = new Text2('Welcome to Poppin\' Tags: A Thrift Shop Tribute.', { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.zIndex = 2; // Increase zIndex to place text in front of instruction box instructionBox.addChild(instructionText); instructionBox.interactive = true; var clickCount = 0; instructionBox.on('down', function () { clickCount++; if (clickCount === 1) { instructionText.setText('You have $20 in your pocket and are huntin\' for a come-up.'); } else if (clickCount === 2) { instructionText.setText('Try and buy all items on your shopping list \n as cheap as you can. This is gonna be AWESOME!!!'); } else if (clickCount === 3) { instructionBox.destroy(); shoppingCart = new ShoppingCart(20); // Create a shopping cart with $20 in budget var shoppingCartDisplay = game.addChild(LK.getAsset('moneyContainer', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 300, scaleX: 1.5, scaleY: 1.5 })); budgetText = new Text2('$' + shoppingCart.getBudget(), { size: 50, fill: 0xFFFFFF }); budgetText.anchor.set(0.5, 0.5); budgetText.zIndex = 2; // Increase zIndex to place text in front of shopping cart shoppingCartDisplay.addChild(budgetText); // Add shopping list to top left corner (avoiding the menu icon area) var shoppingListDisplay = game.addChild(LK.getAsset('Shoppinglist', { anchorX: 0, anchorY: 0, x: 0, // Position away from top-left menu icon y: 370, scaleX: 0.6, scaleY: 0.6 })); // Make shopping list interactive shoppingListDisplay.interactive = true; // Create enlarged shopping list (initially hidden) var enlargedShoppingList = null; shoppingListDisplay.on('down', function () { if (enlargedShoppingList) { // If already showing, hide it enlargedShoppingList.destroy(); enlargedShoppingList = null; } else { // Create enlarged shopping list container enlargedShoppingList = game.addChild(new Container()); enlargedShoppingList.x = 1024; enlargedShoppingList.y = 1366; // Add background for enlarged list var listBackground = enlargedShoppingList.addChild(LK.getAsset('listBackground', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 2.5 })); // Initialize shopping list items if not already done if (shoppingListItems.length === 0) { generateNewShoppingList(); } // Add title text var titleText = enlargedShoppingList.addChild(new Text2('Shopping List #' + currentChecklistNumber, { size: 60, fill: 0x000000 })); titleText.anchor.set(0.5, 0.5); titleText.x = 0; titleText.y = -200; // Add items to the list with checkmarks for purchased items for (var i = 0; i < shoppingListItems.length; i++) { // Check purchase status using indexOf to determine if item exists in purchasedItems array var isPurchased = purchasedItems.indexOf(shoppingListItems[i].name) !== -1; // Add checkbox background (empty slot for all items) var checkbox = enlargedShoppingList.addChild(LK.getAsset('itemSlot', { anchorX: 0.5, anchorY: 0.5, x: -400, y: -100 + i * 80, scaleX: 0.3, scaleY: 0.3 })); // Add visible checkmark if item is purchased (purchase status check result) if (isPurchased) { var checkmark = enlargedShoppingList.addChild(LK.getAsset('checkmark', { anchorX: 0.5, anchorY: 0.5, x: -400, y: -100 + i * 80, scaleX: 0.3, scaleY: 0.3 })); } // Style item text differently for purchased items (green with strikethrough effect) vs unpurchased (black) var itemText = enlargedShoppingList.addChild(new Text2(isPurchased ? "✓ " + shoppingListItems[i].name : shoppingListItems[i].name, { size: 70, fill: isPurchased ? 0x32cd32 : 0x000000 })); itemText.anchor.set(0.5, 0.5); itemText.x = 0; itemText.y = -100 + i * 80; } // Make enlarged list clickable to close enlargedShoppingList.interactive = true; enlargedShoppingList.on('down', function () { enlargedShoppingList.destroy(); enlargedShoppingList = null; }); } }); } }); }); var ShoppingCart = /*#__PURE__*/function () { function ShoppingCart(initialBudget) { _classCallCheck(this, ShoppingCart); this.budget = Math.round(initialBudget * 100) / 100; // Round to 2 decimal places this.items = []; } return _createClass(ShoppingCart, [{ key: "addItem", value: function addItem(item, price) { var roundedPrice = Math.round(price * 100) / 100; // Round price to 2 decimal places if (this.budget >= roundedPrice) { this.items.push(item); this.budget = Math.round((this.budget - roundedPrice) * 100) / 100; // Prevent floating-point errors if (this.items.length === 17) { // Show win explanation dialogue var winDialogue = game.addChild(new Container()); winDialogue.x = 1024; winDialogue.y = 900; var winBg = winDialogue.addChild(LK.getAsset('instructionBox', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 1.2, scaleY: 1.0, alpha: 0.7 })); var winText = winDialogue.addChild(new Text2("You did it! You popped them tags and achieved the ultimate come up!", { size: 90, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 1500 })); winText.anchor.set(0.5, 0.5); winText.x = 0; winText.y = 0; // Play poptags sound when this text is being displayed LK.getSound('Poptags').play(); // Make dialogue dismissible on tap, then show you win winDialogue.interactive = true; winDialogue.on('down', function () { if (winDialogue) { winDialogue.destroy(); } LK.showYouWin(); }); return true; } return true; } return false; } }, { key: "removeItem", value: function removeItem(item, price) { var index = this.items.indexOf(item); if (index > -1) { this.items.splice(index, 1); var roundedPrice = Math.round(price * 100) / 100; // Round price to 2 decimal places this.budget = Math.round((this.budget + roundedPrice) * 100) / 100; // Prevent floating-point errors } } }, { key: "getBudget", value: function getBudget() { return Math.round(this.budget * 100) / 100; // Always return properly rounded budget } }, { key: "getItems", value: function getItems() { return this.items; } }]); }(); function _createClass(Constructor, protoProps, staticProps) { if (protoProps) { protoProps.forEach(function (prop) { Object.defineProperty(Constructor.prototype, prop.key, prop); }); } if (staticProps) { staticProps.forEach(function (prop) { Object.defineProperty(Constructor, prop.key, prop); }); } return Constructor; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Discount class to handle discounted item prices
var Discount = Container.expand(function () {
var self = Container.call(this);
// Set the discount tag asset
self.setDiscountTag = function (assetId, options) {
if (self.discountTagAsset) {
self.removeChild(self.discountTagAsset);
}
options = options || {};
if (options.anchorX === undefined) options.anchorX = 0.5;
if (options.anchorY === undefined) options.anchorY = 0.5;
if (options.x === undefined) options.x = 0;
if (options.y === undefined) options.y = 0;
self.discountTagAsset = self.attachAsset(assetId, {});
};
// Set the discounted price text
self.setDiscountPrice = function (discountPrice, options) {
if (self.discountPriceText) {
self.removeChild(self.discountPriceText);
}
options = options || {};
var size = options.size || 40;
var fill = options.fill || "#ff0";
self.discountPriceText = new Text2('$' + discountPrice.toFixed(2), {
size: size,
fill: fill
});
self.discountPriceText.anchor.set(0.5, 0.5);
self.discountPriceText.x = options.x !== undefined ? options.x : 0;
self.discountPriceText.y = options.y !== undefined ? options.y : 0;
self.addChild(self.discountPriceText);
};
return self;
});
// Pricetag class to organize pricetag assets
var Pricetag = Container.expand(function () {
var self = Container.call(this);
// Add a pricetag asset (default is the generic 'pricetag' shape, can be replaced with a specific asset)
self.setTag = function (assetId, options) {
// Remove previous tag if any
if (self.tagAsset) {
self.removeChild(self.tagAsset);
}
// Default options
options = options || {};
if (options.anchorX === undefined) options.anchorX = 0.5;
if (options.anchorY === undefined) options.anchorY = 0.5;
if (options.x === undefined) options.x = 0;
if (options.y === undefined) options.y = 0;
self.tagAsset = self.attachAsset(assetId, {});
};
// Optionally, add price text
self.setPrice = function (price, options) {
if (self.priceText) {
self.removeChild(self.priceText);
}
options = options || {};
var size = options.size || 40;
var fill = options.fill || "#fff";
self.priceText = new Text2('$' + price.toFixed(2), {
size: size,
fill: fill
});
self.priceText.anchor.set(0.5, 0.5);
self.priceText.x = options.x !== undefined ? options.x : 0;
self.priceText.y = options.y !== undefined ? options.y : 0;
self.addChild(self.priceText);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// --- Begin floating price tag and click-to-buy system ---
// List of items and their price tag asset/image IDs and prices
var titlePage = game.addChild(new Container());
titlePage.addChild(LK.getAsset('titlescreen', {
anchorX: 0.5,
anchorY: 0.5,
x: 1124,
y: 1366
}));
// Add saxbutton2 image to the title screen, centered horizontally, below the title
var saxbutton2 = titlePage.addChild(LK.getAsset('Saxbutton2', {
anchorX: 0.5,
anchorY: 0.5,
x: 1124 + 600,
y: 1800
}));
// --- Add 8 interactive dots in front of saxbutton2 on the title screen ---
// Build dotPositions step by step to avoid referencing undefined array elements
var dotPositions = [];
// Dot 1
dotPositions.push({
x: 1600,
y: saxbutton2.y - 320 - 50 // Move dot 1 up by 50 pixels
});
// Dot 2
dotPositions.push({
x: 1000 + 400 + 250 - 50,
y: saxbutton2.y - 200 + 50 + 20
});
// Dot 3 (now dotPositions[1] is defined)
dotPositions.push({
x: dotPositions[1].x,
y: dotPositions[1].y + 150 + 100 - 20 // Move dot 3 down by 100 pixels, then up by 20
});
// Dot 4
dotPositions.push({
x: dotPositions[2].x,
y: dotPositions[2].y + 150 + 50 // Place dot 4 directly under dot 3, then move down by 50
});
// Dot 5
dotPositions.push({
x: dotPositions[0].x + 250 + 20,
// Move dot 5 to the right of dot 1 (250px + 20px to the right)
y: dotPositions[0].y + 50 // Move dot 5 down by 50 pixels
});
// Dot 6
dotPositions.push({
x: dotPositions[4].x,
y: dotPositions[4].y + 200 + 50 // Move dot 6 down by 50 pixels
});
// Dot 7
dotPositions.push({
x: dotPositions[5].x,
y: dotPositions[5].y + 200 + 50 // Move dot 7 under dot 6, then down by 50
});
// Dot 8
dotPositions.push({
x: dotPositions[3].x + 250 + 20 - 50 - 50,
// Move dot8 to the right of dot4 (dotPositions[3]), then left by 50, then left by 50 again
y: dotPositions[3].y + 50 // Move dot8 down by 50 pixels
});
var titleDots = [];
for (var i = 0; i < 8; ++i) {
var dot = titlePage.addChild(LK.getAsset('saleTag', {
anchorX: 0.5,
anchorY: 0.5,
x: dotPositions[i].x,
y: dotPositions[i].y,
scaleX: i === 0 || i === 1 || i === 2 || i === 3 || i === 4 || i === 5 || i === 6 || i === 7 ? 3.0 : 1.2,
scaleY: i === 0 || i === 1 || i === 2 || i === 3 || i === 4 || i === 5 || i === 6 || i === 7 ? 3.0 : 1.2,
alpha: 0.0
}));
dot.interactive = true;
// Simple interaction: pulse the dot on tap
dot.on('down', function (dotRef, dotIndex) {
return function () {
// --- Begin dot order logic ---
if (typeof window.dotOrderState === "undefined") {
window.dotOrderState = {
current: 0,
triggered: false
};
}
if (!window.dotOrderState.triggered) {
if (dotIndex === window.dotOrderState.current) {
window.dotOrderState.current++;
// Play sound for this dot
if (dotIndex === 0) LK.getSound('1').play();
if (dotIndex === 1) LK.getSound('2').play();
if (dotIndex === 2) LK.getSound('3').play();
if (dotIndex === 3) LK.getSound('4').play();
if (dotIndex === 4) LK.getSound('5').play();
if (dotIndex === 5) LK.getSound('6').play();
if (dotIndex === 6) LK.getSound('7').play();
if (dotIndex === 7) LK.getSound('8').play();
if (window.dotOrderState.current === 8) {
window.dotOrderState.triggered = true;
// Simulate start button press
if (typeof startButton !== "undefined" && startButton && startButton.emit) {
startButton.emit('down');
}
}
} else {
// Reset if wrong order
window.dotOrderState.current = 0;
}
} else {
// Play sound for this dot (after triggered)
if (dotIndex === 0) LK.getSound('1').play();
if (dotIndex === 1) LK.getSound('2').play();
if (dotIndex === 2) LK.getSound('3').play();
if (dotIndex === 3) LK.getSound('4').play();
if (dotIndex === 4) LK.getSound('5').play();
if (dotIndex === 5) LK.getSound('6').play();
if (dotIndex === 6) LK.getSound('7').play();
if (dotIndex === 7) LK.getSound('8').play();
}
// --- End dot order logic ---
tween(dotRef, {
scaleX: 1.7,
scaleY: 1.7
}, {
duration: 120,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(dotRef, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 120,
easing: tween.easeInOut
});
}
});
};
}(dot, i));
titleDots.push(dot);
}
// Play heymacklemore sound when title screen first appears
LK.getSound('Heymacklemore').play();
// Create a start button using the Startbutton asset
var startButton = titlePage.addChild(LK.getAsset('Startbutton', {
anchorX: 0.5,
anchorY: 0.5,
// Centered horizontally, positioned near the bottom of the screen, moved up by 50, then down by 500
x: 1024 + 100,
y: 2732 - 200 - 200 - 50 + 500,
alpha: 0 // Make the start button invisible
}));
startButton.interactive = true;
startButton.on('down', function () {
// Play instrumental music when the start button is pressed
LK.playMusic('instrumentalMusic');
// Remove the title page when the start button is clicked
titlePage.destroy();
// Add the thrift background when the start button is clicked
game.addChild(LK.getAsset('thriftBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Initialize inventory bar without background
var inventoryBar = new Container();
inventoryBar.y += 300; // Extend inventory bar on top screen by 300 pixels
game.addChild(inventoryBar);
// Initialize bottom inventory bar without background
var bottomInventoryBar = new Container();
game.addChild(bottomInventoryBar);
// Add shopkeeper to the game screen
var shopkeeper = game.addChild(LK.getAsset('shopkeeper', {
anchorX: 0.5,
anchorY: 0.5,
x: 1224,
y: 1430
}));
// --- Shopkeeper dialogue logic ---
var shopkeeperDialogue = null;
shopkeeper.interactive = true;
shopkeeper.on('down', function () {
// Play heymacklemore sound when shopkeeper is clicked
LK.getSound('Heymacklemore').play();
// If dialogue is already showing, do nothing
if (shopkeeperDialogue) return;
// Create dialogue container
shopkeeperDialogue = game.addChild(new Container());
shopkeeperDialogue.x = 1024;
shopkeeperDialogue.y = 900;
// Add background for dialogue (bigger and transparent)
var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7 // semi-transparent
}));
// Add dialogue text
var dialogueText = shopkeeperDialogue.addChild(new Text2("Welcome to the Thrift Shop!\n\nCan I help you with anything?", {
size: 90,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = 0;
dialogueText.y = -120;
// Add Yes and No buttons
var buttonWidth = 350;
var buttonHeight = 120;
var buttonSpacing = 80;
var buttonY = 180;
// Yes button
var yesButtonBg = shopkeeperDialogue.addChild(LK.getAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
x: -buttonWidth / 2 - buttonSpacing / 2,
y: buttonY,
scaleX: buttonWidth / 200,
scaleY: buttonHeight / 80,
alpha: 0.85
}));
var yesButtonText = shopkeeperDialogue.addChild(new Text2("Yes", {
size: 70,
fill: "#fff"
}));
yesButtonText.anchor.set(0.5, 0.5);
yesButtonText.x = yesButtonBg.x;
yesButtonText.y = yesButtonBg.y;
yesButtonBg.interactive = true;
yesButtonBg.on('down', function () {
// Dismiss dialogue on Yes
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
// Show instructions about shopping list and price matching
shopkeeperDialogue = game.addChild(new Container());
shopkeeperDialogue.x = 1024;
shopkeeperDialogue.y = 900;
// Add background for dialogue (bigger and transparent)
var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7 // semi-transparent
}));
// Add instruction text
var dialogueText = shopkeeperDialogue.addChild(new Text2("Check the shopping list to see what yo need to buy then match a price with an item to check it off the list. Pop all them tags for the ultimate come up.", {
size: 90,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = 0;
dialogueText.y = 0;
// Make the instruction message dismissible on tap
shopkeeperDialogue.interactive = true;
shopkeeperDialogue.on('down', function () {
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
});
});
// No button
var noButtonBg = shopkeeperDialogue.addChild(LK.getAsset('categoryButton', {
anchorX: 0.5,
anchorY: 0.5,
x: buttonWidth / 2 + buttonSpacing / 2,
y: buttonY,
scaleX: buttonWidth / 200,
scaleY: buttonHeight / 80,
alpha: 0.85
}));
var noButtonText = shopkeeperDialogue.addChild(new Text2("No", {
size: 70,
fill: "#fff"
}));
noButtonText.anchor.set(0.5, 0.5);
noButtonText.x = noButtonBg.x;
noButtonText.y = noButtonBg.y;
noButtonBg.interactive = true;
noButtonBg.on('down', function () {
// Dismiss dialogue on No
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
// Show follow-up message
shopkeeperDialogue = game.addChild(new Container());
shopkeeperDialogue.x = 1024;
shopkeeperDialogue.y = 900;
// Add background for dialogue (bigger and transparent)
var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7 // semi-transparent
}));
// Add follow-up text
var dialogueText = shopkeeperDialogue.addChild(new Text2("One man's trash is another man's come up!", {
size: 90,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = 0;
dialogueText.y = 0;
// Make the follow-up message dismissible on tap
shopkeeperDialogue.interactive = true;
shopkeeperDialogue.on('down', function () {
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
});
});
// Remove old tap-to-dismiss logic (dialogue is now dismissed by Yes/No buttons only)
});
// --- Begin floating price tag and click-to-buy system ---
// List of items and their price tag asset/image IDs and prices
var itemData = [{
name: 'Big Ass Coat',
asset: 'bigAssCoat',
price: 4.00,
pricetagAsset: 'Pricetagbigasscoat',
x: 1524,
y: 2040
}, {
name: 'Dookie Brown Leather Jacket',
asset: 'dookieBrownLeatherJacket',
price: 3.50,
pricetagAsset: 'pricetagdookiebrownjacket',
x: 2004,
y: 2040
}, {
name: 'Grandma\'s Coat',
asset: 'granddadsClothes',
price: 2.50,
pricetagAsset: 'pricetaggrandadscoat',
x: 1769,
y: 2020
}, {
name: 'Pink Leopard Mink',
asset: 'pinkLeopardMink',
price: 5.00,
pricetagAsset: 'pricetagpinkleaperdmink',
x: 300,
y: 2100
}, {
name: 'Plaid Button-Up Shirt',
asset: 'plaidButtonUpShirt',
price: 2.00,
pricetagAsset: 'pricetagpladbuttonupshirt',
x: 550,
y: 1620
}, {
name: 'Velour Jumpsuit',
asset: 'velourJumpsuit',
price: 3.00,
pricetagAsset: 'Pricetagvelourjumpsuit',
x: 100,
y: 2120
}, {
name: 'Built-In Onesie With Socks',
asset: 'builtInOnesieWithSocks',
price: 2.00,
pricetagAsset: 'Pricetagbuiltinonesiewithsocks',
discountTagAsset: 'Discountbuiltinonesiewithsocks',
x: 820,
y: 1600
}, {
name: 'Zebra Pajamas',
asset: 'flannelZebraPyjamas',
price: 2.50,
pricetagAsset: 'Pricetagzebrapyjamas',
x: 750,
y: 2020
}, {
name: 'Fox Skin',
asset: 'furFoxSkin',
price: 4.50,
pricetagAsset: 'pricetagfoxskin',
x: 970,
y: 2000
}, {
name: 'Skeet Blanket',
asset: 'skeetBlanket',
price: 2.00,
pricetagAsset: 'Pricetagskeetblanket',
x: 1200,
y: 2000
}, {
name: 'House Slippers',
asset: 'houseSlippers',
price: 1.50,
pricetagAsset: 'pricetaghouseslippers',
x: 1700,
y: 1320
}, {
name: 'Wolf Skin Hat',
asset: 'wolfSkinHat',
price: 2.00,
pricetagAsset: 'pricetagwolfskinhat',
x: 520,
y: 1290
}, {
name: 'Gator Shoes',
asset: 'gatorShoes',
price: 3.00,
pricetagAsset: 'Pricetaggatorshoes',
x: 1800,
y: 1430
}, {
name: 'Velcro Sneakers',
asset: 'velcroSneakers',
price: 2.00,
pricetagAsset: 'Pricetagvelcrosneakers',
x: 1900,
y: 1310
}, {
name: 'Telescope',
asset: 'telescope',
price: 3.00,
pricetagAsset: 'Pricetagtelescope',
x: 900,
y: 1030
}, {
name: 'Kneeboard',
asset: 'kneeBoard',
price: 4.00,
pricetagAsset: 'Pricetagkneeboard',
x: 1500,
y: 2200
}, {
name: 'Broken Keyboard',
asset: 'brokenKeyboard',
price: 2.00,
pricetagAsset: 'pricetagbrokenkeybord',
x: 1770,
y: 970
}];
// Store references to item containers and price tags
var itemObjects = [];
var priceTagObjects = [];
// Import tween plugin for animating price tags
// Helper to get a random position within the game area (not overlapping items and not too close to other tags)
function getRandomTagPosition(existingTags) {
var margin = 60;
var minDistance = 350; // Increased minimum distance between tags (in px)
var maxAttempts = 60;
var attempt = 0;
var x, y, valid;
do {
x = Math.random() * (2048 - 2 * margin) + margin;
y = Math.random() * (2732 - 2 * margin) + margin;
valid = true;
if (existingTags && existingTags.length) {
for (var i = 0; i < existingTags.length; ++i) {
var tag = existingTags[i];
// Use tag.x/tag.y if set, else skip
if (typeof tag.x === "number" && typeof tag.y === "number") {
var dx = tag.x - x;
var dy = tag.y - y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDistance) {
valid = false;
break;
}
}
}
}
attempt++;
} while (!valid && attempt < maxAttempts);
return {
x: x,
y: y
};
}
// Create items (static, not interactive for buying)
for (var i = 0; i < itemData.length; ++i) {
var data = itemData[i];
var item = game.addChild(LK.getAsset(data.asset, {
anchorX: 0.5,
anchorY: 0.5,
x: data.x,
y: data.y
}));
item.itemName = data.name;
item.itemPrice = data.price;
item.pricetagAsset = data.pricetagAsset;
itemObjects.push(item);
}
// Create floating price tags
for (var i = 0; i < itemData.length; ++i) {
var data = itemData[i];
var tag = new Pricetag();
tag.setTag(data.pricetagAsset, {
anchorX: 0.5,
anchorY: 0.5
});
tag.setPrice(data.price, {
size: 36,
fill: "#fff",
x: 0,
y: 60
});
if (tag.priceText) tag.priceText.alpha = 0; // Make small text invisible
// Set tag's starting position to match the item's position
tag.x = data.x;
tag.y = data.y;
tag.anchorX = 0.5;
tag.anchorY = 0.5;
tag.itemName = data.name;
tag.itemPrice = data.price;
tag.pricetagAsset = data.pricetagAsset;
tag.interactive = true;
priceTagObjects.push(tag);
game.addChild(tag);
}
// Animate price tags to randomly move around the game scene using tweens
function moveTagRandomly(tag) {
var margin = 60;
var tagWidth = tag.width || 100;
var tagHeight = tag.height || 100;
// Calculate random position within bounds, avoiding bunching with other tags
var minDistance = 350;
var maxAttempts = 60;
var attempt = 0;
var newX, newY, valid;
do {
var minX = margin + tagWidth / 2;
var maxX = 2048 - margin - tagWidth / 2;
var minY = margin + tagHeight / 2;
var maxY = 2732 - margin - tagHeight / 2;
newX = Math.random() * (maxX - minX) + minX;
newY = Math.random() * (maxY - minY) + minY;
valid = true;
// Check against all other tags (except self)
for (var i = 0; i < priceTagObjects.length; ++i) {
var other = priceTagObjects[i];
if (other !== tag && typeof other.x === "number" && typeof other.y === "number") {
var dx = other.x - newX;
var dy = other.y - newY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDistance) {
valid = false;
break;
}
}
}
attempt++;
} while (!valid && attempt < maxAttempts);
var duration = 12000 + Math.random() * 5000; // 12s to 17s (much slower movement)
tween(tag, {
x: newX,
y: newY
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
// After reaching the new position, check for overlap and nudge if needed
var overlapFound = false;
for (var i = 0; i < priceTagObjects.length; ++i) {
var other = priceTagObjects[i];
if (other !== tag && typeof other.x === "number" && typeof other.y === "number") {
var dx = other.x - tag.x;
var dy = other.y - tag.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDistance) {
// Nudge this tag away from the overlapping tag
var angle = Math.atan2(dy, dx);
tag.x = other.x + Math.cos(angle) * minDistance;
tag.y = other.y + Math.sin(angle) * minDistance;
overlapFound = true;
}
}
}
// After resolving, move again
moveTagRandomly(tag);
}
});
}
// Start random movement for all price tags
for (var i = 0; i < priceTagObjects.length; ++i) {
moveTagRandomly(priceTagObjects[i]);
}
// --- Flash tags to the music beat and harmony ---
// Beat pattern in ms (simulate a 4/4 beat, e.g. 900ms per beat for less frequent flashes)
var tagFlashBeatPattern = [900, 900, 900, 1100, 900, 900, 1200]; // slower, less frequent flashes
var tagFlashBeatIndex = 0;
// Helper to get N unique random indices from 0..max-1
function getNUniqueRandomIndices(n, max) {
var indices = [];
var available = [];
for (var i = 0; i < max; ++i) available.push(i);
for (var j = 0; j < n && available.length > 0; ++j) {
var pick = Math.floor(Math.random() * available.length);
indices.push(available[pick]);
available.splice(pick, 1);
}
return indices;
}
function flashRandomTags() {
// Pick 3 unique random tags to flash
var numToFlash = Math.min(3, priceTagObjects.length);
var indices = getNUniqueRandomIndices(numToFlash, priceTagObjects.length);
for (var i = 0; i < indices.length; ++i) {
(function (tag) {
// Pulse up
tween(tag, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
// Pulse down
tween(tag, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 180,
easing: tween.easeIn
});
}
});
})(priceTagObjects[indices[i]]);
}
// Schedule next flash based on beat pattern
tagFlashBeatIndex = (tagFlashBeatIndex + 1) % tagFlashBeatPattern.length;
LK.setTimeout(flashRandomTags, tagFlashBeatPattern[tagFlashBeatIndex]);
}
// Start flashing random tags to the beat
LK.setTimeout(flashRandomTags, tagFlashBeatPattern[0]);
// No need for per-frame update for tag movement anymore
game.update = function () {};
// --- Discount price tag swap logic ---
// Map of itemName to discount assetId (if available)
var discountTagMap = {
"Big Ass Coat": "discountbigasscoat",
"Dookie Brown Leather Jacket": "discountleatherjacket",
"Grandma's Coat": "discountgrandadscoat",
"Pink Leopard Mink": "discountpinkleoperdmink",
"Plaid Button-Up Shirt": "discountplaidbuttonupshirt",
"Velour Jumpsuit": "discountvelourjumpsuit",
"Built-In Onesie With Socks": "Discountbuiltinonesiewithsocks",
"Zebra Pajamas": "discountzebrapajamas",
"Fox Skin": "discountfoxskin",
"Skeet Blanket": "discountskeetblanket",
"House Slippers": "discounthouseslippers",
"Wolf Skin Hat": "discountwolfskinhat",
"Gator Shoes": "Discountgatorshoes",
"Velcro Sneakers": "Discountvelcrosneakers",
"Telescope": "Discounttelescope",
"Kneeboard": "Discountkneeboard",
"Broken Keyboard": "Discountbrokenkeyboard"
};
// Track which tags are currently discounted
var discountedTagIndices = [];
// Helper to swap a price tag to its discount version
function swapToDiscount(tag, itemName) {
var discountAsset = discountTagMap[itemName];
if (discountAsset) {
tag.setTag(discountAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Find the discounted price from the original itemData array
var discountPrice = null;
for (var i = 0; i < itemData.length; ++i) {
if (itemData[i].name === itemName) {
// Special discount price for Fox Skin
if (itemName === "Fox Skin") {
discountPrice = 2.00;
} else if (itemName === "Pink Leopard Mink") {
discountPrice = 0.99;
} else if (itemName === "Skeet Blanket") {
discountPrice = 0.50;
} else if (itemName === "Broken Keyboard") {
discountPrice = 1.00;
} else if (typeof itemData[i].price === "number" && itemData[i].price < tag.itemPrice) {
discountPrice = itemData[i].price;
} else {
discountPrice = tag.itemPrice * 0.7; // Default: 30% off if not specified
}
break;
}
}
// Always force Fox Skin discount price to $2.00
if (itemName === "Fox Skin") {
discountPrice = 2.00;
}
// Always force Pink Leopard Mink discount price to $0.99
if (itemName === "Pink Leopard Mink") {
discountPrice = 0.99;
}
// Always force Skeet Blanket discount price to $0.50
if (itemName === "Skeet Blanket") {
discountPrice = 0.50;
}
// Always force Broken Keyboard discount price to $1.00
if (itemName === "Broken Keyboard") {
discountPrice = 1.00;
}
if (discountPrice === null) discountPrice = tag.itemPrice * 0.7;
tag.setPrice(discountPrice, {
size: 36,
fill: "#ff0",
x: 0,
y: 60
});
if (tag.priceText) tag.priceText.alpha = 0; // Make discount price text invisible
tag.itemPrice = discountPrice;
tag.isDiscounted = true;
}
}
// Helper to swap a price tag back to its original version
function swapToOriginal(tag, itemName) {
// Find the original asset and price from itemData
for (var i = 0; i < itemData.length; ++i) {
if (itemData[i].name === itemName) {
tag.setTag(itemData[i].pricetagAsset, {
anchorX: 0.5,
anchorY: 0.5
});
tag.setPrice(itemData[i].price, {
size: 36,
fill: "#fff",
x: 0,
y: 60
});
if (tag.priceText) tag.priceText.alpha = 0; // Make original price text invisible
tag.itemPrice = itemData[i].price;
tag.isDiscounted = false;
break;
}
}
}
// Timer to randomly swap price tags with discount assets every 10 seconds
LK.setInterval(function () {
// First, revert any currently discounted tags to original
for (var i = 0; i < discountedTagIndices.length; ++i) {
var idx = discountedTagIndices[i];
if (priceTagObjects[idx]) {
swapToOriginal(priceTagObjects[idx], priceTagObjects[idx].itemName);
}
}
discountedTagIndices = [];
// Pick a random number of tags to discount (at least 1, up to 1/3 of tags)
var numToDiscount = 1 + Math.floor(Math.random() * Math.max(1, Math.floor(priceTagObjects.length / 3)));
var availableIndices = [];
for (var i = 0; i < priceTagObjects.length; ++i) {
// Only allow discount if a discount asset exists for this item
if (discountTagMap[priceTagObjects[i].itemName]) {
availableIndices.push(i);
}
}
// Shuffle availableIndices
for (var i = availableIndices.length - 1; i > 0; --i) {
var j = Math.floor(Math.random() * (i + 1));
var temp = availableIndices[i];
availableIndices[i] = availableIndices[j];
availableIndices[j] = temp;
}
// Apply discount to the first numToDiscount tags
for (var i = 0; i < numToDiscount && i < availableIndices.length; ++i) {
var idx = availableIndices[i];
swapToDiscount(priceTagObjects[idx], priceTagObjects[idx].itemName);
discountedTagIndices.push(idx);
}
}, 10000);
// --- Click-to-buy logic ---
// Track selection state
var selectedTag = null;
var selectedItem = null;
// Track purchased items globally
var purchasedItems = [];
// Track which checklist we're on (1 or 2) and purchased count for current list
var currentChecklistNumber = 1;
var currentChecklistPurchaseCount = 0;
// Store shopping list items globally so they persist
var shoppingListItems = [];
// Helper function to generate new shopping list
function generateNewShoppingList() {
var usedIndices = [];
// Get remaining unpurchased items
var availableItems = [];
for (var i = 0; i < itemData.length; i++) {
if (purchasedItems.indexOf(itemData[i].name) === -1) {
availableItems.push(i);
}
}
// If we have enough unpurchased items for a full list, use them
if (availableItems.length >= 5) {
// Shuffle available items
for (var i = availableItems.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = availableItems[i];
availableItems[i] = availableItems[j];
availableItems[j] = temp;
}
// Add first 5 items from shuffled available pool
for (var i = 0; i < 5; i++) {
shoppingListItems.push(itemData[availableItems[i]]);
}
} else if (availableItems.length > 0) {
// Add all remaining unpurchased items
for (var i = 0; i < availableItems.length; i++) {
shoppingListItems.push(itemData[availableItems[i]]);
}
// Fill remaining slots with random items from full pool
while (shoppingListItems.length < 5 && usedIndices.length < itemData.length) {
var randomIndex = Math.floor(Math.random() * itemData.length);
if (usedIndices.indexOf(randomIndex) === -1) {
var alreadyInList = false;
for (var j = 0; j < shoppingListItems.length; j++) {
if (shoppingListItems[j].name === itemData[randomIndex].name) {
alreadyInList = true;
break;
}
}
if (!alreadyInList) {
shoppingListItems.push(itemData[randomIndex]);
usedIndices.push(randomIndex);
}
}
}
} else {
// All items purchased - create random list from all items
while (shoppingListItems.length < 5 && usedIndices.length < itemData.length) {
var randomIndex = Math.floor(Math.random() * itemData.length);
if (usedIndices.indexOf(randomIndex) === -1) {
shoppingListItems.push(itemData[randomIndex]);
usedIndices.push(randomIndex);
}
}
}
}
// Helper: highlight a tag or item
function highlight(obj, on) {
if (!obj) return;
if (on) {
obj.alpha = 0.7;
} else {
obj.alpha = 1.0;
}
}
// Price tag click handler
function onTagDown(tag) {
return function () {
// If already selected, deselect
if (selectedTag === tag) {
highlight(selectedTag, false);
selectedTag = null;
return;
}
// If an item is already selected, try to buy
if (selectedItem && selectedItem.itemName === tag.itemName) {
// Calculate price - apply 20% discount if tag is discounted
var finalPrice = tag.itemPrice;
if (tag.isDiscounted) {
// Special case: Pink Leopard Mink discount price is always $0.99, do not apply 20% off logic
if (tag.itemName === "Pink Leopard Mink") {
finalPrice = 0.99;
} else if (tag.itemName === "Fox Skin") {
finalPrice = 2.00;
} else if (tag.itemName === "Skeet Blanket") {
finalPrice = 0.50;
} else if (tag.itemName === "Broken Keyboard") {
finalPrice = 1.00;
} else {
// Find original price from itemData
var originalPrice = null;
for (var i = 0; i < itemData.length; ++i) {
if (itemData[i].name === tag.itemName) {
originalPrice = itemData[i].price;
break;
}
}
if (originalPrice) {
finalPrice = originalPrice * 0.8; // 20% off original price
}
}
}
// Check if player can afford the item, show game over if not
if (shoppingCart.getBudget() < finalPrice) {
// Check if player can afford ANYTHING on the current shopping list
var canAffordSomething = false;
for (var i = 0; i < shoppingListItems.length; i++) {
// Only check unpurchased items
if (purchasedItems.indexOf(shoppingListItems[i].name) === -1) {
// Find the tag for this item
for (var j = 0; j < priceTagObjects.length; j++) {
if (priceTagObjects[j].itemName === shoppingListItems[i].name) {
var tagPrice = priceTagObjects[j].itemPrice;
// If discounted, check for special prices
if (priceTagObjects[j].isDiscounted) {
if (priceTagObjects[j].itemName === "Pink Leopard Mink") tagPrice = 0.99;else if (priceTagObjects[j].itemName === "Fox Skin") tagPrice = 2.00;else if (priceTagObjects[j].itemName === "Skeet Blanket") tagPrice = 0.50;else if (priceTagObjects[j].itemName === "Broken Keyboard") tagPrice = 1.00;else {
// Find original price
for (var k = 0; k < itemData.length; ++k) {
if (itemData[k].name === priceTagObjects[j].itemName) {
tagPrice = itemData[k].price * 0.8;
break;
}
}
}
}
if (shoppingCart.getBudget() >= tagPrice) {
canAffordSomething = true;
break;
}
}
}
}
if (canAffordSomething) break;
}
if (!canAffordSomething) {
// Show dialogue explaining can't afford anything else
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
shopkeeperDialogue = game.addChild(new Container());
shopkeeperDialogue.x = 1024;
shopkeeperDialogue.y = 900;
var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7
}));
var dialogueText = shopkeeperDialogue.addChild(new Text2("Looks like you can't afford anything else on your list!\n\nBetter luck next time!", {
size: 90,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = 0;
dialogueText.y = 0;
// Play probsshoulda sound when this text is being displayed
LK.getSound('Probsshoulda').play();
// Make dialogue dismissible on tap, then go to game over
shopkeeperDialogue.interactive = true;
shopkeeperDialogue.on('down', function () {
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
LK.showGameOver();
});
} else {
LK.showGameOver();
}
return;
}
// Attempt to buy
if (shoppingCart.addItem(tag.itemName, finalPrice)) {
// Play leopard mink sound if Pink Leopard Mink is purchased
if (tag.itemName === "Pink Leopard Mink") {
LK.getSound('Leopardmink').play();
}
// Play bigasscoat sound if Big Ass Coat is purchased
if (tag.itemName === "Big Ass Coat") {
LK.getSound('Bigasscoat').play();
}
// Play builtinonesie sound if Built-In Onesie With Socks is purchased
if (tag.itemName === "Built-In Onesie With Socks") {
LK.getSound('Builtinonesie').play();
}
// Play gatorshoes sound if Gator Shoes is purchased
if (tag.itemName === "Gator Shoes") {
LK.getSound('Gatorshoes').play();
}
// Play velcros sound if Velcro Sneakers is purchased
if (tag.itemName === "Velcro Sneakers") {
LK.getSound('Velcros').play();
}
// Play houseslippers sound if House Slippers is purchased
if (tag.itemName === "House Slippers") {
LK.getSound('Houseslippers').play();
}
// Play skeetblanket sound if Skeet Blanket is purchased
if (tag.itemName === "Skeet Blanket") {
LK.getSound('Skeetblanket').play();
}
// Play velourjumpsuit sound if Velour Jumpsuit is purchased
if (tag.itemName === "Velour Jumpsuit") {
LK.getSound('Velourjumpsuit').play();
}
// Play plaidshirt sound if Plaid Button-Up Shirt is purchased
if (tag.itemName === "Plaid Button-Up Shirt") {
LK.getSound('Plaidshirt').play();
}
// Play grandmascoat sound if Grandma's Coat is purchased
if (tag.itemName === "Grandma's Coat") {
LK.getSound('Grandmascoat').play();
}
// Play foxfur sound if Fox Skin is purchased
if (tag.itemName === "Fox Skin") {
LK.getSound('Foxfur').play();
}
// Play wolfhat sound if Wolf Skin Hat is purchased
if (tag.itemName === "Wolf Skin Hat") {
LK.getSound('Wolfhat').play();
}
// Play zebrajamies sound if Zebra Pajamas is purchased
if (tag.itemName === "Zebra Pajamas") {
LK.getSound('Zebrajamies').play();
}
// Play dookiebrown sound if Dookie Brown Leather Jacket is purchased
if (tag.itemName === "Dookie Brown Leather Jacket") {
LK.getSound('Dookiebrown').play();
}
budgetText.setText('$' + shoppingCart.getBudget());
// Play kneeboard sound if Kneeboard is purchased
if (tag.itemName === "Kneeboard") {
LK.getSound('Kneeboard').play();
}
// Play brokenkeyboard sound if Broken Keyboard is purchased
if (tag.itemName === "Broken Keyboard") {
LK.getSound('Brokenkeyboard').play();
}
// Play telescope sound if Telescope is purchased
if (tag.itemName === "Telescope") {
LK.getSound('Telescope').play();
}
// Track purchased item
if (purchasedItems.indexOf(tag.itemName) === -1) {
purchasedItems.push(tag.itemName);
// Check if this item is on the current shopping list
var isOnCurrentList = false;
for (var j = 0; j < shoppingListItems.length; j++) {
if (shoppingListItems[j].name === tag.itemName) {
isOnCurrentList = true;
break;
}
}
if (isOnCurrentList) {
currentChecklistPurchaseCount++;
// Check if we've purchased 5 items from current list
if (currentChecklistPurchaseCount >= 5) {
// Calculate voucher amount based on checklist number
var voucherAmount = currentChecklistNumber === 1 ? 3.00 : currentChecklistNumber === 2 ? 5.00 : 5.00;
shoppingCart.budget = Math.round((shoppingCart.budget + voucherAmount) * 100) / 100;
LK.getSound('Cash').play();
budgetText.setText('$' + shoppingCart.getBudget());
// Show shopkeeper dialogue about voucher
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
shopkeeperDialogue = game.addChild(new Container());
shopkeeperDialogue.x = 1024;
shopkeeperDialogue.y = 900;
// Add background for dialogue
var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7
}));
// Add voucher dialogue text
var dialogueText = shopkeeperDialogue.addChild(new Text2("Congratulations!\n\nYou completed your shopping list!\nHere's a $" + voucherAmount.toFixed(2) + " voucher for your next purchase.", {
size: 80,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = 0;
dialogueText.y = 0;
// Make dialogue dismissible on tap
shopkeeperDialogue.interactive = true;
shopkeeperDialogue.on('down', function () {
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
});
// Generate new checklist
currentChecklistNumber++;
currentChecklistPurchaseCount = 0;
// Clear current shopping list and generate new one
shoppingListItems = [];
generateNewShoppingList();
}
}
}
// Remove both tag and item from scene
tag.destroy();
selectedItem.destroy();
// Add to inventory bar
var targetBar = inventoryBar.children.length < 10 ? inventoryBar : bottomInventoryBar;
var itemSlot = targetBar.addChild(LK.getAsset('itemSlot', {
anchorX: 0.5,
anchorY: 0.5,
x: targetBar.children.length * 180 + 90,
y: 125
}));
itemSlot.addChild(LK.getAsset(selectedItem.assetId || tag.assetId || tag.itemName, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 0.5,
scaleY: 0.5
}));
}
highlight(selectedTag, false);
highlight(selectedItem, false);
selectedTag = null;
selectedItem = null;
return;
}
// Otherwise, select this tag
if (selectedTag) highlight(selectedTag, false);
selectedTag = tag;
highlight(selectedTag, true);
};
}
// Item click handler
function onItemDown(item) {
return function () {
// If already selected, deselect
if (selectedItem === item) {
highlight(selectedItem, false);
selectedItem = null;
return;
}
// If a tag is already selected, try to buy
if (selectedTag && selectedTag.itemName === item.itemName) {
// Calculate price - apply 20% discount if tag is discounted
var finalPrice = selectedTag.itemPrice;
if (selectedTag.isDiscounted) {
// Special case: Pink Leopard Mink discount price is always $0.99, do not apply 20% off logic
if (selectedTag.itemName === "Pink Leopard Mink") {
finalPrice = 0.99;
} else if (selectedTag.itemName === "Fox Skin") {
finalPrice = 2.00;
} else if (selectedTag.itemName === "Skeet Blanket") {
finalPrice = 0.50;
} else if (selectedTag.itemName === "Broken Keyboard") {
finalPrice = 1.00;
} else {
// Find original price from itemData
var originalPrice = null;
for (var i = 0; i < itemData.length; ++i) {
if (itemData[i].name === selectedTag.itemName) {
originalPrice = itemData[i].price;
break;
}
}
if (originalPrice) {
finalPrice = originalPrice * 0.8; // 20% off original price
}
}
}
// Check if player can afford the item, show game over if not
if (shoppingCart.getBudget() < finalPrice) {
// Check if player can afford ANYTHING on the current shopping list
var canAffordSomething = false;
for (var i = 0; i < shoppingListItems.length; i++) {
// Only check unpurchased items
if (purchasedItems.indexOf(shoppingListItems[i].name) === -1) {
// Find the tag for this item
for (var j = 0; j < priceTagObjects.length; j++) {
if (priceTagObjects[j].itemName === shoppingListItems[i].name) {
var tagPrice = priceTagObjects[j].itemPrice;
// If discounted, check for special prices
if (priceTagObjects[j].isDiscounted) {
if (priceTagObjects[j].itemName === "Pink Leopard Mink") tagPrice = 0.99;else if (priceTagObjects[j].itemName === "Fox Skin") tagPrice = 2.00;else if (priceTagObjects[j].itemName === "Skeet Blanket") tagPrice = 0.50;else if (priceTagObjects[j].itemName === "Broken Keyboard") tagPrice = 1.00;else {
// Find original price
for (var k = 0; k < itemData.length; ++k) {
if (itemData[k].name === priceTagObjects[j].itemName) {
tagPrice = itemData[k].price * 0.8;
break;
}
}
}
}
if (shoppingCart.getBudget() >= tagPrice) {
canAffordSomething = true;
break;
}
}
}
}
if (canAffordSomething) break;
}
if (!canAffordSomething) {
// Show dialogue explaining can't afford anything else
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
shopkeeperDialogue = game.addChild(new Container());
shopkeeperDialogue.x = 1024;
shopkeeperDialogue.y = 900;
var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7
}));
var dialogueText = shopkeeperDialogue.addChild(new Text2("Looks like you can't afford anything else on your list!\n\nBetter luck next time!", {
size: 90,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = 0;
dialogueText.y = 0;
// Play probsshoulda sound when this text is being displayed
LK.getSound('Probsshoulda').play();
// Make dialogue dismissible on tap, then go to game over
shopkeeperDialogue.interactive = true;
shopkeeperDialogue.on('down', function () {
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
LK.showGameOver();
});
} else {
LK.showGameOver();
}
return;
}
// Attempt to buy
if (shoppingCart.addItem(item.itemName, finalPrice)) {
// Play leopard mink sound if Pink Leopard Mink is purchased
if (item.itemName === "Pink Leopard Mink") {
LK.getSound('Leopardmink').play();
}
// Play bigasscoat sound if Big Ass Coat is purchased
if (item.itemName === "Big Ass Coat") {
LK.getSound('Bigasscoat').play();
}
// Play builtinonesie sound if Built-In Onesie With Socks is purchased
if (item.itemName === "Built-In Onesie With Socks") {
LK.getSound('Builtinonesie').play();
}
// Play gatorshoes sound if Gator Shoes is purchased
if (item.itemName === "Gator Shoes") {
LK.getSound('Gatorshoes').play();
}
// Play velcros sound if Velcro Sneakers is purchased
if (item.itemName === "Velcro Sneakers") {
LK.getSound('Velcros').play();
}
// Play houseslippers sound if House Slippers is purchased
if (item.itemName === "House Slippers") {
LK.getSound('Houseslippers').play();
}
// Play skeetblanket sound if Skeet Blanket is purchased
if (item.itemName === "Skeet Blanket") {
LK.getSound('Skeetblanket').play();
}
// Play velourjumpsuit sound if Velour Jumpsuit is purchased
if (item.itemName === "Velour Jumpsuit") {
LK.getSound('Velourjumpsuit').play();
}
// Play plaidshirt sound if Plaid Button-Up Shirt is purchased
if (item.itemName === "Plaid Button-Up Shirt") {
LK.getSound('Plaidshirt').play();
}
// Play grandmascoat sound if Grandma's Coat is purchased
if (item.itemName === "Grandma's Coat") {
LK.getSound('Grandmascoat').play();
}
// Play foxfur sound if Fox Skin is purchased
if (item.itemName === "Fox Skin") {
LK.getSound('Foxfur').play();
}
// Play wolfhat sound if Wolf Skin Hat is purchased
if (item.itemName === "Wolf Skin Hat") {
LK.getSound('Wolfhat').play();
}
// Play zebrajamies sound if Zebra Pajamas is purchased
if (item.itemName === "Zebra Pajamas") {
LK.getSound('Zebrajamies').play();
}
// Play dookiebrown sound if Dookie Brown Leather Jacket is purchased
if (item.itemName === "Dookie Brown Leather Jacket") {
LK.getSound('Dookiebrown').play();
}
budgetText.setText('$' + shoppingCart.getBudget());
// Play kneeboard sound if Kneeboard is purchased
if (item.itemName === "Kneeboard") {
LK.getSound('Kneeboard').play();
}
// Play brokenkeyboard sound if Broken Keyboard is purchased
if (item.itemName === "Broken Keyboard") {
LK.getSound('Brokenkeyboard').play();
}
// Play telescope sound if Telescope is purchased
if (item.itemName === "Telescope") {
LK.getSound('Telescope').play();
}
// Track purchased item
if (purchasedItems.indexOf(item.itemName) === -1) {
purchasedItems.push(item.itemName);
// Check if this item is on the current shopping list
var isOnCurrentList = false;
for (var j = 0; j < shoppingListItems.length; j++) {
if (shoppingListItems[j].name === item.itemName) {
isOnCurrentList = true;
break;
}
}
if (isOnCurrentList) {
currentChecklistPurchaseCount++;
// Check if we've purchased 5 items from current list
if (currentChecklistPurchaseCount >= 5) {
// Calculate voucher amount based on checklist number
var voucherAmount = currentChecklistNumber === 1 ? 3.00 : currentChecklistNumber === 2 ? 5.00 : 5.00;
shoppingCart.budget = Math.round((shoppingCart.budget + voucherAmount) * 100) / 100;
LK.getSound('Cash').play();
budgetText.setText('$' + shoppingCart.getBudget());
// Show shopkeeper dialogue about voucher
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
shopkeeperDialogue = game.addChild(new Container());
shopkeeperDialogue.x = 1024;
shopkeeperDialogue.y = 900;
// Add background for dialogue
var dialogueBg = shopkeeperDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7
}));
// Add voucher dialogue text
var dialogueText = shopkeeperDialogue.addChild(new Text2("Congratulations!\n\nYou completed your shopping list!\nHere's a $" + voucherAmount.toFixed(2) + " voucher for your next purchase.", {
size: 80,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = 0;
dialogueText.y = 0;
// Make dialogue dismissible on tap
shopkeeperDialogue.interactive = true;
shopkeeperDialogue.on('down', function () {
if (shopkeeperDialogue) {
shopkeeperDialogue.destroy();
shopkeeperDialogue = null;
}
});
// Generate new checklist
currentChecklistNumber++;
currentChecklistPurchaseCount = 0;
// Clear current shopping list and generate new one
shoppingListItems = [];
generateNewShoppingList();
}
}
}
// Remove both tag and item from scene
selectedTag.destroy();
item.destroy();
// Add to inventory bar
var targetBar = inventoryBar.children.length < 10 ? inventoryBar : bottomInventoryBar;
var itemSlot = targetBar.addChild(LK.getAsset('itemSlot', {
anchorX: 0.5,
anchorY: 0.5,
x: targetBar.children.length * 180 + 90,
y: 125
}));
itemSlot.addChild(LK.getAsset(item.assetId || selectedTag.assetId || item.itemName, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 0.5,
scaleY: 0.5
}));
}
highlight(selectedTag, false);
highlight(selectedItem, false);
selectedTag = null;
selectedItem = null;
return;
}
// Otherwise, select this item
if (selectedItem) highlight(selectedItem, false);
selectedItem = item;
highlight(selectedItem, true);
};
}
// Attach click handlers
for (var i = 0; i < priceTagObjects.length; ++i) {
var tag = priceTagObjects[i];
tag.on('down', onTagDown(tag));
}
for (var i = 0; i < itemObjects.length; ++i) {
var item = itemObjects[i];
item.interactive = true;
item.assetId = itemData[i].asset;
item.on('down', onItemDown(item));
}
// --- End floating price tag and click-to-buy system ---
// Add instruction box with black background to the middle of the screen
var instructionBox = game.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.5,
scaleY: 1.5
}));
var shoppingCart = new ShoppingCart(20); // Initialize shoppingCart with $20 in budget
var budgetText = new Text2('$' + shoppingCart.getBudget(), {
size: 50,
fill: 0xFFFFFF
});
budgetText.anchor.set(0.5, 0.5);
budgetText.zIndex = 2; // Increase zIndex to place text in front of shopping cart
var instructionText = new Text2('Welcome to Poppin\' Tags: A Thrift Shop Tribute.', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.zIndex = 2; // Increase zIndex to place text in front of instruction box
instructionBox.addChild(instructionText);
instructionBox.interactive = true;
var clickCount = 0;
instructionBox.on('down', function () {
clickCount++;
if (clickCount === 1) {
instructionText.setText('You have $20 in your pocket and are huntin\' for a come-up.');
} else if (clickCount === 2) {
instructionText.setText('Try and buy all items on your shopping list \n as cheap as you can. This is gonna be AWESOME!!!');
} else if (clickCount === 3) {
instructionBox.destroy();
shoppingCart = new ShoppingCart(20); // Create a shopping cart with $20 in budget
var shoppingCartDisplay = game.addChild(LK.getAsset('moneyContainer', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 300,
scaleX: 1.5,
scaleY: 1.5
}));
budgetText = new Text2('$' + shoppingCart.getBudget(), {
size: 50,
fill: 0xFFFFFF
});
budgetText.anchor.set(0.5, 0.5);
budgetText.zIndex = 2; // Increase zIndex to place text in front of shopping cart
shoppingCartDisplay.addChild(budgetText);
// Add shopping list to top left corner (avoiding the menu icon area)
var shoppingListDisplay = game.addChild(LK.getAsset('Shoppinglist', {
anchorX: 0,
anchorY: 0,
x: 0,
// Position away from top-left menu icon
y: 370,
scaleX: 0.6,
scaleY: 0.6
}));
// Make shopping list interactive
shoppingListDisplay.interactive = true;
// Create enlarged shopping list (initially hidden)
var enlargedShoppingList = null;
shoppingListDisplay.on('down', function () {
if (enlargedShoppingList) {
// If already showing, hide it
enlargedShoppingList.destroy();
enlargedShoppingList = null;
} else {
// Create enlarged shopping list container
enlargedShoppingList = game.addChild(new Container());
enlargedShoppingList.x = 1024;
enlargedShoppingList.y = 1366;
// Add background for enlarged list
var listBackground = enlargedShoppingList.addChild(LK.getAsset('listBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 2.5
}));
// Initialize shopping list items if not already done
if (shoppingListItems.length === 0) {
generateNewShoppingList();
}
// Add title text
var titleText = enlargedShoppingList.addChild(new Text2('Shopping List #' + currentChecklistNumber, {
size: 60,
fill: 0x000000
}));
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -200;
// Add items to the list with checkmarks for purchased items
for (var i = 0; i < shoppingListItems.length; i++) {
// Check purchase status using indexOf to determine if item exists in purchasedItems array
var isPurchased = purchasedItems.indexOf(shoppingListItems[i].name) !== -1;
// Add checkbox background (empty slot for all items)
var checkbox = enlargedShoppingList.addChild(LK.getAsset('itemSlot', {
anchorX: 0.5,
anchorY: 0.5,
x: -400,
y: -100 + i * 80,
scaleX: 0.3,
scaleY: 0.3
}));
// Add visible checkmark if item is purchased (purchase status check result)
if (isPurchased) {
var checkmark = enlargedShoppingList.addChild(LK.getAsset('checkmark', {
anchorX: 0.5,
anchorY: 0.5,
x: -400,
y: -100 + i * 80,
scaleX: 0.3,
scaleY: 0.3
}));
}
// Style item text differently for purchased items (green with strikethrough effect) vs unpurchased (black)
var itemText = enlargedShoppingList.addChild(new Text2(isPurchased ? "✓ " + shoppingListItems[i].name : shoppingListItems[i].name, {
size: 70,
fill: isPurchased ? 0x32cd32 : 0x000000
}));
itemText.anchor.set(0.5, 0.5);
itemText.x = 0;
itemText.y = -100 + i * 80;
}
// Make enlarged list clickable to close
enlargedShoppingList.interactive = true;
enlargedShoppingList.on('down', function () {
enlargedShoppingList.destroy();
enlargedShoppingList = null;
});
}
});
}
});
});
var ShoppingCart = /*#__PURE__*/function () {
function ShoppingCart(initialBudget) {
_classCallCheck(this, ShoppingCart);
this.budget = Math.round(initialBudget * 100) / 100; // Round to 2 decimal places
this.items = [];
}
return _createClass(ShoppingCart, [{
key: "addItem",
value: function addItem(item, price) {
var roundedPrice = Math.round(price * 100) / 100; // Round price to 2 decimal places
if (this.budget >= roundedPrice) {
this.items.push(item);
this.budget = Math.round((this.budget - roundedPrice) * 100) / 100; // Prevent floating-point errors
if (this.items.length === 17) {
// Show win explanation dialogue
var winDialogue = game.addChild(new Container());
winDialogue.x = 1024;
winDialogue.y = 900;
var winBg = winDialogue.addChild(LK.getAsset('instructionBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 1.0,
alpha: 0.7
}));
var winText = winDialogue.addChild(new Text2("You did it! You popped them tags and achieved the ultimate come up!", {
size: 90,
fill: 0xFFFFFF,
align: "center",
wordWrap: true,
wordWrapWidth: 1500
}));
winText.anchor.set(0.5, 0.5);
winText.x = 0;
winText.y = 0;
// Play poptags sound when this text is being displayed
LK.getSound('Poptags').play();
// Make dialogue dismissible on tap, then show you win
winDialogue.interactive = true;
winDialogue.on('down', function () {
if (winDialogue) {
winDialogue.destroy();
}
LK.showYouWin();
});
return true;
}
return true;
}
return false;
}
}, {
key: "removeItem",
value: function removeItem(item, price) {
var index = this.items.indexOf(item);
if (index > -1) {
this.items.splice(index, 1);
var roundedPrice = Math.round(price * 100) / 100; // Round price to 2 decimal places
this.budget = Math.round((this.budget + roundedPrice) * 100) / 100; // Prevent floating-point errors
}
}
}, {
key: "getBudget",
value: function getBudget() {
return Math.round(this.budget * 100) / 100; // Always return properly rounded budget
}
}, {
key: "getItems",
value: function getItems() {
return this.items;
}
}]);
}();
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) {
protoProps.forEach(function (prop) {
Object.defineProperty(Constructor.prototype, prop.key, prop);
});
}
if (staticProps) {
staticProps.forEach(function (prop) {
Object.defineProperty(Constructor, prop.key, prop);
});
}
return Constructor;
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
onesie with socks. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
big coat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
brown leather jacket. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
flannel zebra pyjamas. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
fur fox skin. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Pink leopard mink coat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Wolf skin hat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Velour jumpsuit. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Telescope. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Dirty blanket. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Velcro sneakers. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Plaid button up shirt. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
music keyboard. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Shopping list that says Big ass coat, Broken keyboard, skeet blanket, pink leopard mink, built-in onesie with the socks. In-Game asset. 2d. High contrast. No shadows
Price tag that says big ass coat $4.00. In-Game asset. 2d. High contrast. No shadows
Price tag that says Kneeboard $4.00. In-Game asset. 2d. High contrast. No shadows
police tag that says Broken Keyboard for $2. In-Game asset. 2d. High contrast. No shadows
Price tag that says Telescope $3.00. In-Game asset. 2d. High contrast. No shadows
price tag that's says Dookie Brown Leather Jacket $3.50. In-Game asset. 2d. High contrast. No shadows
price tag that says pink leopard mink $5. In-Game asset. 2d. High contrast. No shadows
price tag that says plaid button up shirt $2. In-Game asset. 2d. High contrast. No shadows
Price tag that says Gator shoes $3.00. In-Game asset. 2d. High contrast. No shadows
price tag that says fox skin $4.50. In-Game asset. 2d. High contrast. No shadows
Price tag that says Velcro sneakers $2.00. In-Game asset. 2d. High contrast. No shadows
price tag that says house slippers $1.50. In-Game asset. 2d. High contrast. No shadows
Price tag that says velour jumpsuit $3.00. In-Game asset. 2d. High contrast. No shadows
price tag that says wolf skin hat $2. In-Game asset. 2d. High contrast. No shadows
Price tag that says skeet blanket $2.00. In-Game asset. 2d. High contrast. No shadows
Price tag that says Zebra Pyjamas $2.50. In-Game asset. 2d. High contrast. No shadows
Green Discount price tag that says Big ass coat $2.40. In-Game asset. 2d. High contrast. No shadows
green price tag that says discount Dookie Brown Leather Jacket $2.80. In-Game asset. 2d. High contrast. No shadows
Green price tag that says discount kneeboard $3.20. In-Game asset. 2d. High contrast. No shadows
green price tag that says discount plaid button up shirt $1.60. In-Game asset. 2d. High contrast. No shadows
green price tag that says discount zebra pajamas $2. In-Game asset. 2d. High contrast. No shadows
Green pricetag that says discount Telescope $2.40. In-Game asset. 2d. High contrast. No shadows
green price tag that says discount velour jumpsuit $2.40. In-Game asset. 2d. High contrast. No shadows
Green pricetag that says discount Velcro sneakers $1.60. In-Game asset. 2d. High contrast. No shadows
green price tag that says discount house slippers $1.20. In-Game asset. 2d. High contrast. No shadows
green price tag that says discount wolf skin hat $1.60. In-Game asset. 2d. High contrast. No shadows
Green pricetag that says discount gator shoes $2.40. In-Game asset. 2d. High contrast. No shadows
Green pricetag that says discount built in onesie with socks $1.60. In-Game asset. 2d. High contrast. No shadows
Price tag that says built-in onesie with socks $2.00. In-Game asset. 2d. High contrast. No shadows
green price tag that says discount pink leopard mink 99 cents! In-Game asset. 2d. High contrast. No shadows
green price tag that says discount fox skin $2 In-Game asset. 2d. High contrast. No shadows
green price tag that says discount skeet blanket $0.50 In-Game asset. 2d. High contrast. No shadows
Green price tag that says discount broken keyboard $1 In-Game asset. 2d. High contrast. No shadows
Make picture transparent
Make picture transparent
Make picture transparent
Make picture transparent
Make picture transparent
Add number 5 to painted area
Sign that says play the notes in right order to start the game. In-Game asset. 2d. High contrast. No shadows
portrait banner, high definition, for a game titled "Poppin' Tags: A Thrift Shop Trubute"
How to play button. In-Game asset. 2d. High contrast. No shadows
1
Sound effect
2
Sound effect
3
Sound effect
4
Sound effect
5
Sound effect
6
Sound effect
7
Sound effect
8
Sound effect
Item1
Sound effect
Instrumental
Music
instrumentalMusic
Music
Heymacklemore
Sound effect
Cash
Sound effect
Leopardmink
Sound effect
Gatorshoes
Sound effect
Houseslippers
Sound effect
Dookiebrown
Sound effect
Velcros
Sound effect
Grandmascoat
Sound effect
Bigasscoat
Sound effect
Kneeboard
Sound effect
Brokenkeyboard
Sound effect
Skeetblanket
Sound effect
Foxfur
Sound effect
Builtinonesie
Sound effect
Plaidshirt
Sound effect
Telescope
Sound effect
Velourjumpsuit
Sound effect
Wolfhat
Sound effect
Zebrajamies
Sound effect
Poptags
Sound effect
Probsshoulda
Sound effect