/****
* 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