/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Customer = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('customer', { anchorX: 0.5, anchorY: 1 }); self.items = []; self.currentItemIndex = 0; self.isBeingServed = false; self.patience = 100; self.maxPatience = 100; self.waitTime = 0; self.isShopping = true; self.targetShelf = null; self.itemsToCollect = Math.floor(Math.random() * 3) + 2; self.upset = false; self.angry = false; self.upsetStartTime = 0; self.paid = false; self.placeItemsOnCounter = function () { var startY = counterY + 50 - self.items.length * 70 / 2; for (var i = 0; i < self.items.length; i++) { var item = self.items[i]; // Don't add item directly, it's already part of customer // Instead, create a new product with the same properties var counterItem = new Product(item.productType); counterItem.value = item.value; counterItem.name = item.name; counterItem.productType = item.productType; counterItem.x = 900; // Move to the left from center counterItem.y = startY + i * 70; // Place items vertically game.addChild(counterItem); // If automatic scanner is owned, automatically scan the item if (hasAutomaticScanner) { counterItem.scanned = true; // Find the graphics child and make it transparent for (var g = 0; g < counterItem.children.length; g++) { if (counterItem.children[g].alpha !== undefined) { counterItem.children[g].alpha = 0.5; break; } } LK.getSound('itemScan').play(); } // Replace the item in the array with the counter version self.items[i] = counterItem; } }; self.allItemsScanned = function () { for (var i = 0; i < self.items.length; i++) { if (!self.items[i].scanned) { return false; } } return true; }; self.getTotalValue = function () { var total = 0; for (var i = 0; i < self.items.length; i++) { total += self.items[i].value; } return total; }; self.completeTransaction = function () { // Mark customer as paid self.paid = true; // If customer was upset, stop shaking animation if (self.upset) { tween.stop(self, { x: true }); self.x = self.originalX; } // Remove items from counter for (var i = 0; i < self.items.length; i++) { if (self.items[i].parent) { self.items[i].destroy(); } } // Add to money var earnings = self.getTotalValue(); money += earnings; dailyEarnings += earnings; scoreTxt.setText(money + '₺'); // Play sound LK.getSound('cashRegister').play(); // Move customer out tween(self, { x: -200 }, { duration: 1000, onFinish: function onFinish() { totalCustomersExited++; // Increment exit counter self.destroy(); } }); }; self.collectItemFromShelf = function () { if (self.items.length < self.itemsToCollect && self.targetShelf) { var takenProduct = self.targetShelf.takeProduct(); if (takenProduct) { // Store the product data directly without creating a visual product yet self.items.push({ productType: takenProduct.productType, value: takenProduct.value, name: takenProduct.name, scanned: false }); // Visual feedback tween(graphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, onFinish: function onFinish() { tween(graphics, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); // Play sound when customer takes item LK.getSound('customerPurchase').play(); } } }; self.update = function () { // Track wait time for customers being served if (self.isBeingServed && !self.upset && !self.angry && !self.paid) { self.waitTime++; // Check if customer should become upset (10 seconds = 600 frames at 60fps) if (self.waitTime >= 600) { self.upset = true; self.upsetStartTime = 0; // Change color to indicate upset state (slightly darker) graphics.tint = 0x888888; // Start shaking animation self.originalX = self.x; self.shakeAnimation = function () { if (self.upset && !self.angry && !self.paid) { tween(self, { x: self.originalX + (Math.random() - 0.5) * 20 }, { duration: 100, onFinish: function onFinish() { if (self.upset && !self.angry && !self.paid) { self.shakeAnimation(); } } }); } }; self.shakeAnimation(); } } // Track upset time and transition to angry (only if not paid) if (self.upset && !self.angry && !self.paid) { self.upsetStartTime++; // Check if customer should become angry (5 seconds = 300 frames at 60fps) if (self.upsetStartTime >= 300) { self.angry = true; // Stop shaking animation tween.stop(self, { x: true }); self.x = self.originalX; // Change color to red when angry graphics.tint = 0xFF0000; // Remove items from counter when angry customer leaves for (var i = 0; i < self.items.length; i++) { if (self.items[i].parent) { self.items[i].destroy(); } } // Make angry customer leave the store tween(self, { x: -200 }, { duration: 1000, onFinish: function onFinish() { totalCustomersExited++; // Increment exit counter self.destroy(); } }); } } }; return self; }); var Product = Container.expand(function (productType) { var self = Container.call(this); // Define product types with their properties var productTypes = [{ asset: 'apple', name: 'Apple', value: 20 }, { asset: 'banana', name: 'Banana', value: 40 }, { asset: 'orange', name: 'Orange', value: 30 }, { asset: 'milk', name: 'Milk', value: 50 }, { asset: 'bread', name: 'Bread', value: 10 }, { asset: 'cheese', name: 'Cheese', value: 30 }]; // Use specified product type or randomly select one var selectedType; if (productType) { // Find the product type that matches the specified type for (var i = 0; i < productTypes.length; i++) { if (productTypes[i].asset === productType) { selectedType = productTypes[i]; break; } } } if (!selectedType) { // Fallback to random selection if no type specified or not found selectedType = productTypes[Math.floor(Math.random() * productTypes.length)]; } var graphics = self.attachAsset(selectedType.asset, { anchorX: 0.5, anchorY: 0.5 }); self.scanned = false; self.value = selectedType.value; self.name = selectedType.name; self.productType = selectedType.asset; // Visual feedback for scanned items self.scan = function () { if (!self.scanned) { self.scanned = true; graphics.alpha = 0.5; // Make transparent when scanned LK.getSound('itemScan').play(); } }; self.down = function (x, y, obj) { if (!shopOpen) { self.scan(); } }; return self; }); var Shelf = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('shelf', { anchorX: 0.5, anchorY: 0.5 }); self.products = []; // Create products on shelf self.createProducts = function () { var rows = 3; var cols = 3; var spacing = 100; var startX = -120; var startY = -120; // Define product types for this shelf var productTypes = [{ asset: 'apple', name: 'Apple', value: 20 }, { asset: 'banana', name: 'Banana', value: 40 }, { asset: 'orange', name: 'Orange', value: 30 }, { asset: 'milk', name: 'Milk', value: 50 }, { asset: 'bread', name: 'Bread', value: 10 }, { asset: 'cheese', name: 'Cheese', value: 30 }]; // Each shelf will have products organized by type in rows var shelfProductTypes = []; var numTypes = Math.min(rows, productTypes.length); // One type per row, max 3 types for (var t = 0; t < numTypes; t++) { var randomType = productTypes[Math.floor(Math.random() * productTypes.length)]; // Make sure we don't duplicate types on same shelf var alreadyExists = false; for (var e = 0; e < shelfProductTypes.length; e++) { if (shelfProductTypes[e].asset === randomType.asset) { alreadyExists = true; break; } } if (!alreadyExists) { shelfProductTypes.push(randomType); } else { t--; // Try again with different type } } for (var row = 0; row < rows; row++) { for (var col = 0; col < cols; col++) { // Each row has the same product type var selectedType = shelfProductTypes[row % shelfProductTypes.length]; var product = self.attachAsset(selectedType.asset, { anchorX: 0.5, anchorY: 0.5 }); product.x = startX + col * spacing; product.y = startY + row * (spacing + 20); // Add extra 20px spacing between rows product.available = true; product.productType = selectedType.asset; product.name = selectedType.name; product.value = selectedType.value; self.products.push(product); } } }; // Only create products on Day 1 if (currentDay === 1) { self.createProducts(); } self.takeProduct = function () { for (var i = 0; i < self.products.length; i++) { if (self.products[i].available) { var product = self.products[i]; product.available = false; product.visible = false; return { value: product.value, name: product.name, productType: product.productType }; } } return null; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xfffca1, width: 3072, height: 4098 }); /**** * Game Code ****/ var customers = []; var customerQueue = []; var currentCustomer = null; var spawnTimer = 0; var spawnDelay = Math.floor(Math.random() * (540 - 360 + 1)) + 360; // Random between 6-9 seconds (360-540 frames at 60fps) var counterY = 3450; // Bottom of screen // Load money based on whether we're continuing the same day or starting fresh var money = storage.lastPlayedDay === currentDay ? storage.money : storage.dayStartMoney || 0; var totalCustomersSpawned = 0; // Track total customers spawned var totalCustomersExited = 0; // Track total customers who left the store var currentDay = storage.currentDay || 1; // Current day number var dailyEarnings = 0; // Money earned today var dayStartMoney = storage.dayStartMoney || 0; // Money at the start of the current day var gameOverPaused = false; // Track if game is paused for day summary var storeOpen = false; // Track if store is open or closed - start closed var shopOpen = false; // Track if shop overlay is open var dayJustStarted = true; // Track if day just started to prevent immediate day end var hasAutomaticScanner = storage.hasAutomaticScanner || false; // Track if automatic scanner is purchased // No changes needed - the code already ensures only the customer being served gets angry var shelves = []; // Load shelves from storage or use default positions var totalShelves = storage.totalShelves || 4; var defaultShelfPositions = [{ x: 400, y: 1000 }, { x: 1600, y: 1000 }, { x: 400, y: 1600 }, { x: 1600, y: 1600 }]; for (var i = 0; i < totalShelves; i++) { var shelf = new Shelf(); // Load from storage if available, otherwise use default positions if (storage['shelf' + i + 'X'] !== undefined && storage['shelf' + i + 'Y'] !== undefined) { shelf.x = storage['shelf' + i + 'X']; shelf.y = storage['shelf' + i + 'Y']; } else if (i < defaultShelfPositions.length) { shelf.x = defaultShelfPositions[i].x; shelf.y = defaultShelfPositions[i].y; // Save default positions to storage for future use storage['shelf' + i + 'X'] = shelf.x; storage['shelf' + i + 'Y'] = shelf.y; } else { // New shelf without default position, place at center shelf.x = 1024; shelf.y = 1366; } shelves.push(shelf); game.addChild(shelf); } // Create cash register at bottom center var cashRegister = game.addChild(LK.getAsset('cashRegister', { anchorX: 0.5, anchorY: 0.5 })); cashRegister.x = 1536; // Center of screen cashRegister.y = counterY; // Bottom position // Create open/close button below cash register - start with Close image var openCloseBtn = game.addChild(LK.getAsset('Close', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1536; openCloseBtn.y = counterY + 300; // Position further below cash register openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; // Handle open/close button click openCloseBtn.down = function () { if (!gameOverPaused && !shopOpen) { // Check if trying to open the store if (!storeOpen && areAllShelvesEmpty()) { // Don't allow opening if no products return; } storeOpen = !storeOpen; if (storeOpen) { // Replace with Open image openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Open', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; openCloseBtn.down = arguments.callee; // Re-assign click handler } else { // Replace with Close image openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Close', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; openCloseBtn.down = arguments.callee; // Re-assign click handler } } }; // Create queue line var queueLine = game.addChild(LK.getAsset('queueLine', { anchorX: 0.5, anchorY: 0.5 })); queueLine.x = 1536; // Center of screen queueLine.y = counterY - 300; // Position above cash register // Create black rectangle first (so it appears behind) var blackRect = LK.getAsset('blackRectangle', { anchorX: 0.5, anchorY: 0 }); blackRect.y = 135; // Position behind the money text LK.gui.top.addChild(blackRect); // Create day counter display in top left var dayTxt = new Text2('Day ' + currentDay, { size: 50, fill: 0x000000 }); dayTxt.anchor.set(0, 0); dayTxt.x = 150; // Position to avoid menu icon area LK.gui.topLeft.addChild(dayTxt); // Save initial money for day 1 if not already saved if (!storage.dayStartMoney) { storage.dayStartMoney = money; storage.lastPlayedDay = currentDay; } // Create money display (added after, so it appears on top) var scoreTxt = new Text2('₺' + money, { size: 60, fill: 0x006400 }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 150; // Move money display lower LK.gui.top.addChild(scoreTxt); // Create instructions var instructionsTxt = new Text2('Tap items to scan them!', { size: 40, fill: 0x0000 }); instructionsTxt.anchor.set(0.5, 0); instructionsTxt.y = 80; LK.gui.top.addChild(instructionsTxt); // Create customer counter displays in top right var spawnedCounterTxt = new Text2('Spawned: 0', { size: 40, fill: 0x000000 }); spawnedCounterTxt.anchor.set(1, 0); LK.gui.topRight.addChild(spawnedCounterTxt); var exitedCounterTxt = new Text2('Exited: 0', { size: 40, fill: 0x000000 }); exitedCounterTxt.anchor.set(1, 0); exitedCounterTxt.y = 50; LK.gui.topRight.addChild(exitedCounterTxt); function spawnCustomer() { var customer = new Customer(); customer.x = 1536; // Center of screen customer.y = -200; // Above screen customers.push(customer); game.addChild(customer); totalCustomersSpawned++; // Increment customer counter // Customer shopping sequence var shelfIndex = 0; var _visitShelf = function visitShelf() { if (shelfIndex < shelves.length && customer.items.length < customer.itemsToCollect) { // Find shelves with available products var availableShelves = []; for (var s = 0; s < shelves.length; s++) { var shelf = shelves[s]; var hasAvailableProducts = false; for (var p = 0; p < shelf.products.length; p++) { if (shelf.products[p].available) { hasAvailableProducts = true; break; } } if (hasAvailableProducts) { availableShelves.push(shelf); } } // If no shelves have products, customer leaves without shopping if (availableShelves.length === 0) { // Done shopping (forced), join queue with current items customer.isShopping = false; customerQueue.push(customer); var queuePosition = queueLine.x + customerQueue.length * 200; tween(customer, { x: queuePosition, y: queueLine.y }, { duration: 1500 }); return; } // Select random shelf from available ones var targetShelf = availableShelves[Math.floor(Math.random() * availableShelves.length)]; tween(customer, { x: targetShelf.x, y: targetShelf.y + 250 }, { duration: 1500, onFinish: function onFinish() { customer.targetShelf = targetShelf; customer.collectItemFromShelf(); shelfIndex++; LK.setTimeout(function () { if (customer.items.length < customer.itemsToCollect) { _visitShelf(); } else { // Done shopping, join queue customer.isShopping = false; customerQueue.push(customer); var queuePosition = queueLine.x + customerQueue.length * 200; tween(customer, { x: queuePosition, y: queueLine.y }, { duration: 1500 }); } }, 500); } }); } }; // Start shopping by entering store tween(customer, { y: 400 }, { duration: 1000, onFinish: function onFinish() { _visitShelf(); } }); } function areAllShelvesEmpty() { for (var i = 0; i < shelves.length; i++) { var shelf = shelves[i]; for (var j = 0; j < shelf.products.length; j++) { if (shelf.products[j].available) { return false; } } } return true; } function canAcceptMoreProducts(productType) { // First check if we've reached maximum capacity var currentProducts = 0; for (var s = 0; s < shelves.length; s++) { var shelf = shelves[s]; for (var p = 0; p < shelf.products.length; p++) { if (shelf.products[p] && shelf.products[p].available) { currentProducts++; } } } if (currentProducts >= maxProducts) { return false; } // Check if any shelf has empty space for this product type for (var s = 0; s < shelves.length; s++) { var shelf = shelves[s]; // Check each row for empty space for (var row = 0; row < 3; row++) { var rowEmpty = true; // Check if this row is empty for (var col = 0; col < 3; col++) { var index = row * 3 + col; if (shelf.products[index] && shelf.products[index].available) { rowEmpty = false; break; } } // If row is empty, we can accept more products if (rowEmpty) { return true; } } } return false; } function showDaySummary() { gameOverPaused = true; // Set store to closed to prevent customer spawning storeOpen = false; // Make all remaining customers exit the store for (var i = customers.length - 1; i >= 0; i--) { var customer = customers[i]; if (customer.parent) { // Stop any ongoing tweens tween.stop(customer, { x: true, y: true }); // Make customer exit tween(customer, { x: -200 }, { duration: 1000, onFinish: function onFinish() { totalCustomersExited++; customer.destroy(); } }); } } // Clear customer arrays and current customer customers = []; customerQueue = []; currentCustomer = null; // Update open/close button to show Close openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Close', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; // Re-assign click handler openCloseBtn.down = function () { if (!gameOverPaused && !shopOpen) { // Check if trying to open the store if (!storeOpen && areAllShelvesEmpty()) { // Don't allow opening if no products return; } storeOpen = !storeOpen; if (storeOpen) { // Replace with Open image openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Open', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; openCloseBtn.down = arguments.callee; // Re-assign click handler } else { // Replace with Close image openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Close', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; openCloseBtn.down = arguments.callee; // Re-assign click handler } } }; // Create dark overlay var overlay = game.addChild(LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5 })); overlay.x = 1024; overlay.y = 1366; overlay.alpha = 0; overlay.tint = 0x000000; // Create summary text var summaryTxt = new Text2('Day ' + currentDay + ' Complete!\n\nCustomers Served: ' + totalCustomersExited, { size: 60, fill: 0xffffff }); summaryTxt.anchor.set(0.5, 0.5); summaryTxt.x = 1024; summaryTxt.y = 1200; summaryTxt.alpha = 0; game.addChild(summaryTxt); // Create earnings display - centered and green var earningsTxt = new Text2(dailyEarnings + '₺', { size: 120, fill: 0x00ff00 }); earningsTxt.anchor.set(0.5, 0.5); earningsTxt.x = 1024; earningsTxt.y = 1700; earningsTxt.alpha = 0; game.addChild(earningsTxt); // Create continue button var continueBtn = game.addChild(LK.getAsset('continueButton', { anchorX: 0.5, anchorY: 0.5 })); continueBtn.x = 1024; continueBtn.y = 2400; continueBtn.alpha = 0; // Fade in animation tween(overlay, { alpha: 0.8 }, { duration: 1000 }); tween(summaryTxt, { alpha: 1 }, { duration: 1000 }); tween(earningsTxt, { alpha: 1 }, { duration: 1000 }); tween(continueBtn, { alpha: 1 }, { duration: 1000 }); // Handle continue button click continueBtn.down = function () { // Fade out animation tween(overlay, { alpha: 0 }, { duration: 1000 }); tween(summaryTxt, { alpha: 0 }, { duration: 1000 }); tween(earningsTxt, { alpha: 0 }, { duration: 1000 }); tween(continueBtn, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { // Remove summary elements after fade out overlay.destroy(); summaryTxt.destroy(); earningsTxt.destroy(); continueBtn.destroy(); gameOverPaused = false; startNextDay(); } }); }; } function startNextDay() { // Reset day variables currentDay++; dailyEarnings = 0; totalCustomersSpawned = 0; totalCustomersExited = 0; spawnTimer = 0; spawnDelay = Math.floor(Math.random() * (540 - 360 + 1)) + 360; // Random between 6-9 seconds // Save all game data to storage when starting next day storage.currentDay = currentDay; storage.dayStartMoney = money; // Save money at start of new day storage.lastPlayedDay = currentDay; // Track which day we're on storage.money = money; // Save shelf positions and count storage.totalShelves = shelves.length; for (var i = 0; i < shelves.length; i++) { storage['shelf' + i + 'X'] = shelves[i].x; storage['shelf' + i + 'Y'] = shelves[i].y; } // Save max products capacity storage.maxProducts = maxProducts; // Update day display dayTxt.setText('Day ' + currentDay); // Don't restock shelves automatically - players must buy from shop // Clear any remaining customers for (var i = customers.length - 1; i >= 0; i--) { customers[i].destroy(); } customers = []; customerQueue = []; currentCustomer = null; // Start spawning customers again dayJustStarted = true; // Set flag to prevent immediate day end // Don't spawn customer immediately, let the spawn timer handle it LK.setTimeout(function () { dayJustStarted = false; // Allow day to end after spawn delay passes }, spawnDelay * 16.67); //{79} // Convert frames to milliseconds (60fps = ~16.67ms per frame) } function serveNextCustomer() { if (customerQueue.length > 0 && !currentCustomer) { currentCustomer = customerQueue.shift(); currentCustomer.isBeingServed = true; // Move customer to cash register tween(currentCustomer, { x: 896, y: queueLine.y }, { duration: 1500, onFinish: function onFinish() { if (currentCustomer && currentCustomer.parent) { currentCustomer.placeItemsOnCounter(); } } }); // Move other customers forward in queue - only move existing queue members for (var i = 0; i < customerQueue.length; i++) { var queuePos = queueLine.x + (i + 1) * 200; tween(customerQueue[i], { x: queuePos, y: queueLine.y }, { duration: 1000 }); } } } // Handle dragging shelf during placement mode game.move = function (x, y, obj) { if (shelfPlacementMode && draggingShelf) { draggingShelf.x = x; draggingShelf.y = y; } }; game.update = function () { // Don't update game logic during day summary or shelf placement if (gameOverPaused || shelfPlacementMode) { return; } // Hide/show instruction text based on shop state instructionsTxt.visible = !shopOpen; // Move money elements to top when shop is open if (shopOpen) { blackRect.y = 10; scoreTxt.y = 25; } else { blackRect.y = 135; scoreTxt.y = 150; } // Check if all shelves are empty and handle customers accordingly if (areAllShelvesEmpty()) { // Automatically close the store when no products available if (storeOpen) { storeOpen = false; // Update button to show Close image openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Close', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; // Re-assign click handler openCloseBtn.down = function () { if (!gameOverPaused && !shopOpen) { // Check if trying to open the store if (!storeOpen && areAllShelvesEmpty()) { // Don't allow opening if no products return; } storeOpen = !storeOpen; if (storeOpen) { // Replace with Open image openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Open', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; openCloseBtn.down = arguments.callee; // Re-assign click handler } else { // Replace with Close image openCloseBtn.destroy(); openCloseBtn = game.addChild(LK.getAsset('Close', { anchorX: 0.5, anchorY: 0.5 })); openCloseBtn.x = 1024; openCloseBtn.y = counterY + 300; openCloseBtn.scaleX = 2; openCloseBtn.scaleY = 2; openCloseBtn.down = arguments.callee; // Re-assign click handler } } }; } // Make customers who are still shopping leave without products for (var i = customers.length - 1; i >= 0; i--) { var customer = customers[i]; if (customer.isShopping && customer.items.length === 0) { // Customer leaves empty-handed tween(customer, { x: -200 }, { duration: 1000, onFinish: function onFinish() { totalCustomersExited++; customer.destroy(); } }); customers.splice(i, 1); } } // Don't spawn new customers when shelves are empty or store is closed } else if (storeOpen) { spawnTimer++; // Spawn new customers if (spawnTimer >= spawnDelay) { spawnCustomer(); spawnTimer = 0; // Set new random spawn delay between 6-9 seconds spawnDelay = Math.floor(Math.random() * (540 - 360 + 1)) + 360; } } // Check if current customer transaction is complete if (currentCustomer && currentCustomer.isBeingServed) { // Shaking effect is now handled by tween animations instead of direct position manipulation // Only check for scanned items if customer hasn't left if (currentCustomer.parent && currentCustomer.allItemsScanned()) { currentCustomer.completeTransaction(); // Remove from customers array for (var i = customers.length - 1; i >= 0; i--) { if (customers[i] === currentCustomer) { customers.splice(i, 1); break; } } currentCustomer = null; // Serve next customer after a short delay LK.setTimeout(function () { serveNextCustomer(); }, 500); } // Check if customer left angry if (currentCustomer && !currentCustomer.parent) { // Remove from customers array for (var i = customers.length - 1; i >= 0; i--) { if (customers[i] === currentCustomer) { customers.splice(i, 1); break; } } currentCustomer = null; // Serve next customer after a short delay LK.setTimeout(function () { serveNextCustomer(); }, 500); } } // Serve next customer if none is being served if (!currentCustomer) { serveNextCustomer(); } // Update customer counter displays spawnedCounterTxt.setText('Spawned: ' + totalCustomersSpawned); exitedCounterTxt.setText('Exited: ' + totalCustomersExited); // Day end condition - when all shelves are empty and all customers have left (and at least 1 customer visited) if (areAllShelvesEmpty() && totalCustomersSpawned === totalCustomersExited && totalCustomersExited > 0 && !gameOverPaused && !dayJustStarted) { showDaySummary(); } // Game over condition - too many customers waiting if (customerQueue.length >= 5) { LK.showGameOver(); } }; // Create end day button in bottom right var endDayBtn = game.addChild(LK.getAsset('blackRectangle', { anchorX: 0.5, anchorY: 0.5 })); endDayBtn.x = 2700; endDayBtn.y = 3900; endDayBtn.width = 300; endDayBtn.height = 150; endDayBtn.tint = 0x444444; var endDayTxt = new Text2('End Day', { size: 40, fill: 0xffffff }); endDayTxt.anchor.set(0.5, 0.5); endDayTxt.x = 2700; endDayTxt.y = 3900; game.addChild(endDayTxt); // Handle end day button click endDayBtn.down = function () { if (!gameOverPaused && !shopOpen) { showDaySummary(); } }; // Create shop button in bottom left var shopBtn = game.addChild(LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5 })); shopBtn.x = 300; shopBtn.y = 3900; // Shop overlay variables var shopOverlay = null; var shopItems = []; var currentShopCategory = 'products'; // Shelf placement mode variables var shelfPlacementMode = false; var draggingShelf = null; var placementButton = null; var maxProducts = storage.maxProducts || defaultShelfPositions.length * 9; // Load from storage or calculate based on shelf count // Handle shop button click // Shop overlay variables var currentShopCategory = 'products'; shopBtn.down = function () { if (!gameOverPaused && !shopOverlay && !storeOpen && totalCustomersExited === totalCustomersSpawned) { shopOpen = true; // Function to clear current category items var clearCategoryItems = function clearCategoryItems() { // Remove category-specific items (keep overlay, title, category buttons, and close button) for (var i = shopItems.length - 1; i >= 0; i--) { if (shopItems[i].isCategoryItem) { shopItems[i].destroy(); shopItems.splice(i, 1); } } }; // Function to show products category var showProducts = function showProducts() { currentShopCategory = 'products'; clearCategoryItems(); var productItems = [{ name: 'Apple', price: 48, description: 'Restocks apple shelf' }, { name: 'Banana', price: 96, description: 'Restocks banana shelf' }, { name: 'Orange', price: 72, description: 'Restocks orange shelf' }, { name: 'Milk', price: 120, description: 'Restocks milk shelf' }, { name: 'Bread', price: 24, description: 'Restocks bread shelf' }, { name: 'Cheese', price: 72, description: 'Restocks cheese shelf' }]; // Create product cards for (var i = 0; i < productItems.length; i++) { var item = productItems[i]; var xPos = 340 + i % 3 * 600; var yPos = 700 + Math.floor(i / 3) * 500; // Item background var itemBg = game.addChild(LK.getAsset('shopItem', { anchorX: 0.5, anchorY: 0.5 })); itemBg.x = xPos; itemBg.y = yPos; itemBg.width = 400; itemBg.height = 450; itemBg.isCategoryItem = true; shopItems.push(itemBg); // Item name var itemName = new Text2(item.name, { size: 32, fill: 0xffffff }); itemName.anchor.set(0.5, 0.5); itemName.x = xPos; itemName.y = yPos - 100; itemName.isCategoryItem = true; game.addChild(itemName); shopItems.push(itemName); // Item description var itemDesc = new Text2(item.description, { size: 22, fill: 0xffffff }); itemDesc.anchor.set(0.5, 0.5); itemDesc.x = xPos; itemDesc.y = yPos - 50; itemDesc.isCategoryItem = true; game.addChild(itemDesc); shopItems.push(itemDesc); // Item price var itemPrice = new Text2(item.price + '₺', { size: 40, fill: 0x90ee90 }); itemPrice.anchor.set(0.5, 0.5); itemPrice.x = xPos; itemPrice.y = yPos; itemPrice.isCategoryItem = true; game.addChild(itemPrice); shopItems.push(itemPrice); // Buy button var buyBtn = game.addChild(LK.getAsset('buyButton', { anchorX: 0.5, anchorY: 0.5 })); buyBtn.x = xPos; buyBtn.y = yPos + 100; buyBtn.width = 250; buyBtn.height = 125; buyBtn.itemData = item; buyBtn.isCategoryItem = true; shopItems.push(buyBtn); // Check if shelves can accept more products of this type var productType = null; if (item.name === 'Apple') { productType = 'apple'; } else if (item.name === 'Banana') { productType = 'banana'; } else if (item.name === 'Orange') { productType = 'orange'; } else if (item.name === 'Milk') { productType = 'milk'; } else if (item.name === 'Bread') { productType = 'bread'; } else if (item.name === 'Cheese') { productType = 'cheese'; } var canBuy = money >= item.price && canAcceptMoreProducts(productType); if (!canBuy) { buyBtn.tint = 0x888888; // Gray out button } else { buyBtn.tint = 0xffffff; // Normal color } // Buy button handler buyBtn.down = function () { // Check if we can buy (enough money and shelf space) var productType = null; if (this.itemData.name === 'Apple') { productType = 'apple'; } else if (this.itemData.name === 'Banana') { productType = 'banana'; } else if (this.itemData.name === 'Orange') { productType = 'orange'; } else if (this.itemData.name === 'Milk') { productType = 'milk'; } else if (this.itemData.name === 'Bread') { productType = 'bread'; } else if (this.itemData.name === 'Cheese') { productType = 'cheese'; } if (money >= this.itemData.price && canAcceptMoreProducts(productType)) { money -= this.itemData.price; scoreTxt.setText(money + '₺'); // Flash green to show purchase LK.effects.flashObject(this, 0x00ff00, 500); // Restock the appropriate shelf based on product type var productType = null; if (this.itemData.name === 'Apple') { productType = 'apple'; } else if (this.itemData.name === 'Banana') { productType = 'banana'; } else if (this.itemData.name === 'Orange') { productType = 'orange'; } else if (this.itemData.name === 'Milk') { productType = 'milk'; } else if (this.itemData.name === 'Bread') { productType = 'bread'; } else if (this.itemData.name === 'Cheese') { productType = 'cheese'; } if (productType) { // Find a shelf that needs this product type and restock it var restocked = false; for (var s = 0; s < shelves.length; s++) { var shelf = shelves[s]; // Check each row for empty space for (var row = 0; row < 3; row++) { var rowEmpty = true; // Check if this row is empty for (var col = 0; col < 3; col++) { var index = row * 3 + col; if (shelf.products[index] && shelf.products[index].available) { rowEmpty = false; break; } } // If row is empty, fill it with the product if (rowEmpty) { var cols = 3; var spacing = 100; var startX = -120; var startY = -120; for (var col = 0; col < cols; col++) { var index = row * 3 + col; // If product slot exists but is not available, make it visible and available if (shelf.products[index]) { shelf.products[index].destroy(); } var product = shelf.attachAsset(productType, { anchorX: 0.5, anchorY: 0.5 }); product.x = startX + col * spacing; product.y = startY + row * (spacing + 20); product.available = true; product.productType = productType; product.name = this.itemData.name; // Get product name product.value = Math.floor(this.itemData.price / 3 / 0.8); // Set value based on purchase price for 3 items with 20% profit margin shelf.products[index] = product; } restocked = true; break; } } if (restocked) { break; } } // If no empty row found in any shelf, notify player if (!restocked) { // Could add a notification here that all shelves are full } } } }; // Update all buy button colors based on current capacity for (var b = 0; b < productItems.length; b++) { var checkItem = productItems[b]; var checkProductType = null; if (checkItem.name === 'Apple') { checkProductType = 'apple'; } else if (checkItem.name === 'Banana') { checkProductType = 'banana'; } else if (checkItem.name === 'Orange') { checkProductType = 'orange'; } else if (checkItem.name === 'Milk') { checkProductType = 'milk'; } else if (checkItem.name === 'Bread') { checkProductType = 'bread'; } else if (checkItem.name === 'Cheese') { checkProductType = 'cheese'; } var canBuyItem = money >= checkItem.price && canAcceptMoreProducts(checkProductType); // Find the corresponding buy button (it's the last item added for each product) var buyButtonIndex = (b + 1) * 5 - 1; // Buy button is 5th item for each product (bg, name, desc, price, buy) if (shopItems[buyButtonIndex]) { if (!canBuyItem) { shopItems[buyButtonIndex].tint = 0x888888; // Gray out button } else { shopItems[buyButtonIndex].tint = 0xffffff; // Normal color } } } } }; // Function to show equipment category var showEquipment = function showEquipment() { currentShopCategory = 'equipment'; clearCategoryItems(); var equipmentItems = [{ name: 'Extra Shelf', price: 5000, description: 'Add more shelf space' }, { name: 'Refrigerator', price: 800, description: 'Keep dairy products fresh' }, { name: 'Automatic Scanner', price: 0, description: 'Automatically scan all items' }, { name: 'Security Camera', price: 400, description: 'Reduce theft' }]; // Create equipment cards for (var i = 0; i < equipmentItems.length; i++) { var item = equipmentItems[i]; // Apply progressive pricing for Extra Shelf if (item.name === 'Extra Shelf') { var shelfCount = shelves.length; if (shelfCount === 4) { item.price = 5000; } else if (shelfCount === 5) { item.price = 8000; } else if (shelfCount === 6) { item.price = 10000; } else if (shelfCount === 7) { item.price = 15000; } else if (shelfCount >= 8) { item.price = 20000; } } var xPos = 340 + i % 2 * 600; var yPos = 700 + Math.floor(i / 2) * 500; // Item background var itemBg = game.addChild(LK.getAsset('shopItem', { anchorX: 0.5, anchorY: 0.5 })); itemBg.x = xPos; itemBg.y = yPos; itemBg.width = 400; itemBg.height = 450; itemBg.isCategoryItem = true; shopItems.push(itemBg); // Item name var itemName = new Text2(item.name, { size: 36, fill: 0xffffff }); itemName.anchor.set(0.5, 0.5); itemName.x = xPos; itemName.y = yPos - 100; itemName.isCategoryItem = true; game.addChild(itemName); shopItems.push(itemName); // Item description var itemDesc = new Text2(item.description, { size: 24, fill: 0xffffff }); itemDesc.anchor.set(0.5, 0.5); itemDesc.x = xPos; itemDesc.y = yPos - 50; itemDesc.isCategoryItem = true; game.addChild(itemDesc); shopItems.push(itemDesc); // Item price var itemPrice = new Text2(item.price + '₺', { size: 50, fill: 0x90ee90 }); itemPrice.anchor.set(0.5, 0.5); itemPrice.x = xPos; itemPrice.y = yPos; itemPrice.isCategoryItem = true; game.addChild(itemPrice); shopItems.push(itemPrice); // Buy button var buyBtn = game.addChild(LK.getAsset('buyButton', { anchorX: 0.5, anchorY: 0.5 })); buyBtn.x = xPos; buyBtn.y = yPos + 100; buyBtn.width = 250; buyBtn.height = 125; buyBtn.itemData = item; buyBtn.isCategoryItem = true; shopItems.push(buyBtn); // Check if this is Extra Shelf and we already have 8 shelves var canBuy = money >= item.price; if (item.name === 'Extra Shelf' && shelves.length >= 8) { canBuy = false; } // Check if Automatic Scanner is already purchased if (item.name === 'Automatic Scanner' && hasAutomaticScanner) { canBuy = false; } if (!canBuy) { buyBtn.tint = 0x888888; // Gray out button } else { buyBtn.tint = 0xffffff; // Normal color } // Buy button handler buyBtn.down = function () { if (money >= this.itemData.price) { // Check if trying to buy Extra Shelf and already have 8 shelves if (this.itemData.name === 'Extra Shelf' && shelves.length >= 8) { // Don't allow purchase - flash red instead LK.effects.flashObject(this, 0xff0000, 500); return; } money -= this.itemData.price; scoreTxt.setText(money + '₺'); // Flash green to show purchase LK.effects.flashObject(this, 0x00ff00, 500); // Special handling for Automatic Scanner if (this.itemData.name === 'Automatic Scanner') { // Set global flag for automatic scanning hasAutomaticScanner = true; storage.hasAutomaticScanner = true; // Disable the buy button after purchase this.tint = 0x888888; // Gray out button this.down = function () {}; // Remove click handler } // Special handling for Extra Shelf if (this.itemData.name === 'Extra Shelf') { // Close shop and enter shelf placement mode shopOverlay.destroy(); shopOverlay = null; for (var j = 0; j < shopItems.length; j++) { shopItems[j].destroy(); } shopItems = []; shopOpen = false; shelfPlacementMode = true; maxProducts += 9; // Increase max product capacity // Create draggable transparent shelf draggingShelf = game.addChild(LK.getAsset('shelf', { anchorX: 0.5, anchorY: 0.5 })); draggingShelf.x = 1024; draggingShelf.y = 1366; draggingShelf.alpha = 0.5; // Create green placement button placementButton = game.addChild(LK.getAsset('openCloseButton', { anchorX: 0.5, anchorY: 0.5 })); placementButton.x = 1024; placementButton.y = 2500; placementButton.tint = 0x00ff00; placementButton.scaleX = 2; placementButton.scaleY = 2; // Add placement button text var placementText = new Text2('Place Shelf', { size: 30, fill: 0x000000 }); placementText.anchor.set(0.5, 0.5); placementText.x = 1024; placementText.y = 2500; game.addChild(placementText); // Placement button handler placementButton.down = function () { if (shelfPlacementMode && draggingShelf) { // Extract the new shelf position as literal values var newShelfX = Math.floor(draggingShelf.x); var newShelfY = Math.floor(draggingShelf.y); // Create the new shelf var newShelf = new Shelf(); newShelf.x = newShelfX; newShelf.y = newShelfY; shelves.push(newShelf); game.addChild(newShelf); // Clean up placement mode draggingShelf.destroy(); draggingShelf = null; placementButton.destroy(); placementButton = null; placementText.destroy(); shelfPlacementMode = false; } }; } } }; } }; // Function to show customization category var showCustomization = function showCustomization() { currentShopCategory = 'customization'; clearCategoryItems(); var customizeItems = [{ name: 'Store Sign', price: 200, description: 'Custom store branding' }, { name: 'Floor Tiles', price: 150, description: 'Improve store appearance' }, { name: 'Lighting', price: 300, description: 'Better store lighting' }, { name: 'Music System', price: 250, description: 'Background music' }]; // Create customization cards for (var i = 0; i < customizeItems.length; i++) { var item = customizeItems[i]; var xPos = 340 + i % 2 * 600; var yPos = 700 + Math.floor(i / 2) * 500; // Item background var itemBg = game.addChild(LK.getAsset('shopItem', { anchorX: 0.5, anchorY: 0.5 })); itemBg.x = xPos; itemBg.y = yPos; itemBg.width = 400; itemBg.height = 450; itemBg.isCategoryItem = true; shopItems.push(itemBg); // Item name var itemName = new Text2(item.name, { size: 36, fill: 0xffffff }); itemName.anchor.set(0.5, 0.5); itemName.x = xPos; itemName.y = yPos - 100; itemName.isCategoryItem = true; game.addChild(itemName); shopItems.push(itemName); // Item description var itemDesc = new Text2(item.description, { size: 24, fill: 0xffffff }); itemDesc.anchor.set(0.5, 0.5); itemDesc.x = xPos; itemDesc.y = yPos - 50; itemDesc.isCategoryItem = true; game.addChild(itemDesc); shopItems.push(itemDesc); // Item price var itemPrice = new Text2(item.price + '₺', { size: 50, fill: 0x90ee90 }); itemPrice.anchor.set(0.5, 0.5); itemPrice.x = xPos; itemPrice.y = yPos; itemPrice.isCategoryItem = true; game.addChild(itemPrice); shopItems.push(itemPrice); // Buy button var buyBtn = game.addChild(LK.getAsset('buyButton', { anchorX: 0.5, anchorY: 0.5 })); buyBtn.x = xPos; buyBtn.y = yPos + 100; buyBtn.width = 250; buyBtn.height = 125; buyBtn.itemData = item; buyBtn.isCategoryItem = true; shopItems.push(buyBtn); // Buy button handler buyBtn.down = function () { if (money >= this.itemData.price) { money -= this.itemData.price; scoreTxt.setText(money + '₺'); // Flash green to show purchase LK.effects.flashObject(this, 0x00ff00, 500); } }; } }; // Category button handlers // Create white overlay shopOverlay = game.addChild(LK.getAsset('shopOverlay', { anchorX: 0.5, anchorY: 0.5 })); shopOverlay.x = 1536; shopOverlay.y = 2049; shopOverlay.alpha = 0.95; // Create shop title var shopTitle = new Text2('Market Shop', { size: 80, fill: 0x000000 }); shopTitle.anchor.set(0.5, 0.5); shopTitle.x = 1536; shopTitle.y = 300; game.addChild(shopTitle); shopItems.push(shopTitle); // Create category buttons var productsBtn = game.addChild(LK.getAsset('productsCategoryImage', { anchorX: 0.5, anchorY: 0.5 })); productsBtn.x = 400; productsBtn.y = 350; productsBtn.width = 250; productsBtn.height = 125; shopItems.push(productsBtn); var equipmentBtn = game.addChild(LK.getAsset('equipmentCategoryImage', { anchorX: 0.5, anchorY: 0.5 })); equipmentBtn.x = 1536; equipmentBtn.y = 350; equipmentBtn.width = 250; equipmentBtn.height = 125; shopItems.push(equipmentBtn); var customizeBtn = game.addChild(LK.getAsset('customizationCategoryImage', { anchorX: 0.5, anchorY: 0.5 })); customizeBtn.x = 2472; customizeBtn.y = 350; customizeBtn.width = 250; customizeBtn.height = 125; shopItems.push(customizeBtn); productsBtn.down = function () { showProducts(); }; equipmentBtn.down = function () { showEquipment(); }; customizeBtn.down = function () { showCustomization(); }; // Show default category (products) showProducts(); // Close button var closeBtn = game.addChild(LK.getAsset('blackRectangle', { anchorX: 0.5, anchorY: 0.5 })); closeBtn.x = 1536; closeBtn.y = 3600; closeBtn.width = 200; closeBtn.height = 100; shopItems.push(closeBtn); var closeText = new Text2('Close', { size: 40, fill: 0xffffff }); closeText.anchor.set(0.5, 0.5); closeText.x = 1536; closeText.y = 3600; game.addChild(closeText); shopItems.push(closeText); // Close button handler closeBtn.down = function () { // Remove all shop elements shopOverlay.destroy(); shopOverlay = null; for (var j = 0; j < shopItems.length; j++) { shopItems[j].destroy(); } shopItems = []; shopOpen = false; }; } }; // Initial customer spawn // Don't spawn customer immediately, let the spawn timer handle it LK.setTimeout(function () { dayJustStarted = false; // Allow day to end after spawn delay passes }, spawnDelay * 16.67); //{dV} // Convert frames to milliseconds (60fps = ~16.67ms per frame) // No changes required - the current implementation already makes angry customers walk out normally through the store entrance using tween animations;;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Customer = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('customer', {
anchorX: 0.5,
anchorY: 1
});
self.items = [];
self.currentItemIndex = 0;
self.isBeingServed = false;
self.patience = 100;
self.maxPatience = 100;
self.waitTime = 0;
self.isShopping = true;
self.targetShelf = null;
self.itemsToCollect = Math.floor(Math.random() * 3) + 2;
self.upset = false;
self.angry = false;
self.upsetStartTime = 0;
self.paid = false;
self.placeItemsOnCounter = function () {
var startY = counterY + 50 - self.items.length * 70 / 2;
for (var i = 0; i < self.items.length; i++) {
var item = self.items[i];
// Don't add item directly, it's already part of customer
// Instead, create a new product with the same properties
var counterItem = new Product(item.productType);
counterItem.value = item.value;
counterItem.name = item.name;
counterItem.productType = item.productType;
counterItem.x = 900; // Move to the left from center
counterItem.y = startY + i * 70; // Place items vertically
game.addChild(counterItem);
// If automatic scanner is owned, automatically scan the item
if (hasAutomaticScanner) {
counterItem.scanned = true;
// Find the graphics child and make it transparent
for (var g = 0; g < counterItem.children.length; g++) {
if (counterItem.children[g].alpha !== undefined) {
counterItem.children[g].alpha = 0.5;
break;
}
}
LK.getSound('itemScan').play();
}
// Replace the item in the array with the counter version
self.items[i] = counterItem;
}
};
self.allItemsScanned = function () {
for (var i = 0; i < self.items.length; i++) {
if (!self.items[i].scanned) {
return false;
}
}
return true;
};
self.getTotalValue = function () {
var total = 0;
for (var i = 0; i < self.items.length; i++) {
total += self.items[i].value;
}
return total;
};
self.completeTransaction = function () {
// Mark customer as paid
self.paid = true;
// If customer was upset, stop shaking animation
if (self.upset) {
tween.stop(self, {
x: true
});
self.x = self.originalX;
}
// Remove items from counter
for (var i = 0; i < self.items.length; i++) {
if (self.items[i].parent) {
self.items[i].destroy();
}
}
// Add to money
var earnings = self.getTotalValue();
money += earnings;
dailyEarnings += earnings;
scoreTxt.setText(money + '₺');
// Play sound
LK.getSound('cashRegister').play();
// Move customer out
tween(self, {
x: -200
}, {
duration: 1000,
onFinish: function onFinish() {
totalCustomersExited++; // Increment exit counter
self.destroy();
}
});
};
self.collectItemFromShelf = function () {
if (self.items.length < self.itemsToCollect && self.targetShelf) {
var takenProduct = self.targetShelf.takeProduct();
if (takenProduct) {
// Store the product data directly without creating a visual product yet
self.items.push({
productType: takenProduct.productType,
value: takenProduct.value,
name: takenProduct.name,
scanned: false
});
// Visual feedback
tween(graphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
// Play sound when customer takes item
LK.getSound('customerPurchase').play();
}
}
};
self.update = function () {
// Track wait time for customers being served
if (self.isBeingServed && !self.upset && !self.angry && !self.paid) {
self.waitTime++;
// Check if customer should become upset (10 seconds = 600 frames at 60fps)
if (self.waitTime >= 600) {
self.upset = true;
self.upsetStartTime = 0;
// Change color to indicate upset state (slightly darker)
graphics.tint = 0x888888;
// Start shaking animation
self.originalX = self.x;
self.shakeAnimation = function () {
if (self.upset && !self.angry && !self.paid) {
tween(self, {
x: self.originalX + (Math.random() - 0.5) * 20
}, {
duration: 100,
onFinish: function onFinish() {
if (self.upset && !self.angry && !self.paid) {
self.shakeAnimation();
}
}
});
}
};
self.shakeAnimation();
}
}
// Track upset time and transition to angry (only if not paid)
if (self.upset && !self.angry && !self.paid) {
self.upsetStartTime++;
// Check if customer should become angry (5 seconds = 300 frames at 60fps)
if (self.upsetStartTime >= 300) {
self.angry = true;
// Stop shaking animation
tween.stop(self, {
x: true
});
self.x = self.originalX;
// Change color to red when angry
graphics.tint = 0xFF0000;
// Remove items from counter when angry customer leaves
for (var i = 0; i < self.items.length; i++) {
if (self.items[i].parent) {
self.items[i].destroy();
}
}
// Make angry customer leave the store
tween(self, {
x: -200
}, {
duration: 1000,
onFinish: function onFinish() {
totalCustomersExited++; // Increment exit counter
self.destroy();
}
});
}
}
};
return self;
});
var Product = Container.expand(function (productType) {
var self = Container.call(this);
// Define product types with their properties
var productTypes = [{
asset: 'apple',
name: 'Apple',
value: 20
}, {
asset: 'banana',
name: 'Banana',
value: 40
}, {
asset: 'orange',
name: 'Orange',
value: 30
}, {
asset: 'milk',
name: 'Milk',
value: 50
}, {
asset: 'bread',
name: 'Bread',
value: 10
}, {
asset: 'cheese',
name: 'Cheese',
value: 30
}];
// Use specified product type or randomly select one
var selectedType;
if (productType) {
// Find the product type that matches the specified type
for (var i = 0; i < productTypes.length; i++) {
if (productTypes[i].asset === productType) {
selectedType = productTypes[i];
break;
}
}
}
if (!selectedType) {
// Fallback to random selection if no type specified or not found
selectedType = productTypes[Math.floor(Math.random() * productTypes.length)];
}
var graphics = self.attachAsset(selectedType.asset, {
anchorX: 0.5,
anchorY: 0.5
});
self.scanned = false;
self.value = selectedType.value;
self.name = selectedType.name;
self.productType = selectedType.asset;
// Visual feedback for scanned items
self.scan = function () {
if (!self.scanned) {
self.scanned = true;
graphics.alpha = 0.5; // Make transparent when scanned
LK.getSound('itemScan').play();
}
};
self.down = function (x, y, obj) {
if (!shopOpen) {
self.scan();
}
};
return self;
});
var Shelf = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('shelf', {
anchorX: 0.5,
anchorY: 0.5
});
self.products = [];
// Create products on shelf
self.createProducts = function () {
var rows = 3;
var cols = 3;
var spacing = 100;
var startX = -120;
var startY = -120;
// Define product types for this shelf
var productTypes = [{
asset: 'apple',
name: 'Apple',
value: 20
}, {
asset: 'banana',
name: 'Banana',
value: 40
}, {
asset: 'orange',
name: 'Orange',
value: 30
}, {
asset: 'milk',
name: 'Milk',
value: 50
}, {
asset: 'bread',
name: 'Bread',
value: 10
}, {
asset: 'cheese',
name: 'Cheese',
value: 30
}];
// Each shelf will have products organized by type in rows
var shelfProductTypes = [];
var numTypes = Math.min(rows, productTypes.length); // One type per row, max 3 types
for (var t = 0; t < numTypes; t++) {
var randomType = productTypes[Math.floor(Math.random() * productTypes.length)];
// Make sure we don't duplicate types on same shelf
var alreadyExists = false;
for (var e = 0; e < shelfProductTypes.length; e++) {
if (shelfProductTypes[e].asset === randomType.asset) {
alreadyExists = true;
break;
}
}
if (!alreadyExists) {
shelfProductTypes.push(randomType);
} else {
t--; // Try again with different type
}
}
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
// Each row has the same product type
var selectedType = shelfProductTypes[row % shelfProductTypes.length];
var product = self.attachAsset(selectedType.asset, {
anchorX: 0.5,
anchorY: 0.5
});
product.x = startX + col * spacing;
product.y = startY + row * (spacing + 20); // Add extra 20px spacing between rows
product.available = true;
product.productType = selectedType.asset;
product.name = selectedType.name;
product.value = selectedType.value;
self.products.push(product);
}
}
};
// Only create products on Day 1
if (currentDay === 1) {
self.createProducts();
}
self.takeProduct = function () {
for (var i = 0; i < self.products.length; i++) {
if (self.products[i].available) {
var product = self.products[i];
product.available = false;
product.visible = false;
return {
value: product.value,
name: product.name,
productType: product.productType
};
}
}
return null;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xfffca1,
width: 3072,
height: 4098
});
/****
* Game Code
****/
var customers = [];
var customerQueue = [];
var currentCustomer = null;
var spawnTimer = 0;
var spawnDelay = Math.floor(Math.random() * (540 - 360 + 1)) + 360; // Random between 6-9 seconds (360-540 frames at 60fps)
var counterY = 3450; // Bottom of screen
// Load money based on whether we're continuing the same day or starting fresh
var money = storage.lastPlayedDay === currentDay ? storage.money : storage.dayStartMoney || 0;
var totalCustomersSpawned = 0; // Track total customers spawned
var totalCustomersExited = 0; // Track total customers who left the store
var currentDay = storage.currentDay || 1; // Current day number
var dailyEarnings = 0; // Money earned today
var dayStartMoney = storage.dayStartMoney || 0; // Money at the start of the current day
var gameOverPaused = false; // Track if game is paused for day summary
var storeOpen = false; // Track if store is open or closed - start closed
var shopOpen = false; // Track if shop overlay is open
var dayJustStarted = true; // Track if day just started to prevent immediate day end
var hasAutomaticScanner = storage.hasAutomaticScanner || false; // Track if automatic scanner is purchased
// No changes needed - the code already ensures only the customer being served gets angry
var shelves = [];
// Load shelves from storage or use default positions
var totalShelves = storage.totalShelves || 4;
var defaultShelfPositions = [{
x: 400,
y: 1000
}, {
x: 1600,
y: 1000
}, {
x: 400,
y: 1600
}, {
x: 1600,
y: 1600
}];
for (var i = 0; i < totalShelves; i++) {
var shelf = new Shelf();
// Load from storage if available, otherwise use default positions
if (storage['shelf' + i + 'X'] !== undefined && storage['shelf' + i + 'Y'] !== undefined) {
shelf.x = storage['shelf' + i + 'X'];
shelf.y = storage['shelf' + i + 'Y'];
} else if (i < defaultShelfPositions.length) {
shelf.x = defaultShelfPositions[i].x;
shelf.y = defaultShelfPositions[i].y;
// Save default positions to storage for future use
storage['shelf' + i + 'X'] = shelf.x;
storage['shelf' + i + 'Y'] = shelf.y;
} else {
// New shelf without default position, place at center
shelf.x = 1024;
shelf.y = 1366;
}
shelves.push(shelf);
game.addChild(shelf);
}
// Create cash register at bottom center
var cashRegister = game.addChild(LK.getAsset('cashRegister', {
anchorX: 0.5,
anchorY: 0.5
}));
cashRegister.x = 1536; // Center of screen
cashRegister.y = counterY; // Bottom position
// Create open/close button below cash register - start with Close image
var openCloseBtn = game.addChild(LK.getAsset('Close', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1536;
openCloseBtn.y = counterY + 300; // Position further below cash register
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
// Handle open/close button click
openCloseBtn.down = function () {
if (!gameOverPaused && !shopOpen) {
// Check if trying to open the store
if (!storeOpen && areAllShelvesEmpty()) {
// Don't allow opening if no products
return;
}
storeOpen = !storeOpen;
if (storeOpen) {
// Replace with Open image
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Open', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
openCloseBtn.down = arguments.callee; // Re-assign click handler
} else {
// Replace with Close image
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Close', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
openCloseBtn.down = arguments.callee; // Re-assign click handler
}
}
};
// Create queue line
var queueLine = game.addChild(LK.getAsset('queueLine', {
anchorX: 0.5,
anchorY: 0.5
}));
queueLine.x = 1536; // Center of screen
queueLine.y = counterY - 300; // Position above cash register
// Create black rectangle first (so it appears behind)
var blackRect = LK.getAsset('blackRectangle', {
anchorX: 0.5,
anchorY: 0
});
blackRect.y = 135; // Position behind the money text
LK.gui.top.addChild(blackRect);
// Create day counter display in top left
var dayTxt = new Text2('Day ' + currentDay, {
size: 50,
fill: 0x000000
});
dayTxt.anchor.set(0, 0);
dayTxt.x = 150; // Position to avoid menu icon area
LK.gui.topLeft.addChild(dayTxt);
// Save initial money for day 1 if not already saved
if (!storage.dayStartMoney) {
storage.dayStartMoney = money;
storage.lastPlayedDay = currentDay;
}
// Create money display (added after, so it appears on top)
var scoreTxt = new Text2('₺' + money, {
size: 60,
fill: 0x006400
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 150; // Move money display lower
LK.gui.top.addChild(scoreTxt);
// Create instructions
var instructionsTxt = new Text2('Tap items to scan them!', {
size: 40,
fill: 0x0000
});
instructionsTxt.anchor.set(0.5, 0);
instructionsTxt.y = 80;
LK.gui.top.addChild(instructionsTxt);
// Create customer counter displays in top right
var spawnedCounterTxt = new Text2('Spawned: 0', {
size: 40,
fill: 0x000000
});
spawnedCounterTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(spawnedCounterTxt);
var exitedCounterTxt = new Text2('Exited: 0', {
size: 40,
fill: 0x000000
});
exitedCounterTxt.anchor.set(1, 0);
exitedCounterTxt.y = 50;
LK.gui.topRight.addChild(exitedCounterTxt);
function spawnCustomer() {
var customer = new Customer();
customer.x = 1536; // Center of screen
customer.y = -200; // Above screen
customers.push(customer);
game.addChild(customer);
totalCustomersSpawned++; // Increment customer counter
// Customer shopping sequence
var shelfIndex = 0;
var _visitShelf = function visitShelf() {
if (shelfIndex < shelves.length && customer.items.length < customer.itemsToCollect) {
// Find shelves with available products
var availableShelves = [];
for (var s = 0; s < shelves.length; s++) {
var shelf = shelves[s];
var hasAvailableProducts = false;
for (var p = 0; p < shelf.products.length; p++) {
if (shelf.products[p].available) {
hasAvailableProducts = true;
break;
}
}
if (hasAvailableProducts) {
availableShelves.push(shelf);
}
}
// If no shelves have products, customer leaves without shopping
if (availableShelves.length === 0) {
// Done shopping (forced), join queue with current items
customer.isShopping = false;
customerQueue.push(customer);
var queuePosition = queueLine.x + customerQueue.length * 200;
tween(customer, {
x: queuePosition,
y: queueLine.y
}, {
duration: 1500
});
return;
}
// Select random shelf from available ones
var targetShelf = availableShelves[Math.floor(Math.random() * availableShelves.length)];
tween(customer, {
x: targetShelf.x,
y: targetShelf.y + 250
}, {
duration: 1500,
onFinish: function onFinish() {
customer.targetShelf = targetShelf;
customer.collectItemFromShelf();
shelfIndex++;
LK.setTimeout(function () {
if (customer.items.length < customer.itemsToCollect) {
_visitShelf();
} else {
// Done shopping, join queue
customer.isShopping = false;
customerQueue.push(customer);
var queuePosition = queueLine.x + customerQueue.length * 200;
tween(customer, {
x: queuePosition,
y: queueLine.y
}, {
duration: 1500
});
}
}, 500);
}
});
}
};
// Start shopping by entering store
tween(customer, {
y: 400
}, {
duration: 1000,
onFinish: function onFinish() {
_visitShelf();
}
});
}
function areAllShelvesEmpty() {
for (var i = 0; i < shelves.length; i++) {
var shelf = shelves[i];
for (var j = 0; j < shelf.products.length; j++) {
if (shelf.products[j].available) {
return false;
}
}
}
return true;
}
function canAcceptMoreProducts(productType) {
// First check if we've reached maximum capacity
var currentProducts = 0;
for (var s = 0; s < shelves.length; s++) {
var shelf = shelves[s];
for (var p = 0; p < shelf.products.length; p++) {
if (shelf.products[p] && shelf.products[p].available) {
currentProducts++;
}
}
}
if (currentProducts >= maxProducts) {
return false;
}
// Check if any shelf has empty space for this product type
for (var s = 0; s < shelves.length; s++) {
var shelf = shelves[s];
// Check each row for empty space
for (var row = 0; row < 3; row++) {
var rowEmpty = true;
// Check if this row is empty
for (var col = 0; col < 3; col++) {
var index = row * 3 + col;
if (shelf.products[index] && shelf.products[index].available) {
rowEmpty = false;
break;
}
}
// If row is empty, we can accept more products
if (rowEmpty) {
return true;
}
}
}
return false;
}
function showDaySummary() {
gameOverPaused = true;
// Set store to closed to prevent customer spawning
storeOpen = false;
// Make all remaining customers exit the store
for (var i = customers.length - 1; i >= 0; i--) {
var customer = customers[i];
if (customer.parent) {
// Stop any ongoing tweens
tween.stop(customer, {
x: true,
y: true
});
// Make customer exit
tween(customer, {
x: -200
}, {
duration: 1000,
onFinish: function onFinish() {
totalCustomersExited++;
customer.destroy();
}
});
}
}
// Clear customer arrays and current customer
customers = [];
customerQueue = [];
currentCustomer = null;
// Update open/close button to show Close
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Close', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
// Re-assign click handler
openCloseBtn.down = function () {
if (!gameOverPaused && !shopOpen) {
// Check if trying to open the store
if (!storeOpen && areAllShelvesEmpty()) {
// Don't allow opening if no products
return;
}
storeOpen = !storeOpen;
if (storeOpen) {
// Replace with Open image
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Open', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
openCloseBtn.down = arguments.callee; // Re-assign click handler
} else {
// Replace with Close image
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Close', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
openCloseBtn.down = arguments.callee; // Re-assign click handler
}
}
};
// Create dark overlay
var overlay = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5
}));
overlay.x = 1024;
overlay.y = 1366;
overlay.alpha = 0;
overlay.tint = 0x000000;
// Create summary text
var summaryTxt = new Text2('Day ' + currentDay + ' Complete!\n\nCustomers Served: ' + totalCustomersExited, {
size: 60,
fill: 0xffffff
});
summaryTxt.anchor.set(0.5, 0.5);
summaryTxt.x = 1024;
summaryTxt.y = 1200;
summaryTxt.alpha = 0;
game.addChild(summaryTxt);
// Create earnings display - centered and green
var earningsTxt = new Text2(dailyEarnings + '₺', {
size: 120,
fill: 0x00ff00
});
earningsTxt.anchor.set(0.5, 0.5);
earningsTxt.x = 1024;
earningsTxt.y = 1700;
earningsTxt.alpha = 0;
game.addChild(earningsTxt);
// Create continue button
var continueBtn = game.addChild(LK.getAsset('continueButton', {
anchorX: 0.5,
anchorY: 0.5
}));
continueBtn.x = 1024;
continueBtn.y = 2400;
continueBtn.alpha = 0;
// Fade in animation
tween(overlay, {
alpha: 0.8
}, {
duration: 1000
});
tween(summaryTxt, {
alpha: 1
}, {
duration: 1000
});
tween(earningsTxt, {
alpha: 1
}, {
duration: 1000
});
tween(continueBtn, {
alpha: 1
}, {
duration: 1000
});
// Handle continue button click
continueBtn.down = function () {
// Fade out animation
tween(overlay, {
alpha: 0
}, {
duration: 1000
});
tween(summaryTxt, {
alpha: 0
}, {
duration: 1000
});
tween(earningsTxt, {
alpha: 0
}, {
duration: 1000
});
tween(continueBtn, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
// Remove summary elements after fade out
overlay.destroy();
summaryTxt.destroy();
earningsTxt.destroy();
continueBtn.destroy();
gameOverPaused = false;
startNextDay();
}
});
};
}
function startNextDay() {
// Reset day variables
currentDay++;
dailyEarnings = 0;
totalCustomersSpawned = 0;
totalCustomersExited = 0;
spawnTimer = 0;
spawnDelay = Math.floor(Math.random() * (540 - 360 + 1)) + 360; // Random between 6-9 seconds
// Save all game data to storage when starting next day
storage.currentDay = currentDay;
storage.dayStartMoney = money; // Save money at start of new day
storage.lastPlayedDay = currentDay; // Track which day we're on
storage.money = money;
// Save shelf positions and count
storage.totalShelves = shelves.length;
for (var i = 0; i < shelves.length; i++) {
storage['shelf' + i + 'X'] = shelves[i].x;
storage['shelf' + i + 'Y'] = shelves[i].y;
}
// Save max products capacity
storage.maxProducts = maxProducts;
// Update day display
dayTxt.setText('Day ' + currentDay);
// Don't restock shelves automatically - players must buy from shop
// Clear any remaining customers
for (var i = customers.length - 1; i >= 0; i--) {
customers[i].destroy();
}
customers = [];
customerQueue = [];
currentCustomer = null;
// Start spawning customers again
dayJustStarted = true; // Set flag to prevent immediate day end
// Don't spawn customer immediately, let the spawn timer handle it
LK.setTimeout(function () {
dayJustStarted = false; // Allow day to end after spawn delay passes
}, spawnDelay * 16.67); //{79} // Convert frames to milliseconds (60fps = ~16.67ms per frame)
}
function serveNextCustomer() {
if (customerQueue.length > 0 && !currentCustomer) {
currentCustomer = customerQueue.shift();
currentCustomer.isBeingServed = true;
// Move customer to cash register
tween(currentCustomer, {
x: 896,
y: queueLine.y
}, {
duration: 1500,
onFinish: function onFinish() {
if (currentCustomer && currentCustomer.parent) {
currentCustomer.placeItemsOnCounter();
}
}
});
// Move other customers forward in queue - only move existing queue members
for (var i = 0; i < customerQueue.length; i++) {
var queuePos = queueLine.x + (i + 1) * 200;
tween(customerQueue[i], {
x: queuePos,
y: queueLine.y
}, {
duration: 1000
});
}
}
}
// Handle dragging shelf during placement mode
game.move = function (x, y, obj) {
if (shelfPlacementMode && draggingShelf) {
draggingShelf.x = x;
draggingShelf.y = y;
}
};
game.update = function () {
// Don't update game logic during day summary or shelf placement
if (gameOverPaused || shelfPlacementMode) {
return;
}
// Hide/show instruction text based on shop state
instructionsTxt.visible = !shopOpen;
// Move money elements to top when shop is open
if (shopOpen) {
blackRect.y = 10;
scoreTxt.y = 25;
} else {
blackRect.y = 135;
scoreTxt.y = 150;
}
// Check if all shelves are empty and handle customers accordingly
if (areAllShelvesEmpty()) {
// Automatically close the store when no products available
if (storeOpen) {
storeOpen = false;
// Update button to show Close image
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Close', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
// Re-assign click handler
openCloseBtn.down = function () {
if (!gameOverPaused && !shopOpen) {
// Check if trying to open the store
if (!storeOpen && areAllShelvesEmpty()) {
// Don't allow opening if no products
return;
}
storeOpen = !storeOpen;
if (storeOpen) {
// Replace with Open image
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Open', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
openCloseBtn.down = arguments.callee; // Re-assign click handler
} else {
// Replace with Close image
openCloseBtn.destroy();
openCloseBtn = game.addChild(LK.getAsset('Close', {
anchorX: 0.5,
anchorY: 0.5
}));
openCloseBtn.x = 1024;
openCloseBtn.y = counterY + 300;
openCloseBtn.scaleX = 2;
openCloseBtn.scaleY = 2;
openCloseBtn.down = arguments.callee; // Re-assign click handler
}
}
};
}
// Make customers who are still shopping leave without products
for (var i = customers.length - 1; i >= 0; i--) {
var customer = customers[i];
if (customer.isShopping && customer.items.length === 0) {
// Customer leaves empty-handed
tween(customer, {
x: -200
}, {
duration: 1000,
onFinish: function onFinish() {
totalCustomersExited++;
customer.destroy();
}
});
customers.splice(i, 1);
}
}
// Don't spawn new customers when shelves are empty or store is closed
} else if (storeOpen) {
spawnTimer++;
// Spawn new customers
if (spawnTimer >= spawnDelay) {
spawnCustomer();
spawnTimer = 0;
// Set new random spawn delay between 6-9 seconds
spawnDelay = Math.floor(Math.random() * (540 - 360 + 1)) + 360;
}
}
// Check if current customer transaction is complete
if (currentCustomer && currentCustomer.isBeingServed) {
// Shaking effect is now handled by tween animations instead of direct position manipulation
// Only check for scanned items if customer hasn't left
if (currentCustomer.parent && currentCustomer.allItemsScanned()) {
currentCustomer.completeTransaction();
// Remove from customers array
for (var i = customers.length - 1; i >= 0; i--) {
if (customers[i] === currentCustomer) {
customers.splice(i, 1);
break;
}
}
currentCustomer = null;
// Serve next customer after a short delay
LK.setTimeout(function () {
serveNextCustomer();
}, 500);
}
// Check if customer left angry
if (currentCustomer && !currentCustomer.parent) {
// Remove from customers array
for (var i = customers.length - 1; i >= 0; i--) {
if (customers[i] === currentCustomer) {
customers.splice(i, 1);
break;
}
}
currentCustomer = null;
// Serve next customer after a short delay
LK.setTimeout(function () {
serveNextCustomer();
}, 500);
}
}
// Serve next customer if none is being served
if (!currentCustomer) {
serveNextCustomer();
}
// Update customer counter displays
spawnedCounterTxt.setText('Spawned: ' + totalCustomersSpawned);
exitedCounterTxt.setText('Exited: ' + totalCustomersExited);
// Day end condition - when all shelves are empty and all customers have left (and at least 1 customer visited)
if (areAllShelvesEmpty() && totalCustomersSpawned === totalCustomersExited && totalCustomersExited > 0 && !gameOverPaused && !dayJustStarted) {
showDaySummary();
}
// Game over condition - too many customers waiting
if (customerQueue.length >= 5) {
LK.showGameOver();
}
};
// Create end day button in bottom right
var endDayBtn = game.addChild(LK.getAsset('blackRectangle', {
anchorX: 0.5,
anchorY: 0.5
}));
endDayBtn.x = 2700;
endDayBtn.y = 3900;
endDayBtn.width = 300;
endDayBtn.height = 150;
endDayBtn.tint = 0x444444;
var endDayTxt = new Text2('End Day', {
size: 40,
fill: 0xffffff
});
endDayTxt.anchor.set(0.5, 0.5);
endDayTxt.x = 2700;
endDayTxt.y = 3900;
game.addChild(endDayTxt);
// Handle end day button click
endDayBtn.down = function () {
if (!gameOverPaused && !shopOpen) {
showDaySummary();
}
};
// Create shop button in bottom left
var shopBtn = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5
}));
shopBtn.x = 300;
shopBtn.y = 3900;
// Shop overlay variables
var shopOverlay = null;
var shopItems = [];
var currentShopCategory = 'products';
// Shelf placement mode variables
var shelfPlacementMode = false;
var draggingShelf = null;
var placementButton = null;
var maxProducts = storage.maxProducts || defaultShelfPositions.length * 9; // Load from storage or calculate based on shelf count
// Handle shop button click
// Shop overlay variables
var currentShopCategory = 'products';
shopBtn.down = function () {
if (!gameOverPaused && !shopOverlay && !storeOpen && totalCustomersExited === totalCustomersSpawned) {
shopOpen = true;
// Function to clear current category items
var clearCategoryItems = function clearCategoryItems() {
// Remove category-specific items (keep overlay, title, category buttons, and close button)
for (var i = shopItems.length - 1; i >= 0; i--) {
if (shopItems[i].isCategoryItem) {
shopItems[i].destroy();
shopItems.splice(i, 1);
}
}
}; // Function to show products category
var showProducts = function showProducts() {
currentShopCategory = 'products';
clearCategoryItems();
var productItems = [{
name: 'Apple',
price: 48,
description: 'Restocks apple shelf'
}, {
name: 'Banana',
price: 96,
description: 'Restocks banana shelf'
}, {
name: 'Orange',
price: 72,
description: 'Restocks orange shelf'
}, {
name: 'Milk',
price: 120,
description: 'Restocks milk shelf'
}, {
name: 'Bread',
price: 24,
description: 'Restocks bread shelf'
}, {
name: 'Cheese',
price: 72,
description: 'Restocks cheese shelf'
}];
// Create product cards
for (var i = 0; i < productItems.length; i++) {
var item = productItems[i];
var xPos = 340 + i % 3 * 600;
var yPos = 700 + Math.floor(i / 3) * 500;
// Item background
var itemBg = game.addChild(LK.getAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5
}));
itemBg.x = xPos;
itemBg.y = yPos;
itemBg.width = 400;
itemBg.height = 450;
itemBg.isCategoryItem = true;
shopItems.push(itemBg);
// Item name
var itemName = new Text2(item.name, {
size: 32,
fill: 0xffffff
});
itemName.anchor.set(0.5, 0.5);
itemName.x = xPos;
itemName.y = yPos - 100;
itemName.isCategoryItem = true;
game.addChild(itemName);
shopItems.push(itemName);
// Item description
var itemDesc = new Text2(item.description, {
size: 22,
fill: 0xffffff
});
itemDesc.anchor.set(0.5, 0.5);
itemDesc.x = xPos;
itemDesc.y = yPos - 50;
itemDesc.isCategoryItem = true;
game.addChild(itemDesc);
shopItems.push(itemDesc);
// Item price
var itemPrice = new Text2(item.price + '₺', {
size: 40,
fill: 0x90ee90
});
itemPrice.anchor.set(0.5, 0.5);
itemPrice.x = xPos;
itemPrice.y = yPos;
itemPrice.isCategoryItem = true;
game.addChild(itemPrice);
shopItems.push(itemPrice);
// Buy button
var buyBtn = game.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5
}));
buyBtn.x = xPos;
buyBtn.y = yPos + 100;
buyBtn.width = 250;
buyBtn.height = 125;
buyBtn.itemData = item;
buyBtn.isCategoryItem = true;
shopItems.push(buyBtn);
// Check if shelves can accept more products of this type
var productType = null;
if (item.name === 'Apple') {
productType = 'apple';
} else if (item.name === 'Banana') {
productType = 'banana';
} else if (item.name === 'Orange') {
productType = 'orange';
} else if (item.name === 'Milk') {
productType = 'milk';
} else if (item.name === 'Bread') {
productType = 'bread';
} else if (item.name === 'Cheese') {
productType = 'cheese';
}
var canBuy = money >= item.price && canAcceptMoreProducts(productType);
if (!canBuy) {
buyBtn.tint = 0x888888; // Gray out button
} else {
buyBtn.tint = 0xffffff; // Normal color
}
// Buy button handler
buyBtn.down = function () {
// Check if we can buy (enough money and shelf space)
var productType = null;
if (this.itemData.name === 'Apple') {
productType = 'apple';
} else if (this.itemData.name === 'Banana') {
productType = 'banana';
} else if (this.itemData.name === 'Orange') {
productType = 'orange';
} else if (this.itemData.name === 'Milk') {
productType = 'milk';
} else if (this.itemData.name === 'Bread') {
productType = 'bread';
} else if (this.itemData.name === 'Cheese') {
productType = 'cheese';
}
if (money >= this.itemData.price && canAcceptMoreProducts(productType)) {
money -= this.itemData.price;
scoreTxt.setText(money + '₺');
// Flash green to show purchase
LK.effects.flashObject(this, 0x00ff00, 500);
// Restock the appropriate shelf based on product type
var productType = null;
if (this.itemData.name === 'Apple') {
productType = 'apple';
} else if (this.itemData.name === 'Banana') {
productType = 'banana';
} else if (this.itemData.name === 'Orange') {
productType = 'orange';
} else if (this.itemData.name === 'Milk') {
productType = 'milk';
} else if (this.itemData.name === 'Bread') {
productType = 'bread';
} else if (this.itemData.name === 'Cheese') {
productType = 'cheese';
}
if (productType) {
// Find a shelf that needs this product type and restock it
var restocked = false;
for (var s = 0; s < shelves.length; s++) {
var shelf = shelves[s];
// Check each row for empty space
for (var row = 0; row < 3; row++) {
var rowEmpty = true;
// Check if this row is empty
for (var col = 0; col < 3; col++) {
var index = row * 3 + col;
if (shelf.products[index] && shelf.products[index].available) {
rowEmpty = false;
break;
}
}
// If row is empty, fill it with the product
if (rowEmpty) {
var cols = 3;
var spacing = 100;
var startX = -120;
var startY = -120;
for (var col = 0; col < cols; col++) {
var index = row * 3 + col;
// If product slot exists but is not available, make it visible and available
if (shelf.products[index]) {
shelf.products[index].destroy();
}
var product = shelf.attachAsset(productType, {
anchorX: 0.5,
anchorY: 0.5
});
product.x = startX + col * spacing;
product.y = startY + row * (spacing + 20);
product.available = true;
product.productType = productType;
product.name = this.itemData.name; // Get product name
product.value = Math.floor(this.itemData.price / 3 / 0.8); // Set value based on purchase price for 3 items with 20% profit margin
shelf.products[index] = product;
}
restocked = true;
break;
}
}
if (restocked) {
break;
}
}
// If no empty row found in any shelf, notify player
if (!restocked) {
// Could add a notification here that all shelves are full
}
}
}
};
// Update all buy button colors based on current capacity
for (var b = 0; b < productItems.length; b++) {
var checkItem = productItems[b];
var checkProductType = null;
if (checkItem.name === 'Apple') {
checkProductType = 'apple';
} else if (checkItem.name === 'Banana') {
checkProductType = 'banana';
} else if (checkItem.name === 'Orange') {
checkProductType = 'orange';
} else if (checkItem.name === 'Milk') {
checkProductType = 'milk';
} else if (checkItem.name === 'Bread') {
checkProductType = 'bread';
} else if (checkItem.name === 'Cheese') {
checkProductType = 'cheese';
}
var canBuyItem = money >= checkItem.price && canAcceptMoreProducts(checkProductType);
// Find the corresponding buy button (it's the last item added for each product)
var buyButtonIndex = (b + 1) * 5 - 1; // Buy button is 5th item for each product (bg, name, desc, price, buy)
if (shopItems[buyButtonIndex]) {
if (!canBuyItem) {
shopItems[buyButtonIndex].tint = 0x888888; // Gray out button
} else {
shopItems[buyButtonIndex].tint = 0xffffff; // Normal color
}
}
}
}
}; // Function to show equipment category
var showEquipment = function showEquipment() {
currentShopCategory = 'equipment';
clearCategoryItems();
var equipmentItems = [{
name: 'Extra Shelf',
price: 5000,
description: 'Add more shelf space'
}, {
name: 'Refrigerator',
price: 800,
description: 'Keep dairy products fresh'
}, {
name: 'Automatic Scanner',
price: 0,
description: 'Automatically scan all items'
}, {
name: 'Security Camera',
price: 400,
description: 'Reduce theft'
}];
// Create equipment cards
for (var i = 0; i < equipmentItems.length; i++) {
var item = equipmentItems[i];
// Apply progressive pricing for Extra Shelf
if (item.name === 'Extra Shelf') {
var shelfCount = shelves.length;
if (shelfCount === 4) {
item.price = 5000;
} else if (shelfCount === 5) {
item.price = 8000;
} else if (shelfCount === 6) {
item.price = 10000;
} else if (shelfCount === 7) {
item.price = 15000;
} else if (shelfCount >= 8) {
item.price = 20000;
}
}
var xPos = 340 + i % 2 * 600;
var yPos = 700 + Math.floor(i / 2) * 500;
// Item background
var itemBg = game.addChild(LK.getAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5
}));
itemBg.x = xPos;
itemBg.y = yPos;
itemBg.width = 400;
itemBg.height = 450;
itemBg.isCategoryItem = true;
shopItems.push(itemBg);
// Item name
var itemName = new Text2(item.name, {
size: 36,
fill: 0xffffff
});
itemName.anchor.set(0.5, 0.5);
itemName.x = xPos;
itemName.y = yPos - 100;
itemName.isCategoryItem = true;
game.addChild(itemName);
shopItems.push(itemName);
// Item description
var itemDesc = new Text2(item.description, {
size: 24,
fill: 0xffffff
});
itemDesc.anchor.set(0.5, 0.5);
itemDesc.x = xPos;
itemDesc.y = yPos - 50;
itemDesc.isCategoryItem = true;
game.addChild(itemDesc);
shopItems.push(itemDesc);
// Item price
var itemPrice = new Text2(item.price + '₺', {
size: 50,
fill: 0x90ee90
});
itemPrice.anchor.set(0.5, 0.5);
itemPrice.x = xPos;
itemPrice.y = yPos;
itemPrice.isCategoryItem = true;
game.addChild(itemPrice);
shopItems.push(itemPrice);
// Buy button
var buyBtn = game.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5
}));
buyBtn.x = xPos;
buyBtn.y = yPos + 100;
buyBtn.width = 250;
buyBtn.height = 125;
buyBtn.itemData = item;
buyBtn.isCategoryItem = true;
shopItems.push(buyBtn);
// Check if this is Extra Shelf and we already have 8 shelves
var canBuy = money >= item.price;
if (item.name === 'Extra Shelf' && shelves.length >= 8) {
canBuy = false;
}
// Check if Automatic Scanner is already purchased
if (item.name === 'Automatic Scanner' && hasAutomaticScanner) {
canBuy = false;
}
if (!canBuy) {
buyBtn.tint = 0x888888; // Gray out button
} else {
buyBtn.tint = 0xffffff; // Normal color
}
// Buy button handler
buyBtn.down = function () {
if (money >= this.itemData.price) {
// Check if trying to buy Extra Shelf and already have 8 shelves
if (this.itemData.name === 'Extra Shelf' && shelves.length >= 8) {
// Don't allow purchase - flash red instead
LK.effects.flashObject(this, 0xff0000, 500);
return;
}
money -= this.itemData.price;
scoreTxt.setText(money + '₺');
// Flash green to show purchase
LK.effects.flashObject(this, 0x00ff00, 500);
// Special handling for Automatic Scanner
if (this.itemData.name === 'Automatic Scanner') {
// Set global flag for automatic scanning
hasAutomaticScanner = true;
storage.hasAutomaticScanner = true;
// Disable the buy button after purchase
this.tint = 0x888888; // Gray out button
this.down = function () {}; // Remove click handler
}
// Special handling for Extra Shelf
if (this.itemData.name === 'Extra Shelf') {
// Close shop and enter shelf placement mode
shopOverlay.destroy();
shopOverlay = null;
for (var j = 0; j < shopItems.length; j++) {
shopItems[j].destroy();
}
shopItems = [];
shopOpen = false;
shelfPlacementMode = true;
maxProducts += 9; // Increase max product capacity
// Create draggable transparent shelf
draggingShelf = game.addChild(LK.getAsset('shelf', {
anchorX: 0.5,
anchorY: 0.5
}));
draggingShelf.x = 1024;
draggingShelf.y = 1366;
draggingShelf.alpha = 0.5;
// Create green placement button
placementButton = game.addChild(LK.getAsset('openCloseButton', {
anchorX: 0.5,
anchorY: 0.5
}));
placementButton.x = 1024;
placementButton.y = 2500;
placementButton.tint = 0x00ff00;
placementButton.scaleX = 2;
placementButton.scaleY = 2;
// Add placement button text
var placementText = new Text2('Place Shelf', {
size: 30,
fill: 0x000000
});
placementText.anchor.set(0.5, 0.5);
placementText.x = 1024;
placementText.y = 2500;
game.addChild(placementText);
// Placement button handler
placementButton.down = function () {
if (shelfPlacementMode && draggingShelf) {
// Extract the new shelf position as literal values
var newShelfX = Math.floor(draggingShelf.x);
var newShelfY = Math.floor(draggingShelf.y);
// Create the new shelf
var newShelf = new Shelf();
newShelf.x = newShelfX;
newShelf.y = newShelfY;
shelves.push(newShelf);
game.addChild(newShelf);
// Clean up placement mode
draggingShelf.destroy();
draggingShelf = null;
placementButton.destroy();
placementButton = null;
placementText.destroy();
shelfPlacementMode = false;
}
};
}
}
};
}
}; // Function to show customization category
var showCustomization = function showCustomization() {
currentShopCategory = 'customization';
clearCategoryItems();
var customizeItems = [{
name: 'Store Sign',
price: 200,
description: 'Custom store branding'
}, {
name: 'Floor Tiles',
price: 150,
description: 'Improve store appearance'
}, {
name: 'Lighting',
price: 300,
description: 'Better store lighting'
}, {
name: 'Music System',
price: 250,
description: 'Background music'
}];
// Create customization cards
for (var i = 0; i < customizeItems.length; i++) {
var item = customizeItems[i];
var xPos = 340 + i % 2 * 600;
var yPos = 700 + Math.floor(i / 2) * 500;
// Item background
var itemBg = game.addChild(LK.getAsset('shopItem', {
anchorX: 0.5,
anchorY: 0.5
}));
itemBg.x = xPos;
itemBg.y = yPos;
itemBg.width = 400;
itemBg.height = 450;
itemBg.isCategoryItem = true;
shopItems.push(itemBg);
// Item name
var itemName = new Text2(item.name, {
size: 36,
fill: 0xffffff
});
itemName.anchor.set(0.5, 0.5);
itemName.x = xPos;
itemName.y = yPos - 100;
itemName.isCategoryItem = true;
game.addChild(itemName);
shopItems.push(itemName);
// Item description
var itemDesc = new Text2(item.description, {
size: 24,
fill: 0xffffff
});
itemDesc.anchor.set(0.5, 0.5);
itemDesc.x = xPos;
itemDesc.y = yPos - 50;
itemDesc.isCategoryItem = true;
game.addChild(itemDesc);
shopItems.push(itemDesc);
// Item price
var itemPrice = new Text2(item.price + '₺', {
size: 50,
fill: 0x90ee90
});
itemPrice.anchor.set(0.5, 0.5);
itemPrice.x = xPos;
itemPrice.y = yPos;
itemPrice.isCategoryItem = true;
game.addChild(itemPrice);
shopItems.push(itemPrice);
// Buy button
var buyBtn = game.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5
}));
buyBtn.x = xPos;
buyBtn.y = yPos + 100;
buyBtn.width = 250;
buyBtn.height = 125;
buyBtn.itemData = item;
buyBtn.isCategoryItem = true;
shopItems.push(buyBtn);
// Buy button handler
buyBtn.down = function () {
if (money >= this.itemData.price) {
money -= this.itemData.price;
scoreTxt.setText(money + '₺');
// Flash green to show purchase
LK.effects.flashObject(this, 0x00ff00, 500);
}
};
}
}; // Category button handlers
// Create white overlay
shopOverlay = game.addChild(LK.getAsset('shopOverlay', {
anchorX: 0.5,
anchorY: 0.5
}));
shopOverlay.x = 1536;
shopOverlay.y = 2049;
shopOverlay.alpha = 0.95;
// Create shop title
var shopTitle = new Text2('Market Shop', {
size: 80,
fill: 0x000000
});
shopTitle.anchor.set(0.5, 0.5);
shopTitle.x = 1536;
shopTitle.y = 300;
game.addChild(shopTitle);
shopItems.push(shopTitle);
// Create category buttons
var productsBtn = game.addChild(LK.getAsset('productsCategoryImage', {
anchorX: 0.5,
anchorY: 0.5
}));
productsBtn.x = 400;
productsBtn.y = 350;
productsBtn.width = 250;
productsBtn.height = 125;
shopItems.push(productsBtn);
var equipmentBtn = game.addChild(LK.getAsset('equipmentCategoryImage', {
anchorX: 0.5,
anchorY: 0.5
}));
equipmentBtn.x = 1536;
equipmentBtn.y = 350;
equipmentBtn.width = 250;
equipmentBtn.height = 125;
shopItems.push(equipmentBtn);
var customizeBtn = game.addChild(LK.getAsset('customizationCategoryImage', {
anchorX: 0.5,
anchorY: 0.5
}));
customizeBtn.x = 2472;
customizeBtn.y = 350;
customizeBtn.width = 250;
customizeBtn.height = 125;
shopItems.push(customizeBtn);
productsBtn.down = function () {
showProducts();
};
equipmentBtn.down = function () {
showEquipment();
};
customizeBtn.down = function () {
showCustomization();
};
// Show default category (products)
showProducts();
// Close button
var closeBtn = game.addChild(LK.getAsset('blackRectangle', {
anchorX: 0.5,
anchorY: 0.5
}));
closeBtn.x = 1536;
closeBtn.y = 3600;
closeBtn.width = 200;
closeBtn.height = 100;
shopItems.push(closeBtn);
var closeText = new Text2('Close', {
size: 40,
fill: 0xffffff
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1536;
closeText.y = 3600;
game.addChild(closeText);
shopItems.push(closeText);
// Close button handler
closeBtn.down = function () {
// Remove all shop elements
shopOverlay.destroy();
shopOverlay = null;
for (var j = 0; j < shopItems.length; j++) {
shopItems[j].destroy();
}
shopItems = [];
shopOpen = false;
};
}
};
// Initial customer spawn
// Don't spawn customer immediately, let the spawn timer handle it
LK.setTimeout(function () {
dayJustStarted = false; // Allow day to end after spawn delay passes
}, spawnDelay * 16.67); //{dV} // Convert frames to milliseconds (60fps = ~16.67ms per frame)
// No changes required - the current implementation already makes angry customers walk out normally through the store entrance using tween animations;;
A shiny blue ball. In-Game asset. 2d. High contrast. No shadows
Üzerinde meyve, sebze gibi ürün bulundurmayan; market kasa bankosu. Üstten görünüm.. In-Game asset. 2d. High contrast. No shadows
Shiny apple. In-Game asset. 2d. High contrast. No shadows
Koparılmamış ve ayrılmamış, bir tutam muz. In-Game asset. 2d. High contrast. No shadows
Cheese. In-Game asset. 2d. High contrast. No shadows
Milk. In-Game asset. 2d. High contrast. No shadows
Orange. In-Game asset. 2d. High contrast. No shadows
Shelf. In-Game asset. 2d. High contrast. No shadows
Bread. In-Game asset. 2d. High contrast. No shadows
Continue button. In-Game asset. 2d. High contrast. No shadows
Cut this
Shop button. In-Game asset. 2d. High contrast. No shadows
A green Open button. In-Game asset. 2d. High contrast. No shadows
Rectangle red close button with "close" title. In-Game asset. 2d. High contrast. No shadows
Buy button. In-Game asset. 2d. High contrast. No shadows
Yiyecek kategorisi butonu. In-Game asset. 2d. High contrast. No shadows
Eşya kategorisi butonu. Üstünde "furniture" yazsın. In-Game asset. 2d. High contrast. No shadows
Kişiselleştirme kategorisi butonu. Boyutu 250x125 olsun. Çekiç sembolü olabilir. Rengi turuncu olsun. Yazı ingilizce olsun. Duş çerçevesi siyah olsun.. In-Game asset. 2d. High contrast. No shadows
İtem çerçevesi. In-Game asset. 2d. High contrast. No shadows