/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
money: 200,
hoeLevel: 1,
wateringCanLevel: 1,
harvesterLevel: 1,
unlockedPlots: 2,
maxPlots: 36,
experience: 0,
level: 1,
nextLevelExp: 100,
harvested: {}
});
/****
* Classes
****/
var CoinEffect = Container.expand(function () {
var self = Container.call(this);
var coinGraphic = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.animate = function (startX, startY) {
self.x = startX;
self.y = startY;
self.alpha = 1;
game.addChild(self);
// Animate coin floating up and fading out
tween(self, {
y: startY - 100,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(self);
coinEffectsPool.push(self);
}
});
};
return self;
});
var ExperienceBar = Container.expand(function () {
var self = Container.call(this);
// Background for the experience bar
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 0.5
});
background.tint = 0x333333;
// Create the fill bar (progress)
self.fillBar = self.attachAsset('button', {
anchorX: 0,
anchorY: 0.5,
scaleX: 0,
scaleY: 0.3,
x: -background.width / 2
});
self.fillBar.tint = 0x4CAF50; // Green for experience
// Level text
self.levelText = new Text2("Level 1", {
size: 38,
fill: 0xFFFFFF
});
self.levelText.anchor.set(0.5, 0.5);
self.levelText.y = -20;
self.addChild(self.levelText);
// Experience text
self.expText = new Text2("0/100 XP", {
size: 32,
fill: 0xFFFFFF
});
self.expText.anchor.set(0.5, 0.5);
self.expText.y = 5;
self.addChild(self.expText);
// Update experience bar display
self.updateExp = function (exp, nextLevel, level) {
var percentage = Math.min(1, exp / nextLevel);
self.fillBar.scaleX = percentage * background.width / 100;
self.expText.setText(exp + "/" + nextLevel + " XP");
self.levelText.setText("Level " + level);
};
return self;
});
var HarvestButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0x32CD32; // Lime green
// Add stats icon using the new asset
var statsIcon = self.attachAsset('icon-stats', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
y: -18
});
// statsIcon.tint = 0xF5DEB3; // Optional: Remove or adjust tint if needed for the new icon
var titleText = new Text2("Stats", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleHarvestPanel();
};
return self;
});
var HarvestTracker = Container.expand(function () {
var self = Container.call(this);
// Track harvested crops
self.harvested = {
"carrot": 0,
"tomato": 0,
"wheat": 0,
"total": 0
};
// Visual elements
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 4
});
background.tint = 0x333333;
background.alpha = 0.9;
var titleText = new Text2("Harvest Statistics", {
size: 80,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0);
titleText.y = -140;
self.addChild(titleText);
// Container for harvest counts
self.harvestContainer = new Container();
self.addChild(self.harvestContainer);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 250;
closeButton.y = -140;
closeButton.down = function () {
toggleHarvestPanel();
};
self.addChild(closeButton);
// Track a new harvested crop
self.trackHarvest = function (type) {
if (self.harvested.hasOwnProperty(type)) {
self.harvested[type]++;
self.harvested.total++;
// Store the data in storage
storage.harvested = self.harvested;
self.updateDisplay();
return true;
}
return false;
};
// Update the visual display
self.updateDisplay = function () {
// Clear current display
while (self.harvestContainer.children.length > 0) {
self.harvestContainer.removeChild(self.harvestContainer.children[0]);
}
var yPos = -70;
var spacing = 70;
// Add each crop type
for (var cropType in self.harvested) {
if (cropType === "total") {
continue;
} // Skip the total counter for display
var container = new Container();
// Create background for each crop entry
var entryBg = container.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 0.7,
alpha: 0.3
});
entryBg.tint = 0x666666;
// Crop icon
var cropIcon = container.attachAsset('crop-mature', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
x: -120
});
// Crop color based on type
if (cropType === "carrot") {
cropIcon.tint = 0xFF9900;
} else if (cropType === "tomato") {
cropIcon.tint = 0xFF3333;
} else if (cropType === "wheat") {
cropIcon.tint = 0xF5DEB3;
}
// Crop name and count
var text = new Text2(cropType + ": " + self.harvested[cropType], {
size: 54,
fill: 0xFFFFFF
});
text.anchor.set(0, 0.5);
text.x = -70;
container.addChild(text);
container.y = yPos;
yPos += spacing;
self.harvestContainer.addChild(container);
}
// Add total harvested
var totalContainer = new Container();
var totalBg = totalContainer.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 0.7,
alpha: 0.5
});
totalBg.tint = 0x444444;
var totalText = new Text2("Total Harvested: " + self.harvested.total, {
size: 54,
fill: 0xFFFF00
});
totalText.anchor.set(0.5, 0.5);
totalContainer.addChild(totalText);
totalContainer.y = yPos + 20;
self.harvestContainer.addChild(totalContainer);
};
// Initialize from stored data
if (storage.harvested) {
self.harvested = storage.harvested;
}
// Initialize display
self.updateDisplay();
return self;
});
var Inventory = Container.expand(function () {
var self = Container.call(this);
self.seeds = {
"carrot": 0,
"tomato": 0,
"wheat": 0
};
// Visual elements
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 4
});
background.tint = 0x333333;
background.alpha = 0.9;
var titleText = new Text2("Seeds Inventory", {
size: 80,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0);
titleText.y = -140;
self.addChild(titleText);
// Container for seed counts
self.seedCountContainer = new Container();
self.addChild(self.seedCountContainer);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 250;
closeButton.y = -140;
closeButton.down = function () {
toggleInventoryPanel();
};
self.addChild(closeButton);
// Add seed to inventory
self.addSeed = function (type, amount) {
if (self.seeds.hasOwnProperty(type)) {
self.seeds[type] += amount;
self.updateDisplay();
return true;
}
return false;
};
// Remove seed from inventory
self.removeSeed = function (type, amount) {
if (self.seeds.hasOwnProperty(type) && self.seeds[type] >= amount) {
self.seeds[type] -= amount;
self.updateDisplay();
return true;
}
return false;
};
// Check if player has enough seeds
self.hasSeed = function (type, amount) {
return self.seeds.hasOwnProperty(type) && self.seeds[type] >= amount;
};
// Update the visual display
self.updateDisplay = function () {
// Clear current display
while (self.seedCountContainer.children.length > 0) {
self.seedCountContainer.removeChild(self.seedCountContainer.children[0]);
}
var yPos = -70;
var spacing = 70;
// Add each seed type
for (var seedType in self.seeds) {
var container = new Container();
// Create background for each seed entry
var entryBg = container.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 0.7,
alpha: 0.3
});
entryBg.tint = 0x666666;
// Seed icon
var seedIcon = container.attachAsset('crop-seed', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
x: -120
});
// Seed color based on type
if (seedType === "carrot") {
seedIcon.tint = 0xFF9900;
} else if (seedType === "tomato") {
seedIcon.tint = 0xFF3333;
} else if (seedType === "wheat") {
seedIcon.tint = 0xF5DEB3;
}
// Seed name and count
var text = new Text2(seedType + ": " + self.seeds[seedType], {
size: 54,
fill: 0xFFFFFF
});
text.anchor.set(0, 0.5);
text.x = -70;
container.addChild(text);
container.y = yPos;
yPos += spacing;
self.seedCountContainer.addChild(container);
}
};
// Initialize display
self.updateDisplay();
return self;
});
var InventoryButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0x8B4513; // Brown for inventory button
// Add seeds icon using the new asset
var seedsIcon = self.attachAsset('icon-seeds', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
y: -18
});
// seedsIcon.tint = 0xF5DEB3; // Optional: Remove or adjust tint if needed for the new icon
var titleText = new Text2("Seeds", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleInventoryPanel();
};
return self;
});
var Plot = Container.expand(function () {
var self = Container.call(this);
self.state = "empty"; // empty, seeded, growing, ready
self.growthProgress = 0;
self.growthRequired = 100;
self.value = 10;
self.unlocked = false;
self.isWatered = false; // Track if the plot is currently watered
self.waterDuration = 0; // How long the water effect lasts
var plotBackground = self.attachAsset('plot', {
anchorX: 0.5,
anchorY: 0.5
});
var soilGraphic = self.attachAsset('soil', {
anchorX: 0.5,
anchorY: 0.5
});
// The crop that shows on this plot
self.cropGraphic = null;
self.unlock = function () {
self.unlocked = true;
plotBackground.alpha = 1;
soilGraphic.alpha = 1;
};
self.lock = function () {
self.unlocked = false;
plotBackground.alpha = 0.3;
soilGraphic.alpha = 0.3;
self.clearCrop();
};
self.clearCrop = function () {
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
self.cropGraphic = null;
}
self.state = "empty";
self.growthProgress = 0;
};
self.plant = function () {
if (!self.unlocked || self.state !== "empty") {
return false;
}
// Check if player has seeds in inventory
if (!playerInventory.hasSeed(activeSeed, 1)) {
return false;
}
// Use seed from inventory
playerInventory.removeSeed(activeSeed, 1);
self.state = "seeded";
self.seedType = activeSeed;
self.growthProgress = 0;
// Set crop values based on seed type
if (activeSeed === "carrot") {
self.growthRequired = 80;
self.value = 15;
} else if (activeSeed === "tomato") {
self.growthRequired = 120;
self.value = 25;
} else if (activeSeed === "wheat") {
self.growthRequired = 60;
self.value = 10;
}
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
}
self.cropGraphic = self.attachAsset('crop-seed', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint the seed based on type
if (activeSeed === "carrot") {
self.cropGraphic.tint = 0xFF9900;
} else if (activeSeed === "tomato") {
self.cropGraphic.tint = 0xFF3333;
} else if (activeSeed === "wheat") {
self.cropGraphic.tint = 0xF5DEB3;
}
// Grant experience for planting
addExperience(5);
return true;
};
self.water = function () {
if (!self.unlocked || self.state !== "seeded" && self.state !== "growing") {
return false;
}
// Set watered state and duration
self.isWatered = true;
// Duration based on watering can level - better watering cans make water last longer
self.waterDuration = 300 + storage.wateringCanLevel * 120; // Use storage value directly
// Visual indication that plot is watered
soilGraphic.tint = 0x6b8cff; // Bluish tint for watered soil
return true;
};
self.harvest = function () {
if (!self.unlocked || self.state !== "ready") {
return 0;
}
// Use storage value directly for more accurate calculations
var harvestValue = self.value * (1 + (storage.harvesterLevel - 1) * 0.2);
// Add one seed of the harvested type to inventory
playerInventory.addSeed(self.seedType, 1);
// Track the harvested crop
harvestTracker.trackHarvest(self.seedType);
// Grant experience based on crop type
var expGain = 0;
if (self.seedType === "carrot") {
expGain = 10;
} else if (self.seedType === "tomato") {
expGain = 15;
} else if (self.seedType === "wheat") {
expGain = 8;
}
addExperience(expGain);
self.clearCrop();
return Math.floor(harvestValue);
};
self.update = function () {
// Handle watering duration and effect
if (self.isWatered && (self.state === "seeded" || self.state === "growing")) {
// Apply growth effect while watered
var wateringEfficiency = 5 * storage.wateringCanLevel / 60; // Use storage value directly
self.growthProgress += wateringEfficiency;
// Decrease water duration
self.waterDuration--;
// Check if water effect has ended
if (self.waterDuration <= 0) {
self.isWatered = false;
soilGraphic.tint = 0xFFFFFF; // Reset soil tint
}
// Process growth stage transitions
self.checkGrowthStages();
}
// Rain effect (now lasts longer than just one tick)
if (currentWeather === "rain" && (self.state === "seeded" || self.state === "growing")) {
// Rain automatically waters plants a little bit
if (LK.ticks % 60 === 0) {
// Every second
self.growthProgress += 1;
// If not already watered, make soil look wet
if (!self.isWatered) {
soilGraphic.tint = 0x9cb6ff; // Lighter blue tint for rain-watered soil
}
self.checkGrowthStages();
}
} else if (!self.isWatered && soilGraphic.tint !== 0xFFFFFF) {
// Reset soil tint when not raining and not manually watered
soilGraphic.tint = 0xFFFFFF;
}
};
// Helper method to check growth stages and update visuals
self.checkGrowthStages = function () {
if (self.growthProgress >= self.growthRequired / 2 && self.state === "seeded") {
self.state = "growing";
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
}
self.cropGraphic = self.attachAsset('crop-growing', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint the growing crop based on seed type
if (self.seedType === "carrot") {
self.cropGraphic.tint = 0xFF9900;
} else if (self.seedType === "tomato") {
self.cropGraphic.tint = 0xFF3333;
} else if (self.seedType === "wheat") {
self.cropGraphic.tint = 0xF5DEB3;
}
}
if (self.growthProgress >= self.growthRequired) {
self.state = "ready";
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
}
self.cropGraphic = self.attachAsset('crop-mature', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint the mature crop based on seed type
if (self.seedType === "carrot") {
self.cropGraphic.tint = 0xFF9900;
} else if (self.seedType === "tomato") {
self.cropGraphic.tint = 0xFF3333;
} else if (self.seedType === "wheat") {
self.cropGraphic.tint = 0xF5DEB3;
}
}
};
self.down = function (x, y, obj) {
if (!self.unlocked) {
return;
}
var gamePos = game.toLocal(self.parent.toGlobal(self.position));
if (activeTool === "hoe") {
// Check if player has seeds in inventory
if (playerInventory.hasSeed(activeSeed, 1)) {
if (self.plant()) {
LK.getSound('plant').play();
}
} else if (money >= seedCosts[activeSeed]) {
// If no seeds in inventory but enough money, show inventory
toggleInventoryPanel();
}
} else if (activeTool === "water") {
if (self.water()) {
LK.getSound('water').play();
}
} else if (activeTool === "harvest") {
var value = self.harvest();
if (value > 0) {
LK.getSound('harvest').play();
LK.getSound('coin').play();
updateMoney(value);
spawnCoinEffect(gamePos.x, gamePos.y);
}
}
};
// Initially plots should be locked unless specified
self.lock();
return self;
});
var SeedButton = Container.expand(function (seedType, cost) {
var self = Container.call(this);
self.seedType = seedType;
self.cost = cost;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
// Change button color to represent seed type
if (seedType === "carrot") {
background.tint = 0xFF9900;
background.alpha = 0.8;
} else if (seedType === "tomato") {
background.tint = 0xFF3333;
background.alpha = 0.8;
} else if (seedType === "wheat") {
background.tint = 0xF5DEB3;
background.alpha = 0.8;
}
var nameText = new Text2(seedType, {
size: 42,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -15;
self.addChild(nameText);
var costText = new Text2(cost + " coins", {
size: 34,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0.5);
costText.y = 15;
self.addChild(costText);
self.down = function (x, y, obj) {
if (money >= self.cost) {
// Buy seeds and add to inventory
updateMoney(-self.cost);
LK.getSound('coin').play();
playerInventory.addSeed(self.seedType, 1);
activeSeed = self.seedType;
seedButtons.forEach(function (button) {
if (button.seedType === activeSeed) {
tween(button, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeOut
});
} else {
tween(button, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
};
return self;
});
var SellCropButton = Container.expand(function (cropType, baseValue) {
var self = Container.call(this);
self.cropType = cropType;
self.baseValue = baseValue;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 1.4
});
// Change button color to represent crop type
if (cropType === "carrot") {
background.tint = 0xFF9900;
background.alpha = 0.7;
} else if (cropType === "tomato") {
background.tint = 0xFF3333;
background.alpha = 0.7;
} else if (cropType === "wheat") {
background.tint = 0xF5DEB3;
background.alpha = 0.7;
}
// Crop icon
var cropIcon = self.attachAsset('crop-mature', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
x: -120
});
// Tint the icon based on crop type
if (cropType === "carrot") {
cropIcon.tint = 0xFF9900;
} else if (cropType === "tomato") {
cropIcon.tint = 0xFF3333;
} else if (cropType === "wheat") {
cropIcon.tint = 0xF5DEB3;
}
var nameText = new Text2(cropType, {
size: 50,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -20;
nameText.x = 0;
self.addChild(nameText);
var valueText = new Text2(baseValue + " coins each", {
size: 40,
fill: 0xFFFFFF
});
valueText.anchor.set(0.5, 0.5);
valueText.y = 20;
valueText.x = 0;
self.addChild(valueText);
// Quantity counter
var quantity = 0;
var minusBtn = new Container();
var minusBg = minusBtn.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
minusBg.tint = 0x777777;
var minusText = new Text2("-", {
size: 50,
fill: 0xFFFFFF
});
minusText.anchor.set(0.5, 0.5);
minusBtn.addChild(minusText);
minusBtn.x = 80;
minusBtn.y = -20;
self.addChild(minusBtn);
var plusBtn = new Container();
var plusBg = plusBtn.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
plusBg.tint = 0x777777;
var plusText = new Text2("+", {
size: 50,
fill: 0xFFFFFF
});
plusText.anchor.set(0.5, 0.5);
plusBtn.addChild(plusText);
plusBtn.x = 160;
plusBtn.y = -20;
self.addChild(plusBtn);
var qtyText = new Text2("0", {
size: 46,
fill: 0xFFFFFF
});
qtyText.anchor.set(0.5, 0.5);
qtyText.x = 120;
qtyText.y = -20;
self.addChild(qtyText);
var sellBtn = new Container();
var sellBg = sellBtn.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.4
});
sellBg.tint = 0x4CAF50;
var sellText = new Text2("Sell", {
size: 40,
fill: 0xFFFFFF
});
sellText.anchor.set(0.5, 0.5);
sellBtn.addChild(sellText);
sellBtn.x = 120;
sellBtn.y = 20;
self.addChild(sellBtn);
minusBtn.down = function () {
if (quantity > 0) {
quantity--;
qtyText.setText(quantity.toString());
}
};
plusBtn.down = function () {
if (playerInventory.hasSeed(cropType, 1)) {
quantity++;
qtyText.setText(quantity.toString());
}
};
sellBtn.down = function () {
if (quantity > 0 && playerInventory.hasSeed(cropType, quantity)) {
playerInventory.removeSeed(cropType, quantity);
var value = baseValue * quantity;
updateMoney(value);
LK.getSound('coin').play();
// Spawn multiple coin effects for bigger sales
var effectCount = Math.min(5, Math.floor(quantity / 2) + 1);
for (var i = 0; i < effectCount; i++) {
spawnCoinEffect(game.toLocal(self.parent.toGlobal(self.position)).x, game.toLocal(self.parent.toGlobal(self.position)).y);
}
quantity = 0;
qtyText.setText("0");
}
};
return self;
});
var ShopButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0x4169E1; // Royal blue for shop button
// Add shop icon using the new asset
var shopIcon = self.attachAsset('icon-shop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
// Adjusted scale for potentially different icon size
scaleY: 0.8,
y: -18
});
var titleText = new Text2("Shop", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleShopPanel();
};
return self;
});
var ShopPanel = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
// Make it wide enough
scaleY: 8 // Make it tall enough
});
background.tint = 0x333333;
background.alpha = 0.95;
// Add decorative header bar
var headerBar = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 0.8,
y: -300
});
headerBar.tint = 0x4169E1; // Royal blue to match shop button
headerBar.alpha = 0.8;
var titleText = new Text2("Farm Shop", {
size: 90,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -300;
self.addChild(titleText);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 400;
closeButton.y = -300;
closeButton.down = function () {
toggleShopPanel();
};
self.addChild(closeButton);
// Section titles
var seedTitle = new Text2("Seeds", {
size: 60,
fill: 0xFFFF00
});
seedTitle.anchor.set(0.5, 0);
seedTitle.y = -200;
self.addChild(seedTitle);
var upgradeTitle = new Text2("Upgrades", {
size: 60,
fill: 0xFFFF00
});
upgradeTitle.anchor.set(0.5, 0);
upgradeTitle.y = 50;
self.addChild(upgradeTitle);
// Containers for each section
self.seedContainer = new Container();
self.seedContainer.y = -150;
self.addChild(self.seedContainer);
self.upgradeContainer = new Container();
self.upgradeContainer.y = 100;
self.addChild(self.upgradeContainer);
return self;
});
var StoreButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0xFFD700; // Gold color for store button
// Add store icon using the new asset
var storeIcon = self.attachAsset('icon-store', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
// Adjusted scale for potentially different icon size
scaleY: 0.8,
y: -18
});
var titleText = new Text2("Store", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleStorePanel();
};
return self;
});
var StorePanel = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 8
});
background.tint = 0x333333;
background.alpha = 0.95;
// Add decorative header bar
var headerBar = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 0.8,
y: -300
});
headerBar.tint = 0xFFD700; // Gold to match store button
headerBar.alpha = 0.8;
var titleText = new Text2("Market Store", {
size: 90,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -300;
self.addChild(titleText);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 400;
closeButton.y = -300;
closeButton.down = function () {
toggleStorePanel();
};
self.addChild(closeButton);
// Description
var descText = new Text2("Sell your harvested crops for coins!", {
size: 50,
fill: 0xFFFF00
});
descText.anchor.set(0.5, 0);
descText.y = -200;
self.addChild(descText);
// Containers for crop selling options
self.sellContainer = new Container();
self.sellContainer.y = -100;
self.addChild(self.sellContainer);
return self;
});
var ToolButton = Container.expand(function (toolType) {
var self = Container.call(this);
self.toolType = toolType;
var assetName = 'tool-' + toolType;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1
});
// Set background color based on tool type
if (toolType === "hoe") {
background.tint = 0x8B4513; // Brown
} else if (toolType === "water") {
background.tint = 0x4682B4; // Steel blue
} else if (toolType === "harvest") {
background.tint = 0xFFD700; // Gold
}
background.alpha = 0.6;
var toolGraphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
y: -15
});
var levelText = new Text2('Lv 1', {
size: 44,
fill: 0xFFFF00
});
levelText.anchor.set(0.5, 0.5);
levelText.y = 40;
self.addChild(levelText);
// Add indicator to show which tool is active
var indicator = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 0.15,
y: -70
});
indicator.tint = 0xFFFFFF;
indicator.alpha = 0; // Initially hidden
self.setActive = function (isActive) {
indicator.alpha = isActive ? 1 : 0;
tween(self, {
scaleX: isActive ? 1.2 : 1.0,
scaleY: isActive ? 1.2 : 1.0
}, {
duration: 200,
easing: tween.easeOut
});
};
self.updateLevel = function (level) {
levelText.setText('Lv ' + level);
};
self.down = function (x, y, obj) {
activeTool = self.toolType;
// Update active tool indicator for all tools
toolButtons.forEach(function (button) {
button.setActive(button.toolType === activeTool);
});
// Show active tool name
updateToolDisplay();
};
return self;
});
var UpgradeButton = Container.expand(function (upgradeType, cost) {
var self = Container.call(this);
self.upgradeType = upgradeType;
self.cost = cost;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.4,
scaleY: 1.2
});
// Set button color based on upgrade type
if (upgradeType === "hoe") {
background.tint = 0x964B00; // Brown
} else if (upgradeType === "water") {
background.tint = 0x4682B4; // Steel blue
} else if (upgradeType === "harvest") {
background.tint = 0xFFD700; // Gold
} else if (upgradeType === "plot") {
background.tint = 0x7C5837; // Earth brown
}
background.alpha = 0.8;
var title;
if (upgradeType === "hoe") {
title = "Upgrade Hoe";
} else if (upgradeType === "water") {
title = "Upgrade Watering Can";
} else if (upgradeType === "harvest") {
title = "Upgrade Harvester";
} else if (upgradeType === "plot") {
title = "Buy New Plot";
}
// Add icon for the tool being upgraded
if (upgradeType === "hoe" || upgradeType === "water" || upgradeType === "harvest") {
var toolIcon = self.attachAsset('tool-' + upgradeType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
x: -100,
y: -20
});
}
var titleText = new Text2(title, {
size: 46,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -20;
self.addChild(titleText);
var costText = new Text2(cost + " coins", {
size: 40,
fill: 0xFFFF00
});
costText.anchor.set(0.5, 0.5);
costText.y = 20;
self.addChild(costText);
self.updateCost = function (newCost) {
self.cost = newCost;
costText.setText(newCost + " coins");
};
self.down = function (x, y, obj) {
if (money >= self.cost) {
LK.getSound('upgrade').play();
updateMoney(-self.cost);
if (upgradeType === "hoe") {
// Update both the local variable and storage
hoeLevel++;
storage.hoeLevel = hoeLevel;
self.updateCost(self.cost * 2);
toolButtons[0].updateLevel(hoeLevel);
} else if (upgradeType === "water") {
wateringCanLevel++;
storage.wateringCanLevel = wateringCanLevel;
self.updateCost(self.cost * 2);
toolButtons[1].updateLevel(wateringCanLevel);
} else if (upgradeType === "harvest") {
harvesterLevel++;
storage.harvesterLevel = harvesterLevel;
self.updateCost(self.cost * 2);
toolButtons[2].updateLevel(harvesterLevel);
} else if (upgradeType === "plot") {
if (unlockedPlots < storage.maxPlots) {
unlockedPlots++;
storage.unlockedPlots = unlockedPlots;
self.updateCost(self.cost * 2);
plots[unlockedPlots - 1].unlock();
// If all plots unlocked, hide this button
if (unlockedPlots >= storage.maxPlots) {
self.visible = false;
}
}
}
}
};
return self;
});
var WeatherSystem = Container.expand(function () {
var self = Container.call(this);
self.weatherType = "sun"; // sun or rain
var gameTime = 0; // Game time in minutes (0-24)
var isDay = true;
// Create clock/calendar background
var clockBg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.9
});
clockBg.tint = 0x000066;
clockBg.alpha = 0.8;
// Create time display instead of sun
var timeBackground = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.4,
y: -5
});
timeBackground.tint = 0x000099;
var timeText = new Text2("6:00 AM", {
size: 50,
fill: 0xFFFFFF
});
timeText.anchor.set(0.5, 0.5);
timeText.y = -5;
self.addChild(timeText);
// Create weather label
var weatherLabel = new Text2("Weather:", {
size: 34,
fill: 0xFFFFFF
});
weatherLabel.anchor.set(0.5, 0.5);
weatherLabel.y = 30;
self.addChild(weatherLabel);
var rainGraphic = self.attachAsset('weather-rain', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0,
// Initially hidden
scaleX: 0.6,
scaleY: 0.6,
y: 60 // Position below time display
});
self.changeWeather = function (type) {
self.weatherType = type;
if (type === "sun") {
tween(rainGraphic, {
alpha: 0
}, {
duration: 1000
});
} else if (type === "rain") {
tween(rainGraphic, {
alpha: 1
}, {
duration: 1000
});
}
};
// Update the time display
self.updateTime = function () {
// Format time to 12-hour format with AM/PM
var hours = Math.floor(gameTime);
var minutes = Math.floor(gameTime % 1 * 60);
var period = hours >= 12 ? "PM" : "AM";
var formattedHours = hours % 12;
if (formattedHours === 0) {
formattedHours = 12;
}
var timeString = formattedHours + ":" + (minutes < 10 ? "0" : "") + minutes + " " + period;
timeText.setText(timeString);
// Change background color based on time of day
var isDayNow = hours >= 6 && hours < 18;
if (isDayNow !== isDay) {
isDay = isDayNow;
if (isDay) {
tween(timeBackground, {
tint: 0x000066
}, {
duration: 1000
});
} else {
tween(timeBackground, {
tint: 0x330033
}, {
duration: 1000
});
}
}
};
// Start time cycle and weather changes
self.startWeatherCycle = function () {
// Initialize game time to 6:00 AM
gameTime = 6;
// Update time every second
LK.setInterval(function () {
// Advance time by 10 minutes every second
gameTime = (gameTime + 10 / 60) % 24;
self.updateTime();
}, 1000);
// Weather changes
LK.setInterval(function () {
// 30% chance of rain, 70% sun
var newWeather = Math.random() < 0.3 ? "rain" : "sun";
self.changeWeather(newWeather);
currentWeather = newWeather;
}, 20000); // Change every 20 seconds
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x4CAF50 // Grassy green background
});
/****
* Game Code
****/
// Global variables from storage
var money = storage.money;
var hoeLevel = storage.hoeLevel;
var wateringCanLevel = storage.wateringCanLevel;
var harvesterLevel = storage.harvesterLevel;
var unlockedPlots = storage.unlockedPlots;
var experience = storage.experience;
var playerLevel = storage.level;
var nextLevelExp = storage.nextLevelExp;
// Game elements
var plots = [];
var toolButtons = [];
var seedButtons = [];
var upgradeButtons = [];
var sellCropButtons = [];
var activeTool = "hoe"; // Default tool
var activeSeed = "carrot"; // Default seed
var seedCosts = {
"carrot": 5,
"tomato": 10,
"wheat": 3
};
var cropValues = {
"carrot": 8,
"tomato": 15,
"wheat": 5
};
var shopButton;
var shopPanel;
var shopVisible = false;
var storeButton;
var storePanel;
var storeVisible = false;
var inventoryButton;
var inventoryPanel;
var inventoryVisible = false;
var harvestButton;
var harvestPanel;
var harvestVisible = false;
var harvestTracker;
var playerInventory;
var moneyText;
var toolDisplayText;
var levelText;
var expBar;
var currentWeather = "sun";
var weatherSystem;
var coinEffectsPool = [];
// Function to update tool display text
function updateToolDisplay() {
var toolName = "";
switch (activeTool) {
case "hoe":
toolName = "Hoe (Plant Seeds)";
break;
case "water":
toolName = "Watering Can";
break;
case "harvest":
toolName = "Harvester";
break;
}
toolDisplayText.setText("Active Tool: " + toolName);
}
// Create plot grid
function createPlots() {
var plotSize = 160; // Reduce size to fit more plots
var gridSize = 6; // 6x6 grid instead of 5x5
var startX = 2048 / 2 - plotSize * gridSize / 2 + plotSize / 2;
var startY = 2732 / 2 - plotSize * gridSize / 2 + plotSize / 2; // Center vertically on screen
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
var plot = new Plot();
var index = row * gridSize + col;
plot.x = startX + col * plotSize;
plot.y = startY + row * plotSize;
// First plot starts unlocked
if (index < storage.unlockedPlots) {
plot.unlock();
}
game.addChild(plot);
plots.push(plot);
}
}
}
// Create toolbar with farming tools
function createToolbar() {
var toolTypes = ["hoe", "water", "harvest"];
var startX = 2048 / 2 - 350; // Move starting position further left
var toolbarY = 2600; // Move to bottom of screen
toolTypes.forEach(function (toolType, index) {
var button = new ToolButton(toolType);
button.x = startX + index * 350; // Increase spacing between tools
button.y = toolbarY;
// Set initial level using storage values directly
if (toolType === "hoe") {
button.updateLevel(storage.hoeLevel);
} else if (toolType === "water") {
button.updateLevel(storage.wateringCanLevel);
} else if (toolType === "harvest") {
button.updateLevel(storage.harvesterLevel);
}
// First button (hoe) is selected by default
if (index === 0) {
button.scaleX = 1.2;
button.scaleY = 1.2;
}
game.addChild(button);
toolButtons.push(button);
});
// Create shortcut buttons at the corners of the screen
// These are small, easily accessible buttons for quick tool switching
var shortcutSize = 80;
var shortcuts = [{
tool: "hoe",
x: 160,
y: 160,
key: "1"
}, {
tool: "water",
x: 320,
// Increased spacing between shortcut buttons
y: 160,
key: "2"
}, {
tool: "harvest",
x: 480,
// Increased spacing between shortcut buttons
y: 160,
key: "3"
}];
shortcuts.forEach(function (shortcut) {
var shortcutButton = new Container();
// Create tool icon
var bg = shortcutButton.attachAsset('tool-' + shortcut.tool, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
// Create key label
var keyLabel = new Text2(shortcut.key, {
size: 24,
fill: 0xFFFFFF
});
keyLabel.anchor.set(0.5, 0.5);
keyLabel.y = 30;
shortcutButton.addChild(keyLabel);
// Position the button
shortcutButton.x = shortcut.x;
shortcutButton.y = shortcut.y;
// Add interaction
shortcutButton.interactive = true;
shortcutButton.down = function () {
activeTool = shortcut.tool;
toolButtons.forEach(function (button) {
button.setActive(button.toolType === activeTool);
});
updateToolDisplay();
};
game.addChild(shortcutButton);
});
// Create seed buttons for shop panel
var seedTypes = [{
type: "carrot",
cost: seedCosts.carrot
}, {
type: "tomato",
cost: seedCosts.tomato
}, {
type: "wheat",
cost: seedCosts.wheat
}];
// We'll add these to the shop panel later in initGame
seedTypes.forEach(function (seed, index) {
var button = new SeedButton(seed.type, seed.cost);
// First button (carrot) is selected by default
if (index === 0) {
button.scaleX = 1.1;
button.scaleY = 1.1;
}
seedButtons.push(button);
});
}
// Create upgrade shop
function createUpgradeShop() {
var upgrades = [{
type: "hoe",
cost: 100
}, {
type: "water",
cost: 150
}, {
type: "harvest",
cost: 200
}, {
type: "plot",
cost: 300
}];
upgrades.forEach(function (upgrade, index) {
var button = new UpgradeButton(upgrade.type, upgrade.cost);
// Update costs based on current levels from storage
if (upgrade.type === "hoe") {
button.updateCost(upgrade.cost * Math.pow(2, storage.hoeLevel - 1));
} else if (upgrade.type === "water") {
button.updateCost(upgrade.cost * Math.pow(2, storage.wateringCanLevel - 1));
} else if (upgrade.type === "harvest") {
button.updateCost(upgrade.cost * Math.pow(2, storage.harvesterLevel - 1));
} else if (upgrade.type === "plot") {
button.updateCost(upgrade.cost * Math.pow(2, storage.unlockedPlots - 1));
// Hide plot upgrade if all are unlocked
if (storage.unlockedPlots >= storage.maxPlots) {
button.visible = false;
}
}
upgradeButtons.push(button);
});
}
// Create UI elements
// Create sell shop UI
function createStore() {
var cropTypes = [{
type: "carrot",
value: cropValues.carrot
}, {
type: "tomato",
value: cropValues.tomato
}, {
type: "wheat",
value: cropValues.wheat
}];
cropTypes.forEach(function (crop, index) {
var button = new SellCropButton(crop.type, crop.value);
button.y = index * 120;
sellCropButtons.push(button);
storePanel.sellContainer.addChild(button);
});
}
function createUI() {
// No header bar behind the title for cleaner look
// Create money counter with icon
var coinIcon = new Container();
var coinGraphic = coinIcon.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
coinIcon.x = 0;
coinIcon.y = 120;
LK.gui.top.addChild(coinIcon);
moneyText = new Text2(money.toString() + " coins", {
size: 65,
fill: 0xFFFF00
});
moneyText.anchor.set(0, 0.5);
moneyText.x = 40;
moneyText.y = 120;
LK.gui.top.addChild(moneyText);
// Create active tool display above the tool selector
toolDisplayText = new Text2("Active Tool: Hoe", {
size: 60,
fill: 0xFFFFFF
});
toolDisplayText.anchor.set(0.5, 0.5);
// Position above the tool selector
toolDisplayText.x = 2048 / 2;
toolDisplayText.y = 2500; // Higher above the tool selector (which is at y=2600)
game.addChild(toolDisplayText); // Add to game instead of gui.top
// Create weather system with in-game time
weatherSystem = new WeatherSystem();
weatherSystem.x = 1800;
weatherSystem.y = 150;
game.addChild(weatherSystem);
weatherSystem.startWeatherCycle();
// Create title
var titleText = new Text2("Harvest Heroes", {
size: 110,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 35;
LK.gui.top.addChild(titleText);
// Create level display to the left of money
levelText = new Text2("Level " + playerLevel, {
size: 55,
fill: 0xFFFF00
});
levelText.anchor.set(1, 0.5);
levelText.x = -40;
levelText.y = 120;
LK.gui.top.addChild(levelText);
// Create experience bar
expBar = new ExperienceBar();
expBar.x = 2048 / 2;
expBar.y = 2400; // Position higher to avoid blocking the active tool UI
game.addChild(expBar);
expBar.updateExp(experience, nextLevelExp, playerLevel);
// Create menu panel for buttons on right middle side of the screen
var menuPanel = game.attachAsset('button', {
anchorX: 1,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 5.5,
// Increased to accommodate harvest button
x: 2048,
y: 1366 // Center vertically (2732/2)
});
menuPanel.tint = 0x333333;
menuPanel.alpha = 0.6;
// Create shop button
shopButton = new ShopButton();
shopButton.x = 1800;
shopButton.y = 1166; // Position buttons around the middle
game.addChild(shopButton);
// Create store button
storeButton = new StoreButton();
storeButton.x = 1800;
storeButton.y = 1316; // Position buttons around the middle
game.addChild(storeButton);
// Create inventory button
inventoryButton = new InventoryButton();
inventoryButton.x = 1800;
inventoryButton.y = 1466; // Position buttons around the middle
game.addChild(inventoryButton);
// Create harvest tracker button
harvestButton = new HarvestButton();
harvestButton.x = 1800;
harvestButton.y = 1616; // Position buttons around the middle
game.addChild(harvestButton);
// Create shop panel (initially hidden)
shopPanel = new ShopPanel();
shopPanel.x = 2048 / 2;
shopPanel.y = 2732 / 2;
shopPanel.visible = false;
game.addChild(shopPanel);
// Create store panel (initially hidden)
storePanel = new StorePanel();
storePanel.x = 2048 / 2;
storePanel.y = 2732 / 2;
storePanel.visible = false;
game.addChild(storePanel);
// Create inventory panel (initially hidden)
playerInventory = new Inventory();
inventoryPanel = playerInventory;
inventoryPanel.x = 2048 / 2;
inventoryPanel.y = 2732 / 2;
inventoryPanel.visible = false;
game.addChild(inventoryPanel);
// Create harvest tracker panel (initially hidden)
harvestTracker = new HarvestTracker();
harvestPanel = harvestTracker;
harvestPanel.x = 2048 / 2;
harvestPanel.y = 2732 / 2;
harvestPanel.visible = false;
game.addChild(harvestPanel);
// Pre-create some coin effects for the pool
for (var i = 0; i < 10; i++) {
coinEffectsPool.push(new CoinEffect());
}
}
function updateMoney(amount) {
// Update both local variable and storage immediately
money += amount;
storage.money = money;
// Update UI to reflect new money amount
moneyText.setText(money.toString() + " coins");
}
function spawnCoinEffect(x, y) {
var coinEffect;
if (coinEffectsPool.length > 0) {
coinEffect = coinEffectsPool.pop();
} else {
coinEffect = new CoinEffect();
}
coinEffect.animate(x, y);
}
function addExperience(amount) {
// Update both local variable and storage
experience += amount;
storage.experience = experience;
// Check for level up
while (experience >= nextLevelExp) {
playerLevel++;
storage.level = playerLevel;
// Calculate next level requirement (increases by 50% each level)
nextLevelExp = Math.floor(nextLevelExp * 1.5);
storage.nextLevelExp = nextLevelExp;
// Show level up effect
var levelUpText = new Text2("LEVEL UP!", {
size: 100,
fill: 0xFFFF00
});
levelUpText.anchor.set(0.5, 0.5);
levelUpText.x = 2048 / 2;
levelUpText.y = 2732 / 2;
game.addChild(levelUpText);
// Scale and fade animation
tween(levelUpText, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(levelUpText);
}
});
// Give bonus for leveling up
updateMoney(playerLevel * 50);
}
// Update experience UI
if (expBar) {
expBar.updateExp(experience, nextLevelExp, playerLevel);
}
}
function toggleShopPanel() {
// Hide other panels if visible
if (inventoryVisible) {
toggleInventoryPanel();
}
if (storeVisible) {
toggleStorePanel();
}
if (harvestVisible) {
toggleHarvestPanel();
}
shopVisible = !shopVisible;
if (shopVisible) {
// Show shop panel with animation
shopPanel.visible = true;
shopPanel.alpha = 0;
tween(shopPanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide shop panel with animation
tween(shopPanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
shopPanel.visible = false;
}
});
}
}
function toggleInventoryPanel() {
// Hide other panels if visible
if (shopVisible) {
toggleShopPanel();
}
if (storeVisible) {
toggleStorePanel();
}
if (harvestVisible) {
toggleHarvestPanel();
}
inventoryVisible = !inventoryVisible;
if (inventoryVisible) {
// Show inventory panel with animation
inventoryPanel.visible = true;
inventoryPanel.alpha = 0;
tween(inventoryPanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide inventory panel with animation
tween(inventoryPanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
inventoryPanel.visible = false;
}
});
}
}
function toggleStorePanel() {
// Hide other panels if visible
if (shopVisible) {
toggleShopPanel();
}
if (inventoryVisible) {
toggleInventoryPanel();
}
if (harvestVisible) {
toggleHarvestPanel();
}
storeVisible = !storeVisible;
if (storeVisible) {
// Show store panel with animation
storePanel.visible = true;
storePanel.alpha = 0;
tween(storePanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide store panel with animation
tween(storePanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
storePanel.visible = false;
}
});
}
}
// Initialize the game
function initGame() {
createPlots();
createToolbar();
createUpgradeShop();
createUI();
createStore();
// Initialize active tool display
updateToolDisplay();
// Initialize experience display
addExperience(0); // Updates UI without adding experience
// Make the first tool button active (hoe is default)
toolButtons[0].setActive(true);
// Arrange seed buttons in shop panel
var seedStartX = -200;
seedButtons.forEach(function (button, index) {
button.x = seedStartX + index * 200;
button.y = 0;
shopPanel.seedContainer.addChild(button);
});
// Arrange upgrade buttons in shop panel
var upgradeStartX = -300;
var upgradeStartY = 0;
upgradeButtons.forEach(function (button, index) {
// 2 rows of 2 buttons
if (index < 2) {
button.x = upgradeStartX + index * 600;
button.y = upgradeStartY;
} else {
button.x = upgradeStartX + (index - 2) * 600;
button.y = upgradeStartY + 120;
}
shopPanel.upgradeContainer.addChild(button);
});
// Start background music
LK.playMusic('bgmusic');
}
initGame();
// Game update loop
game.update = function () {
// Update all plots
for (var i = 0; i < plots.length; i++) {
plots[i].update();
}
// Update score to track maximum money earned
if (money > LK.getScore()) {
LK.setScore(money);
}
};
// Game-level event handlers
game.down = function (x, y, obj) {
// This is handled by individual objects
};
game.up = function (x, y, obj) {
// Nothing needed here
};
game.move = function (x, y, obj) {
// Nothing needed here
};
function toggleHarvestPanel() {
// Hide other panels if visible
if (shopVisible) {
toggleShopPanel();
}
if (storeVisible) {
toggleStorePanel();
}
if (inventoryVisible) {
toggleInventoryPanel();
}
harvestVisible = !harvestVisible;
if (harvestVisible) {
// Show harvest panel with animation
harvestPanel.visible = true;
harvestPanel.alpha = 0;
tween(harvestPanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide harvest panel with animation
tween(harvestPanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
harvestPanel.visible = false;
}
});
}
} /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
money: 200,
hoeLevel: 1,
wateringCanLevel: 1,
harvesterLevel: 1,
unlockedPlots: 2,
maxPlots: 36,
experience: 0,
level: 1,
nextLevelExp: 100,
harvested: {}
});
/****
* Classes
****/
var CoinEffect = Container.expand(function () {
var self = Container.call(this);
var coinGraphic = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.animate = function (startX, startY) {
self.x = startX;
self.y = startY;
self.alpha = 1;
game.addChild(self);
// Animate coin floating up and fading out
tween(self, {
y: startY - 100,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(self);
coinEffectsPool.push(self);
}
});
};
return self;
});
var ExperienceBar = Container.expand(function () {
var self = Container.call(this);
// Background for the experience bar
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 0.5
});
background.tint = 0x333333;
// Create the fill bar (progress)
self.fillBar = self.attachAsset('button', {
anchorX: 0,
anchorY: 0.5,
scaleX: 0,
scaleY: 0.3,
x: -background.width / 2
});
self.fillBar.tint = 0x4CAF50; // Green for experience
// Level text
self.levelText = new Text2("Level 1", {
size: 38,
fill: 0xFFFFFF
});
self.levelText.anchor.set(0.5, 0.5);
self.levelText.y = -20;
self.addChild(self.levelText);
// Experience text
self.expText = new Text2("0/100 XP", {
size: 32,
fill: 0xFFFFFF
});
self.expText.anchor.set(0.5, 0.5);
self.expText.y = 5;
self.addChild(self.expText);
// Update experience bar display
self.updateExp = function (exp, nextLevel, level) {
var percentage = Math.min(1, exp / nextLevel);
self.fillBar.scaleX = percentage * background.width / 100;
self.expText.setText(exp + "/" + nextLevel + " XP");
self.levelText.setText("Level " + level);
};
return self;
});
var HarvestButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0x32CD32; // Lime green
// Add stats icon using the new asset
var statsIcon = self.attachAsset('icon-stats', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
y: -18
});
// statsIcon.tint = 0xF5DEB3; // Optional: Remove or adjust tint if needed for the new icon
var titleText = new Text2("Stats", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleHarvestPanel();
};
return self;
});
var HarvestTracker = Container.expand(function () {
var self = Container.call(this);
// Track harvested crops
self.harvested = {
"carrot": 0,
"tomato": 0,
"wheat": 0,
"total": 0
};
// Visual elements
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 4
});
background.tint = 0x333333;
background.alpha = 0.9;
var titleText = new Text2("Harvest Statistics", {
size: 80,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0);
titleText.y = -140;
self.addChild(titleText);
// Container for harvest counts
self.harvestContainer = new Container();
self.addChild(self.harvestContainer);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 250;
closeButton.y = -140;
closeButton.down = function () {
toggleHarvestPanel();
};
self.addChild(closeButton);
// Track a new harvested crop
self.trackHarvest = function (type) {
if (self.harvested.hasOwnProperty(type)) {
self.harvested[type]++;
self.harvested.total++;
// Store the data in storage
storage.harvested = self.harvested;
self.updateDisplay();
return true;
}
return false;
};
// Update the visual display
self.updateDisplay = function () {
// Clear current display
while (self.harvestContainer.children.length > 0) {
self.harvestContainer.removeChild(self.harvestContainer.children[0]);
}
var yPos = -70;
var spacing = 70;
// Add each crop type
for (var cropType in self.harvested) {
if (cropType === "total") {
continue;
} // Skip the total counter for display
var container = new Container();
// Create background for each crop entry
var entryBg = container.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 0.7,
alpha: 0.3
});
entryBg.tint = 0x666666;
// Crop icon
var cropIcon = container.attachAsset('crop-mature', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
x: -120
});
// Crop color based on type
if (cropType === "carrot") {
cropIcon.tint = 0xFF9900;
} else if (cropType === "tomato") {
cropIcon.tint = 0xFF3333;
} else if (cropType === "wheat") {
cropIcon.tint = 0xF5DEB3;
}
// Crop name and count
var text = new Text2(cropType + ": " + self.harvested[cropType], {
size: 54,
fill: 0xFFFFFF
});
text.anchor.set(0, 0.5);
text.x = -70;
container.addChild(text);
container.y = yPos;
yPos += spacing;
self.harvestContainer.addChild(container);
}
// Add total harvested
var totalContainer = new Container();
var totalBg = totalContainer.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 0.7,
alpha: 0.5
});
totalBg.tint = 0x444444;
var totalText = new Text2("Total Harvested: " + self.harvested.total, {
size: 54,
fill: 0xFFFF00
});
totalText.anchor.set(0.5, 0.5);
totalContainer.addChild(totalText);
totalContainer.y = yPos + 20;
self.harvestContainer.addChild(totalContainer);
};
// Initialize from stored data
if (storage.harvested) {
self.harvested = storage.harvested;
}
// Initialize display
self.updateDisplay();
return self;
});
var Inventory = Container.expand(function () {
var self = Container.call(this);
self.seeds = {
"carrot": 0,
"tomato": 0,
"wheat": 0
};
// Visual elements
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 4
});
background.tint = 0x333333;
background.alpha = 0.9;
var titleText = new Text2("Seeds Inventory", {
size: 80,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0);
titleText.y = -140;
self.addChild(titleText);
// Container for seed counts
self.seedCountContainer = new Container();
self.addChild(self.seedCountContainer);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 250;
closeButton.y = -140;
closeButton.down = function () {
toggleInventoryPanel();
};
self.addChild(closeButton);
// Add seed to inventory
self.addSeed = function (type, amount) {
if (self.seeds.hasOwnProperty(type)) {
self.seeds[type] += amount;
self.updateDisplay();
return true;
}
return false;
};
// Remove seed from inventory
self.removeSeed = function (type, amount) {
if (self.seeds.hasOwnProperty(type) && self.seeds[type] >= amount) {
self.seeds[type] -= amount;
self.updateDisplay();
return true;
}
return false;
};
// Check if player has enough seeds
self.hasSeed = function (type, amount) {
return self.seeds.hasOwnProperty(type) && self.seeds[type] >= amount;
};
// Update the visual display
self.updateDisplay = function () {
// Clear current display
while (self.seedCountContainer.children.length > 0) {
self.seedCountContainer.removeChild(self.seedCountContainer.children[0]);
}
var yPos = -70;
var spacing = 70;
// Add each seed type
for (var seedType in self.seeds) {
var container = new Container();
// Create background for each seed entry
var entryBg = container.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 0.7,
alpha: 0.3
});
entryBg.tint = 0x666666;
// Seed icon
var seedIcon = container.attachAsset('crop-seed', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
x: -120
});
// Seed color based on type
if (seedType === "carrot") {
seedIcon.tint = 0xFF9900;
} else if (seedType === "tomato") {
seedIcon.tint = 0xFF3333;
} else if (seedType === "wheat") {
seedIcon.tint = 0xF5DEB3;
}
// Seed name and count
var text = new Text2(seedType + ": " + self.seeds[seedType], {
size: 54,
fill: 0xFFFFFF
});
text.anchor.set(0, 0.5);
text.x = -70;
container.addChild(text);
container.y = yPos;
yPos += spacing;
self.seedCountContainer.addChild(container);
}
};
// Initialize display
self.updateDisplay();
return self;
});
var InventoryButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0x8B4513; // Brown for inventory button
// Add seeds icon using the new asset
var seedsIcon = self.attachAsset('icon-seeds', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
y: -18
});
// seedsIcon.tint = 0xF5DEB3; // Optional: Remove or adjust tint if needed for the new icon
var titleText = new Text2("Seeds", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleInventoryPanel();
};
return self;
});
var Plot = Container.expand(function () {
var self = Container.call(this);
self.state = "empty"; // empty, seeded, growing, ready
self.growthProgress = 0;
self.growthRequired = 100;
self.value = 10;
self.unlocked = false;
self.isWatered = false; // Track if the plot is currently watered
self.waterDuration = 0; // How long the water effect lasts
var plotBackground = self.attachAsset('plot', {
anchorX: 0.5,
anchorY: 0.5
});
var soilGraphic = self.attachAsset('soil', {
anchorX: 0.5,
anchorY: 0.5
});
// The crop that shows on this plot
self.cropGraphic = null;
self.unlock = function () {
self.unlocked = true;
plotBackground.alpha = 1;
soilGraphic.alpha = 1;
};
self.lock = function () {
self.unlocked = false;
plotBackground.alpha = 0.3;
soilGraphic.alpha = 0.3;
self.clearCrop();
};
self.clearCrop = function () {
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
self.cropGraphic = null;
}
self.state = "empty";
self.growthProgress = 0;
};
self.plant = function () {
if (!self.unlocked || self.state !== "empty") {
return false;
}
// Check if player has seeds in inventory
if (!playerInventory.hasSeed(activeSeed, 1)) {
return false;
}
// Use seed from inventory
playerInventory.removeSeed(activeSeed, 1);
self.state = "seeded";
self.seedType = activeSeed;
self.growthProgress = 0;
// Set crop values based on seed type
if (activeSeed === "carrot") {
self.growthRequired = 80;
self.value = 15;
} else if (activeSeed === "tomato") {
self.growthRequired = 120;
self.value = 25;
} else if (activeSeed === "wheat") {
self.growthRequired = 60;
self.value = 10;
}
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
}
self.cropGraphic = self.attachAsset('crop-seed', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint the seed based on type
if (activeSeed === "carrot") {
self.cropGraphic.tint = 0xFF9900;
} else if (activeSeed === "tomato") {
self.cropGraphic.tint = 0xFF3333;
} else if (activeSeed === "wheat") {
self.cropGraphic.tint = 0xF5DEB3;
}
// Grant experience for planting
addExperience(5);
return true;
};
self.water = function () {
if (!self.unlocked || self.state !== "seeded" && self.state !== "growing") {
return false;
}
// Set watered state and duration
self.isWatered = true;
// Duration based on watering can level - better watering cans make water last longer
self.waterDuration = 300 + storage.wateringCanLevel * 120; // Use storage value directly
// Visual indication that plot is watered
soilGraphic.tint = 0x6b8cff; // Bluish tint for watered soil
return true;
};
self.harvest = function () {
if (!self.unlocked || self.state !== "ready") {
return 0;
}
// Use storage value directly for more accurate calculations
var harvestValue = self.value * (1 + (storage.harvesterLevel - 1) * 0.2);
// Add one seed of the harvested type to inventory
playerInventory.addSeed(self.seedType, 1);
// Track the harvested crop
harvestTracker.trackHarvest(self.seedType);
// Grant experience based on crop type
var expGain = 0;
if (self.seedType === "carrot") {
expGain = 10;
} else if (self.seedType === "tomato") {
expGain = 15;
} else if (self.seedType === "wheat") {
expGain = 8;
}
addExperience(expGain);
self.clearCrop();
return Math.floor(harvestValue);
};
self.update = function () {
// Handle watering duration and effect
if (self.isWatered && (self.state === "seeded" || self.state === "growing")) {
// Apply growth effect while watered
var wateringEfficiency = 5 * storage.wateringCanLevel / 60; // Use storage value directly
self.growthProgress += wateringEfficiency;
// Decrease water duration
self.waterDuration--;
// Check if water effect has ended
if (self.waterDuration <= 0) {
self.isWatered = false;
soilGraphic.tint = 0xFFFFFF; // Reset soil tint
}
// Process growth stage transitions
self.checkGrowthStages();
}
// Rain effect (now lasts longer than just one tick)
if (currentWeather === "rain" && (self.state === "seeded" || self.state === "growing")) {
// Rain automatically waters plants a little bit
if (LK.ticks % 60 === 0) {
// Every second
self.growthProgress += 1;
// If not already watered, make soil look wet
if (!self.isWatered) {
soilGraphic.tint = 0x9cb6ff; // Lighter blue tint for rain-watered soil
}
self.checkGrowthStages();
}
} else if (!self.isWatered && soilGraphic.tint !== 0xFFFFFF) {
// Reset soil tint when not raining and not manually watered
soilGraphic.tint = 0xFFFFFF;
}
};
// Helper method to check growth stages and update visuals
self.checkGrowthStages = function () {
if (self.growthProgress >= self.growthRequired / 2 && self.state === "seeded") {
self.state = "growing";
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
}
self.cropGraphic = self.attachAsset('crop-growing', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint the growing crop based on seed type
if (self.seedType === "carrot") {
self.cropGraphic.tint = 0xFF9900;
} else if (self.seedType === "tomato") {
self.cropGraphic.tint = 0xFF3333;
} else if (self.seedType === "wheat") {
self.cropGraphic.tint = 0xF5DEB3;
}
}
if (self.growthProgress >= self.growthRequired) {
self.state = "ready";
if (self.cropGraphic) {
self.removeChild(self.cropGraphic);
}
self.cropGraphic = self.attachAsset('crop-mature', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint the mature crop based on seed type
if (self.seedType === "carrot") {
self.cropGraphic.tint = 0xFF9900;
} else if (self.seedType === "tomato") {
self.cropGraphic.tint = 0xFF3333;
} else if (self.seedType === "wheat") {
self.cropGraphic.tint = 0xF5DEB3;
}
}
};
self.down = function (x, y, obj) {
if (!self.unlocked) {
return;
}
var gamePos = game.toLocal(self.parent.toGlobal(self.position));
if (activeTool === "hoe") {
// Check if player has seeds in inventory
if (playerInventory.hasSeed(activeSeed, 1)) {
if (self.plant()) {
LK.getSound('plant').play();
}
} else if (money >= seedCosts[activeSeed]) {
// If no seeds in inventory but enough money, show inventory
toggleInventoryPanel();
}
} else if (activeTool === "water") {
if (self.water()) {
LK.getSound('water').play();
}
} else if (activeTool === "harvest") {
var value = self.harvest();
if (value > 0) {
LK.getSound('harvest').play();
LK.getSound('coin').play();
updateMoney(value);
spawnCoinEffect(gamePos.x, gamePos.y);
}
}
};
// Initially plots should be locked unless specified
self.lock();
return self;
});
var SeedButton = Container.expand(function (seedType, cost) {
var self = Container.call(this);
self.seedType = seedType;
self.cost = cost;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
// Change button color to represent seed type
if (seedType === "carrot") {
background.tint = 0xFF9900;
background.alpha = 0.8;
} else if (seedType === "tomato") {
background.tint = 0xFF3333;
background.alpha = 0.8;
} else if (seedType === "wheat") {
background.tint = 0xF5DEB3;
background.alpha = 0.8;
}
var nameText = new Text2(seedType, {
size: 42,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -15;
self.addChild(nameText);
var costText = new Text2(cost + " coins", {
size: 34,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0.5);
costText.y = 15;
self.addChild(costText);
self.down = function (x, y, obj) {
if (money >= self.cost) {
// Buy seeds and add to inventory
updateMoney(-self.cost);
LK.getSound('coin').play();
playerInventory.addSeed(self.seedType, 1);
activeSeed = self.seedType;
seedButtons.forEach(function (button) {
if (button.seedType === activeSeed) {
tween(button, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeOut
});
} else {
tween(button, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
};
return self;
});
var SellCropButton = Container.expand(function (cropType, baseValue) {
var self = Container.call(this);
self.cropType = cropType;
self.baseValue = baseValue;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 1.4
});
// Change button color to represent crop type
if (cropType === "carrot") {
background.tint = 0xFF9900;
background.alpha = 0.7;
} else if (cropType === "tomato") {
background.tint = 0xFF3333;
background.alpha = 0.7;
} else if (cropType === "wheat") {
background.tint = 0xF5DEB3;
background.alpha = 0.7;
}
// Crop icon
var cropIcon = self.attachAsset('crop-mature', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
x: -120
});
// Tint the icon based on crop type
if (cropType === "carrot") {
cropIcon.tint = 0xFF9900;
} else if (cropType === "tomato") {
cropIcon.tint = 0xFF3333;
} else if (cropType === "wheat") {
cropIcon.tint = 0xF5DEB3;
}
var nameText = new Text2(cropType, {
size: 50,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -20;
nameText.x = 0;
self.addChild(nameText);
var valueText = new Text2(baseValue + " coins each", {
size: 40,
fill: 0xFFFFFF
});
valueText.anchor.set(0.5, 0.5);
valueText.y = 20;
valueText.x = 0;
self.addChild(valueText);
// Quantity counter
var quantity = 0;
var minusBtn = new Container();
var minusBg = minusBtn.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
minusBg.tint = 0x777777;
var minusText = new Text2("-", {
size: 50,
fill: 0xFFFFFF
});
minusText.anchor.set(0.5, 0.5);
minusBtn.addChild(minusText);
minusBtn.x = 80;
minusBtn.y = -20;
self.addChild(minusBtn);
var plusBtn = new Container();
var plusBg = plusBtn.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
plusBg.tint = 0x777777;
var plusText = new Text2("+", {
size: 50,
fill: 0xFFFFFF
});
plusText.anchor.set(0.5, 0.5);
plusBtn.addChild(plusText);
plusBtn.x = 160;
plusBtn.y = -20;
self.addChild(plusBtn);
var qtyText = new Text2("0", {
size: 46,
fill: 0xFFFFFF
});
qtyText.anchor.set(0.5, 0.5);
qtyText.x = 120;
qtyText.y = -20;
self.addChild(qtyText);
var sellBtn = new Container();
var sellBg = sellBtn.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.4
});
sellBg.tint = 0x4CAF50;
var sellText = new Text2("Sell", {
size: 40,
fill: 0xFFFFFF
});
sellText.anchor.set(0.5, 0.5);
sellBtn.addChild(sellText);
sellBtn.x = 120;
sellBtn.y = 20;
self.addChild(sellBtn);
minusBtn.down = function () {
if (quantity > 0) {
quantity--;
qtyText.setText(quantity.toString());
}
};
plusBtn.down = function () {
if (playerInventory.hasSeed(cropType, 1)) {
quantity++;
qtyText.setText(quantity.toString());
}
};
sellBtn.down = function () {
if (quantity > 0 && playerInventory.hasSeed(cropType, quantity)) {
playerInventory.removeSeed(cropType, quantity);
var value = baseValue * quantity;
updateMoney(value);
LK.getSound('coin').play();
// Spawn multiple coin effects for bigger sales
var effectCount = Math.min(5, Math.floor(quantity / 2) + 1);
for (var i = 0; i < effectCount; i++) {
spawnCoinEffect(game.toLocal(self.parent.toGlobal(self.position)).x, game.toLocal(self.parent.toGlobal(self.position)).y);
}
quantity = 0;
qtyText.setText("0");
}
};
return self;
});
var ShopButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0x4169E1; // Royal blue for shop button
// Add shop icon using the new asset
var shopIcon = self.attachAsset('icon-shop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
// Adjusted scale for potentially different icon size
scaleY: 0.8,
y: -18
});
var titleText = new Text2("Shop", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleShopPanel();
};
return self;
});
var ShopPanel = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
// Make it wide enough
scaleY: 8 // Make it tall enough
});
background.tint = 0x333333;
background.alpha = 0.95;
// Add decorative header bar
var headerBar = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 0.8,
y: -300
});
headerBar.tint = 0x4169E1; // Royal blue to match shop button
headerBar.alpha = 0.8;
var titleText = new Text2("Farm Shop", {
size: 90,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -300;
self.addChild(titleText);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 400;
closeButton.y = -300;
closeButton.down = function () {
toggleShopPanel();
};
self.addChild(closeButton);
// Section titles
var seedTitle = new Text2("Seeds", {
size: 60,
fill: 0xFFFF00
});
seedTitle.anchor.set(0.5, 0);
seedTitle.y = -200;
self.addChild(seedTitle);
var upgradeTitle = new Text2("Upgrades", {
size: 60,
fill: 0xFFFF00
});
upgradeTitle.anchor.set(0.5, 0);
upgradeTitle.y = 50;
self.addChild(upgradeTitle);
// Containers for each section
self.seedContainer = new Container();
self.seedContainer.y = -150;
self.addChild(self.seedContainer);
self.upgradeContainer = new Container();
self.upgradeContainer.y = 100;
self.addChild(self.upgradeContainer);
return self;
});
var StoreButton = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 1.3
});
background.tint = 0xFFD700; // Gold color for store button
// Add store icon using the new asset
var storeIcon = self.attachAsset('icon-store', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
// Adjusted scale for potentially different icon size
scaleY: 0.8,
y: -18
});
var titleText = new Text2("Store", {
size: 50,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 20;
self.addChild(titleText);
self.down = function (x, y, obj) {
toggleStorePanel();
};
return self;
});
var StorePanel = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 8
});
background.tint = 0x333333;
background.alpha = 0.95;
// Add decorative header bar
var headerBar = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 0.8,
y: -300
});
headerBar.tint = 0xFFD700; // Gold to match store button
headerBar.alpha = 0.8;
var titleText = new Text2("Market Store", {
size: 90,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -300;
self.addChild(titleText);
// Add close button
var closeButton = new Container();
var closeBg = closeButton.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
closeBg.tint = 0xFF0000;
var closeText = new Text2("X", {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = 400;
closeButton.y = -300;
closeButton.down = function () {
toggleStorePanel();
};
self.addChild(closeButton);
// Description
var descText = new Text2("Sell your harvested crops for coins!", {
size: 50,
fill: 0xFFFF00
});
descText.anchor.set(0.5, 0);
descText.y = -200;
self.addChild(descText);
// Containers for crop selling options
self.sellContainer = new Container();
self.sellContainer.y = -100;
self.addChild(self.sellContainer);
return self;
});
var ToolButton = Container.expand(function (toolType) {
var self = Container.call(this);
self.toolType = toolType;
var assetName = 'tool-' + toolType;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1
});
// Set background color based on tool type
if (toolType === "hoe") {
background.tint = 0x8B4513; // Brown
} else if (toolType === "water") {
background.tint = 0x4682B4; // Steel blue
} else if (toolType === "harvest") {
background.tint = 0xFFD700; // Gold
}
background.alpha = 0.6;
var toolGraphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
y: -15
});
var levelText = new Text2('Lv 1', {
size: 44,
fill: 0xFFFF00
});
levelText.anchor.set(0.5, 0.5);
levelText.y = 40;
self.addChild(levelText);
// Add indicator to show which tool is active
var indicator = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 0.15,
y: -70
});
indicator.tint = 0xFFFFFF;
indicator.alpha = 0; // Initially hidden
self.setActive = function (isActive) {
indicator.alpha = isActive ? 1 : 0;
tween(self, {
scaleX: isActive ? 1.2 : 1.0,
scaleY: isActive ? 1.2 : 1.0
}, {
duration: 200,
easing: tween.easeOut
});
};
self.updateLevel = function (level) {
levelText.setText('Lv ' + level);
};
self.down = function (x, y, obj) {
activeTool = self.toolType;
// Update active tool indicator for all tools
toolButtons.forEach(function (button) {
button.setActive(button.toolType === activeTool);
});
// Show active tool name
updateToolDisplay();
};
return self;
});
var UpgradeButton = Container.expand(function (upgradeType, cost) {
var self = Container.call(this);
self.upgradeType = upgradeType;
self.cost = cost;
var background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.4,
scaleY: 1.2
});
// Set button color based on upgrade type
if (upgradeType === "hoe") {
background.tint = 0x964B00; // Brown
} else if (upgradeType === "water") {
background.tint = 0x4682B4; // Steel blue
} else if (upgradeType === "harvest") {
background.tint = 0xFFD700; // Gold
} else if (upgradeType === "plot") {
background.tint = 0x7C5837; // Earth brown
}
background.alpha = 0.8;
var title;
if (upgradeType === "hoe") {
title = "Upgrade Hoe";
} else if (upgradeType === "water") {
title = "Upgrade Watering Can";
} else if (upgradeType === "harvest") {
title = "Upgrade Harvester";
} else if (upgradeType === "plot") {
title = "Buy New Plot";
}
// Add icon for the tool being upgraded
if (upgradeType === "hoe" || upgradeType === "water" || upgradeType === "harvest") {
var toolIcon = self.attachAsset('tool-' + upgradeType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
x: -100,
y: -20
});
}
var titleText = new Text2(title, {
size: 46,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -20;
self.addChild(titleText);
var costText = new Text2(cost + " coins", {
size: 40,
fill: 0xFFFF00
});
costText.anchor.set(0.5, 0.5);
costText.y = 20;
self.addChild(costText);
self.updateCost = function (newCost) {
self.cost = newCost;
costText.setText(newCost + " coins");
};
self.down = function (x, y, obj) {
if (money >= self.cost) {
LK.getSound('upgrade').play();
updateMoney(-self.cost);
if (upgradeType === "hoe") {
// Update both the local variable and storage
hoeLevel++;
storage.hoeLevel = hoeLevel;
self.updateCost(self.cost * 2);
toolButtons[0].updateLevel(hoeLevel);
} else if (upgradeType === "water") {
wateringCanLevel++;
storage.wateringCanLevel = wateringCanLevel;
self.updateCost(self.cost * 2);
toolButtons[1].updateLevel(wateringCanLevel);
} else if (upgradeType === "harvest") {
harvesterLevel++;
storage.harvesterLevel = harvesterLevel;
self.updateCost(self.cost * 2);
toolButtons[2].updateLevel(harvesterLevel);
} else if (upgradeType === "plot") {
if (unlockedPlots < storage.maxPlots) {
unlockedPlots++;
storage.unlockedPlots = unlockedPlots;
self.updateCost(self.cost * 2);
plots[unlockedPlots - 1].unlock();
// If all plots unlocked, hide this button
if (unlockedPlots >= storage.maxPlots) {
self.visible = false;
}
}
}
}
};
return self;
});
var WeatherSystem = Container.expand(function () {
var self = Container.call(this);
self.weatherType = "sun"; // sun or rain
var gameTime = 0; // Game time in minutes (0-24)
var isDay = true;
// Create clock/calendar background
var clockBg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.9
});
clockBg.tint = 0x000066;
clockBg.alpha = 0.8;
// Create time display instead of sun
var timeBackground = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.4,
y: -5
});
timeBackground.tint = 0x000099;
var timeText = new Text2("6:00 AM", {
size: 50,
fill: 0xFFFFFF
});
timeText.anchor.set(0.5, 0.5);
timeText.y = -5;
self.addChild(timeText);
// Create weather label
var weatherLabel = new Text2("Weather:", {
size: 34,
fill: 0xFFFFFF
});
weatherLabel.anchor.set(0.5, 0.5);
weatherLabel.y = 30;
self.addChild(weatherLabel);
var rainGraphic = self.attachAsset('weather-rain', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0,
// Initially hidden
scaleX: 0.6,
scaleY: 0.6,
y: 60 // Position below time display
});
self.changeWeather = function (type) {
self.weatherType = type;
if (type === "sun") {
tween(rainGraphic, {
alpha: 0
}, {
duration: 1000
});
} else if (type === "rain") {
tween(rainGraphic, {
alpha: 1
}, {
duration: 1000
});
}
};
// Update the time display
self.updateTime = function () {
// Format time to 12-hour format with AM/PM
var hours = Math.floor(gameTime);
var minutes = Math.floor(gameTime % 1 * 60);
var period = hours >= 12 ? "PM" : "AM";
var formattedHours = hours % 12;
if (formattedHours === 0) {
formattedHours = 12;
}
var timeString = formattedHours + ":" + (minutes < 10 ? "0" : "") + minutes + " " + period;
timeText.setText(timeString);
// Change background color based on time of day
var isDayNow = hours >= 6 && hours < 18;
if (isDayNow !== isDay) {
isDay = isDayNow;
if (isDay) {
tween(timeBackground, {
tint: 0x000066
}, {
duration: 1000
});
} else {
tween(timeBackground, {
tint: 0x330033
}, {
duration: 1000
});
}
}
};
// Start time cycle and weather changes
self.startWeatherCycle = function () {
// Initialize game time to 6:00 AM
gameTime = 6;
// Update time every second
LK.setInterval(function () {
// Advance time by 10 minutes every second
gameTime = (gameTime + 10 / 60) % 24;
self.updateTime();
}, 1000);
// Weather changes
LK.setInterval(function () {
// 30% chance of rain, 70% sun
var newWeather = Math.random() < 0.3 ? "rain" : "sun";
self.changeWeather(newWeather);
currentWeather = newWeather;
}, 20000); // Change every 20 seconds
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x4CAF50 // Grassy green background
});
/****
* Game Code
****/
// Global variables from storage
var money = storage.money;
var hoeLevel = storage.hoeLevel;
var wateringCanLevel = storage.wateringCanLevel;
var harvesterLevel = storage.harvesterLevel;
var unlockedPlots = storage.unlockedPlots;
var experience = storage.experience;
var playerLevel = storage.level;
var nextLevelExp = storage.nextLevelExp;
// Game elements
var plots = [];
var toolButtons = [];
var seedButtons = [];
var upgradeButtons = [];
var sellCropButtons = [];
var activeTool = "hoe"; // Default tool
var activeSeed = "carrot"; // Default seed
var seedCosts = {
"carrot": 5,
"tomato": 10,
"wheat": 3
};
var cropValues = {
"carrot": 8,
"tomato": 15,
"wheat": 5
};
var shopButton;
var shopPanel;
var shopVisible = false;
var storeButton;
var storePanel;
var storeVisible = false;
var inventoryButton;
var inventoryPanel;
var inventoryVisible = false;
var harvestButton;
var harvestPanel;
var harvestVisible = false;
var harvestTracker;
var playerInventory;
var moneyText;
var toolDisplayText;
var levelText;
var expBar;
var currentWeather = "sun";
var weatherSystem;
var coinEffectsPool = [];
// Function to update tool display text
function updateToolDisplay() {
var toolName = "";
switch (activeTool) {
case "hoe":
toolName = "Hoe (Plant Seeds)";
break;
case "water":
toolName = "Watering Can";
break;
case "harvest":
toolName = "Harvester";
break;
}
toolDisplayText.setText("Active Tool: " + toolName);
}
// Create plot grid
function createPlots() {
var plotSize = 160; // Reduce size to fit more plots
var gridSize = 6; // 6x6 grid instead of 5x5
var startX = 2048 / 2 - plotSize * gridSize / 2 + plotSize / 2;
var startY = 2732 / 2 - plotSize * gridSize / 2 + plotSize / 2; // Center vertically on screen
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
var plot = new Plot();
var index = row * gridSize + col;
plot.x = startX + col * plotSize;
plot.y = startY + row * plotSize;
// First plot starts unlocked
if (index < storage.unlockedPlots) {
plot.unlock();
}
game.addChild(plot);
plots.push(plot);
}
}
}
// Create toolbar with farming tools
function createToolbar() {
var toolTypes = ["hoe", "water", "harvest"];
var startX = 2048 / 2 - 350; // Move starting position further left
var toolbarY = 2600; // Move to bottom of screen
toolTypes.forEach(function (toolType, index) {
var button = new ToolButton(toolType);
button.x = startX + index * 350; // Increase spacing between tools
button.y = toolbarY;
// Set initial level using storage values directly
if (toolType === "hoe") {
button.updateLevel(storage.hoeLevel);
} else if (toolType === "water") {
button.updateLevel(storage.wateringCanLevel);
} else if (toolType === "harvest") {
button.updateLevel(storage.harvesterLevel);
}
// First button (hoe) is selected by default
if (index === 0) {
button.scaleX = 1.2;
button.scaleY = 1.2;
}
game.addChild(button);
toolButtons.push(button);
});
// Create shortcut buttons at the corners of the screen
// These are small, easily accessible buttons for quick tool switching
var shortcutSize = 80;
var shortcuts = [{
tool: "hoe",
x: 160,
y: 160,
key: "1"
}, {
tool: "water",
x: 320,
// Increased spacing between shortcut buttons
y: 160,
key: "2"
}, {
tool: "harvest",
x: 480,
// Increased spacing between shortcut buttons
y: 160,
key: "3"
}];
shortcuts.forEach(function (shortcut) {
var shortcutButton = new Container();
// Create tool icon
var bg = shortcutButton.attachAsset('tool-' + shortcut.tool, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
// Create key label
var keyLabel = new Text2(shortcut.key, {
size: 24,
fill: 0xFFFFFF
});
keyLabel.anchor.set(0.5, 0.5);
keyLabel.y = 30;
shortcutButton.addChild(keyLabel);
// Position the button
shortcutButton.x = shortcut.x;
shortcutButton.y = shortcut.y;
// Add interaction
shortcutButton.interactive = true;
shortcutButton.down = function () {
activeTool = shortcut.tool;
toolButtons.forEach(function (button) {
button.setActive(button.toolType === activeTool);
});
updateToolDisplay();
};
game.addChild(shortcutButton);
});
// Create seed buttons for shop panel
var seedTypes = [{
type: "carrot",
cost: seedCosts.carrot
}, {
type: "tomato",
cost: seedCosts.tomato
}, {
type: "wheat",
cost: seedCosts.wheat
}];
// We'll add these to the shop panel later in initGame
seedTypes.forEach(function (seed, index) {
var button = new SeedButton(seed.type, seed.cost);
// First button (carrot) is selected by default
if (index === 0) {
button.scaleX = 1.1;
button.scaleY = 1.1;
}
seedButtons.push(button);
});
}
// Create upgrade shop
function createUpgradeShop() {
var upgrades = [{
type: "hoe",
cost: 100
}, {
type: "water",
cost: 150
}, {
type: "harvest",
cost: 200
}, {
type: "plot",
cost: 300
}];
upgrades.forEach(function (upgrade, index) {
var button = new UpgradeButton(upgrade.type, upgrade.cost);
// Update costs based on current levels from storage
if (upgrade.type === "hoe") {
button.updateCost(upgrade.cost * Math.pow(2, storage.hoeLevel - 1));
} else if (upgrade.type === "water") {
button.updateCost(upgrade.cost * Math.pow(2, storage.wateringCanLevel - 1));
} else if (upgrade.type === "harvest") {
button.updateCost(upgrade.cost * Math.pow(2, storage.harvesterLevel - 1));
} else if (upgrade.type === "plot") {
button.updateCost(upgrade.cost * Math.pow(2, storage.unlockedPlots - 1));
// Hide plot upgrade if all are unlocked
if (storage.unlockedPlots >= storage.maxPlots) {
button.visible = false;
}
}
upgradeButtons.push(button);
});
}
// Create UI elements
// Create sell shop UI
function createStore() {
var cropTypes = [{
type: "carrot",
value: cropValues.carrot
}, {
type: "tomato",
value: cropValues.tomato
}, {
type: "wheat",
value: cropValues.wheat
}];
cropTypes.forEach(function (crop, index) {
var button = new SellCropButton(crop.type, crop.value);
button.y = index * 120;
sellCropButtons.push(button);
storePanel.sellContainer.addChild(button);
});
}
function createUI() {
// No header bar behind the title for cleaner look
// Create money counter with icon
var coinIcon = new Container();
var coinGraphic = coinIcon.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
coinIcon.x = 0;
coinIcon.y = 120;
LK.gui.top.addChild(coinIcon);
moneyText = new Text2(money.toString() + " coins", {
size: 65,
fill: 0xFFFF00
});
moneyText.anchor.set(0, 0.5);
moneyText.x = 40;
moneyText.y = 120;
LK.gui.top.addChild(moneyText);
// Create active tool display above the tool selector
toolDisplayText = new Text2("Active Tool: Hoe", {
size: 60,
fill: 0xFFFFFF
});
toolDisplayText.anchor.set(0.5, 0.5);
// Position above the tool selector
toolDisplayText.x = 2048 / 2;
toolDisplayText.y = 2500; // Higher above the tool selector (which is at y=2600)
game.addChild(toolDisplayText); // Add to game instead of gui.top
// Create weather system with in-game time
weatherSystem = new WeatherSystem();
weatherSystem.x = 1800;
weatherSystem.y = 150;
game.addChild(weatherSystem);
weatherSystem.startWeatherCycle();
// Create title
var titleText = new Text2("Harvest Heroes", {
size: 110,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = 35;
LK.gui.top.addChild(titleText);
// Create level display to the left of money
levelText = new Text2("Level " + playerLevel, {
size: 55,
fill: 0xFFFF00
});
levelText.anchor.set(1, 0.5);
levelText.x = -40;
levelText.y = 120;
LK.gui.top.addChild(levelText);
// Create experience bar
expBar = new ExperienceBar();
expBar.x = 2048 / 2;
expBar.y = 2400; // Position higher to avoid blocking the active tool UI
game.addChild(expBar);
expBar.updateExp(experience, nextLevelExp, playerLevel);
// Create menu panel for buttons on right middle side of the screen
var menuPanel = game.attachAsset('button', {
anchorX: 1,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 5.5,
// Increased to accommodate harvest button
x: 2048,
y: 1366 // Center vertically (2732/2)
});
menuPanel.tint = 0x333333;
menuPanel.alpha = 0.6;
// Create shop button
shopButton = new ShopButton();
shopButton.x = 1800;
shopButton.y = 1166; // Position buttons around the middle
game.addChild(shopButton);
// Create store button
storeButton = new StoreButton();
storeButton.x = 1800;
storeButton.y = 1316; // Position buttons around the middle
game.addChild(storeButton);
// Create inventory button
inventoryButton = new InventoryButton();
inventoryButton.x = 1800;
inventoryButton.y = 1466; // Position buttons around the middle
game.addChild(inventoryButton);
// Create harvest tracker button
harvestButton = new HarvestButton();
harvestButton.x = 1800;
harvestButton.y = 1616; // Position buttons around the middle
game.addChild(harvestButton);
// Create shop panel (initially hidden)
shopPanel = new ShopPanel();
shopPanel.x = 2048 / 2;
shopPanel.y = 2732 / 2;
shopPanel.visible = false;
game.addChild(shopPanel);
// Create store panel (initially hidden)
storePanel = new StorePanel();
storePanel.x = 2048 / 2;
storePanel.y = 2732 / 2;
storePanel.visible = false;
game.addChild(storePanel);
// Create inventory panel (initially hidden)
playerInventory = new Inventory();
inventoryPanel = playerInventory;
inventoryPanel.x = 2048 / 2;
inventoryPanel.y = 2732 / 2;
inventoryPanel.visible = false;
game.addChild(inventoryPanel);
// Create harvest tracker panel (initially hidden)
harvestTracker = new HarvestTracker();
harvestPanel = harvestTracker;
harvestPanel.x = 2048 / 2;
harvestPanel.y = 2732 / 2;
harvestPanel.visible = false;
game.addChild(harvestPanel);
// Pre-create some coin effects for the pool
for (var i = 0; i < 10; i++) {
coinEffectsPool.push(new CoinEffect());
}
}
function updateMoney(amount) {
// Update both local variable and storage immediately
money += amount;
storage.money = money;
// Update UI to reflect new money amount
moneyText.setText(money.toString() + " coins");
}
function spawnCoinEffect(x, y) {
var coinEffect;
if (coinEffectsPool.length > 0) {
coinEffect = coinEffectsPool.pop();
} else {
coinEffect = new CoinEffect();
}
coinEffect.animate(x, y);
}
function addExperience(amount) {
// Update both local variable and storage
experience += amount;
storage.experience = experience;
// Check for level up
while (experience >= nextLevelExp) {
playerLevel++;
storage.level = playerLevel;
// Calculate next level requirement (increases by 50% each level)
nextLevelExp = Math.floor(nextLevelExp * 1.5);
storage.nextLevelExp = nextLevelExp;
// Show level up effect
var levelUpText = new Text2("LEVEL UP!", {
size: 100,
fill: 0xFFFF00
});
levelUpText.anchor.set(0.5, 0.5);
levelUpText.x = 2048 / 2;
levelUpText.y = 2732 / 2;
game.addChild(levelUpText);
// Scale and fade animation
tween(levelUpText, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(levelUpText);
}
});
// Give bonus for leveling up
updateMoney(playerLevel * 50);
}
// Update experience UI
if (expBar) {
expBar.updateExp(experience, nextLevelExp, playerLevel);
}
}
function toggleShopPanel() {
// Hide other panels if visible
if (inventoryVisible) {
toggleInventoryPanel();
}
if (storeVisible) {
toggleStorePanel();
}
if (harvestVisible) {
toggleHarvestPanel();
}
shopVisible = !shopVisible;
if (shopVisible) {
// Show shop panel with animation
shopPanel.visible = true;
shopPanel.alpha = 0;
tween(shopPanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide shop panel with animation
tween(shopPanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
shopPanel.visible = false;
}
});
}
}
function toggleInventoryPanel() {
// Hide other panels if visible
if (shopVisible) {
toggleShopPanel();
}
if (storeVisible) {
toggleStorePanel();
}
if (harvestVisible) {
toggleHarvestPanel();
}
inventoryVisible = !inventoryVisible;
if (inventoryVisible) {
// Show inventory panel with animation
inventoryPanel.visible = true;
inventoryPanel.alpha = 0;
tween(inventoryPanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide inventory panel with animation
tween(inventoryPanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
inventoryPanel.visible = false;
}
});
}
}
function toggleStorePanel() {
// Hide other panels if visible
if (shopVisible) {
toggleShopPanel();
}
if (inventoryVisible) {
toggleInventoryPanel();
}
if (harvestVisible) {
toggleHarvestPanel();
}
storeVisible = !storeVisible;
if (storeVisible) {
// Show store panel with animation
storePanel.visible = true;
storePanel.alpha = 0;
tween(storePanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide store panel with animation
tween(storePanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
storePanel.visible = false;
}
});
}
}
// Initialize the game
function initGame() {
createPlots();
createToolbar();
createUpgradeShop();
createUI();
createStore();
// Initialize active tool display
updateToolDisplay();
// Initialize experience display
addExperience(0); // Updates UI without adding experience
// Make the first tool button active (hoe is default)
toolButtons[0].setActive(true);
// Arrange seed buttons in shop panel
var seedStartX = -200;
seedButtons.forEach(function (button, index) {
button.x = seedStartX + index * 200;
button.y = 0;
shopPanel.seedContainer.addChild(button);
});
// Arrange upgrade buttons in shop panel
var upgradeStartX = -300;
var upgradeStartY = 0;
upgradeButtons.forEach(function (button, index) {
// 2 rows of 2 buttons
if (index < 2) {
button.x = upgradeStartX + index * 600;
button.y = upgradeStartY;
} else {
button.x = upgradeStartX + (index - 2) * 600;
button.y = upgradeStartY + 120;
}
shopPanel.upgradeContainer.addChild(button);
});
// Start background music
LK.playMusic('bgmusic');
}
initGame();
// Game update loop
game.update = function () {
// Update all plots
for (var i = 0; i < plots.length; i++) {
plots[i].update();
}
// Update score to track maximum money earned
if (money > LK.getScore()) {
LK.setScore(money);
}
};
// Game-level event handlers
game.down = function (x, y, obj) {
// This is handled by individual objects
};
game.up = function (x, y, obj) {
// Nothing needed here
};
game.move = function (x, y, obj) {
// Nothing needed here
};
function toggleHarvestPanel() {
// Hide other panels if visible
if (shopVisible) {
toggleShopPanel();
}
if (storeVisible) {
toggleStorePanel();
}
if (inventoryVisible) {
toggleInventoryPanel();
}
harvestVisible = !harvestVisible;
if (harvestVisible) {
// Show harvest panel with animation
harvestPanel.visible = true;
harvestPanel.alpha = 0;
tween(harvestPanel, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Hide harvest panel with animation
tween(harvestPanel, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
harvestPanel.visible = false;
}
});
}
}
Let's make a Farming Hoe so that we can till soil with it. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Watering can. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Harvesting tool. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Create a tilled soil square. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Rain. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Sun. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Gold coin with design in the center. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Plant seeds. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Wheat plant. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
overview of a grass field. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Farmer. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Rectangle button for farming UI. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Barn. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
farmers Market stand. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
3 bar graphs and different heights. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Pile of seeds. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows