/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, lastGameScore: 0 }); /**** * Classes ****/ var BuildingCard = Container.expand(function (buildingType, cost, resourceDelta) { var self = Container.call(this); self.buildingType = buildingType; self.cost = cost; self.resourceDelta = resourceDelta; var cardBg = self.attachAsset('cardBackground', { anchorX: 0.5, anchorY: 0.5 }); var building = self.attachAsset(buildingType, { anchorX: 0.5, anchorY: 0.5, y: -30, scale: 0.8 }); var costText = new Text2(cost + "c", { size: 32, fill: 0x000000 }); costText.anchor.set(0.5, 0.5); costText.y = 40; self.addChild(costText); var resourceInfo = new Text2("", { size: 24, fill: 0x000000 }); resourceInfo.anchor.set(0.5, 0.5); resourceInfo.y = 70; if (resourceDelta.population) { resourceInfo.setText("P:" + (resourceDelta.population > 0 ? "+" : "") + resourceDelta.population); } else if (resourceDelta.income) { resourceInfo.setText("$:" + (resourceDelta.income > 0 ? "+" : "") + resourceDelta.income); } else if (resourceDelta.happiness) { resourceInfo.setText("H:" + (resourceDelta.happiness > 0 ? "+" : "") + resourceDelta.happiness); } self.addChild(resourceInfo); self.setEnabled = function (enabled) { if (enabled) { tween(self, { alpha: 1 }, { duration: 200 }); } else { tween(self, { alpha: 0.5 }, { duration: 200 }); } }; self.down = function (x, y, obj) { if (coins >= self.cost) { selectBuildingType(self.buildingType); } else { // Indicate not enough resources tween(self, { y: self.y + 10 }, { duration: 100, onFinish: function onFinish() { tween(self, { y: self.y - 10 }, { duration: 100 }); } }); LK.getSound('alert').play(); } }; return self; }); var BuildingSpot = Container.expand(function () { var self = Container.call(this); self.type = null; self.building = null; self.isOccupied = false; var spotGraphic = self.attachAsset('buildingSpot', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); self.highlight = function () { tween(spotGraphic, { alpha: 0.8 }, { duration: 200 }); }; self.unhighlight = function () { tween(spotGraphic, { alpha: 0.5 }, { duration: 200 }); }; self.placeBuilding = function (buildingType) { if (self.isOccupied) { return false; } self.type = buildingType; self.isOccupied = true; var building = LK.getAsset(buildingType, { anchorX: 0.5, anchorY: 0.5, scale: 0.9 }); tween(building, { scale: 1 }, { duration: 300, easing: tween.elasticOut }); self.building = self.addChild(building); LK.getSound('build').play(); return true; }; self.removeBuilding = function () { if (!self.isOccupied) { return false; } if (self.building) { tween(self.building, { alpha: 0, scale: 0.5 }, { duration: 200, onFinish: function onFinish() { self.removeChild(self.building); self.building = null; } }); } self.type = null; self.isOccupied = false; return true; }; self.down = function (x, y, obj) { if (currentBuildingType && !self.isOccupied) { if (self.placeBuilding(currentBuildingType)) { updateResources(currentBuildingType); updateScore(); } } else if (self.isOccupied && isDeleteMode) { if (self.removeBuilding()) { refundBuilding(self.type); updateScore(); } } }; return self; }); var Button = Container.expand(function (assetId, label, callback) { var self = Container.call(this); var buttonGraphic = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); if (label) { var buttonText = new Text2(label, { size: 40, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); } self.down = function (x, y, obj) { tween(self, { scale: 0.9 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { scale: 1 }, { duration: 100, onFinish: function onFinish() { if (callback) { callback(); } } }); }; return self; }); var EventPopup = Container.expand(function (eventTitle, description, effect) { var self = Container.call(this); var background = self.attachAsset('actionPanel', { anchorX: 0.5, anchorY: 0.5, width: 1000, height: 600, alpha: 0.9 }); var title = new Text2(eventTitle, { size: 60, fill: 0xFFFFFF }); title.anchor.set(0.5, 0); title.y = -200; self.addChild(title); var desc = new Text2(description, { size: 40, fill: 0xFFFFFF, align: "center", wordWrap: true, wordWrapWidth: 800 }); desc.anchor.set(0.5, 0.5); desc.y = 0; self.addChild(desc); var okButton = new Button('plusButton', "OK", function () { effect(); tween(self, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { game.removeChild(self); isGamePaused = false; } }); }); okButton.y = 200; self.addChild(okButton); self.show = function () { self.alpha = 0; self.scale = 0.5; isGamePaused = true; tween(self, { alpha: 1, scale: 1 }, { duration: 500, easing: tween.elasticOut }); LK.getSound('alert').play(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game state variables var coins = 500; var population = 0; var happiness = 50; var income = 0; var dayCount = 1; var gameScore = 0; var isDeleteMode = false; var currentBuildingType = null; var isGamePaused = false; var nextEventDay = 5; // Grid configuration var gridSize = 5; var gridSpacing = 180; var gridOffsetX = 2048 / 2 - (gridSize - 1) * gridSpacing / 2; var gridOffsetY = 2732 / 2 - (gridSize - 1) * gridSpacing / 2 - 200; var buildingSpots = []; // Building types and costs var buildingData = { 'residential': { cost: 100, resourceDelta: { population: 10, income: 5, happiness: 0 } }, 'commercial': { cost: 150, resourceDelta: { population: 0, income: 20, happiness: 5 } }, 'industrial': { cost: 200, resourceDelta: { population: -5, income: 30, happiness: -10 } }, 'special': { cost: 300, resourceDelta: { population: 5, income: 10, happiness: 15 } } }; // Game events var gameEvents = [{ title: "Economic Boom", description: "The economy is thriving! All commercial buildings generate more income.", effect: function effect() { var extraIncome = 0; buildingSpots.forEach(function (spot) { if (spot.type === 'commercial') { extraIncome += 10; } }); coins += extraIncome; updateResourceDisplay(); if (extraIncome > 0) { LK.getSound('coin').play(); } } }, { title: "Population Increase", description: "The city is attracting new residents! Population growth is accelerated.", effect: function effect() { var populationBoost = Math.floor(population * 0.2); population += populationBoost; updateResourceDisplay(); } }, { title: "Urban Planning Challenge", description: "City officials are challenging you to improve citizen happiness.", effect: function effect() { happiness = Math.max(10, happiness - 20); updateResourceDisplay(); } }, { title: "Resource Shortage", description: "A temporary resource shortage has affected industrial production.", effect: function effect() { var incomeReduction = 0; buildingSpots.forEach(function (spot) { if (spot.type === 'industrial') { incomeReduction += 10; } }); income = Math.max(0, income - incomeReduction); updateResourceDisplay(); } }]; // Create building grid function createBuildingGrid() { for (var y = 0; y < gridSize; y++) { for (var x = 0; x < gridSize; x++) { var spot = new BuildingSpot(); spot.x = gridOffsetX + x * gridSpacing; spot.y = gridOffsetY + y * gridSpacing; game.addChild(spot); buildingSpots.push(spot); } } } // Create UI elements var coinsText = new Text2("Coins: " + coins, { size: 40, fill: 0xFFFFFF }); coinsText.anchor.set(0, 0); LK.gui.topRight.addChild(coinsText); coinsText.x = -300; coinsText.y = 20; var populationText = new Text2("Pop: " + population, { size: 40, fill: 0xFFFFFF }); populationText.anchor.set(0, 0); LK.gui.topRight.addChild(populationText); populationText.x = -300; populationText.y = 70; var happinessText = new Text2("Happiness: " + happiness + "%", { size: 40, fill: 0xFFFFFF }); happinessText.anchor.set(0, 0); LK.gui.topRight.addChild(happinessText); happinessText.x = -300; happinessText.y = 120; var incomeText = new Text2("Income: " + income + "/day", { size: 40, fill: 0xFFFFFF }); incomeText.anchor.set(0, 0); LK.gui.topRight.addChild(incomeText); incomeText.x = -300; incomeText.y = 170; var dayText = new Text2("Day: " + dayCount, { size: 40, fill: 0xFFFFFF }); dayText.anchor.set(0, 0); LK.gui.topLeft.addChild(dayText); dayText.x = 120; dayText.y = 20; var scoreText = new Text2("Score: " + gameScore, { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topLeft.addChild(scoreText); scoreText.x = 120; scoreText.y = 70; // Create action panel at the bottom var actionPanel = LK.getAsset('actionPanel', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 250 }); actionPanel.y = 2732 - 125; actionPanel.x = 2048 / 2; game.addChild(actionPanel); // Create building cards var cardSpacing = 180; var cardsStartX = 2048 / 2 - (Object.keys(buildingData).length - 1) * cardSpacing / 2; var buildingCards = []; var cardIndex = 0; for (var type in buildingData) { var card = new BuildingCard(type, buildingData[type].cost, buildingData[type].resourceDelta); card.x = cardsStartX + cardIndex * cardSpacing; card.y = 2732 - 125; game.addChild(card); buildingCards.push(card); cardIndex++; } // Create delete mode button var deleteButton = new Button('deleteButton', "X", function () { isDeleteMode = !isDeleteMode; currentBuildingType = null; if (isDeleteMode) { deleteButton.scale = 1.2; } else { deleteButton.scale = 1.0; } updateBuildingCardHighlights(); }); deleteButton.x = 2048 - 100; deleteButton.y = 2732 - 125; game.addChild(deleteButton); // Create end day button var endDayButton = new Button('plusButton', "End Day", function () { if (isGamePaused) { return; } processDayEnd(); }); endDayButton.x = 100; endDayButton.y = 2732 - 125; game.addChild(endDayButton); // Game logic functions function selectBuildingType(type) { isDeleteMode = false; deleteButton.scale = 1.0; currentBuildingType = type; updateBuildingCardHighlights(); } function updateBuildingCardHighlights() { buildingCards.forEach(function (card) { if (currentBuildingType === card.buildingType) { tween(card, { scale: 1.2 }, { duration: 200 }); } else { tween(card, { scale: 1.0 }, { duration: 200 }); } }); } function updateResources(buildingType) { var data = buildingData[buildingType]; // Deduct cost coins -= data.cost; // Apply resource changes if (data.resourceDelta.population) { population += data.resourceDelta.population; } if (data.resourceDelta.income) { income += data.resourceDelta.income; } if (data.resourceDelta.happiness) { happiness += data.resourceDelta.happiness; happiness = Math.max(0, Math.min(100, happiness)); } updateResourceDisplay(); } function refundBuilding(buildingType) { var data = buildingData[buildingType]; // Refund partial cost coins += Math.floor(data.cost * 0.7); // Revert resource changes if (data.resourceDelta.population) { population -= data.resourceDelta.population; population = Math.max(0, population); } if (data.resourceDelta.income) { income -= data.resourceDelta.income; income = Math.max(0, income); } if (data.resourceDelta.happiness) { happiness -= data.resourceDelta.happiness; happiness = Math.max(0, Math.min(100, happiness)); } updateResourceDisplay(); } function updateResourceDisplay() { coinsText.setText("Coins: " + coins); populationText.setText("Pop: " + population); happinessText.setText("Happiness: " + happiness + "%"); incomeText.setText("Income: " + income + "/day"); dayText.setText("Day: " + dayCount); // Update card enabled states based on available coins buildingCards.forEach(function (card) { card.setEnabled(coins >= card.cost); }); } function updateScore() { // Calculate score based on city metrics gameScore = Math.floor(population * 2 + income * 10 + happiness * 5 + coins / 10); scoreText.setText("Score: " + gameScore); } function processDayEnd() { // Apply income coins += income; // Happiness effect on population if (happiness > 70) { // Population growth with high happiness population += Math.max(1, Math.floor(population * 0.05)); } else if (happiness < 30 && population > 0) { // Population decline with low happiness population -= Math.max(1, Math.floor(population * 0.03)); } // Happiness normalizes slightly over time if (happiness < 50) { happiness += 1; } else if (happiness > 50) { happiness -= 1; } // Increment day counter dayCount++; // Check for random events if (dayCount === nextEventDay) { triggerRandomEvent(); nextEventDay += Math.floor(Math.random() * 5) + 3; // Next event in 3-7 days } // Update displays updateResourceDisplay(); updateScore(); // Check game over conditions if (population <= 0 && coins < buildingData['residential'].cost) { LK.effects.flashScreen(0xFF0000, 1000); storage.lastGameScore = gameScore; if (gameScore > storage.highScore) { storage.highScore = gameScore; } LK.showGameOver(); } // Win condition: reach 1000 population with 80+ happiness if (population >= 1000 && happiness >= 80) { LK.effects.flashScreen(0x00FF00, 1000); storage.lastGameScore = gameScore; if (gameScore > storage.highScore) { storage.highScore = gameScore; } LK.showYouWin(); } LK.getSound('coin').play(); } function triggerRandomEvent() { var event = gameEvents[Math.floor(Math.random() * gameEvents.length)]; var popup = new EventPopup(event.title, event.description, event.effect); popup.x = 2048 / 2; popup.y = 2732 / 2; game.addChild(popup); popup.show(); } // Initialize the game createBuildingGrid(); updateResourceDisplay(); updateScore(); // Start background music LK.playMusic('bgmusic'); // Main game update function game.update = function () { if (isGamePaused) { return; } // Additional game logic that needs to run every frame would go here }; // Game event handlers game.down = function (x, y, obj) { // Handled by individual objects }; game.up = function (x, y, obj) { // Handled by individual objects }; game.move = function (x, y, obj) { // Mouse/touch movement logic };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,626 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ lastGameScore: 0
+});
+
+/****
+* Classes
+****/
+var BuildingCard = Container.expand(function (buildingType, cost, resourceDelta) {
+ var self = Container.call(this);
+ self.buildingType = buildingType;
+ self.cost = cost;
+ self.resourceDelta = resourceDelta;
+ var cardBg = self.attachAsset('cardBackground', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var building = self.attachAsset(buildingType, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -30,
+ scale: 0.8
+ });
+ var costText = new Text2(cost + "c", {
+ size: 32,
+ fill: 0x000000
+ });
+ costText.anchor.set(0.5, 0.5);
+ costText.y = 40;
+ self.addChild(costText);
+ var resourceInfo = new Text2("", {
+ size: 24,
+ fill: 0x000000
+ });
+ resourceInfo.anchor.set(0.5, 0.5);
+ resourceInfo.y = 70;
+ if (resourceDelta.population) {
+ resourceInfo.setText("P:" + (resourceDelta.population > 0 ? "+" : "") + resourceDelta.population);
+ } else if (resourceDelta.income) {
+ resourceInfo.setText("$:" + (resourceDelta.income > 0 ? "+" : "") + resourceDelta.income);
+ } else if (resourceDelta.happiness) {
+ resourceInfo.setText("H:" + (resourceDelta.happiness > 0 ? "+" : "") + resourceDelta.happiness);
+ }
+ self.addChild(resourceInfo);
+ self.setEnabled = function (enabled) {
+ if (enabled) {
+ tween(self, {
+ alpha: 1
+ }, {
+ duration: 200
+ });
+ } else {
+ tween(self, {
+ alpha: 0.5
+ }, {
+ duration: 200
+ });
+ }
+ };
+ self.down = function (x, y, obj) {
+ if (coins >= self.cost) {
+ selectBuildingType(self.buildingType);
+ } else {
+ // Indicate not enough resources
+ tween(self, {
+ y: self.y + 10
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(self, {
+ y: self.y - 10
+ }, {
+ duration: 100
+ });
+ }
+ });
+ LK.getSound('alert').play();
+ }
+ };
+ return self;
+});
+var BuildingSpot = Container.expand(function () {
+ var self = Container.call(this);
+ self.type = null;
+ self.building = null;
+ self.isOccupied = false;
+ var spotGraphic = self.attachAsset('buildingSpot', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.5
+ });
+ self.highlight = function () {
+ tween(spotGraphic, {
+ alpha: 0.8
+ }, {
+ duration: 200
+ });
+ };
+ self.unhighlight = function () {
+ tween(spotGraphic, {
+ alpha: 0.5
+ }, {
+ duration: 200
+ });
+ };
+ self.placeBuilding = function (buildingType) {
+ if (self.isOccupied) {
+ return false;
+ }
+ self.type = buildingType;
+ self.isOccupied = true;
+ var building = LK.getAsset(buildingType, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scale: 0.9
+ });
+ tween(building, {
+ scale: 1
+ }, {
+ duration: 300,
+ easing: tween.elasticOut
+ });
+ self.building = self.addChild(building);
+ LK.getSound('build').play();
+ return true;
+ };
+ self.removeBuilding = function () {
+ if (!self.isOccupied) {
+ return false;
+ }
+ if (self.building) {
+ tween(self.building, {
+ alpha: 0,
+ scale: 0.5
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ self.removeChild(self.building);
+ self.building = null;
+ }
+ });
+ }
+ self.type = null;
+ self.isOccupied = false;
+ return true;
+ };
+ self.down = function (x, y, obj) {
+ if (currentBuildingType && !self.isOccupied) {
+ if (self.placeBuilding(currentBuildingType)) {
+ updateResources(currentBuildingType);
+ updateScore();
+ }
+ } else if (self.isOccupied && isDeleteMode) {
+ if (self.removeBuilding()) {
+ refundBuilding(self.type);
+ updateScore();
+ }
+ }
+ };
+ return self;
+});
+var Button = Container.expand(function (assetId, label, callback) {
+ var self = Container.call(this);
+ var buttonGraphic = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ if (label) {
+ var buttonText = new Text2(label, {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ buttonText.anchor.set(0.5, 0.5);
+ self.addChild(buttonText);
+ }
+ self.down = function (x, y, obj) {
+ tween(self, {
+ scale: 0.9
+ }, {
+ duration: 100
+ });
+ };
+ self.up = function (x, y, obj) {
+ tween(self, {
+ scale: 1
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ if (callback) {
+ callback();
+ }
+ }
+ });
+ };
+ return self;
+});
+var EventPopup = Container.expand(function (eventTitle, description, effect) {
+ var self = Container.call(this);
+ var background = self.attachAsset('actionPanel', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 1000,
+ height: 600,
+ alpha: 0.9
+ });
+ var title = new Text2(eventTitle, {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ title.anchor.set(0.5, 0);
+ title.y = -200;
+ self.addChild(title);
+ var desc = new Text2(description, {
+ size: 40,
+ fill: 0xFFFFFF,
+ align: "center",
+ wordWrap: true,
+ wordWrapWidth: 800
+ });
+ desc.anchor.set(0.5, 0.5);
+ desc.y = 0;
+ self.addChild(desc);
+ var okButton = new Button('plusButton', "OK", function () {
+ effect();
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ game.removeChild(self);
+ isGamePaused = false;
+ }
+ });
+ });
+ okButton.y = 200;
+ self.addChild(okButton);
+ self.show = function () {
+ self.alpha = 0;
+ self.scale = 0.5;
+ isGamePaused = true;
+ tween(self, {
+ alpha: 1,
+ scale: 1
+ }, {
+ duration: 500,
+ easing: tween.elasticOut
+ });
+ LK.getSound('alert').play();
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87CEEB
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+var coins = 500;
+var population = 0;
+var happiness = 50;
+var income = 0;
+var dayCount = 1;
+var gameScore = 0;
+var isDeleteMode = false;
+var currentBuildingType = null;
+var isGamePaused = false;
+var nextEventDay = 5;
+// Grid configuration
+var gridSize = 5;
+var gridSpacing = 180;
+var gridOffsetX = 2048 / 2 - (gridSize - 1) * gridSpacing / 2;
+var gridOffsetY = 2732 / 2 - (gridSize - 1) * gridSpacing / 2 - 200;
+var buildingSpots = [];
+// Building types and costs
+var buildingData = {
+ 'residential': {
+ cost: 100,
+ resourceDelta: {
+ population: 10,
+ income: 5,
+ happiness: 0
+ }
+ },
+ 'commercial': {
+ cost: 150,
+ resourceDelta: {
+ population: 0,
+ income: 20,
+ happiness: 5
+ }
+ },
+ 'industrial': {
+ cost: 200,
+ resourceDelta: {
+ population: -5,
+ income: 30,
+ happiness: -10
+ }
+ },
+ 'special': {
+ cost: 300,
+ resourceDelta: {
+ population: 5,
+ income: 10,
+ happiness: 15
+ }
+ }
+};
+// Game events
+var gameEvents = [{
+ title: "Economic Boom",
+ description: "The economy is thriving! All commercial buildings generate more income.",
+ effect: function effect() {
+ var extraIncome = 0;
+ buildingSpots.forEach(function (spot) {
+ if (spot.type === 'commercial') {
+ extraIncome += 10;
+ }
+ });
+ coins += extraIncome;
+ updateResourceDisplay();
+ if (extraIncome > 0) {
+ LK.getSound('coin').play();
+ }
+ }
+}, {
+ title: "Population Increase",
+ description: "The city is attracting new residents! Population growth is accelerated.",
+ effect: function effect() {
+ var populationBoost = Math.floor(population * 0.2);
+ population += populationBoost;
+ updateResourceDisplay();
+ }
+}, {
+ title: "Urban Planning Challenge",
+ description: "City officials are challenging you to improve citizen happiness.",
+ effect: function effect() {
+ happiness = Math.max(10, happiness - 20);
+ updateResourceDisplay();
+ }
+}, {
+ title: "Resource Shortage",
+ description: "A temporary resource shortage has affected industrial production.",
+ effect: function effect() {
+ var incomeReduction = 0;
+ buildingSpots.forEach(function (spot) {
+ if (spot.type === 'industrial') {
+ incomeReduction += 10;
+ }
+ });
+ income = Math.max(0, income - incomeReduction);
+ updateResourceDisplay();
+ }
+}];
+// Create building grid
+function createBuildingGrid() {
+ for (var y = 0; y < gridSize; y++) {
+ for (var x = 0; x < gridSize; x++) {
+ var spot = new BuildingSpot();
+ spot.x = gridOffsetX + x * gridSpacing;
+ spot.y = gridOffsetY + y * gridSpacing;
+ game.addChild(spot);
+ buildingSpots.push(spot);
+ }
+ }
+}
+// Create UI elements
+var coinsText = new Text2("Coins: " + coins, {
+ size: 40,
+ fill: 0xFFFFFF
+});
+coinsText.anchor.set(0, 0);
+LK.gui.topRight.addChild(coinsText);
+coinsText.x = -300;
+coinsText.y = 20;
+var populationText = new Text2("Pop: " + population, {
+ size: 40,
+ fill: 0xFFFFFF
+});
+populationText.anchor.set(0, 0);
+LK.gui.topRight.addChild(populationText);
+populationText.x = -300;
+populationText.y = 70;
+var happinessText = new Text2("Happiness: " + happiness + "%", {
+ size: 40,
+ fill: 0xFFFFFF
+});
+happinessText.anchor.set(0, 0);
+LK.gui.topRight.addChild(happinessText);
+happinessText.x = -300;
+happinessText.y = 120;
+var incomeText = new Text2("Income: " + income + "/day", {
+ size: 40,
+ fill: 0xFFFFFF
+});
+incomeText.anchor.set(0, 0);
+LK.gui.topRight.addChild(incomeText);
+incomeText.x = -300;
+incomeText.y = 170;
+var dayText = new Text2("Day: " + dayCount, {
+ size: 40,
+ fill: 0xFFFFFF
+});
+dayText.anchor.set(0, 0);
+LK.gui.topLeft.addChild(dayText);
+dayText.x = 120;
+dayText.y = 20;
+var scoreText = new Text2("Score: " + gameScore, {
+ size: 40,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0, 0);
+LK.gui.topLeft.addChild(scoreText);
+scoreText.x = 120;
+scoreText.y = 70;
+// Create action panel at the bottom
+var actionPanel = LK.getAsset('actionPanel', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 2048,
+ height: 250
+});
+actionPanel.y = 2732 - 125;
+actionPanel.x = 2048 / 2;
+game.addChild(actionPanel);
+// Create building cards
+var cardSpacing = 180;
+var cardsStartX = 2048 / 2 - (Object.keys(buildingData).length - 1) * cardSpacing / 2;
+var buildingCards = [];
+var cardIndex = 0;
+for (var type in buildingData) {
+ var card = new BuildingCard(type, buildingData[type].cost, buildingData[type].resourceDelta);
+ card.x = cardsStartX + cardIndex * cardSpacing;
+ card.y = 2732 - 125;
+ game.addChild(card);
+ buildingCards.push(card);
+ cardIndex++;
+}
+// Create delete mode button
+var deleteButton = new Button('deleteButton', "X", function () {
+ isDeleteMode = !isDeleteMode;
+ currentBuildingType = null;
+ if (isDeleteMode) {
+ deleteButton.scale = 1.2;
+ } else {
+ deleteButton.scale = 1.0;
+ }
+ updateBuildingCardHighlights();
+});
+deleteButton.x = 2048 - 100;
+deleteButton.y = 2732 - 125;
+game.addChild(deleteButton);
+// Create end day button
+var endDayButton = new Button('plusButton', "End Day", function () {
+ if (isGamePaused) {
+ return;
+ }
+ processDayEnd();
+});
+endDayButton.x = 100;
+endDayButton.y = 2732 - 125;
+game.addChild(endDayButton);
+// Game logic functions
+function selectBuildingType(type) {
+ isDeleteMode = false;
+ deleteButton.scale = 1.0;
+ currentBuildingType = type;
+ updateBuildingCardHighlights();
+}
+function updateBuildingCardHighlights() {
+ buildingCards.forEach(function (card) {
+ if (currentBuildingType === card.buildingType) {
+ tween(card, {
+ scale: 1.2
+ }, {
+ duration: 200
+ });
+ } else {
+ tween(card, {
+ scale: 1.0
+ }, {
+ duration: 200
+ });
+ }
+ });
+}
+function updateResources(buildingType) {
+ var data = buildingData[buildingType];
+ // Deduct cost
+ coins -= data.cost;
+ // Apply resource changes
+ if (data.resourceDelta.population) {
+ population += data.resourceDelta.population;
+ }
+ if (data.resourceDelta.income) {
+ income += data.resourceDelta.income;
+ }
+ if (data.resourceDelta.happiness) {
+ happiness += data.resourceDelta.happiness;
+ happiness = Math.max(0, Math.min(100, happiness));
+ }
+ updateResourceDisplay();
+}
+function refundBuilding(buildingType) {
+ var data = buildingData[buildingType];
+ // Refund partial cost
+ coins += Math.floor(data.cost * 0.7);
+ // Revert resource changes
+ if (data.resourceDelta.population) {
+ population -= data.resourceDelta.population;
+ population = Math.max(0, population);
+ }
+ if (data.resourceDelta.income) {
+ income -= data.resourceDelta.income;
+ income = Math.max(0, income);
+ }
+ if (data.resourceDelta.happiness) {
+ happiness -= data.resourceDelta.happiness;
+ happiness = Math.max(0, Math.min(100, happiness));
+ }
+ updateResourceDisplay();
+}
+function updateResourceDisplay() {
+ coinsText.setText("Coins: " + coins);
+ populationText.setText("Pop: " + population);
+ happinessText.setText("Happiness: " + happiness + "%");
+ incomeText.setText("Income: " + income + "/day");
+ dayText.setText("Day: " + dayCount);
+ // Update card enabled states based on available coins
+ buildingCards.forEach(function (card) {
+ card.setEnabled(coins >= card.cost);
+ });
+}
+function updateScore() {
+ // Calculate score based on city metrics
+ gameScore = Math.floor(population * 2 + income * 10 + happiness * 5 + coins / 10);
+ scoreText.setText("Score: " + gameScore);
+}
+function processDayEnd() {
+ // Apply income
+ coins += income;
+ // Happiness effect on population
+ if (happiness > 70) {
+ // Population growth with high happiness
+ population += Math.max(1, Math.floor(population * 0.05));
+ } else if (happiness < 30 && population > 0) {
+ // Population decline with low happiness
+ population -= Math.max(1, Math.floor(population * 0.03));
+ }
+ // Happiness normalizes slightly over time
+ if (happiness < 50) {
+ happiness += 1;
+ } else if (happiness > 50) {
+ happiness -= 1;
+ }
+ // Increment day counter
+ dayCount++;
+ // Check for random events
+ if (dayCount === nextEventDay) {
+ triggerRandomEvent();
+ nextEventDay += Math.floor(Math.random() * 5) + 3; // Next event in 3-7 days
+ }
+ // Update displays
+ updateResourceDisplay();
+ updateScore();
+ // Check game over conditions
+ if (population <= 0 && coins < buildingData['residential'].cost) {
+ LK.effects.flashScreen(0xFF0000, 1000);
+ storage.lastGameScore = gameScore;
+ if (gameScore > storage.highScore) {
+ storage.highScore = gameScore;
+ }
+ LK.showGameOver();
+ }
+ // Win condition: reach 1000 population with 80+ happiness
+ if (population >= 1000 && happiness >= 80) {
+ LK.effects.flashScreen(0x00FF00, 1000);
+ storage.lastGameScore = gameScore;
+ if (gameScore > storage.highScore) {
+ storage.highScore = gameScore;
+ }
+ LK.showYouWin();
+ }
+ LK.getSound('coin').play();
+}
+function triggerRandomEvent() {
+ var event = gameEvents[Math.floor(Math.random() * gameEvents.length)];
+ var popup = new EventPopup(event.title, event.description, event.effect);
+ popup.x = 2048 / 2;
+ popup.y = 2732 / 2;
+ game.addChild(popup);
+ popup.show();
+}
+// Initialize the game
+createBuildingGrid();
+updateResourceDisplay();
+updateScore();
+// Start background music
+LK.playMusic('bgmusic');
+// Main game update function
+game.update = function () {
+ if (isGamePaused) {
+ return;
+ }
+ // Additional game logic that needs to run every frame would go here
+};
+// Game event handlers
+game.down = function (x, y, obj) {
+ // Handled by individual objects
+};
+game.up = function (x, y, obj) {
+ // Handled by individual objects
+};
+game.move = function (x, y, obj) {
+ // Mouse/touch movement logic
+};
\ No newline at end of file