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