Code edit (1 edits merged)
Please save this source code
User prompt
Startup Tycoon: Office Empire
Initial prompt
/**** * Assets ****/ LK.init.shape('companyLogo', {width:180, height:180, color:0x2d8cf0, shape:'ellipse'}) LK.init.shape('competitor', {width:120, height:120, color:0xe74c3c, shape:'box'}) LK.init.shape('employee', {width:80, height:80, color:0xf5a623, shape:'ellipse'}) LK.init.shape('event', {width:120, height:120, color:0x8e44ad, shape:'ellipse'}) LK.init.shape('money', {width:100, height:60, color:0x27ae60, shape:'box'}) LK.init.shape('office', {width:220, height:120, color:0x6c7a89, shape:'box'}) LK.init.shape('upgrade', {width:100, height:100, color:0xf1c40f, shape:'box'}) /**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Employee class var Employee = Container.expand(function () { var self = Container.call(this); var empArt = self.attachAsset('employee', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Event popup class var EventPopup = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('event', { anchorX: 0.5, anchorY: 0.5 }); self.text = new Text2('', { size: 60, fill: '#fff', align: 'center', wordWrap: true, wordWrapWidth: 400 }); self.text.anchor.set(0.5, 0.5); self.text.x = 0; self.text.y = 0; self.addChild(self.text); return self; }); // Office class var Office = Container.expand(function () { var self = Container.call(this); var officeArt = self.attachAsset('office', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Upgrade class var Upgrade = Container.expand(function () { var self = Container.call(this); var upgArt = self.attachAsset('upgrade', { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf4f6fa }); /**** * Game Code ****/ // Company logo (ellipse), office (box), employee (ellipse), money (box), competitor (box), upgrade (box), event (ellipse) // --- Game State --- var START_MONEY = 5000; var START_EMPLOYEES = 1; var START_OFFICES = 1; var ROUND_DURATION = 1200; // ms per round var MAX_ROUNDS = 30; var money = START_MONEY; var employees = START_EMPLOYEES; var offices = START_OFFICES; var upgrades = 0; var round = 1; var competitorProgress = 0; // 0-100 var bankrupt = false; var milestoneReached = false; var eventActive = false; var eventTimeout = null; var lastAction = null; // --- UI Elements --- var logo = LK.getAsset('companyLogo', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 260 }); game.addChild(logo); var officeNodes = []; var employeeNodes = []; var upgradeNodes = []; var moneyTxt = new Text2('', { size: 90, fill: '#27ae60' }); moneyTxt.anchor.set(0.5, 0); LK.gui.top.addChild(moneyTxt); var roundTxt = new Text2('', { size: 60, fill: '#34495e' }); roundTxt.anchor.set(0.5, 0); LK.gui.top.addChild(roundTxt); var competitorBar = LK.getAsset('competitor', { anchorX: 0, anchorY: 0.5, x: 200, y: 400, width: 0, height: 60 }); game.addChild(competitorBar); var competitorLabel = new Text2('Competitor', { size: 48, fill: '#e74c3c' }); competitorLabel.anchor.set(0, 0.5); competitorLabel.x = 200; competitorLabel.y = 340; game.addChild(competitorLabel); var milestoneTxt = new Text2('', { size: 80, fill: '#2980b9' }); milestoneTxt.anchor.set(0.5, 0.5); milestoneTxt.x = 1024; milestoneTxt.y = 600; game.addChild(milestoneTxt); // --- Action Buttons --- var actionBtns = []; var actionNames = [{ id: 'hire', label: 'Hire Employee', desc: '+1 Employee\nCost: $1000', cost: 1000 }, { id: 'expand', label: 'Expand Office', desc: '+1 Office\nCost: $2000', cost: 2000 }, { id: 'market', label: 'Marketing', desc: 'Boost Revenue\nCost: $1500', cost: 1500 }, { id: 'upgrade', label: 'Upgrade', desc: 'Increase Efficiency\nCost: $2500', cost: 2500 }, { id: 'skip', label: 'Skip', desc: 'No Action\nNo Cost', cost: 0 }]; // --- Event Popup --- var eventPopup = new EventPopup(); eventPopup.x = 1024; eventPopup.y = 1366; eventPopup.visible = false; game.addChild(eventPopup); // --- Helper Functions --- function updateUI() { moneyTxt.setText('$' + money); moneyTxt.x = LK.gui.width / 2; moneyTxt.y = 20; roundTxt.setText('Round ' + round + '/' + MAX_ROUNDS); roundTxt.x = LK.gui.width / 2; roundTxt.y = 120; milestoneTxt.setText(milestoneReached ? 'You are a Market Leader!' : ''); milestoneTxt.visible = milestoneReached; // Update competitor bar competitorBar.width = Math.floor(800 * (competitorProgress / 100)); // Offices for (var i = 0; i < officeNodes.length; ++i) { officeNodes[i].visible = false; } for (var i = 0; i < offices; ++i) { if (!officeNodes[i]) { var o = new Office(); o.x = 400 + i * 220; o.y = 900; officeNodes[i] = o; game.addChild(o); } officeNodes[i].visible = true; } // Employees for (var i = 0; i < employeeNodes.length; ++i) { employeeNodes[i].visible = false; } for (var i = 0; i < employees; ++i) { if (!employeeNodes[i]) { var e = new Employee(); e.x = 400 + i % 6 * 120; e.y = 1100 + Math.floor(i / 6) * 120; employeeNodes[i] = e; game.addChild(e); } employeeNodes[i].visible = true; } // Upgrades for (var i = 0; i < upgradeNodes.length; ++i) { upgradeNodes[i].visible = false; } for (var i = 0; i < upgrades; ++i) { if (!upgradeNodes[i]) { var u = new Upgrade(); u.x = 1800; u.y = 900 + i * 120; upgradeNodes[i] = u; game.addChild(u); } upgradeNodes[i].visible = true; } } // --- Action Button Creation --- function createActionButtons() { // Remove old for (var i = 0; i < actionBtns.length; ++i) { if (actionBtns[i].parent) { actionBtns[i].parent.removeChild(actionBtns[i]); } } actionBtns = []; // Create new for (var i = 0; i < actionNames.length; ++i) { var btn = LK.getAsset('money', { anchorX: 0.5, anchorY: 0.5, x: 500 + i * 310, y: 2200, width: 300, height: 220 }); var txt = new Text2(actionNames[i].label, { size: 54, fill: '#fff' }); txt.anchor.set(0.5, 0.5); txt.x = 0; txt.y = -30; btn.addChild(txt); var desc = new Text2(actionNames[i].desc, { size: 36, fill: '#fff' }); desc.anchor.set(0.5, 0.5); desc.x = 0; desc.y = 60; btn.addChild(desc); btn.actionId = actionNames[i].id; btn.actionIdx = i; btn.interactive = true; btn.down = function (x, y, obj) { if (eventActive || bankrupt || milestoneReached) { return; } handleAction(this.actionId); }; game.addChild(btn); actionBtns.push(btn); } } // --- Event System --- var eventList = [{ text: 'Tech Breakthrough!\n+1 Upgrade, +$2000', effect: function effect() { upgrades += 1; money += 2000; } }, { text: 'Market Crash!\nLose $3000', effect: function effect() { money -= 3000; } }, { text: 'Competitor Launches New Product!\nCompetitor gains ground.', effect: function effect() { competitorProgress += 20; } }, { text: 'Viral Marketing!\n+2 Employees', effect: function effect() { employees += 2; } }, { text: 'Office Fire!\nLose 1 Office', effect: function effect() { if (offices > 1) { offices -= 1; } } }, { text: 'Angel Investor!\n+$5000', effect: function effect() { money += 5000; } }, { text: 'Employee Strike!\nLose 2 Employees', effect: function effect() { employees = Math.max(1, employees - 2); } }, { text: 'Tax Refund!\n+$1500', effect: function effect() { money += 1500; } }, { text: 'Bad Press!\nCompetitor gains ground.', effect: function effect() { competitorProgress += 15; } }, { text: 'Product Recall!\nLose $2000', effect: function effect() { money -= 2000; } }]; function maybeTriggerEvent() { if (eventActive) { return; } // 30% chance of event if (Math.random() < 0.3) { var idx = Math.floor(Math.random() * eventList.length); var ev = eventList[idx]; eventActive = true; eventPopup.text.setText(ev.text); eventPopup.visible = true; tween(eventPopup, { alpha: 1 }, { duration: 200 }); eventTimeout = LK.setTimeout(function () { ev.effect(); eventPopup.visible = false; eventActive = false; updateUI(); checkGameEnd(); }, 1200); } } // --- Game Logic --- function handleAction(actionId) { if (bankrupt || milestoneReached) { return; } lastAction = actionId; switch (actionId) { case 'hire': if (money >= 1000) { money -= 1000; employees += 1; } break; case 'expand': if (money >= 2000) { money -= 2000; offices += 1; } break; case 'market': if (money >= 1500) { money -= 1500; // Marketing: next round revenue boost marketingBoost = 1.5; } break; case 'upgrade': if (money >= 2500) { money -= 2500; upgrades += 1; } break; case 'skip': // No action break; } updateUI(); nextRound(); } var marketingBoost = 1.0; function nextRound() { // Revenue calculation var baseRevenue = 800 * employees * offices; var upgradeBonus = 1 + 0.2 * upgrades; var revenue = Math.floor(baseRevenue * upgradeBonus * marketingBoost); marketingBoost = 1.0; // Expenses var expenses = 600 * employees + 400 * offices + 200 * upgrades; // Net var net = revenue - expenses; money += net; // Competitor progress var compInc = 5 + Math.max(0, 10 - offices - upgrades); competitorProgress += compInc; if (competitorProgress > 100) { competitorProgress = 100; } // Round advance round += 1; updateUI(); checkGameEnd(); maybeTriggerEvent(); } function checkGameEnd() { if (money < 0) { bankrupt = true; LK.effects.flashScreen(0xe74c3c, 1200); LK.showGameOver(); return; } if (competitorProgress >= 100) { bankrupt = true; LK.effects.flashScreen(0xe74c3c, 1200); LK.showGameOver(); return; } if (offices >= 5 && employees >= 10 && upgrades >= 3 && money >= 20000) { milestoneReached = true; LK.effects.flashScreen(0x27ae60, 1200); LK.showYouWin(); return; } if (round > MAX_ROUNDS) { if (money >= 15000) { milestoneReached = true; LK.effects.flashScreen(0x27ae60, 1200); LK.showYouWin(); } else { bankrupt = true; LK.effects.flashScreen(0xe74c3c, 1200); LK.showGameOver(); } return; } } // --- Game Start --- function resetGame() { money = START_MONEY; employees = START_EMPLOYEES; offices = START_OFFICES; upgrades = 0; round = 1; competitorProgress = 0; bankrupt = false; milestoneReached = false; eventActive = false; lastAction = null; marketingBoost = 1.0; updateUI(); createActionButtons(); } resetGame(); // --- Game Update Loop --- game.update = function () { // No per-frame logic needed for MVP }; // --- Touch Handling (for event popup) --- eventPopup.down = function (x, y, obj) { if (!eventActive) { return; } if (eventTimeout) { LK.clearTimeout(eventTimeout); eventTimeout = null; } eventPopup.visible = false; eventActive = false; updateUI(); checkGameEnd(); }; // --- Prevent UI in top left 100x100 --- logo.x = 1024; logo.y = 260; // --- End of File ---
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// ActionButton class
var ActionButton = Container.expand(function () {
var self = Container.call(this);
self.actionType = '';
self.label = '';
self.iconId = '';
self.onAction = null;
self.init = function (actionType, label, iconId, onAction) {
self.actionType = actionType;
self.label = label;
self.iconId = iconId;
self.onAction = onAction;
var icon = self.attachAsset(iconId, {
anchorX: 0.5,
anchorY: 0.5
});
self.icon = icon;
var txt = new Text2(label, {
size: 48,
fill: "#fff"
});
txt.anchor.set(0.5, 0);
txt.y = 50;
self.addChild(txt);
self.txt = txt;
};
// Touch/click event
self.down = function (x, y, obj) {
if (typeof self.onAction === 'function') {
self.onAction(self.actionType);
}
};
return self;
});
// EventPopup class
var EventPopup = Container.expand(function () {
var self = Container.call(this);
self.text = '';
self.onAcknowledge = null;
self.init = function (text, onAcknowledge) {
self.text = text;
self.onAcknowledge = onAcknowledge;
var bg = self.attachAsset('event', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 1.5
});
self.bg = bg;
var txt = new Text2(text, {
size: 60,
fill: "#fff",
font: "Tahoma"
});
txt.anchor.set(0.5, 0.5);
txt.y = 0;
self.addChild(txt);
self.txt = txt;
};
self.down = function (x, y, obj) {
if (typeof self.onAcknowledge === 'function') {
self.onAcknowledge();
}
self.destroy();
};
return self;
});
// Office class (player or rival)
var Office = Container.expand(function () {
var self = Container.call(this);
self.level = 1;
self.employees = 1;
self.upgrades = 0;
self.marketing = 0;
self.cash = 1000;
self.revenue = 0;
self.expenses = 0;
self.isRival = false;
self.updateStats = function (stats) {
if (stats.level !== undefined) self.level = stats.level;
if (stats.employees !== undefined) self.employees = stats.employees;
if (stats.upgrades !== undefined) self.upgrades = stats.upgrades;
if (stats.marketing !== undefined) self.marketing = stats.marketing;
if (stats.cash !== undefined) self.cash = stats.cash;
};
self.getRevenue = function () {
// Revenue: base + employees + upgrades + marketing
return 200 * self.level + 120 * self.employees + 180 * self.upgrades + 100 * self.marketing;
};
self.getExpenses = function () {
// Expenses: base + employees + upgrades + marketing
return 100 * self.level + 80 * self.employees + 60 * self.upgrades + 40 * self.marketing;
};
self.getScore = function () {
// Score: cash + revenue - expenses
return self.cash + self.getRevenue() - self.getExpenses();
};
self.attachVisuals = function () {
var assetId = self.isRival ? 'rivalOffice' : 'office';
var officeAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.officeAsset = officeAsset;
};
self.flash = function (color) {
LK.effects.flashObject(self, color, 600);
};
self.attachVisuals();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf4f6fa
});
/****
* Game Code
****/
// Event icon
// Expand icon
// Marketing icon
// Upgrade icon
// Employee icon
// Rival office
// Office (main player asset)
// --- Game State ---
var round = 1;
var maxRounds = 30;
var milestoneCash = 10000;
var milestoneEmployees = 15;
var milestoneLevel = 5;
var player, rival;
var actionButtons = [];
var infoTexts = {};
var eventPopup = null;
var isActionPhase = true;
var lastEvent = null;
var gameOver = false;
// --- UI Setup ---
// Info text for round
var roundTxt = new Text2('Round 1', {
size: 80,
fill: "#222"
});
roundTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(roundTxt);
// Player cash
var cashTxt = new Text2('$1000', {
size: 60,
fill: 0x2ECC71
});
cashTxt.anchor.set(0.5, 0);
cashTxt.y = 90;
LK.gui.top.addChild(cashTxt);
// Rival progress
var rivalTxt = new Text2('Rival: $1000', {
size: 48,
fill: 0xE74C3C
});
rivalTxt.anchor.set(0.5, 0);
rivalTxt.y = 160;
LK.gui.top.addChild(rivalTxt);
// --- Offices ---
player = new Office();
player.x = 2048 / 2 - 400;
player.y = 1100;
game.addChild(player);
rival = new Office();
rival.isRival = true;
rival.x = 2048 / 2 + 400;
rival.y = 1100;
game.addChild(rival);
// --- Action Buttons ---
var actions = [{
type: 'hire',
label: 'Hire',
icon: 'employee'
}, {
type: 'upgrade',
label: 'Upgrade',
icon: 'upgrade'
}, {
type: 'marketing',
label: 'Marketing',
icon: 'marketing'
}, {
type: 'expand',
label: 'Expand',
icon: 'expand'
}];
for (var i = 0; i < actions.length; i++) {
var ab = new ActionButton();
ab.init(actions[i].type, actions[i].label, actions[i].icon, handleAction);
ab.x = 2048 / 2 - 300 + i * 200;
ab.y = 1800;
game.addChild(ab);
actionButtons.push(ab);
}
// --- Info Texts (player stats) ---
var statsTxt = new Text2('', {
size: 48,
fill: 0x34495E
});
statsTxt.anchor.set(0.5, 0);
statsTxt.x = 2048 / 2 - 400;
statsTxt.y = 1350;
game.addChild(statsTxt);
var rivalStatsTxt = new Text2('', {
size: 48,
fill: 0xC0392B
});
rivalStatsTxt.anchor.set(0.5, 0);
rivalStatsTxt.x = 2048 / 2 + 400;
rivalStatsTxt.y = 1350;
game.addChild(rivalStatsTxt);
// --- Event Popup (hidden by default) ---
function showEventPopup(text, onAcknowledge) {
if (eventPopup) eventPopup.destroy();
eventPopup = new EventPopup();
eventPopup.init(text, onAcknowledge);
eventPopup.x = 2048 / 2;
eventPopup.y = 900;
game.addChild(eventPopup);
}
// --- Game Logic ---
function updateUI() {
roundTxt.setText('Round ' + round);
cashTxt.setText('$' + player.cash);
rivalTxt.setText('Rival: $' + rival.cash);
statsTxt.setText('Lvl: ' + player.level + ' Emp: ' + player.employees + ' Upg: ' + player.upgrades + ' Mkt: ' + player.marketing + '\nRevenue: $' + player.getRevenue() + ' Expenses: $' + player.getExpenses());
rivalStatsTxt.setText('Lvl: ' + rival.level + ' Emp: ' + rival.employees + ' Upg: ' + rival.upgrades + ' Mkt: ' + rival.marketing + '\nRevenue: $' + rival.getRevenue() + ' Expenses: $' + rival.getExpenses());
}
function handleAction(actionType) {
if (!isActionPhase || gameOver) return;
var cost = 0;
var msg = '';
if (actionType === 'hire') {
cost = 300 + 50 * player.employees;
if (player.cash >= cost) {
player.employees += 1;
player.cash -= cost;
msg = 'Hired 1 employee for $' + cost + '!';
} else {
msg = 'Not enough cash to hire!';
}
} else if (actionType === 'upgrade') {
cost = 500 + 100 * player.upgrades;
if (player.cash >= cost) {
player.upgrades += 1;
player.cash -= cost;
msg = 'Upgraded efficiency for $' + cost + '!';
} else {
msg = 'Not enough cash to upgrade!';
}
} else if (actionType === 'marketing') {
cost = 400 + 80 * player.marketing;
if (player.cash >= cost) {
player.marketing += 1;
player.cash -= cost;
msg = 'Launched marketing for $' + cost + '!';
} else {
msg = 'Not enough cash for marketing!';
}
} else if (actionType === 'expand') {
cost = 1000 + 200 * player.level;
if (player.cash >= cost) {
player.level += 1;
player.cash -= cost;
msg = 'Expanded office for $' + cost + '!';
} else {
msg = 'Not enough cash to expand!';
}
}
updateUI();
if (msg) {
player.flash(0x2ecc71);
showEventPopup(msg, function () {
isActionPhase = false;
nextPhase();
});
}
}
function nextPhase() {
// After action, process round: revenue, expenses, events, rival
if (gameOver) return;
// 1. Player revenue/expenses
var revenue = player.getRevenue();
var expenses = player.getExpenses();
player.cash += revenue - expenses;
// 2. Rival AI: simple catch-up logic
var rivalAction = Math.floor(Math.random() * 4);
if (rivalAction === 0) {
rival.employees += 1;
} else if (rivalAction === 1) {
rival.upgrades += 1;
} else if (rivalAction === 2) {
rival.marketing += 1;
} else if (rivalAction === 3) {
rival.level += 1;
}
rival.cash += rival.getRevenue() - rival.getExpenses();
// 3. Random event
var eventRoll = Math.random();
var eventMsg = '';
var eventEffect = null;
if (eventRoll < 0.18) {
// Good event
var bonus = 400 + Math.floor(Math.random() * 200);
eventMsg = 'Viral Success! You gain $' + bonus;
eventEffect = function eventEffect() {
player.cash += bonus;
};
} else if (eventRoll < 0.36) {
// Bad event
var loss = 300 + Math.floor(Math.random() * 200);
eventMsg = 'Unexpected Expense! Lose $' + loss;
eventEffect = function eventEffect() {
player.cash -= loss;
};
} else if (eventRoll < 0.48) {
// Neutral event
eventMsg = 'Market is stable. No major events this round.';
eventEffect = function eventEffect() {};
} else if (eventRoll < 0.60) {
// Rival gets boost
var rivalBonus = 400 + Math.floor(Math.random() * 200);
eventMsg = 'Rival gets a boost! Rival gains $' + rivalBonus;
eventEffect = function eventEffect() {
rival.cash += rivalBonus;
};
} else if (eventRoll < 0.70) {
// Employee leaves
if (player.employees > 1) {
eventMsg = 'An employee left! -1 employee';
eventEffect = function eventEffect() {
player.employees -= 1;
};
}
} else if (eventRoll < 0.80) {
// Free upgrade
eventMsg = 'Efficiency breakthrough! Free upgrade!';
eventEffect = function eventEffect() {
player.upgrades += 1;
};
} else if (eventRoll < 0.90) {
// Rival loses cash
var rivalLoss = 300 + Math.floor(Math.random() * 200);
eventMsg = 'Rival faces setback! Rival loses $' + rivalLoss;
eventEffect = function eventEffect() {
rival.cash -= rivalLoss;
};
} else {
// Nothing
eventMsg = 'Quiet round. Focus on your strategy!';
eventEffect = function eventEffect() {};
}
// 4. Update UI and show event
updateUI();
// 5. Check for win/lose
var win = false,
lose = false,
winMsg = '',
loseMsg = '';
if (player.cash >= milestoneCash || player.employees >= milestoneEmployees || player.level >= milestoneLevel) {
win = true;
winMsg = 'Congratulations! You built a market leader startup!';
} else if (player.cash < 0) {
lose = true;
loseMsg = 'You went bankrupt! Game Over.';
} else if (rival.cash >= milestoneCash || rival.employees >= milestoneEmployees || rival.level >= milestoneLevel) {
lose = true;
loseMsg = 'Rival overtook you! Game Over.';
} else if (round >= maxRounds) {
if (player.cash > rival.cash) {
win = true;
winMsg = 'You survived 30 rounds and outperformed your rival!';
} else {
lose = true;
loseMsg = 'Rival outperformed you after 30 rounds!';
}
}
if (win) {
gameOver = true;
LK.showYouWin();
return;
}
if (lose) {
gameOver = true;
LK.showGameOver();
return;
}
// 6. Show event popup, then advance round
showEventPopup(eventMsg, function () {
if (typeof eventEffect === 'function') eventEffect();
round += 1;
updateUI();
isActionPhase = true;
});
}
// --- Game Update Loop ---
game.update = function () {
// No per-frame logic needed for MVP
};
// --- Start Game ---
updateUI();
isActionPhase = true; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,418 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// ActionButton class
+var ActionButton = Container.expand(function () {
+ var self = Container.call(this);
+ self.actionType = '';
+ self.label = '';
+ self.iconId = '';
+ self.onAction = null;
+ self.init = function (actionType, label, iconId, onAction) {
+ self.actionType = actionType;
+ self.label = label;
+ self.iconId = iconId;
+ self.onAction = onAction;
+ var icon = self.attachAsset(iconId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.icon = icon;
+ var txt = new Text2(label, {
+ size: 48,
+ fill: "#fff"
+ });
+ txt.anchor.set(0.5, 0);
+ txt.y = 50;
+ self.addChild(txt);
+ self.txt = txt;
+ };
+ // Touch/click event
+ self.down = function (x, y, obj) {
+ if (typeof self.onAction === 'function') {
+ self.onAction(self.actionType);
+ }
+ };
+ return self;
+});
+// EventPopup class
+var EventPopup = Container.expand(function () {
+ var self = Container.call(this);
+ self.text = '';
+ self.onAcknowledge = null;
+ self.init = function (text, onAcknowledge) {
+ self.text = text;
+ self.onAcknowledge = onAcknowledge;
+ var bg = self.attachAsset('event', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 2.5,
+ scaleY: 1.5
+ });
+ self.bg = bg;
+ var txt = new Text2(text, {
+ size: 60,
+ fill: "#fff",
+ font: "Tahoma"
+ });
+ txt.anchor.set(0.5, 0.5);
+ txt.y = 0;
+ self.addChild(txt);
+ self.txt = txt;
+ };
+ self.down = function (x, y, obj) {
+ if (typeof self.onAcknowledge === 'function') {
+ self.onAcknowledge();
+ }
+ self.destroy();
+ };
+ return self;
+});
+// Office class (player or rival)
+var Office = Container.expand(function () {
+ var self = Container.call(this);
+ self.level = 1;
+ self.employees = 1;
+ self.upgrades = 0;
+ self.marketing = 0;
+ self.cash = 1000;
+ self.revenue = 0;
+ self.expenses = 0;
+ self.isRival = false;
+ self.updateStats = function (stats) {
+ if (stats.level !== undefined) self.level = stats.level;
+ if (stats.employees !== undefined) self.employees = stats.employees;
+ if (stats.upgrades !== undefined) self.upgrades = stats.upgrades;
+ if (stats.marketing !== undefined) self.marketing = stats.marketing;
+ if (stats.cash !== undefined) self.cash = stats.cash;
+ };
+ self.getRevenue = function () {
+ // Revenue: base + employees + upgrades + marketing
+ return 200 * self.level + 120 * self.employees + 180 * self.upgrades + 100 * self.marketing;
+ };
+ self.getExpenses = function () {
+ // Expenses: base + employees + upgrades + marketing
+ return 100 * self.level + 80 * self.employees + 60 * self.upgrades + 40 * self.marketing;
+ };
+ self.getScore = function () {
+ // Score: cash + revenue - expenses
+ return self.cash + self.getRevenue() - self.getExpenses();
+ };
+ self.attachVisuals = function () {
+ var assetId = self.isRival ? 'rivalOffice' : 'office';
+ var officeAsset = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.officeAsset = officeAsset;
+ };
+ self.flash = function (color) {
+ LK.effects.flashObject(self, color, 600);
+ };
+ self.attachVisuals();
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xf4f6fa
+});
+
+/****
+* Game Code
+****/
+// Event icon
+// Expand icon
+// Marketing icon
+// Upgrade icon
+// Employee icon
+// Rival office
+// Office (main player asset)
+// --- Game State ---
+var round = 1;
+var maxRounds = 30;
+var milestoneCash = 10000;
+var milestoneEmployees = 15;
+var milestoneLevel = 5;
+var player, rival;
+var actionButtons = [];
+var infoTexts = {};
+var eventPopup = null;
+var isActionPhase = true;
+var lastEvent = null;
+var gameOver = false;
+// --- UI Setup ---
+// Info text for round
+var roundTxt = new Text2('Round 1', {
+ size: 80,
+ fill: "#222"
+});
+roundTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(roundTxt);
+// Player cash
+var cashTxt = new Text2('$1000', {
+ size: 60,
+ fill: 0x2ECC71
+});
+cashTxt.anchor.set(0.5, 0);
+cashTxt.y = 90;
+LK.gui.top.addChild(cashTxt);
+// Rival progress
+var rivalTxt = new Text2('Rival: $1000', {
+ size: 48,
+ fill: 0xE74C3C
+});
+rivalTxt.anchor.set(0.5, 0);
+rivalTxt.y = 160;
+LK.gui.top.addChild(rivalTxt);
+// --- Offices ---
+player = new Office();
+player.x = 2048 / 2 - 400;
+player.y = 1100;
+game.addChild(player);
+rival = new Office();
+rival.isRival = true;
+rival.x = 2048 / 2 + 400;
+rival.y = 1100;
+game.addChild(rival);
+// --- Action Buttons ---
+var actions = [{
+ type: 'hire',
+ label: 'Hire',
+ icon: 'employee'
+}, {
+ type: 'upgrade',
+ label: 'Upgrade',
+ icon: 'upgrade'
+}, {
+ type: 'marketing',
+ label: 'Marketing',
+ icon: 'marketing'
+}, {
+ type: 'expand',
+ label: 'Expand',
+ icon: 'expand'
+}];
+for (var i = 0; i < actions.length; i++) {
+ var ab = new ActionButton();
+ ab.init(actions[i].type, actions[i].label, actions[i].icon, handleAction);
+ ab.x = 2048 / 2 - 300 + i * 200;
+ ab.y = 1800;
+ game.addChild(ab);
+ actionButtons.push(ab);
+}
+// --- Info Texts (player stats) ---
+var statsTxt = new Text2('', {
+ size: 48,
+ fill: 0x34495E
+});
+statsTxt.anchor.set(0.5, 0);
+statsTxt.x = 2048 / 2 - 400;
+statsTxt.y = 1350;
+game.addChild(statsTxt);
+var rivalStatsTxt = new Text2('', {
+ size: 48,
+ fill: 0xC0392B
+});
+rivalStatsTxt.anchor.set(0.5, 0);
+rivalStatsTxt.x = 2048 / 2 + 400;
+rivalStatsTxt.y = 1350;
+game.addChild(rivalStatsTxt);
+// --- Event Popup (hidden by default) ---
+function showEventPopup(text, onAcknowledge) {
+ if (eventPopup) eventPopup.destroy();
+ eventPopup = new EventPopup();
+ eventPopup.init(text, onAcknowledge);
+ eventPopup.x = 2048 / 2;
+ eventPopup.y = 900;
+ game.addChild(eventPopup);
+}
+// --- Game Logic ---
+function updateUI() {
+ roundTxt.setText('Round ' + round);
+ cashTxt.setText('$' + player.cash);
+ rivalTxt.setText('Rival: $' + rival.cash);
+ statsTxt.setText('Lvl: ' + player.level + ' Emp: ' + player.employees + ' Upg: ' + player.upgrades + ' Mkt: ' + player.marketing + '\nRevenue: $' + player.getRevenue() + ' Expenses: $' + player.getExpenses());
+ rivalStatsTxt.setText('Lvl: ' + rival.level + ' Emp: ' + rival.employees + ' Upg: ' + rival.upgrades + ' Mkt: ' + rival.marketing + '\nRevenue: $' + rival.getRevenue() + ' Expenses: $' + rival.getExpenses());
+}
+function handleAction(actionType) {
+ if (!isActionPhase || gameOver) return;
+ var cost = 0;
+ var msg = '';
+ if (actionType === 'hire') {
+ cost = 300 + 50 * player.employees;
+ if (player.cash >= cost) {
+ player.employees += 1;
+ player.cash -= cost;
+ msg = 'Hired 1 employee for $' + cost + '!';
+ } else {
+ msg = 'Not enough cash to hire!';
+ }
+ } else if (actionType === 'upgrade') {
+ cost = 500 + 100 * player.upgrades;
+ if (player.cash >= cost) {
+ player.upgrades += 1;
+ player.cash -= cost;
+ msg = 'Upgraded efficiency for $' + cost + '!';
+ } else {
+ msg = 'Not enough cash to upgrade!';
+ }
+ } else if (actionType === 'marketing') {
+ cost = 400 + 80 * player.marketing;
+ if (player.cash >= cost) {
+ player.marketing += 1;
+ player.cash -= cost;
+ msg = 'Launched marketing for $' + cost + '!';
+ } else {
+ msg = 'Not enough cash for marketing!';
+ }
+ } else if (actionType === 'expand') {
+ cost = 1000 + 200 * player.level;
+ if (player.cash >= cost) {
+ player.level += 1;
+ player.cash -= cost;
+ msg = 'Expanded office for $' + cost + '!';
+ } else {
+ msg = 'Not enough cash to expand!';
+ }
+ }
+ updateUI();
+ if (msg) {
+ player.flash(0x2ecc71);
+ showEventPopup(msg, function () {
+ isActionPhase = false;
+ nextPhase();
+ });
+ }
+}
+function nextPhase() {
+ // After action, process round: revenue, expenses, events, rival
+ if (gameOver) return;
+ // 1. Player revenue/expenses
+ var revenue = player.getRevenue();
+ var expenses = player.getExpenses();
+ player.cash += revenue - expenses;
+ // 2. Rival AI: simple catch-up logic
+ var rivalAction = Math.floor(Math.random() * 4);
+ if (rivalAction === 0) {
+ rival.employees += 1;
+ } else if (rivalAction === 1) {
+ rival.upgrades += 1;
+ } else if (rivalAction === 2) {
+ rival.marketing += 1;
+ } else if (rivalAction === 3) {
+ rival.level += 1;
+ }
+ rival.cash += rival.getRevenue() - rival.getExpenses();
+ // 3. Random event
+ var eventRoll = Math.random();
+ var eventMsg = '';
+ var eventEffect = null;
+ if (eventRoll < 0.18) {
+ // Good event
+ var bonus = 400 + Math.floor(Math.random() * 200);
+ eventMsg = 'Viral Success! You gain $' + bonus;
+ eventEffect = function eventEffect() {
+ player.cash += bonus;
+ };
+ } else if (eventRoll < 0.36) {
+ // Bad event
+ var loss = 300 + Math.floor(Math.random() * 200);
+ eventMsg = 'Unexpected Expense! Lose $' + loss;
+ eventEffect = function eventEffect() {
+ player.cash -= loss;
+ };
+ } else if (eventRoll < 0.48) {
+ // Neutral event
+ eventMsg = 'Market is stable. No major events this round.';
+ eventEffect = function eventEffect() {};
+ } else if (eventRoll < 0.60) {
+ // Rival gets boost
+ var rivalBonus = 400 + Math.floor(Math.random() * 200);
+ eventMsg = 'Rival gets a boost! Rival gains $' + rivalBonus;
+ eventEffect = function eventEffect() {
+ rival.cash += rivalBonus;
+ };
+ } else if (eventRoll < 0.70) {
+ // Employee leaves
+ if (player.employees > 1) {
+ eventMsg = 'An employee left! -1 employee';
+ eventEffect = function eventEffect() {
+ player.employees -= 1;
+ };
+ }
+ } else if (eventRoll < 0.80) {
+ // Free upgrade
+ eventMsg = 'Efficiency breakthrough! Free upgrade!';
+ eventEffect = function eventEffect() {
+ player.upgrades += 1;
+ };
+ } else if (eventRoll < 0.90) {
+ // Rival loses cash
+ var rivalLoss = 300 + Math.floor(Math.random() * 200);
+ eventMsg = 'Rival faces setback! Rival loses $' + rivalLoss;
+ eventEffect = function eventEffect() {
+ rival.cash -= rivalLoss;
+ };
+ } else {
+ // Nothing
+ eventMsg = 'Quiet round. Focus on your strategy!';
+ eventEffect = function eventEffect() {};
+ }
+ // 4. Update UI and show event
+ updateUI();
+ // 5. Check for win/lose
+ var win = false,
+ lose = false,
+ winMsg = '',
+ loseMsg = '';
+ if (player.cash >= milestoneCash || player.employees >= milestoneEmployees || player.level >= milestoneLevel) {
+ win = true;
+ winMsg = 'Congratulations! You built a market leader startup!';
+ } else if (player.cash < 0) {
+ lose = true;
+ loseMsg = 'You went bankrupt! Game Over.';
+ } else if (rival.cash >= milestoneCash || rival.employees >= milestoneEmployees || rival.level >= milestoneLevel) {
+ lose = true;
+ loseMsg = 'Rival overtook you! Game Over.';
+ } else if (round >= maxRounds) {
+ if (player.cash > rival.cash) {
+ win = true;
+ winMsg = 'You survived 30 rounds and outperformed your rival!';
+ } else {
+ lose = true;
+ loseMsg = 'Rival outperformed you after 30 rounds!';
+ }
+ }
+ if (win) {
+ gameOver = true;
+ LK.showYouWin();
+ return;
+ }
+ if (lose) {
+ gameOver = true;
+ LK.showGameOver();
+ return;
+ }
+ // 6. Show event popup, then advance round
+ showEventPopup(eventMsg, function () {
+ if (typeof eventEffect === 'function') eventEffect();
+ round += 1;
+ updateUI();
+ isActionPhase = true;
+ });
+}
+// --- Game Update Loop ---
+game.update = function () {
+ // No per-frame logic needed for MVP
+};
+// --- Start Game ---
+updateUI();
+isActionPhase = true;
\ No newline at end of file