Code edit (1 edits merged)
Please save this source code
Code edit (14 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'visible')' in or related to this line: 'titleTxt.visible = visible;' Line Number: 385
User prompt
In the game's start menu, click play and the game will start when you click play.
Code edit (1 edits merged)
Please save this source code
User prompt
Shoe Tycoon: Old Money Edition
Initial prompt
This is an idle clicker simulation game where the player grows a shoe-selling business by actively clicking and passively earning money over time. The system is composed of several interrelated modules as follows: 1. User Interface (UI) Components Shoe Button (ShoeBtn): The main interactive element. Each click represents a shoe sale, increasing the player’s currency by a value called clickEarnings. Currency Display (CurrencyText): Continuously updates to show the player’s current money balance in real-time. Upgrade Buttons (UpgradeBtn1, UpgradeBtn2, etc.): Each upgrade button corresponds to a different enhancement (e.g., increase click earnings, add passive income). They are enabled or disabled based on player's currency. 2. Core Game Variables money: Tracks the player’s total currency (initially zero). clickEarnings: The amount of money earned per shoe sale click (starts at 1). autoIncome: Passive income earned automatically per time interval (starts at 0). upgradeCosts: An array or mapping containing the current cost of each upgrade. 3. Click Mechanism When the player clicks ShoeBtn: money += clickEarnings A short sound effect is played (e.g., “ka-ching”). UI updates to reflect new money total. 4. Upgrade System Each upgrade has: A cost (in money). An effect (e.g., double clickEarnings, increase autoIncome by a fixed amount). On clicking an upgrade button: If money >= cost, deduct cost from money. Apply upgrade effect (e.g., clickEarnings *= 2 or autoIncome += 1). Increase the cost for the next upgrade (e.g., double it). Update UI to show new costs and current stats. 5. Idle (Passive) Income Generation A timer triggers every second (or configurable interval): money += autoIncome UI updates accordingly. Optionally plays a soft coin drop sound for feedback. 6. Visual Style and UX The color palette reflects an Old Money aesthetic: creams, navy blue, gold accents. Buttons have elegant, minimalistic designs with serif fonts for text labels. Background mimics a vintage shoe boutique with wood textures and subtle lighting. 7. Sound Effects (Optional Enhancements) Click sound on shoe sales: short, crisp cash register or box opening sound. Upgrade purchase sound: satisfying “ding” or wallet opening effect. Passive income: soft coin drop sound, muted and subtle. Menu navigation: paper page flip or drawer slide sounds. 8. Extensibility and Scaling New shoe types or special editions can be added with distinct sprites and higher earnings. Additional upgrade categories: marketing, staff hiring, store decoration (impacting sales speed or income multiplier). Achievements and milestones to incentivize player progression.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { money: 0, clickValue: 1, clickUpgradeCost: 50, passiveIncome: 0, passiveUpgradeCost: 100 }); /**** * Classes ****/ // Passive Income Upgrade Button var PassiveButton = Container.expand(function () { var self = Container.call(this); var btn = self.attachAsset('passiveBtn', { anchorX: 0.5, anchorY: 0.5 }); var txt = new Text2('', { size: 44, fill: 0xFFFBE6 }); txt.anchor.set(0.5, 0.5); self.addChild(txt); function updateText() { txt.setText("Auto-Sell\n$" + storage.passiveUpgradeCost); } self.updateText = updateText; self.down = function (x, y, obj) { if (storage.money >= storage.passiveUpgradeCost) { storage.money -= storage.passiveUpgradeCost; storage.passiveIncome += 1; storage.passiveUpgradeCost = Math.floor(storage.passiveUpgradeCost * 1.7 + 20); updateMoneyDisplay(); updatePassiveDisplay(); updateUpgradeButtons(); // Animate tween(self, { scaleX: 1.1, scaleY: 1.1 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 80, easing: tween.easeIn }); } }); LK.getSound('upgrade').play(); } else { // Subtle shake if not enough money tween(self, { x: self.x + 18 }, { duration: 60, easing: tween.easeIn, onFinish: function onFinish() { tween(self, { x: self.x - 36 }, { duration: 60, easing: tween.easeIn, onFinish: function onFinish() { tween(self, { x: self.x + 18 }, { duration: 60, easing: tween.easeOut }); } }); } }); } }; updateText(); return self; }); // Shoe Button (tap to sell) var ShoeButton = Container.expand(function () { var self = Container.call(this); var btn = self.attachAsset('shoeBtn', { anchorX: 0.5, anchorY: 0.5 }); // Decorative: subtle bounce on tap self.down = function (x, y, obj) { // Animate scale tween(self, { scaleX: 0.92, scaleY: 0.92 }, { duration: 60, easing: tween.easeIn, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 80, easing: tween.easeOut }); } }); // Play sale sound LK.getSound('sale').play(); // Add money storage.money += storage.clickValue; updateMoneyDisplay(); // Subtle money icon pop popMoneyIcon(); }; return self; }); // Upgrade Button (tap to increase click value) var UpgradeButton = Container.expand(function () { var self = Container.call(this); var btn = self.attachAsset('upgradeBtn', { anchorX: 0.5, anchorY: 0.5 }); var txt = new Text2('', { size: 48, fill: 0xFFFBE6 }); txt.anchor.set(0.5, 0.5); self.addChild(txt); function updateText() { txt.setText("Upgrade\n$" + storage.clickUpgradeCost); } self.updateText = updateText; self.down = function (x, y, obj) { if (storage.money >= storage.clickUpgradeCost) { storage.money -= storage.clickUpgradeCost; storage.clickValue += 1; storage.clickUpgradeCost = Math.floor(storage.clickUpgradeCost * 1.5 + 10); updateMoneyDisplay(); updateClickValueDisplay(); updateUpgradeButtons(); // Animate tween(self, { scaleX: 1.1, scaleY: 1.1 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 80, easing: tween.easeIn }); } }); LK.getSound('upgrade').play(); } else { // Subtle shake if not enough money tween(self, { x: self.x + 18 }, { duration: 60, easing: tween.easeIn, onFinish: function onFinish() { tween(self, { x: self.x - 36 }, { duration: 60, easing: tween.easeIn, onFinish: function onFinish() { tween(self, { x: self.x + 18 }, { duration: 60, easing: tween.easeOut }); } }); } }); } }; updateText(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xede7d2 // Subtle vintage beige }); /**** * Game Code ****/ // Sound for upgrade // Sound for sale // Boutique background (subtle, not a full background, just a decorative element) // Money icon // Passive income upgrade button // Upgrade button // Main shoe button (luxury shoe) // Decorative boutique ellipse at top var boutiqueDeco = LK.getAsset('boutiqueDeco', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 0, scaleX: 1.1, scaleY: 1 }); game.addChild(boutiqueDeco); // Money display var moneyIcon = LK.getAsset('moneyIcon', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 120, y: 120 }); moneyIcon.scaleX = 1.1; moneyIcon.scaleY = 1.1; game.addChild(moneyIcon); var moneyTxt = new Text2('', { size: 90, fill: 0x7C6F57 }); moneyTxt.anchor.set(0, 0.5); moneyTxt.x = 2048 / 2 - 60; moneyTxt.y = 120; game.addChild(moneyTxt); function formatMoney(val) { if (val >= 1e9) { return (val / 1e9).toFixed(2) + "B"; } if (val >= 1e6) { return (val / 1e6).toFixed(2) + "M"; } if (val >= 1e3) { return (val / 1e3).toFixed(1) + "K"; } return "" + Math.floor(val); } function updateMoneyDisplay() { moneyTxt.setText("$" + formatMoney(storage.money)); } function popMoneyIcon() { tween.stop(moneyIcon, { scaleX: true, scaleY: true }); moneyIcon.scaleX = 1.1; moneyIcon.scaleY = 1.1; tween(moneyIcon, { scaleX: 1.25, scaleY: 1.25 }, { duration: 60, easing: tween.easeOut, onFinish: function onFinish() { tween(moneyIcon, { scaleX: 1.1, scaleY: 1.1 }, { duration: 80, easing: tween.easeIn }); } }); } // Click value display var clickValueTxt = new Text2('', { size: 48, fill: 0x8B7B5A }); clickValueTxt.anchor.set(0.5, 0); clickValueTxt.x = 2048 / 2; clickValueTxt.y = 320; game.addChild(clickValueTxt); function updateClickValueDisplay() { clickValueTxt.setText("Per Tap: $" + formatMoney(storage.clickValue)); } // Passive income display var passiveTxt = new Text2('', { size: 44, fill: 0xB7A77A }); passiveTxt.anchor.set(0.5, 0); passiveTxt.x = 2048 / 2; passiveTxt.y = 390; game.addChild(passiveTxt); function updatePassiveDisplay() { if (storage.passiveIncome > 0) { passiveTxt.setText("Auto: $" + formatMoney(storage.passiveIncome) + "/sec"); } else { passiveTxt.setText("Auto: $0/sec"); } } // Main shoe button var shoeBtn = new ShoeButton(); shoeBtn.x = 2048 / 2; shoeBtn.y = 800; game.addChild(shoeBtn); // Upgrade buttons var upgradeBtn = new UpgradeButton(); upgradeBtn.x = 2048 / 2 - 220; upgradeBtn.y = 1200; game.addChild(upgradeBtn); var passiveBtn = new PassiveButton(); passiveBtn.x = 2048 / 2 + 220; passiveBtn.y = 1200; game.addChild(passiveBtn); function updateUpgradeButtons() { upgradeBtn.updateText(); passiveBtn.updateText(); } // --- START MENU IMPLEMENTATION --- var startMenuContainer = new Container(); var startBg = LK.getAsset('boutiqueDeco', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 2.2, scaleY: 2.2 }); startMenuContainer.addChild(startBg); var startTitle = new Text2('SHOE TYCOON', { size: 120, fill: 0x7C6F57 }); startTitle.anchor.set(0.5, 0.5); startTitle.x = 2048 / 2; startTitle.y = 900; startMenuContainer.addChild(startTitle); var playBtn = LK.getAsset('upgradeBtn', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 1400, scaleX: 1.4, scaleY: 1.2 }); startMenuContainer.addChild(playBtn); var playTxt = new Text2('PLAY', { size: 80, fill: 0xFFFBE6 }); playTxt.anchor.set(0.5, 0.5); playTxt.x = 2048 / 2; playTxt.y = 1400; startMenuContainer.addChild(playTxt); game.addChild(startMenuContainer); // Hide all gameplay UI until play is pressed function setGameplayUIVisible(visible) { moneyIcon.visible = visible; moneyTxt.visible = visible; clickValueTxt.visible = visible; passiveTxt.visible = visible; shoeBtn.visible = visible; upgradeBtn.visible = visible; passiveBtn.visible = visible; boutiqueDeco.visible = visible; titleTxt.visible = visible; } setGameplayUIVisible(false); // Play button handler playBtn.interactive = true; playBtn.down = function (x, y, obj) { // Animate play button tween(playBtn, { scaleX: 1.2, scaleY: 1.1 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { tween(playBtn, { scaleX: 1.4, scaleY: 1.2 }, { duration: 80, easing: tween.easeIn }); } }); // Fade out menu tween(startMenuContainer, { alpha: 0 }, { duration: 220, easing: tween.easeIn, onFinish: function onFinish() { startMenuContainer.visible = false; setGameplayUIVisible(true); } }); }; // GUI Title var titleTxt = new Text2('SHOE TYCOON', { size: 100, fill: 0x7C6F57 }); titleTxt.anchor.set(0.5, 0); LK.gui.top.addChild(titleTxt); // Center title, but not in top left 100x100 titleTxt.x = LK.gui.top.width / 100; titleTxt.y = 1000; // Initial display update updateMoneyDisplay(); updateClickValueDisplay(); updatePassiveDisplay(); updateUpgradeButtons(); // Passive income timer var passiveTimer = LK.setInterval(function () { if (storage.passiveIncome > 0) { storage.money += storage.passiveIncome; updateMoneyDisplay(); popMoneyIcon(); } }, 1000); // Save progress every 2 seconds var saveTimer = LK.setInterval(function () { // Storage is auto-persistent, but we can force a write if needed // (No-op, but placeholder for future expansion) }, 2000); // Game update (not much needed, but could be used for future features) game.update = function () { // No per-frame logic needed for MVP }; // Clean up on game over (not strictly needed, but good practice) game.on('destroy', function () { LK.clearInterval(passiveTimer); LK.clearInterval(saveTimer); }); // Touch handling for shoeBtn and upgrade buttons // (Handled by their own .down methods, no need for game.down) // Prevent elements in top left 100x100 // (All elements are centered or offset from center, so this is satisfied);
===================================================================
--- original.js
+++ change.js
@@ -239,11 +239,17 @@
moneyTxt.x = 2048 / 2 - 60;
moneyTxt.y = 120;
game.addChild(moneyTxt);
function formatMoney(val) {
- if (val >= 1e9) return (val / 1e9).toFixed(2) + "B";
- if (val >= 1e6) return (val / 1e6).toFixed(2) + "M";
- if (val >= 1e3) return (val / 1e3).toFixed(1) + "K";
+ if (val >= 1e9) {
+ return (val / 1e9).toFixed(2) + "B";
+ }
+ if (val >= 1e6) {
+ return (val / 1e6).toFixed(2) + "M";
+ }
+ if (val >= 1e3) {
+ return (val / 1e3).toFixed(1) + "K";
+ }
return "" + Math.floor(val);
}
function updateMoneyDisplay() {
moneyTxt.setText("$" + formatMoney(storage.money));
@@ -317,18 +323,100 @@
function updateUpgradeButtons() {
upgradeBtn.updateText();
passiveBtn.updateText();
}
+// --- START MENU IMPLEMENTATION ---
+var startMenuContainer = new Container();
+var startBg = LK.getAsset('boutiqueDeco', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 2732 / 2,
+ scaleX: 2.2,
+ scaleY: 2.2
+});
+startMenuContainer.addChild(startBg);
+var startTitle = new Text2('SHOE TYCOON', {
+ size: 120,
+ fill: 0x7C6F57
+});
+startTitle.anchor.set(0.5, 0.5);
+startTitle.x = 2048 / 2;
+startTitle.y = 900;
+startMenuContainer.addChild(startTitle);
+var playBtn = LK.getAsset('upgradeBtn', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 1400,
+ scaleX: 1.4,
+ scaleY: 1.2
+});
+startMenuContainer.addChild(playBtn);
+var playTxt = new Text2('PLAY', {
+ size: 80,
+ fill: 0xFFFBE6
+});
+playTxt.anchor.set(0.5, 0.5);
+playTxt.x = 2048 / 2;
+playTxt.y = 1400;
+startMenuContainer.addChild(playTxt);
+game.addChild(startMenuContainer);
+// Hide all gameplay UI until play is pressed
+function setGameplayUIVisible(visible) {
+ moneyIcon.visible = visible;
+ moneyTxt.visible = visible;
+ clickValueTxt.visible = visible;
+ passiveTxt.visible = visible;
+ shoeBtn.visible = visible;
+ upgradeBtn.visible = visible;
+ passiveBtn.visible = visible;
+ boutiqueDeco.visible = visible;
+ titleTxt.visible = visible;
+}
+setGameplayUIVisible(false);
+// Play button handler
+playBtn.interactive = true;
+playBtn.down = function (x, y, obj) {
+ // Animate play button
+ tween(playBtn, {
+ scaleX: 1.2,
+ scaleY: 1.1
+ }, {
+ duration: 80,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(playBtn, {
+ scaleX: 1.4,
+ scaleY: 1.2
+ }, {
+ duration: 80,
+ easing: tween.easeIn
+ });
+ }
+ });
+ // Fade out menu
+ tween(startMenuContainer, {
+ alpha: 0
+ }, {
+ duration: 220,
+ easing: tween.easeIn,
+ onFinish: function onFinish() {
+ startMenuContainer.visible = false;
+ setGameplayUIVisible(true);
+ }
+ });
+};
// GUI Title
-var titleTxt = new Text2('Shoe Tycoon', {
- size: 90,
+var titleTxt = new Text2('SHOE TYCOON', {
+ size: 100,
fill: 0x7C6F57
});
titleTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(titleTxt);
// Center title, but not in top left 100x100
-titleTxt.x = LK.gui.top.width / 2;
-titleTxt.y = 20;
+titleTxt.x = LK.gui.top.width / 100;
+titleTxt.y = 1000;
// Initial display update
updateMoneyDisplay();
updateClickValueDisplay();
updatePassiveDisplay();
@@ -357,5 +445,5 @@
});
// Touch handling for shoeBtn and upgrade buttons
// (Handled by their own .down methods, no need for game.down)
// Prevent elements in top left 100x100
-// (All elements are centered or offset from center, so this is satisfied)
\ No newline at end of file
+// (All elements are centered or offset from center, so this is satisfied);
\ No newline at end of file