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