/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
money: 1000,
day: 1,
products: 3,
customers: 0,
staff: 0,
storeLevel: 1,
priceMultiplier: 1,
lastSave: undefined
});
/****
* Classes
****/
var Button = Container.expand(function (text, width, height) {
var self = Container.call(this);
width = width || 300;
height = height || 80;
var buttonBg = self.attachAsset('btnBg', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: height
});
var buttonText = new Text2(text, {
size: 40,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function () {
tween(buttonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
self.up = function () {
tween(buttonBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
self.setText = function (newText) {
buttonText.setText(newText);
};
self.setEnabled = function (enabled) {
self.interactive = enabled;
buttonBg.alpha = enabled ? 1.0 : 0.5;
};
self.setEnabled(true);
return self;
});
var CashParticle = Container.expand(function () {
var self = Container.call(this);
var cashGraphics = self.attachAsset('cash', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = (Math.random() - 0.5) * 10;
self.vy = -5 - Math.random() * 10;
self.gravity = 0.5;
self.lifespan = 60; // 1 second at 60fps
self.update = function () {
self.x += self.vx;
self.vy += self.gravity;
self.y += self.vy;
self.lifespan--;
if (self.lifespan <= 0) {
self.readyToRemove = true;
}
};
return self;
});
var Customer = Container.expand(function () {
var self = Container.call(this);
var customerGraphics = self.attachAsset('customer', {
anchorX: 0.5,
anchorY: 0.5
});
// Customer properties
self.patience = 60 + Math.random() * 180; // 1-4 seconds patience (60fps)
self.waitTime = 0;
self.spending = 20 + Math.floor(Math.random() * 80); // How much they want to spend
self.targetProducts = 1 + Math.floor(Math.random() * 2); // How many products they want to buy
self.productsBought = 0;
self.state = "entering"; // entering, shopping, leaving
self.happiness = 1.0; // 0.0 to 1.0
// Personalization - random tint
var randomHue = Math.random() * 0x1000000;
customerGraphics.tint = randomHue;
self.update = function () {
if (self.state === "shopping") {
self.waitTime++;
// Decrease happiness as they wait
self.happiness = Math.max(0, 1 - self.waitTime / self.patience);
// Visual feedback - customer turns redder as they get impatient
var redTint = Math.floor(0xff0000 * (1 - self.happiness));
customerGraphics.tint = 0xffffff - redTint;
// Customer leaves if too impatient
if (self.waitTime >= self.patience) {
self.state = "leaving";
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.readyToRemove = true;
}
});
}
}
};
self.shop = function (availableProducts) {
if (availableProducts > 0 && self.productsBought < self.targetProducts) {
self.productsBought++;
// Flash the customer when they buy something
LK.effects.flashObject(self, 0x00ff00, 500);
if (self.productsBought >= self.targetProducts) {
// Customer satisfied, will leave happy
self.state = "leaving";
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.readyToRemove = true;
}
});
// Calculate money earned from this customer
var baseSpending = self.spending * self.productsBought;
var happinessBonus = baseSpending * self.happiness * 0.5;
self.moneySpent = Math.floor(baseSpending + happinessBonus);
return self.moneySpent;
}
return 0; // No money yet, still shopping
}
return 0; // No products available
};
return self;
});
var Product = Container.expand(function () {
var self = Container.call(this);
var productGraphics = self.attachAsset('product', {
anchorX: 0.5,
anchorY: 0.5
});
// Randomize product appearance a bit
var colors = [0x33cc33, 0xcc3333, 0x3333cc, 0xcccc33];
productGraphics.tint = colors[Math.floor(Math.random() * colors.length)];
return self;
});
var Store = Container.expand(function () {
var self = Container.call(this);
var storeGraphics = self.attachAsset('store', {
anchorX: 0.5,
anchorY: 0.5
});
self.level = storage.storeLevel || 1;
self.capacity = 5 + self.level * 3;
self.customerCapacity = 2 + Math.floor(self.level * 1.5);
self.customerSatisfaction = 0.8;
// Visual indicators
self.levelBadge = self.attachAsset('upgradeBadge', {
anchorX: 0.5,
anchorY: 0.5,
x: storeGraphics.width / 2 - 25,
y: -storeGraphics.height / 2 + 25
});
self.levelText = new Text2(self.level.toString(), {
size: 30,
fill: 0xFFFFFF
});
self.levelText.anchor.set(0.5, 0.5);
self.levelText.x = self.levelBadge.x;
self.levelText.y = self.levelBadge.y;
self.addChild(self.levelText);
self.updateAppearance = function () {
// Update store appearance based on level
var newWidth = 400 + self.level * 50;
var newHeight = 300 + self.level * 30;
tween(storeGraphics, {
width: newWidth,
height: newHeight
}, {
duration: 500,
easing: tween.easeOut
});
// Update tint based on store level
var baseTint = 0x80c0ff;
var levelBonus = Math.min(self.level * 0x001100, 0x7F0000);
storeGraphics.tint = baseTint + levelBonus;
// Update capacity values
self.capacity = 5 + self.level * 3;
self.customerCapacity = 2 + Math.floor(self.level * 1.5);
// Update level indicator
self.levelText.setText(self.level.toString());
};
self.upgrade = function () {
if (self.level < 10) {
// Maximum level cap
self.level++;
storage.storeLevel = self.level;
self.updateAppearance();
return true;
}
return false;
};
// Initialize appearance
self.updateAppearance();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game constants
var PRODUCT_COST = 50;
var PRODUCT_PRICE = 100;
var STORE_UPGRADE_BASE_COST = 1000;
var STAFF_COST = 500;
var STAFF_DAILY_WAGE = 100;
var DAILY_EXPENSES = 200;
// Game state variables
var money = storage.money || 1000;
var products = storage.products || 3;
var customers = [];
var particles = [];
var dayCounter = storage.day || 1;
var staffCount = storage.staff || 0;
var priceMultiplier = storage.priceMultiplier || 1.0;
var customerChance = 0.02; // Chance of a new customer per frame
var lastDayTimestamp = storage.lastSave || Date.now();
// UI Elements
var moneyText = new Text2("$" + money, {
size: 60,
fill: 0xFFFFFF
});
moneyText.anchor.set(0, 0);
LK.gui.topRight.addChild(moneyText);
var dayText = new Text2("Day " + dayCounter, {
size: 40,
fill: 0xFFFFFF
});
dayText.anchor.set(0.5, 0);
LK.gui.top.addChild(dayText);
var productsText = new Text2("Products: " + products, {
size: 40,
fill: 0xFFFFFF
});
productsText.anchor.set(0, 0);
productsText.y = 70;
LK.gui.topRight.addChild(productsText);
var customersText = new Text2("Customers: 0", {
size: 40,
fill: 0xFFFFFF
});
customersText.anchor.set(0, 0);
customersText.y = 120;
LK.gui.topRight.addChild(customersText);
var staffText = new Text2("Staff: " + staffCount, {
size: 40,
fill: 0xFFFFFF
});
staffText.anchor.set(0, 0);
staffText.y = 170;
LK.gui.topRight.addChild(staffText);
// Store and tiles
var store = new Store();
store.x = 2048 / 2;
store.y = 2732 / 2 - 200;
game.addChild(store);
// Create floor tiles
var tiles = [];
for (var x = 0; x < 20; x++) {
for (var y = 0; y < 10; y++) {
var tile = LK.getAsset('tile', {
anchorX: 0.5,
anchorY: 0.5,
x: 100 + x * 100,
y: 1800 + y * 100,
alpha: 0.5 + (x + y) % 2 * 0.1
});
game.addChild(tile);
tiles.push(tile);
}
}
// Create action buttons
var buyProductButton = new Button("Buy Product\n($" + PRODUCT_COST + ")", 300, 100);
buyProductButton.x = 300;
buyProductButton.y = 2732 - 200;
game.addChild(buyProductButton);
var hireStaffButton = new Button("Hire Staff\n($" + STAFF_COST + ")", 300, 100);
hireStaffButton.x = 650;
hireStaffButton.y = 2732 - 200;
game.addChild(hireStaffButton);
var adjustPriceButton = new Button("Price: x" + priceMultiplier.toFixed(1), 300, 100);
adjustPriceButton.x = 1000;
adjustPriceButton.y = 2732 - 200;
game.addChild(adjustPriceButton);
var upgradeStoreButton = new Button("Upgrade Store\n($" + getUpgradeCost() + ")", 300, 100);
upgradeStoreButton.x = 1350;
upgradeStoreButton.y = 2732 - 200;
game.addChild(upgradeStoreButton);
var newDayButton = new Button("Start New Day", 300, 100);
newDayButton.x = 1700;
newDayButton.y = 2732 - 200;
game.addChild(newDayButton);
// Function to get the upgrade cost based on current store level
function getUpgradeCost() {
return STORE_UPGRADE_BASE_COST * Math.pow(1.5, store.level - 1);
}
// Button event handlers
buyProductButton.down = function () {
Button.prototype.down.call(this);
};
buyProductButton.up = function () {
Button.prototype.up.call(this);
if (money >= PRODUCT_COST) {
money -= PRODUCT_COST;
products++;
storage.products = products;
storage.money = money;
updateUI();
// Visual feedback - spawn a product at the button location that moves to the store
var newProduct = new Product();
newProduct.x = buyProductButton.x;
newProduct.y = buyProductButton.y;
game.addChild(newProduct);
tween(newProduct, {
x: store.x,
y: store.y
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.effects.flashObject(store, 0x00ff00, 500);
newProduct.destroy();
}
});
}
};
hireStaffButton.down = function () {
Button.prototype.down.call(this);
};
hireStaffButton.up = function () {
Button.prototype.up.call(this);
if (money >= STAFF_COST) {
money -= STAFF_COST;
staffCount++;
storage.staff = staffCount;
storage.money = money;
updateUI();
// Increase customer handling capacity
customerChance += 0.005;
}
};
adjustPriceButton.down = function () {
Button.prototype.down.call(this);
};
adjustPriceButton.up = function () {
Button.prototype.up.call(this);
priceMultiplier = parseFloat((priceMultiplier + 0.1).toFixed(1));
if (priceMultiplier > 2.0) {
priceMultiplier = 0.8;
}
storage.priceMultiplier = priceMultiplier;
adjustPriceButton.setText("Price: x" + priceMultiplier.toFixed(1));
};
upgradeStoreButton.down = function () {
Button.prototype.down.call(this);
};
upgradeStoreButton.up = function () {
Button.prototype.up.call(this);
var upgradeCost = getUpgradeCost();
if (money >= upgradeCost) {
money -= upgradeCost;
storage.money = money;
if (store.upgrade()) {
LK.effects.flashObject(store, 0xffff00, 1000);
upgradeStoreButton.setText("Upgrade Store\n($" + getUpgradeCost() + ")");
updateUI();
}
}
};
newDayButton.down = function () {
Button.prototype.down.call(this);
};
newDayButton.up = function () {
Button.prototype.up.call(this);
// Calculate daily expenses
var dailyExpenses = DAILY_EXPENSES + staffCount * STAFF_DAILY_WAGE;
// Check if player can afford to start a new day
if (money >= dailyExpenses) {
money -= dailyExpenses;
dayCounter++;
storage.day = dayCounter;
storage.money = money;
storage.lastSave = Date.now();
// Remove all customers
for (var i = customers.length - 1; i >= 0; i--) {
customers[i].destroy();
}
customers = [];
// Show day summary
var summaryText = "Day " + (dayCounter - 1) + " Complete!\n\n";
summaryText += "Daily Expenses: $" + dailyExpenses + "\n";
summaryText += "New Balance: $" + money + "\n\n";
summaryText += "Starting Day " + dayCounter;
var dayInfoText = new Text2(summaryText, {
size: 40,
fill: 0xFFFFFF
});
dayInfoText.anchor.set(0.5, 0.5);
dayInfoText.x = 2048 / 2;
dayInfoText.y = 2732 / 2;
LK.gui.center.addChild(dayInfoText);
// Add background for better visibility
var infoBg = LK.getAsset('btnBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 800,
height: 400,
alpha: 0.8
});
infoBg.tint = 0x000000;
LK.gui.center.addChild(infoBg);
LK.gui.center.swapChildren(infoBg, dayInfoText);
// Remove the info after 3 seconds
LK.setTimeout(function () {
tween(dayInfoText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
LK.gui.center.removeChild(dayInfoText);
LK.gui.center.removeChild(infoBg);
}
});
tween(infoBg, {
alpha: 0
}, {
duration: 500
});
}, 3000);
updateUI();
} else {
// Show "not enough money" notification
var errorText = new Text2("Not enough money!\nYou need $" + dailyExpenses + " for daily expenses.", {
size: 40,
fill: 0xFF0000
});
errorText.anchor.set(0.5, 0.5);
errorText.x = 2048 / 2;
errorText.y = 2732 / 2;
LK.gui.center.addChild(errorText);
// Add background for better visibility
var errorBg = LK.getAsset('btnBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 600,
height: 200,
alpha: 0.8
});
errorBg.tint = 0x000000;
LK.gui.center.addChild(errorBg);
LK.gui.center.swapChildren(errorBg, errorText);
// Remove the error after 2 seconds
LK.setTimeout(function () {
tween(errorText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
LK.gui.center.removeChild(errorText);
LK.gui.center.removeChild(errorBg);
}
});
tween(errorBg, {
alpha: 0
}, {
duration: 500
});
}, 2000);
}
};
// Update UI elements
function updateUI() {
moneyText.setText("$" + money);
productsText.setText("Products: " + products);
customersText.setText("Customers: " + customers.length);
staffText.setText("Staff: " + staffCount);
dayText.setText("Day " + dayCounter);
// Update button states based on available money
buyProductButton.setEnabled(money >= PRODUCT_COST);
hireStaffButton.setEnabled(money >= STAFF_COST);
upgradeStoreButton.setEnabled(money >= getUpgradeCost());
// Update button texts that show costs
buyProductButton.setText("Buy Product\n($" + PRODUCT_COST + ")");
hireStaffButton.setText("Hire Staff\n($" + STAFF_COST + ")");
upgradeStoreButton.setText("Upgrade Store\n($" + getUpgradeCost() + ")");
}
// Function to spawn a new customer
function spawnCustomer() {
if (customers.length < store.customerCapacity) {
var customer = new Customer();
// Start off-screen
customer.x = -100 + Math.random() * 200;
customer.y = 1700 + Math.random() * 200;
customer.alpha = 0;
game.addChild(customer);
customers.push(customer);
// Animate customer entering
tween(customer, {
x: 200 + Math.random() * (2048 - 400),
y: 1500 + Math.random() * 300,
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
customer.state = "shopping";
LK.getSound('customer_enter').play();
}
});
updateUI();
}
}
// Function to process customer shopping
function processCustomers() {
for (var i = customers.length - 1; i >= 0; i--) {
var customer = customers[i];
if (customer.readyToRemove) {
customer.destroy();
customers.splice(i, 1);
updateUI();
continue;
}
if (customer.state === "shopping" && products > 0) {
// Calculate autoservice probability based on staff
var serviceChance = 0.01 + staffCount * 0.01;
if (Math.random() < serviceChance) {
// Customer buys a product
products--;
storage.products = products;
var earnings = customer.shop(products);
if (earnings > 0) {
// Apply price multiplier to earnings
var actualEarnings = Math.floor(earnings * priceMultiplier);
money += actualEarnings;
storage.money = money;
// Play cash register sound
LK.getSound('purchase').play();
// Spawn cash particles
spawnCashParticles(customer.x, customer.y, actualEarnings);
updateUI();
}
}
}
}
}
// Function to spawn cash particles for visual feedback
function spawnCashParticles(x, y, amount) {
var particleCount = Math.min(10, Math.max(3, Math.floor(amount / 20)));
for (var i = 0; i < particleCount; i++) {
var particle = new CashParticle();
particle.x = x;
particle.y = y;
game.addChild(particle);
particles.push(particle);
}
}
// Check for game over condition
function checkGameOver() {
if (money < DAILY_EXPENSES && products === 0 && customers.length === 0) {
// Player is bankrupt and has no assets
LK.showGameOver();
}
}
// Check for time-based events (new day)
function checkTimeBasedEvents() {
var currentTime = Date.now();
var hoursPassed = (currentTime - lastDayTimestamp) / (1000 * 60 * 60);
// If real world time passed is more than 1 hour, add a free product
if (hoursPassed >= 1) {
products++;
storage.products = products;
updateUI();
// Reset timestamp
lastDayTimestamp = currentTime;
storage.lastSave = lastDayTimestamp;
}
}
// Initialize UI
updateUI();
// Play background music
LK.playMusic('bgmusic', {
loop: true,
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
// Game update loop
game.update = function () {
// Process customers
for (var i = 0; i < customers.length; i++) {
customers[i].update();
}
// Update particles
for (var j = particles.length - 1; j >= 0; j--) {
particles[j].update();
if (particles[j].readyToRemove) {
particles[j].destroy();
particles.splice(j, 1);
}
}
// Spawn customers based on chance
if (Math.random() < customerChance && customers.length < store.customerCapacity) {
spawnCustomer();
}
// Process customer shopping
processCustomers();
// Check time-based events
if (LK.ticks % 300 === 0) {
// Check every 5 seconds
checkTimeBasedEvents();
}
// Check for game over
if (LK.ticks % 180 === 0) {
// Check every 3 seconds
checkGameOver();
// Auto-save game state
storage.money = money;
storage.products = products;
storage.day = dayCounter;
storage.staff = staffCount;
storage.priceMultiplier = priceMultiplier;
storage.storeLevel = store.level;
}
};
// Prevent placing UI elements in the top-left corner (reserved for menu)
game.down = function (x, y, obj) {
// Nothing to do here, buttons handle their own events
};
game.up = function (x, y, obj) {
// Nothing to do here, buttons handle their own events
};
game.move = function (x, y, obj) {
// Nothing to do here, no dragging in this game
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
money: 1000,
day: 1,
products: 3,
customers: 0,
staff: 0,
storeLevel: 1,
priceMultiplier: 1,
lastSave: undefined
});
/****
* Classes
****/
var Button = Container.expand(function (text, width, height) {
var self = Container.call(this);
width = width || 300;
height = height || 80;
var buttonBg = self.attachAsset('btnBg', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: height
});
var buttonText = new Text2(text, {
size: 40,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function () {
tween(buttonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
self.up = function () {
tween(buttonBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
self.setText = function (newText) {
buttonText.setText(newText);
};
self.setEnabled = function (enabled) {
self.interactive = enabled;
buttonBg.alpha = enabled ? 1.0 : 0.5;
};
self.setEnabled(true);
return self;
});
var CashParticle = Container.expand(function () {
var self = Container.call(this);
var cashGraphics = self.attachAsset('cash', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = (Math.random() - 0.5) * 10;
self.vy = -5 - Math.random() * 10;
self.gravity = 0.5;
self.lifespan = 60; // 1 second at 60fps
self.update = function () {
self.x += self.vx;
self.vy += self.gravity;
self.y += self.vy;
self.lifespan--;
if (self.lifespan <= 0) {
self.readyToRemove = true;
}
};
return self;
});
var Customer = Container.expand(function () {
var self = Container.call(this);
var customerGraphics = self.attachAsset('customer', {
anchorX: 0.5,
anchorY: 0.5
});
// Customer properties
self.patience = 60 + Math.random() * 180; // 1-4 seconds patience (60fps)
self.waitTime = 0;
self.spending = 20 + Math.floor(Math.random() * 80); // How much they want to spend
self.targetProducts = 1 + Math.floor(Math.random() * 2); // How many products they want to buy
self.productsBought = 0;
self.state = "entering"; // entering, shopping, leaving
self.happiness = 1.0; // 0.0 to 1.0
// Personalization - random tint
var randomHue = Math.random() * 0x1000000;
customerGraphics.tint = randomHue;
self.update = function () {
if (self.state === "shopping") {
self.waitTime++;
// Decrease happiness as they wait
self.happiness = Math.max(0, 1 - self.waitTime / self.patience);
// Visual feedback - customer turns redder as they get impatient
var redTint = Math.floor(0xff0000 * (1 - self.happiness));
customerGraphics.tint = 0xffffff - redTint;
// Customer leaves if too impatient
if (self.waitTime >= self.patience) {
self.state = "leaving";
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.readyToRemove = true;
}
});
}
}
};
self.shop = function (availableProducts) {
if (availableProducts > 0 && self.productsBought < self.targetProducts) {
self.productsBought++;
// Flash the customer when they buy something
LK.effects.flashObject(self, 0x00ff00, 500);
if (self.productsBought >= self.targetProducts) {
// Customer satisfied, will leave happy
self.state = "leaving";
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.readyToRemove = true;
}
});
// Calculate money earned from this customer
var baseSpending = self.spending * self.productsBought;
var happinessBonus = baseSpending * self.happiness * 0.5;
self.moneySpent = Math.floor(baseSpending + happinessBonus);
return self.moneySpent;
}
return 0; // No money yet, still shopping
}
return 0; // No products available
};
return self;
});
var Product = Container.expand(function () {
var self = Container.call(this);
var productGraphics = self.attachAsset('product', {
anchorX: 0.5,
anchorY: 0.5
});
// Randomize product appearance a bit
var colors = [0x33cc33, 0xcc3333, 0x3333cc, 0xcccc33];
productGraphics.tint = colors[Math.floor(Math.random() * colors.length)];
return self;
});
var Store = Container.expand(function () {
var self = Container.call(this);
var storeGraphics = self.attachAsset('store', {
anchorX: 0.5,
anchorY: 0.5
});
self.level = storage.storeLevel || 1;
self.capacity = 5 + self.level * 3;
self.customerCapacity = 2 + Math.floor(self.level * 1.5);
self.customerSatisfaction = 0.8;
// Visual indicators
self.levelBadge = self.attachAsset('upgradeBadge', {
anchorX: 0.5,
anchorY: 0.5,
x: storeGraphics.width / 2 - 25,
y: -storeGraphics.height / 2 + 25
});
self.levelText = new Text2(self.level.toString(), {
size: 30,
fill: 0xFFFFFF
});
self.levelText.anchor.set(0.5, 0.5);
self.levelText.x = self.levelBadge.x;
self.levelText.y = self.levelBadge.y;
self.addChild(self.levelText);
self.updateAppearance = function () {
// Update store appearance based on level
var newWidth = 400 + self.level * 50;
var newHeight = 300 + self.level * 30;
tween(storeGraphics, {
width: newWidth,
height: newHeight
}, {
duration: 500,
easing: tween.easeOut
});
// Update tint based on store level
var baseTint = 0x80c0ff;
var levelBonus = Math.min(self.level * 0x001100, 0x7F0000);
storeGraphics.tint = baseTint + levelBonus;
// Update capacity values
self.capacity = 5 + self.level * 3;
self.customerCapacity = 2 + Math.floor(self.level * 1.5);
// Update level indicator
self.levelText.setText(self.level.toString());
};
self.upgrade = function () {
if (self.level < 10) {
// Maximum level cap
self.level++;
storage.storeLevel = self.level;
self.updateAppearance();
return true;
}
return false;
};
// Initialize appearance
self.updateAppearance();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game constants
var PRODUCT_COST = 50;
var PRODUCT_PRICE = 100;
var STORE_UPGRADE_BASE_COST = 1000;
var STAFF_COST = 500;
var STAFF_DAILY_WAGE = 100;
var DAILY_EXPENSES = 200;
// Game state variables
var money = storage.money || 1000;
var products = storage.products || 3;
var customers = [];
var particles = [];
var dayCounter = storage.day || 1;
var staffCount = storage.staff || 0;
var priceMultiplier = storage.priceMultiplier || 1.0;
var customerChance = 0.02; // Chance of a new customer per frame
var lastDayTimestamp = storage.lastSave || Date.now();
// UI Elements
var moneyText = new Text2("$" + money, {
size: 60,
fill: 0xFFFFFF
});
moneyText.anchor.set(0, 0);
LK.gui.topRight.addChild(moneyText);
var dayText = new Text2("Day " + dayCounter, {
size: 40,
fill: 0xFFFFFF
});
dayText.anchor.set(0.5, 0);
LK.gui.top.addChild(dayText);
var productsText = new Text2("Products: " + products, {
size: 40,
fill: 0xFFFFFF
});
productsText.anchor.set(0, 0);
productsText.y = 70;
LK.gui.topRight.addChild(productsText);
var customersText = new Text2("Customers: 0", {
size: 40,
fill: 0xFFFFFF
});
customersText.anchor.set(0, 0);
customersText.y = 120;
LK.gui.topRight.addChild(customersText);
var staffText = new Text2("Staff: " + staffCount, {
size: 40,
fill: 0xFFFFFF
});
staffText.anchor.set(0, 0);
staffText.y = 170;
LK.gui.topRight.addChild(staffText);
// Store and tiles
var store = new Store();
store.x = 2048 / 2;
store.y = 2732 / 2 - 200;
game.addChild(store);
// Create floor tiles
var tiles = [];
for (var x = 0; x < 20; x++) {
for (var y = 0; y < 10; y++) {
var tile = LK.getAsset('tile', {
anchorX: 0.5,
anchorY: 0.5,
x: 100 + x * 100,
y: 1800 + y * 100,
alpha: 0.5 + (x + y) % 2 * 0.1
});
game.addChild(tile);
tiles.push(tile);
}
}
// Create action buttons
var buyProductButton = new Button("Buy Product\n($" + PRODUCT_COST + ")", 300, 100);
buyProductButton.x = 300;
buyProductButton.y = 2732 - 200;
game.addChild(buyProductButton);
var hireStaffButton = new Button("Hire Staff\n($" + STAFF_COST + ")", 300, 100);
hireStaffButton.x = 650;
hireStaffButton.y = 2732 - 200;
game.addChild(hireStaffButton);
var adjustPriceButton = new Button("Price: x" + priceMultiplier.toFixed(1), 300, 100);
adjustPriceButton.x = 1000;
adjustPriceButton.y = 2732 - 200;
game.addChild(adjustPriceButton);
var upgradeStoreButton = new Button("Upgrade Store\n($" + getUpgradeCost() + ")", 300, 100);
upgradeStoreButton.x = 1350;
upgradeStoreButton.y = 2732 - 200;
game.addChild(upgradeStoreButton);
var newDayButton = new Button("Start New Day", 300, 100);
newDayButton.x = 1700;
newDayButton.y = 2732 - 200;
game.addChild(newDayButton);
// Function to get the upgrade cost based on current store level
function getUpgradeCost() {
return STORE_UPGRADE_BASE_COST * Math.pow(1.5, store.level - 1);
}
// Button event handlers
buyProductButton.down = function () {
Button.prototype.down.call(this);
};
buyProductButton.up = function () {
Button.prototype.up.call(this);
if (money >= PRODUCT_COST) {
money -= PRODUCT_COST;
products++;
storage.products = products;
storage.money = money;
updateUI();
// Visual feedback - spawn a product at the button location that moves to the store
var newProduct = new Product();
newProduct.x = buyProductButton.x;
newProduct.y = buyProductButton.y;
game.addChild(newProduct);
tween(newProduct, {
x: store.x,
y: store.y
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.effects.flashObject(store, 0x00ff00, 500);
newProduct.destroy();
}
});
}
};
hireStaffButton.down = function () {
Button.prototype.down.call(this);
};
hireStaffButton.up = function () {
Button.prototype.up.call(this);
if (money >= STAFF_COST) {
money -= STAFF_COST;
staffCount++;
storage.staff = staffCount;
storage.money = money;
updateUI();
// Increase customer handling capacity
customerChance += 0.005;
}
};
adjustPriceButton.down = function () {
Button.prototype.down.call(this);
};
adjustPriceButton.up = function () {
Button.prototype.up.call(this);
priceMultiplier = parseFloat((priceMultiplier + 0.1).toFixed(1));
if (priceMultiplier > 2.0) {
priceMultiplier = 0.8;
}
storage.priceMultiplier = priceMultiplier;
adjustPriceButton.setText("Price: x" + priceMultiplier.toFixed(1));
};
upgradeStoreButton.down = function () {
Button.prototype.down.call(this);
};
upgradeStoreButton.up = function () {
Button.prototype.up.call(this);
var upgradeCost = getUpgradeCost();
if (money >= upgradeCost) {
money -= upgradeCost;
storage.money = money;
if (store.upgrade()) {
LK.effects.flashObject(store, 0xffff00, 1000);
upgradeStoreButton.setText("Upgrade Store\n($" + getUpgradeCost() + ")");
updateUI();
}
}
};
newDayButton.down = function () {
Button.prototype.down.call(this);
};
newDayButton.up = function () {
Button.prototype.up.call(this);
// Calculate daily expenses
var dailyExpenses = DAILY_EXPENSES + staffCount * STAFF_DAILY_WAGE;
// Check if player can afford to start a new day
if (money >= dailyExpenses) {
money -= dailyExpenses;
dayCounter++;
storage.day = dayCounter;
storage.money = money;
storage.lastSave = Date.now();
// Remove all customers
for (var i = customers.length - 1; i >= 0; i--) {
customers[i].destroy();
}
customers = [];
// Show day summary
var summaryText = "Day " + (dayCounter - 1) + " Complete!\n\n";
summaryText += "Daily Expenses: $" + dailyExpenses + "\n";
summaryText += "New Balance: $" + money + "\n\n";
summaryText += "Starting Day " + dayCounter;
var dayInfoText = new Text2(summaryText, {
size: 40,
fill: 0xFFFFFF
});
dayInfoText.anchor.set(0.5, 0.5);
dayInfoText.x = 2048 / 2;
dayInfoText.y = 2732 / 2;
LK.gui.center.addChild(dayInfoText);
// Add background for better visibility
var infoBg = LK.getAsset('btnBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 800,
height: 400,
alpha: 0.8
});
infoBg.tint = 0x000000;
LK.gui.center.addChild(infoBg);
LK.gui.center.swapChildren(infoBg, dayInfoText);
// Remove the info after 3 seconds
LK.setTimeout(function () {
tween(dayInfoText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
LK.gui.center.removeChild(dayInfoText);
LK.gui.center.removeChild(infoBg);
}
});
tween(infoBg, {
alpha: 0
}, {
duration: 500
});
}, 3000);
updateUI();
} else {
// Show "not enough money" notification
var errorText = new Text2("Not enough money!\nYou need $" + dailyExpenses + " for daily expenses.", {
size: 40,
fill: 0xFF0000
});
errorText.anchor.set(0.5, 0.5);
errorText.x = 2048 / 2;
errorText.y = 2732 / 2;
LK.gui.center.addChild(errorText);
// Add background for better visibility
var errorBg = LK.getAsset('btnBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 600,
height: 200,
alpha: 0.8
});
errorBg.tint = 0x000000;
LK.gui.center.addChild(errorBg);
LK.gui.center.swapChildren(errorBg, errorText);
// Remove the error after 2 seconds
LK.setTimeout(function () {
tween(errorText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
LK.gui.center.removeChild(errorText);
LK.gui.center.removeChild(errorBg);
}
});
tween(errorBg, {
alpha: 0
}, {
duration: 500
});
}, 2000);
}
};
// Update UI elements
function updateUI() {
moneyText.setText("$" + money);
productsText.setText("Products: " + products);
customersText.setText("Customers: " + customers.length);
staffText.setText("Staff: " + staffCount);
dayText.setText("Day " + dayCounter);
// Update button states based on available money
buyProductButton.setEnabled(money >= PRODUCT_COST);
hireStaffButton.setEnabled(money >= STAFF_COST);
upgradeStoreButton.setEnabled(money >= getUpgradeCost());
// Update button texts that show costs
buyProductButton.setText("Buy Product\n($" + PRODUCT_COST + ")");
hireStaffButton.setText("Hire Staff\n($" + STAFF_COST + ")");
upgradeStoreButton.setText("Upgrade Store\n($" + getUpgradeCost() + ")");
}
// Function to spawn a new customer
function spawnCustomer() {
if (customers.length < store.customerCapacity) {
var customer = new Customer();
// Start off-screen
customer.x = -100 + Math.random() * 200;
customer.y = 1700 + Math.random() * 200;
customer.alpha = 0;
game.addChild(customer);
customers.push(customer);
// Animate customer entering
tween(customer, {
x: 200 + Math.random() * (2048 - 400),
y: 1500 + Math.random() * 300,
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
customer.state = "shopping";
LK.getSound('customer_enter').play();
}
});
updateUI();
}
}
// Function to process customer shopping
function processCustomers() {
for (var i = customers.length - 1; i >= 0; i--) {
var customer = customers[i];
if (customer.readyToRemove) {
customer.destroy();
customers.splice(i, 1);
updateUI();
continue;
}
if (customer.state === "shopping" && products > 0) {
// Calculate autoservice probability based on staff
var serviceChance = 0.01 + staffCount * 0.01;
if (Math.random() < serviceChance) {
// Customer buys a product
products--;
storage.products = products;
var earnings = customer.shop(products);
if (earnings > 0) {
// Apply price multiplier to earnings
var actualEarnings = Math.floor(earnings * priceMultiplier);
money += actualEarnings;
storage.money = money;
// Play cash register sound
LK.getSound('purchase').play();
// Spawn cash particles
spawnCashParticles(customer.x, customer.y, actualEarnings);
updateUI();
}
}
}
}
}
// Function to spawn cash particles for visual feedback
function spawnCashParticles(x, y, amount) {
var particleCount = Math.min(10, Math.max(3, Math.floor(amount / 20)));
for (var i = 0; i < particleCount; i++) {
var particle = new CashParticle();
particle.x = x;
particle.y = y;
game.addChild(particle);
particles.push(particle);
}
}
// Check for game over condition
function checkGameOver() {
if (money < DAILY_EXPENSES && products === 0 && customers.length === 0) {
// Player is bankrupt and has no assets
LK.showGameOver();
}
}
// Check for time-based events (new day)
function checkTimeBasedEvents() {
var currentTime = Date.now();
var hoursPassed = (currentTime - lastDayTimestamp) / (1000 * 60 * 60);
// If real world time passed is more than 1 hour, add a free product
if (hoursPassed >= 1) {
products++;
storage.products = products;
updateUI();
// Reset timestamp
lastDayTimestamp = currentTime;
storage.lastSave = lastDayTimestamp;
}
}
// Initialize UI
updateUI();
// Play background music
LK.playMusic('bgmusic', {
loop: true,
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
// Game update loop
game.update = function () {
// Process customers
for (var i = 0; i < customers.length; i++) {
customers[i].update();
}
// Update particles
for (var j = particles.length - 1; j >= 0; j--) {
particles[j].update();
if (particles[j].readyToRemove) {
particles[j].destroy();
particles.splice(j, 1);
}
}
// Spawn customers based on chance
if (Math.random() < customerChance && customers.length < store.customerCapacity) {
spawnCustomer();
}
// Process customer shopping
processCustomers();
// Check time-based events
if (LK.ticks % 300 === 0) {
// Check every 5 seconds
checkTimeBasedEvents();
}
// Check for game over
if (LK.ticks % 180 === 0) {
// Check every 3 seconds
checkGameOver();
// Auto-save game state
storage.money = money;
storage.products = products;
storage.day = dayCounter;
storage.staff = staffCount;
storage.priceMultiplier = priceMultiplier;
storage.storeLevel = store.level;
}
};
// Prevent placing UI elements in the top-left corner (reserved for menu)
game.down = function (x, y, obj) {
// Nothing to do here, buttons handle their own events
};
game.up = function (x, y, obj) {
// Nothing to do here, buttons handle their own events
};
game.move = function (x, y, obj) {
// Nothing to do here, no dragging in this game
};