/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { money: 15, cropsSold: 0, fieldsUnlocked: 9, seedQualityLevel: 0, animalPens: 0, hasOven: false, hasBlender: false, hasFishingRod: false }); /**** * Classes ****/ var AnimalPen = Container.expand(function (animalType) { var self = Container.call(this); self.animalType = animalType; self.productionTimer = 0; self.productionInterval = getAnimalInfo(animalType).productionTime * 60; // Convert to frames // Create pen visual var pen = self.attachAsset('soil', { width: 250, height: 250, anchorX: 0.5, anchorY: 0.5 }); pen.alpha = 0.7; // Add animal representation var animalShape = LK.getAsset('carrot', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); animalShape.tint = getAnimalInfo(animalType).color; self.addChild(animalShape); // Product indicator (invisible initially) var productIndicator = new Text2("!", { size: 50, fill: 0xFFFF00 }); productIndicator.anchor.set(0.5); productIndicator.x = 70; productIndicator.y = -70; productIndicator.visible = false; self.addChild(productIndicator); self.productIndicator = productIndicator; // Collect products self.collect = function () { if (self.productIndicator.visible) { money += getAnimalInfo(self.animalType).productValue; updateMoneyDisplay(); self.productIndicator.visible = false; self.productionTimer = 0; // Show collection effect var collectText = new Text2("+" + getAnimalInfo(self.animalType).productValue + "$", { size: 40, fill: 0xFFFF00 }); collectText.anchor.set(0.5); collectText.y = -50; self.addChild(collectText); tween(collectText, { y: -100, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { collectText.destroy(); } }); LK.getSound('harvest').play(); return true; } return false; }; // Interaction handlers self.down = function (x, y, obj) { tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); self.collect(); }; // Update animal pen self.update = function () { self.productionTimer++; if (self.productionTimer >= self.productionInterval && !self.productIndicator.visible) { self.productIndicator.visible = true; // Make indicator bounce tween(self.productIndicator, { y: -80 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self.productIndicator, { y: -70 }, { duration: 500, easing: tween.easeInOut }); } }); } }; return self; }); var CloseButton = Container.expand(function () { var self = Container.call(this); var closeText = new Text2("X", { size: 80, fill: 0xFF0000 }); closeText.anchor.set(0.5); self.addChild(closeText); // Position at bottom left by default self.x = -700; self.y = 800; self.down = function (x, y, obj) { tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); if (self.onClose) { self.onClose(); } }; return self; }); var CropButton = Container.expand(function (cropType) { var self = Container.call(this); self.cropType = cropType; var cropInfo = CropType.getInfo(cropType); var button = self.attachAsset(cropInfo.shape, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6 }); var priceTag = new Text2("$" + cropInfo.seedCost, { size: 25, fill: 0xFFFFFF }); priceTag.anchor.set(0.5, 0); priceTag.y = 40; self.addChild(priceTag); // Add seasonal indicator if current weather is optimal for this crop if (cropInfo.bestSeasons && cropInfo.bestSeasons.includes(currentWeather)) { var seasonalIcon = LK.getAsset('centerCircle', { width: 30, height: 30, anchorX: 0.5, anchorY: 0.5 }); seasonalIcon.tint = 0x00FF00; // Bright green for optimal season seasonalIcon.x = 40; seasonalIcon.y = -40; self.addChild(seasonalIcon); // Make it pulse to draw attention tween(seasonalIcon, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(seasonalIcon, { scaleX: 1.0, scaleY: 1.0 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { // Re-run the first tween to create pulsing effect tween(seasonalIcon, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut }); } }); } }); } // Add warning indicator if current weather is bad for this crop else if (cropInfo.worstSeasons && cropInfo.worstSeasons.includes(currentWeather)) { var warningIcon = LK.getAsset('centerCircle', { width: 30, height: 30, anchorX: 0.5, anchorY: 0.5 }); warningIcon.tint = 0xFF0000; // Red for warning warningIcon.x = 40; warningIcon.y = -40; self.addChild(warningIcon); } self.down = function (x, y, obj) { tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); // Select crop type selectedCropType = self.cropType; selectedTool = 'seed'; updateToolButtons(); // Close selection cropSelectionPanel.visible = false; }; return self; }); var Market = Container.expand(function () { var self = Container.call(this); // Panel visibility state self.visible = false; // Create panel background var marketPanel = LK.getAsset('soil', { width: 1500, height: 1800, anchorX: 0.5, anchorY: 0.5 }); marketPanel.alpha = 0.9; self.addChild(marketPanel); // Title var title = new Text2("Market", { size: 100, fill: 0xFFFFFF }); title.anchor.set(0.5, 0); title.y = -800; self.addChild(title); // Close button var closeButton = new CloseButton(); closeButton.x = 700; closeButton.y = -800; closeButton.onClose = function () { self.hide(); }; self.addChild(closeButton); // Container for crop listings var listingsContainer = new Container(); listingsContainer.y = -600; self.addChild(listingsContainer); self.listingsContainer = listingsContainer; // Stats display var statsText = new Text2("Total crops sold: 0", { size: 50, fill: 0xFFFFFF }); statsText.anchor.set(0.5, 0); statsText.y = 700; self.addChild(statsText); self.statsText = statsText; // Handle close button is now managed by the CloseButton class // Show market with updated listings self.show = function () { self.visible = true; self.updateListings(); self.statsText.setText("Total crops sold: " + storage.cropsSold); }; // Hide market self.hide = function () { self.visible = false; }; // Update crop listings based on ready crops self.updateListings = function () { // Clear current listings while (listingsContainer.children.length > 0) { listingsContainer.children[0].destroy(); } // Initialize listing counts var listings = {}; var yPos = 0; var spacing = 200; // Count ready crops by type plots.forEach(function (plot) { if (plot.state === PlotState.READY) { var type = plot.cropType; if (!listings[type]) { listings[type] = { count: 1, info: CropType.getInfo(type) }; } else { listings[type].count++; } } }); // Create listing for each crop type var listingCount = 0; for (var cropType in listings) { var listing = self.createListing(cropType, listings[cropType]); listing.y = yPos; listingsContainer.addChild(listing); yPos += spacing; listingCount++; } // Show message if no crops ready if (listingCount === 0) { var noItems = new Text2("No crops ready to sell!", { size: 50, fill: 0xFFFFFF }); noItems.anchor.set(0.5, 0); listingsContainer.addChild(noItems); } }; // Create individual listing self.createListing = function (cropType, data) { var container = new Container(); var info = data.info; var count = data.count; // Calculate price boosts from kitchen upgrades var priceMultiplier = 1.0; var upgradeText = ""; if (hasOven && (cropType == CropType.CARROT || cropType == CropType.CORN)) { priceMultiplier += 0.5; upgradeText = " (Oven Bonus)"; } if (hasBlender && cropType == CropType.TOMATO) { priceMultiplier += 0.75; upgradeText = " (Blender Bonus)"; } if (hasFishingRod) { priceMultiplier += 0.2; if (upgradeText === "") upgradeText = " (Fishing Bonus)"; } // Add seasonal pricing bonuses var seasonalBonus = 0; var seasonText = ""; // Check if current weather is a preferred season for this crop type if (info.bestSeasons && info.bestSeasons.includes(currentWeather)) { seasonalBonus = 0.3; // 30% bonus for best seasons seasonText = getWeatherName(currentWeather) + " Season Bonus!"; } // Check if current weather is a detrimental season for this crop else if (info.worstSeasons && info.worstSeasons.includes(currentWeather)) { seasonalBonus = -0.2; // 20% penalty for worst seasons seasonText = getWeatherName(currentWeather) + " Season Penalty"; } // Apply seasonal bonus priceMultiplier += seasonalBonus; // Add seasonal text to upgrade text if it exists if (seasonText) { if (upgradeText) { upgradeText += " + " + seasonText; } else { upgradeText = " (" + seasonText + ")"; } } var totalValue = Math.floor(count * info.sellPrice * priceMultiplier); // Crop icon var icon = LK.getAsset(info.shape, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); icon.x = -550; container.addChild(icon); // Crop info var nameText = new Text2(info.name + " x" + count + upgradeText, { size: 50, fill: 0xFFFFFF }); nameText.anchor.set(0, 0.5); nameText.x = -400; container.addChild(nameText); // Value var valueText = new Text2("$" + totalValue, { size: 50, fill: 0xFFFF00 }); valueText.anchor.set(0, 0.5); valueText.x = 100; container.addChild(valueText); // Sell button var sellButton = LK.getAsset('marketButton', { width: 200, height: 100, anchorX: 0.5, anchorY: 0.5 }); sellButton.x = 500; container.addChild(sellButton); var sellText = new Text2("Sell", { size: 40, fill: 0xFFFFFF }); sellText.anchor.set(0.5); sellText.x = 500; container.addChild(sellText); // Sell button interaction sellButton.down = function (x, y, obj) { tween(sellButton, { alpha: 0.7 }, { duration: 100 }); }; sellButton.up = function (x, y, obj) { tween(sellButton, { alpha: 1 }, { duration: 100 }); // Sell this crop type var soldCount = 0; plots.forEach(function (plot) { if (plot.state === PlotState.READY && plot.cropType == cropType) { plot.reset(); soldCount++; } }); // Award money and update stats if (soldCount > 0) { // Calculate price boosts from kitchen upgrades var priceMultiplier = 1.0; var upgradeBonus = ""; if (hasOven && (cropType == CropType.CARROT || cropType == CropType.CORN)) { priceMultiplier += 0.5; upgradeBonus = " (Oven Bonus)"; } if (hasBlender && cropType == CropType.TOMATO) { priceMultiplier += 0.75; upgradeBonus = " (Blender Bonus)"; } if (hasFishingRod) { priceMultiplier += 0.2; if (upgradeBonus === "") upgradeBonus = " (Fishing Bonus)"; } var totalEarnings = Math.floor(soldCount * info.sellPrice * priceMultiplier); money += totalEarnings; storage.cropsSold += soldCount; storage.money = money; updateMoneyDisplay(); // Show feedback var sellMessage = new Text2("Sold " + soldCount + " " + info.name + " for $" + totalEarnings + "!" + upgradeBonus, { size: 60, fill: 0xFFFF00 }); sellMessage.anchor.set(0.5); sellMessage.x = 0; sellMessage.y = 300; container.addChild(sellMessage); // Animate and remove tween(sellMessage, { alpha: 0, y: 200 }, { duration: 2000, onFinish: function onFinish() { sellMessage.destroy(); self.updateListings(); self.statsText.setText("Total crops sold: " + storage.cropsSold); } }); LK.getSound('sell').play(); } }; return container; }; // Add a close button that appears at the bottom left of the market panel var closeButton = new CloseButton(); closeButton.x = -700; closeButton.y = 800; closeButton.onClose = function () { self.hide(); }; self.addChild(closeButton); return self; }); var MarketButton = Container.expand(function () { var self = Container.call(this); var button = self.attachAsset('marketButton', { anchorX: 0.5, anchorY: 0.5 }); var label = new Text2("Market", { size: 50, fill: 0xFFFFFF }); label.anchor.set(0.5); self.addChild(label); self.down = function (x, y, obj) { tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); // Open market panel marketPanel.show(); }; return self; }); var Plot = Container.expand(function () { var self = Container.call(this); self.state = PlotState.EMPTY; self.cropType = CropType.NONE; self.growthProgress = 0; self.growthTotal = 0; self.needsWater = false; self.isWet = false; // Create soil var soil = self.attachAsset('soil', { anchorX: 0.5, anchorY: 0.5 }); self.soil = soil; // Growth indicator (invisible initially) var seedling = self.attachAsset('seedling', { anchorX: 0.5, anchorY: 1.0, y: 50, visible: false }); self.seedling = seedling; self.plant = function (cropType) { if (self.state !== PlotState.EMPTY || money < CropType.getInfo(cropType).seedCost) { return false; } money -= CropType.getInfo(cropType).seedCost; updateMoneyDisplay(); self.cropType = cropType; self.state = PlotState.SEEDED; self.growthProgress = 0; self.growthTotal = CropType.getInfo(cropType).growthTime * 60; // Convert to frames self.needsWater = true; self.seedling.visible = true; self.seedling.height = 30; // Small at first LK.getSound('plant').play(); return true; }; self.water = function () { if (self.state !== PlotState.SEEDED && self.state !== PlotState.GROWING) { return false; } self.isWet = true; self.needsWater = false; self.soil.texture = LK.getAsset('wetSoil', {}).texture; // Reset drying timeout self.dryTimer = LK.setTimeout(function () { self.isWet = false; self.needsWater = true; self.soil.texture = LK.getAsset('soil', {}).texture; }, 5000); // Soil stays wet for 5 seconds LK.getSound('water').play(); return true; }; self.harvest = function () { if (self.state !== PlotState.READY) { return false; } money += CropType.getInfo(self.cropType).sellPrice; storage.cropsSold++; updateMoneyDisplay(); self.reset(); LK.getSound('harvest').play(); return true; }; self.reset = function () { self.state = PlotState.EMPTY; self.cropType = CropType.NONE; self.growthProgress = 0; self.growthTotal = 0; self.needsWater = false; self.isWet = false; self.soil.texture = LK.getAsset('soil', {}).texture; self.seedling.visible = false; if (self.dryTimer) { LK.clearTimeout(self.dryTimer); } }; self.update = function () { // Growth based on weather and watering status if (self.state === PlotState.SEEDED || self.state === PlotState.GROWING) { // Base growth happens only if plant is watered (except for specific weather effects handled elsewhere) if (self.isWet) { self.growthProgress++; // Apply weather modifiers to crop appearance if (currentWeather === WeatherType.WINTER) { // Plants look slightly wilted in winter self.seedling.tint = 0xCCCCCC; // Grayish } else if (currentWeather === WeatherType.SPRING) { // Plants look extra vibrant in spring self.seedling.tint = 0xFFFFFF; // Normal bright color } else { // Reset tint for other weather self.seedling.tint = 0xFFFFFF; } } // Update crop appearance based on growth progress var growthPercentage = self.growthProgress / self.growthTotal; if (growthPercentage < 0.3) { self.state = PlotState.SEEDED; self.seedling.height = 30 + growthPercentage * 100; } else if (growthPercentage < 1) { self.state = PlotState.GROWING; // If we just entered growing state, change the shape if (self.seedling.texture !== LK.getAsset(CropType.getInfo(self.cropType).shape, {}).texture) { self.seedling.texture = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).texture; self.seedling.width = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).width; self.seedling.height = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).height * growthPercentage; } else { self.seedling.height = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).height * growthPercentage; } } else { // Fully grown self.state = PlotState.READY; self.seedling.height = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).height; self.seedling.tint = 0xFFFFFF; // Reset tint on ready crops // Make it bounce a little to show it's ready tween(self.seedling, { y: 45 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self.seedling, { y: 50 }, { duration: 500, easing: tween.easeInOut }); } }); } } }; // Handle interaction self.down = function (x, y, obj) { // Selection effect tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); if (selectedTool === 'seed') { if (selectedCropType !== CropType.NONE) { self.plant(selectedCropType); } } else if (selectedTool === 'water') { self.water(); } else if (selectedTool === 'harvest') { self.harvest(); } }; return self; }); var RestartButton = Container.expand(function () { var self = Container.call(this); // Create restart button background var button = self.attachAsset('marketButton', { width: 300, height: 150, anchorX: 0.5, anchorY: 0.5 }); // Add restart label var label = new Text2("Restart", { size: 50, fill: 0xFFFFFF }); label.anchor.set(0.5); self.addChild(label); // Button interaction self.down = function (x, y, obj) { tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); // Reset all storage values to default storage.money = 15; storage.cropsSold = 0; storage.fieldsUnlocked = 9; storage.seedQualityLevel = 0; storage.animalPens = 0; storage.hasOven = false; storage.hasBlender = false; storage.hasFishingRod = false; // Clean up UI elements to prevent text overlap if (marketPanel && marketPanel.listingsContainer) { while (marketPanel.listingsContainer.children.length > 0) { marketPanel.listingsContainer.children[0].destroy(); } } if (upgradesPanel && upgradesPanel.upgradesContainer) { while (upgradesPanel.upgradesContainer.children.length > 0) { upgradesPanel.upgradesContainer.children[0].destroy(); } } // Reset the game LK.showYouWin(); }; return self; }); var ToolButton = Container.expand(function (toolType, shape) { var self = Container.call(this); self.toolType = toolType; var button = self.attachAsset(shape, { anchorX: 0.5, anchorY: 0.5 }); var label = new Text2(toolType.charAt(0).toUpperCase() + toolType.slice(1), { size: 30, fill: 0xFFFFFF }); label.anchor.set(0.5); self.addChild(label); self.setSelected = function (isSelected) { button.alpha = isSelected ? 1.0 : 0.7; if (isSelected) { tween(self, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200 }); } else { tween(self, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }; self.down = function (x, y, obj) { tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); // Update selected tool if (self.toolType === 'seed') { openCropSelection(); } else { selectedTool = self.toolType; selectedCropType = CropType.NONE; updateToolButtons(); } }; return self; }); var Upgrade = Container.expand(function (upgradeType) { var self = Container.call(this); var upgradeInfo = getUpgradeInfo(upgradeType); self.upgradeType = upgradeType; // Create button var button = self.attachAsset('marketButton', { width: 400, height: 150, anchorX: 0.5, anchorY: 0.5 }); // Title var title = new Text2(upgradeInfo.name, { size: 40, fill: 0xFFFFFF }); title.anchor.set(0.5, 0); title.y = -50; self.addChild(title); // Price var priceText = new Text2("$" + upgradeInfo.cost, { size: 35, fill: 0xFFFF00 }); priceText.anchor.set(0.5, 0); priceText.y = 10; self.addChild(priceText); // Handle interaction self.down = function (x, y, obj) { tween(self, { alpha: 0.7 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { alpha: 1 }, { duration: 100 }); // Check if player can afford the upgrade if (money >= upgradeInfo.cost) { // Apply upgrade money -= upgradeInfo.cost; updateMoneyDisplay(); if (upgradeType === "newField") { addNewField(); } else if (upgradeType === "newAnimal") { addNewAnimalPen(); } else if (upgradeType === "betterSeeds") { improveSeedQuality(); } else if (upgradeType === "oven") { storage.hasOven = true; hasOven = true; showKitchenUpgradeEffect("Oven"); } else if (upgradeType === "blender") { storage.hasBlender = true; hasBlender = true; showKitchenUpgradeEffect("Blender"); } else if (upgradeType === "fishingRod") { storage.hasFishingRod = true; hasFishingRod = true; showKitchenUpgradeEffect("Fishing Rod"); } // Show success message var successMsg = new Text2("Upgrade purchased!", { size: 50, fill: 0x00FF00 }); successMsg.anchor.set(0.5); successMsg.x = 0; successMsg.y = 200; self.parent.addChild(successMsg); tween(successMsg, { alpha: 0, y: 150 }, { duration: 1500, onFinish: function onFinish() { successMsg.destroy(); } }); // Update upgrades display upgradesPanel.updateUpgrades(); } else { // Show insufficient funds message var errorMsg = new Text2("Not enough money!", { size: 50, fill: 0xFF0000 }); errorMsg.anchor.set(0.5); errorMsg.x = 0; errorMsg.y = 200; self.parent.addChild(errorMsg); tween(errorMsg, { alpha: 0, y: 150 }, { duration: 1500, onFinish: function onFinish() { errorMsg.destroy(); } }); } }; return self; }); var UpgradesPanel = Container.expand(function () { var self = Container.call(this); self.visible = false; // Panel background var background = LK.getAsset('soil', { width: 1500, height: 1800, anchorX: 0.5, anchorY: 0.5 }); background.alpha = 0.9; self.addChild(background); // Title var title = new Text2("Upgrades", { size: 100, fill: 0xFFFFFF }); title.anchor.set(0.5, 0); title.y = -800; self.addChild(title); // Close button var closeButton = new CloseButton(); closeButton.x = 700; closeButton.y = -800; closeButton.onClose = function () { self.hide(); }; self.addChild(closeButton); // Container for upgrade options var upgradesContainer = new Container(); upgradesContainer.y = -500; self.addChild(upgradesContainer); self.upgradesContainer = upgradesContainer; // Add close button var closeButton = new CloseButton(); closeButton.x = -700; closeButton.y = 800; closeButton.onClose = function () { self.hide(); }; self.addChild(closeButton); // Show upgrades panel self.show = function () { self.visible = true; self.updateUpgrades(); }; // Hide upgrades panel self.hide = function () { self.visible = false; }; // Update available upgrades self.updateUpgrades = function () { // Clear current upgrades while (upgradesContainer.children.length > 0) { upgradesContainer.children[0].destroy(); } var yPos = 0; var spacing = 200; // Add "New Field" upgrade if not at maximum if (storage.fieldsUnlocked < 12) { var fieldUpgrade = new Upgrade("newField"); fieldUpgrade.y = yPos; upgradesContainer.addChild(fieldUpgrade); yPos += spacing; } // Add "New Animal" upgrade if not at maximum if (animalPens.length < 3) { var animalUpgrade = new Upgrade("newAnimal"); animalUpgrade.y = yPos; upgradesContainer.addChild(animalUpgrade); yPos += spacing; } // Add "Better Seeds" upgrade if not at maximum level if (storage.seedQualityLevel < 3) { var seedUpgrade = new Upgrade("betterSeeds"); seedUpgrade.y = yPos; upgradesContainer.addChild(seedUpgrade); yPos += spacing; } // Add kitchen upgrades if (!storage.hasOven) { var ovenUpgrade = new Upgrade("oven"); ovenUpgrade.y = yPos; upgradesContainer.addChild(ovenUpgrade); yPos += spacing; } if (!storage.hasBlender) { var blenderUpgrade = new Upgrade("blender"); blenderUpgrade.y = yPos; upgradesContainer.addChild(blenderUpgrade); yPos += spacing; } if (!storage.hasFishingRod) { var fishingRodUpgrade = new Upgrade("fishingRod"); fishingRodUpgrade.y = yPos; upgradesContainer.addChild(fishingRodUpgrade); yPos += spacing; } // Show message if no upgrades available if (upgradesContainer.children.length === 0) { var noUpgrades = new Text2("All upgrades purchased!", { size: 50, fill: 0xFFFFFF }); noUpgrades.anchor.set(0.5, 0); upgradesContainer.addChild(noUpgrades); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game variables var PlotState = { EMPTY: 0, SEEDED: 1, GROWING: 2, READY: 3 }; // Weather types var WeatherType = { SUNNY: 0, RAINY: 1, WINTER: 2, THUNDERSTORM: 3, SPRING: 4 }; // Animal types var AnimalType = { CHICKEN: 1, PIG: 2, COW: 3 }; // Get animal information function getAnimalInfo(type) { switch (type) { case AnimalType.CHICKEN: return { name: "Chicken", productionTime: 30, // seconds productValue: 15, cost: 100, color: 0xFFFFFF }; case AnimalType.PIG: return { name: "Pig", productionTime: 45, // seconds productValue: 35, cost: 250, color: 0xFFB6C1 }; case AnimalType.COW: return { name: "Cow", productionTime: 60, // seconds productValue: 60, cost: 500, color: 0x8B4513 }; default: return { name: "None", productionTime: 0, productValue: 0, cost: 0, color: 0xFFFFFF }; } } // Upgrade definitions function getUpgradeInfo(type) { switch (type) { case "newField": return { name: "New Field", cost: 100 + (storage.fieldsUnlocked - 9) * 50, description: "Expand your farm with a new field" }; case "newAnimal": return { name: "New Animal Pen", cost: 150 + animalPens.length * 100, description: "Add a new animal pen to your farm" }; case "betterSeeds": return { name: "Better Seeds (" + (storage.seedQualityLevel + 1) + "/3)", cost: 200 + storage.seedQualityLevel * 150, description: "Improve crop yield by 25%" }; case "oven": return { name: "Oven", cost: 300, description: "Bake goods to sell for higher prices" }; case "blender": return { name: "Blender", cost: 400, description: "Create smoothies from your fruits" }; case "fishingRod": return { name: "Fishing Rod", cost: 350, description: "Catch fish to sell at the market" }; default: return { name: "Unknown", cost: 0, description: "" }; } } var CropType = { NONE: 0, CARROT: 1, CORN: 2, TOMATO: 3, getInfo: function getInfo(type) { switch (type) { case CropType.CARROT: return { name: "Carrot", growthTime: 35, // in seconds for demo seedCost: 5, sellPrice: 10 + storage.seedQualityLevel * 3, shape: 'carrot', // Seasonal preferences bestSeasons: [WeatherType.WINTER, WeatherType.SPRING], worstSeasons: [WeatherType.THUNDERSTORM] }; case CropType.CORN: return { name: "Corn", growthTime: 45, // in seconds for demo seedCost: 10, sellPrice: 25 + storage.seedQualityLevel * 6, shape: 'corn', // Seasonal preferences bestSeasons: [WeatherType.SUNNY, WeatherType.SPRING], worstSeasons: [WeatherType.WINTER] }; case CropType.TOMATO: return { name: "Tomato", growthTime: 55, // in seconds for demo seedCost: 15, sellPrice: 40 + storage.seedQualityLevel * 10, shape: 'tomato', // Seasonal preferences bestSeasons: [WeatherType.SUNNY, WeatherType.RAINY], worstSeasons: [WeatherType.WINTER, WeatherType.THUNDERSTORM] }; default: return { name: "None", growthTime: 0, seedCost: 0, sellPrice: 0, shape: null, bestSeasons: [], worstSeasons: [] }; } } }; var plots = []; var animalPens = []; var toolButtons = {}; var cropSelectionPanel; var marketPanel; var upgradesPanel; var moneyDisplay; var money = storage.money; var selectedTool = 'seed'; var selectedCropType = CropType.NONE; var hasOven = storage.hasOven; var hasBlender = storage.hasBlender; var hasFishingRod = storage.hasFishingRod; var restartButton; var currentWeather = WeatherType.SUNNY; var weatherEffects = {}; var weatherContainer; var weatherLabel; var weatherTimer = 0; var weatherDuration = 600; // 10 seconds at 60fps // Initialize the farm layout function initializeFarm() { var plotSize = 220; // Size of each plot including margin var gridSize = 3; // 3x3 grid var startX = (2048 - plotSize * gridSize) / 2 + plotSize / 2; var startY = 600; // Start plots below the top UI area // Create plots in a grid for (var row = 0; row < gridSize; row++) { for (var col = 0; col < gridSize; col++) { var plot = new Plot(); plot.x = startX + col * plotSize; plot.y = startY + row * plotSize; // Check if unlocked if (row * gridSize + col < storage.fieldsUnlocked) { game.addChild(plot); plots.push(plot); } } } } // Create UI function createUI() { // Money display moneyDisplay = new Text2("$" + money, { size: 70, fill: 0xFFFF00 }); moneyDisplay.anchor.set(0, 0); moneyDisplay.x = 150; moneyDisplay.y = 50; LK.gui.top.addChild(moneyDisplay); // Title var titleText = new Text2("Harvest Tycoon", { size: 100, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.x = 2048 / 2; titleText.y = 50; LK.gui.addChild(titleText); // Create tool buttons var buttonSize = 120; var buttonSpacing = buttonSize * 1.2; var buttonStartX = 2048 - buttonSize - 50; // Right side of screen with some margin var buttonY = 2732 - buttonSize - 50; // Bottom of screen with some margin // Harvest button (rightmost) toolButtons.harvest = new ToolButton('harvest', 'harvestButton'); toolButtons.harvest.x = buttonStartX; toolButtons.harvest.y = buttonY; game.addChild(toolButtons.harvest); // Water button (middle) toolButtons.water = new ToolButton('water', 'waterButton'); toolButtons.water.x = buttonStartX - buttonSpacing; toolButtons.water.y = buttonY; game.addChild(toolButtons.water); // Seed button (leftmost of the three) toolButtons.seed = new ToolButton('seed', 'seedButton'); toolButtons.seed.x = buttonStartX - buttonSpacing * 2; toolButtons.seed.y = buttonY; game.addChild(toolButtons.seed); // Market button (to sell all ready crops) var marketButton = new MarketButton(); marketButton.x = 2048 - 200; marketButton.y = 200; game.addChild(marketButton); // Upgrades button var upgradesButton = new Container(); var upgradeButtonBg = LK.getAsset('marketButton', { width: 300, height: 150, anchorX: 0.5, anchorY: 0.5 }); upgradesButton.addChild(upgradeButtonBg); var upgradesLabel = new Text2("Upgrades", { size: 50, fill: 0xFFFFFF }); upgradesLabel.anchor.set(0.5); upgradesButton.addChild(upgradesLabel); upgradesButton.x = 2048 - 200; upgradesButton.y = 400; game.addChild(upgradesButton); // Handle upgrades button interaction upgradesButton.down = function (x, y, obj) { tween(upgradesButton, { alpha: 0.7 }, { duration: 100 }); }; upgradesButton.up = function (x, y, obj) { tween(upgradesButton, { alpha: 1 }, { duration: 100 }); // Open upgrades panel upgradesPanel.show(); }; // Create crop selection panel (initially hidden) cropSelectionPanel = new Container(); cropSelectionPanel.visible = false; game.addChild(cropSelectionPanel); // Create market panel (initially hidden) marketPanel = new Market(); marketPanel.x = 2048 / 2; marketPanel.y = 2732 / 2; game.addChild(marketPanel); // Create upgrades panel (initially hidden) upgradesPanel = new UpgradesPanel(); upgradesPanel.x = 2048 / 2; upgradesPanel.y = 2732 / 2; game.addChild(upgradesPanel); // Initialize animal pens if any initializeAnimalPens(); // Clear previous UI elements if they exist before adding restart button if (LK.gui.children) { for (var i = LK.gui.children.length - 1; i >= 0; i--) { if (LK.gui.children[i] instanceof Text2) { LK.gui.children[i].destroy(); } } } // Add restart button restartButton = new RestartButton(); restartButton.x = 200; restartButton.y = 400; game.addChild(restartButton); // Panel background var panelBg = LK.getAsset('soil', { width: 500, height: 200, anchorX: 0.5, anchorY: 0.5 }); panelBg.alpha = 0.8; cropSelectionPanel.addChild(panelBg); // Add close button to crop selection panel var cropPanelCloseButton = new CloseButton(); cropPanelCloseButton.x = -230; cropPanelCloseButton.y = 80; cropPanelCloseButton.onClose = function () { cropSelectionPanel.visible = false; }; cropSelectionPanel.addChild(cropPanelCloseButton); // Add crop buttons var cropButtonX = -150; var cropButtonY = 0; var cropButtonSpacing = 150; var carrotButton = new CropButton(CropType.CARROT); carrotButton.x = cropButtonX; carrotButton.y = cropButtonY; cropSelectionPanel.addChild(carrotButton); var cornButton = new CropButton(CropType.CORN); cornButton.x = cropButtonX + cropButtonSpacing; cornButton.y = cropButtonY; cropSelectionPanel.addChild(cornButton); var tomatoButton = new CropButton(CropType.TOMATO); tomatoButton.x = cropButtonX + cropButtonSpacing * 2; tomatoButton.y = cropButtonY; cropSelectionPanel.addChild(tomatoButton); // Position the panel cropSelectionPanel.x = 2048 / 2; cropSelectionPanel.y = 400; // Set initial tool button states updateToolButtons(); } // Update the money display function updateMoneyDisplay() { moneyDisplay.setText("$" + money); storage.money = money; } // Open crop selection panel function openCropSelection() { cropSelectionPanel.visible = true; selectedTool = 'seed'; updateToolButtons(); } // Update tool button highlighting function updateToolButtons() { for (var tool in toolButtons) { toolButtons[tool].setSelected(tool === selectedTool); } } // Initialize animal pens function initializeAnimalPens() { // Position animal pens to the right of the farm var penStartX = 1700; var penStartY = 1000; var penSpacing = 300; // Create animal pens from storage for (var i = 0; i < storage.animalPens; i++) { addAnimalPenAt(penStartX, penStartY + i * penSpacing, getNextAnimalType(i)); } } // Get appropriate animal type based on index function getNextAnimalType(index) { if (index === 0) return AnimalType.CHICKEN; if (index === 1) return AnimalType.PIG; return AnimalType.COW; } // Add a new field when upgraded function addNewField() { // Find the next unlocked position var plotSize = 220; var gridSize = 4; // Expanded to 4x3 grid var startX = (2048 - plotSize * gridSize) / 2 + plotSize / 2; var startY = 600; var unlocked = storage.fieldsUnlocked; storage.fieldsUnlocked++; // Increment unlocked count // Calculate position var row = Math.floor(unlocked / 3); var col = unlocked % 3; // Create new plot var plot = new Plot(); plot.x = startX + col * plotSize; plot.y = startY + row * plotSize; game.addChild(plot); plots.push(plot); // Show effect tween(plot, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 0 }); tween(plot, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500 }); } // Add a new animal pen when upgraded function addNewAnimalPen() { var penStartX = 1700; var penStartY = 1000; var penSpacing = 300; var animalType = getNextAnimalType(animalPens.length); var pen = addAnimalPenAt(penStartX, penStartY + animalPens.length * penSpacing, animalType); storage.animalPens++; // Show effect tween(pen, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 0 }); tween(pen, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500 }); return pen; } // Helper function to add animal pen at specific position function addAnimalPenAt(x, y, animalType) { var pen = new AnimalPen(animalType); pen.x = x; pen.y = y; game.addChild(pen); animalPens.push(pen); return pen; } // Improve seed quality when upgraded function improveSeedQuality() { storage.seedQualityLevel++; // Show effect on all plots plots.forEach(function (plot) { tween(plot, { alpha: 0.5 }, { duration: 200, onFinish: function onFinish() { tween(plot, { alpha: 1 }, { duration: 200 }); } }); }); } // Show kitchen upgrade effect function showKitchenUpgradeEffect(upgradeName) { // Create a large notification var notification = new Container(); game.addChild(notification); // Background var bg = LK.getAsset('soil', { width: 800, height: 300, anchorX: 0.5, anchorY: 0.5 }); bg.alpha = 0.9; notification.addChild(bg); // Title var title = new Text2(upgradeName + " Purchased!", { size: 60, fill: 0xFFFF00 }); title.anchor.set(0.5, 0); title.y = -100; notification.addChild(title); // Description var desc = new Text2("You can now use your " + upgradeName + " to earn more!", { size: 40, fill: 0xFFFFFF }); desc.anchor.set(0.5, 0); desc.y = 0; notification.addChild(desc); // Position notification notification.x = 2048 / 2; notification.y = 2732 / 2; // Add close button var notificationCloseButton = new CloseButton(); notificationCloseButton.x = 380; notificationCloseButton.y = -120; notificationCloseButton.onClose = function () { tween(notification, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, onFinish: function onFinish() { notification.destroy(); } }); }; notification.addChild(notificationCloseButton); // Animation notification.alpha = 0; notification.scale.set(0.5); tween(notification, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, onFinish: function onFinish() { LK.setTimeout(function () { tween(notification, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, onFinish: function onFinish() { notification.destroy(); } }); }, 3000); } }); } // Initialize weather system function initializeWeather() { // Create container for weather effects weatherContainer = new Container(); game.addChild(weatherContainer); // Create weather label weatherLabel = new Text2("Sunny Day", { size: 60, fill: 0xFFFFFF }); weatherLabel.anchor.set(0, 0); weatherLabel.x = 150; weatherLabel.y = 150; LK.gui.top.addChild(weatherLabel); // Initialize weather effects for each type initializeWeatherEffects(); // Set initial weather changeWeather(WeatherType.SUNNY); } // Initialize weather effect particles for each weather type function initializeWeatherEffects() { // Sunny weatherEffects[WeatherType.SUNNY] = new Container(); var sun = LK.getAsset('centerCircle', { width: 200, height: 200, anchorX: 0.5, anchorY: 0.5 }); sun.tint = 0xFFFF00; sun.x = 200; sun.y = 200; weatherEffects[WeatherType.SUNNY].addChild(sun); // Rainy weatherEffects[WeatherType.RAINY] = new Container(); for (var i = 0; i < 50; i++) { var raindrop = LK.getAsset('seedling', { width: 10, height: 40, anchorX: 0.5, anchorY: 0.5 }); raindrop.tint = 0x1E90FF; raindrop.alpha = 0.7; raindrop.x = Math.random() * 2048; raindrop.y = Math.random() * 1000; raindrop.speedY = 15 + Math.random() * 10; raindrop.update = function () { this.y += this.speedY; if (this.y > 2732) { this.y = -50; this.x = Math.random() * 2048; } }; weatherEffects[WeatherType.RAINY].addChild(raindrop); } // Winter weatherEffects[WeatherType.WINTER] = new Container(); for (var i = 0; i < 50; i++) { var snowflake = LK.getAsset('centerCircle', { width: 10, height: 10, anchorX: 0.5, anchorY: 0.5 }); snowflake.tint = 0xFFFFFF; snowflake.alpha = 0.8; snowflake.x = Math.random() * 2048; snowflake.y = Math.random() * 1000; snowflake.speedY = 2 + Math.random() * 3; snowflake.speedX = Math.random() * 2 - 1; snowflake.update = function () { this.y += this.speedY; this.x += this.speedX; if (this.y > 2732) { this.y = -50; this.x = Math.random() * 2048; } }; weatherEffects[WeatherType.WINTER].addChild(snowflake); } // Thunderstorm weatherEffects[WeatherType.THUNDERSTORM] = new Container(); // Add rain like rainy weather for (var i = 0; i < 70; i++) { var raindrop = LK.getAsset('seedling', { width: 10, height: 40, anchorX: 0.5, anchorY: 0.5 }); raindrop.tint = 0x1E90FF; raindrop.alpha = 0.7; raindrop.x = Math.random() * 2048; raindrop.y = Math.random() * 1000; raindrop.speedY = 20 + Math.random() * 15; raindrop.update = function () { this.y += this.speedY; if (this.y > 2732) { this.y = -50; this.x = Math.random() * 2048; } }; weatherEffects[WeatherType.THUNDERSTORM].addChild(raindrop); } // Lightning effect will be handled separately // Spring weatherEffects[WeatherType.SPRING] = new Container(); for (var i = 0; i < 30; i++) { var flower = LK.getAsset('centerCircle', { width: 15, height: 15, anchorX: 0.5, anchorY: 0.5 }); flower.tint = 0xFF69B4; // Pink flowers flower.alpha = 0.8; flower.x = Math.random() * 2048; flower.y = Math.random() * 1000; flower.speedY = 1 + Math.random() * 2; flower.speedX = Math.random() * 4 - 2; flower.update = function () { this.y += this.speedY; this.x += this.speedX; if (this.y > 2732) { this.y = -50; this.x = Math.random() * 2048; } }; weatherEffects[WeatherType.SPRING].addChild(flower); } } // Change weather to specified type function changeWeather(weatherType) { // Remove current weather effects while (weatherContainer.children.length > 0) { weatherContainer.removeChild(weatherContainer.children[0]); } // Apply new weather effects weatherContainer.addChild(weatherEffects[weatherType]); // Change background color based on weather switch (weatherType) { case WeatherType.SUNNY: game.setBackgroundColor(0x87CEEB); // Sky blue weatherLabel.setText("Sunny Day"); break; case WeatherType.RAINY: game.setBackgroundColor(0x708090); // Slate gray weatherLabel.setText("Rainy Day"); break; case WeatherType.WINTER: game.setBackgroundColor(0xE0FFFF); // Light cyan weatherLabel.setText("Winter Day"); break; case WeatherType.THUNDERSTORM: game.setBackgroundColor(0x4B4B4B); // Dark gray weatherLabel.setText("Thunderstorm"); break; case WeatherType.SPRING: game.setBackgroundColor(0x98FB98); // Pale green weatherLabel.setText("Spring Day"); break; } // Apply weather effects to crops applyWeatherEffectsToCrops(weatherType); // Reset weather timer weatherTimer = 0; // If thunderstorm, schedule random lightning if (weatherType === WeatherType.THUNDERSTORM) { scheduleLightning(); } } // Apply weather effects to all crops function applyWeatherEffectsToCrops(weatherType) { plots.forEach(function (plot) { switch (weatherType) { case WeatherType.RAINY: // Rainy weather automatically waters all plants if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) { plot.water(); // Rainy weather boosts growth for all crops plot.growthProgress += 2; } break; case WeatherType.WINTER: // Winter significantly slows growth and may damage plants if (plot.isWet) { plot.isWet = false; plot.needsWater = true; plot.soil.texture = LK.getAsset('soil', {}).texture; } // Winter slows down growth significantly if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) { plot.growthProgress = Math.max(0, plot.growthProgress - 1); // 5% chance to damage crops in winter if (Math.random() < 0.05) { plot.growthProgress = Math.max(0, plot.growthProgress - 120); // Show freeze effect showFreezeEffect(plot); } } break; case WeatherType.THUNDERSTORM: // Thunderstorm waters plants but may damage some if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) { plot.water(); // 15% chance of crop damage if (Math.random() < 0.15) { plot.growthProgress = Math.max(0, plot.growthProgress - 120); // Set back 2 seconds of growth showLightningDamageEffect(plot); } else { // If not damaged, thunderstorms provide extra nutrients (growth boost) plot.growthProgress += 3; } } break; case WeatherType.SPRING: // Spring significantly speeds up growth for all plants if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) { if (plot.isWet) { plot.growthProgress += 5; // Extra growth in spring - best for growth showSpringBoostEffect(plot); } } break; case WeatherType.SUNNY: // Sunny day provides moderate growth but dries soil faster if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) { if (plot.isWet) { plot.growthProgress += 3; // Good growth in sunny weather // Soil dries faster in sunny weather if (Math.random() < 0.05) { plot.isWet = false; plot.needsWater = true; plot.soil.texture = LK.getAsset('soil', {}).texture; if (plot.dryTimer) { LK.clearTimeout(plot.dryTimer); } } } } break; } }); } // Schedule random lightning flashes for thunderstorm function scheduleLightning() { var delay = 1000 + Math.random() * 5000; // Random delay between 1-6 seconds LK.setTimeout(function () { if (currentWeather === WeatherType.THUNDERSTORM) { // Flash the screen LK.effects.flashScreen(0xFFFFFF, 100); // Schedule next lightning scheduleLightning(); } }, delay); } // Show lightning damage effect on a plot function showLightningDamageEffect(plot) { // Create lightning strike visual effect var lightning = LK.getAsset('seedling', { width: 20, height: 150, anchorX: 0.5, anchorY: 1.0 }); lightning.tint = 0xFFFF00; // Yellow lightning.alpha = 0.8; lightning.x = 0; lightning.y = 0; plot.addChild(lightning); // Create damage text var damageText = new Text2("-2s", { size: 40, fill: 0xFF0000 }); damageText.anchor.set(0.5); damageText.y = -80; plot.addChild(damageText); // Animate and remove tween(lightning, { alpha: 0 }, { duration: 800, onFinish: function onFinish() { lightning.destroy(); } }); tween(damageText, { y: -120, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { damageText.destroy(); } }); } // Show freeze effect on a plot function showFreezeEffect(plot) { // Create freeze visual effect var frost = LK.getAsset('centerCircle', { width: 200, height: 200, anchorX: 0.5, anchorY: 0.5 }); frost.tint = 0xA5F2F3; // Light blue frost.alpha = 0.5; plot.addChild(frost); // Create damage text var damageText = new Text2("Frozen!", { size: 30, fill: 0xA5F2F3 }); damageText.anchor.set(0.5); damageText.y = -50; plot.addChild(damageText); // Animate and remove tween(frost, { alpha: 0 }, { duration: 1200, onFinish: function onFinish() { frost.destroy(); } }); tween(damageText, { y: -80, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { damageText.destroy(); } }); } // Show spring boost effect function showSpringBoostEffect(plot) { if (Math.random() < 0.1) { // Only show occasionally to avoid too many effects // Create growth visual effect var growthEffect = LK.getAsset('centerCircle', { width: 50, height: 50, anchorX: 0.5, anchorY: 0.5 }); growthEffect.tint = 0x00FF00; // Green growthEffect.alpha = 0.5; growthEffect.y = -20; plot.addChild(growthEffect); // Animate and remove tween(growthEffect, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { growthEffect.destroy(); } }); } } // Get readable weather name from weather type function getWeatherName(weatherType) { switch (weatherType) { case WeatherType.SUNNY: return "Sunny"; case WeatherType.RAINY: return "Rainy"; case WeatherType.WINTER: return "Winter"; case WeatherType.THUNDERSTORM: return "Thunderstorm"; case WeatherType.SPRING: return "Spring"; default: return "Unknown"; } } // Update weather effects function updateWeather() { if (weatherContainer && weatherContainer.children.length > 0) { var effects = weatherContainer.children[0]; for (var i = 0; i < effects.children.length; i++) { var effect = effects.children[i]; if (effect.update) { effect.update(); } } } // Check for automatic weather change weatherTimer++; if (weatherTimer > weatherDuration) { // 20% chance to change weather each time period elapses if (Math.random() < 0.2) { var newWeather = Math.floor(Math.random() * 5); if (newWeather !== currentWeather) { currentWeather = newWeather; changeWeather(currentWeather); } } weatherTimer = 0; } } // Initialize game initializeFarm(); createUI(); initializeWeather(); // Play background music LK.playMusic('farmMusic'); // Game update loop game.update = function () { // Update all plots for (var i = 0; i < plots.length; i++) { plots[i].update(); } // Update all animal pens for (var i = 0; i < animalPens.length; i++) { animalPens[i].update(); } // Update weather updateWeather(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
money: 15,
cropsSold: 0,
fieldsUnlocked: 9,
seedQualityLevel: 0,
animalPens: 0,
hasOven: false,
hasBlender: false,
hasFishingRod: false
});
/****
* Classes
****/
var AnimalPen = Container.expand(function (animalType) {
var self = Container.call(this);
self.animalType = animalType;
self.productionTimer = 0;
self.productionInterval = getAnimalInfo(animalType).productionTime * 60; // Convert to frames
// Create pen visual
var pen = self.attachAsset('soil', {
width: 250,
height: 250,
anchorX: 0.5,
anchorY: 0.5
});
pen.alpha = 0.7;
// Add animal representation
var animalShape = LK.getAsset('carrot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
animalShape.tint = getAnimalInfo(animalType).color;
self.addChild(animalShape);
// Product indicator (invisible initially)
var productIndicator = new Text2("!", {
size: 50,
fill: 0xFFFF00
});
productIndicator.anchor.set(0.5);
productIndicator.x = 70;
productIndicator.y = -70;
productIndicator.visible = false;
self.addChild(productIndicator);
self.productIndicator = productIndicator;
// Collect products
self.collect = function () {
if (self.productIndicator.visible) {
money += getAnimalInfo(self.animalType).productValue;
updateMoneyDisplay();
self.productIndicator.visible = false;
self.productionTimer = 0;
// Show collection effect
var collectText = new Text2("+" + getAnimalInfo(self.animalType).productValue + "$", {
size: 40,
fill: 0xFFFF00
});
collectText.anchor.set(0.5);
collectText.y = -50;
self.addChild(collectText);
tween(collectText, {
y: -100,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
collectText.destroy();
}
});
LK.getSound('harvest').play();
return true;
}
return false;
};
// Interaction handlers
self.down = function (x, y, obj) {
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
self.collect();
};
// Update animal pen
self.update = function () {
self.productionTimer++;
if (self.productionTimer >= self.productionInterval && !self.productIndicator.visible) {
self.productIndicator.visible = true;
// Make indicator bounce
tween(self.productIndicator, {
y: -80
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.productIndicator, {
y: -70
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var CloseButton = Container.expand(function () {
var self = Container.call(this);
var closeText = new Text2("X", {
size: 80,
fill: 0xFF0000
});
closeText.anchor.set(0.5);
self.addChild(closeText);
// Position at bottom left by default
self.x = -700;
self.y = 800;
self.down = function (x, y, obj) {
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
if (self.onClose) {
self.onClose();
}
};
return self;
});
var CropButton = Container.expand(function (cropType) {
var self = Container.call(this);
self.cropType = cropType;
var cropInfo = CropType.getInfo(cropType);
var button = self.attachAsset(cropInfo.shape, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var priceTag = new Text2("$" + cropInfo.seedCost, {
size: 25,
fill: 0xFFFFFF
});
priceTag.anchor.set(0.5, 0);
priceTag.y = 40;
self.addChild(priceTag);
// Add seasonal indicator if current weather is optimal for this crop
if (cropInfo.bestSeasons && cropInfo.bestSeasons.includes(currentWeather)) {
var seasonalIcon = LK.getAsset('centerCircle', {
width: 30,
height: 30,
anchorX: 0.5,
anchorY: 0.5
});
seasonalIcon.tint = 0x00FF00; // Bright green for optimal season
seasonalIcon.x = 40;
seasonalIcon.y = -40;
self.addChild(seasonalIcon);
// Make it pulse to draw attention
tween(seasonalIcon, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(seasonalIcon, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Re-run the first tween to create pulsing effect
tween(seasonalIcon, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
});
}
// Add warning indicator if current weather is bad for this crop
else if (cropInfo.worstSeasons && cropInfo.worstSeasons.includes(currentWeather)) {
var warningIcon = LK.getAsset('centerCircle', {
width: 30,
height: 30,
anchorX: 0.5,
anchorY: 0.5
});
warningIcon.tint = 0xFF0000; // Red for warning
warningIcon.x = 40;
warningIcon.y = -40;
self.addChild(warningIcon);
}
self.down = function (x, y, obj) {
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
// Select crop type
selectedCropType = self.cropType;
selectedTool = 'seed';
updateToolButtons();
// Close selection
cropSelectionPanel.visible = false;
};
return self;
});
var Market = Container.expand(function () {
var self = Container.call(this);
// Panel visibility state
self.visible = false;
// Create panel background
var marketPanel = LK.getAsset('soil', {
width: 1500,
height: 1800,
anchorX: 0.5,
anchorY: 0.5
});
marketPanel.alpha = 0.9;
self.addChild(marketPanel);
// Title
var title = new Text2("Market", {
size: 100,
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0);
title.y = -800;
self.addChild(title);
// Close button
var closeButton = new CloseButton();
closeButton.x = 700;
closeButton.y = -800;
closeButton.onClose = function () {
self.hide();
};
self.addChild(closeButton);
// Container for crop listings
var listingsContainer = new Container();
listingsContainer.y = -600;
self.addChild(listingsContainer);
self.listingsContainer = listingsContainer;
// Stats display
var statsText = new Text2("Total crops sold: 0", {
size: 50,
fill: 0xFFFFFF
});
statsText.anchor.set(0.5, 0);
statsText.y = 700;
self.addChild(statsText);
self.statsText = statsText;
// Handle close button is now managed by the CloseButton class
// Show market with updated listings
self.show = function () {
self.visible = true;
self.updateListings();
self.statsText.setText("Total crops sold: " + storage.cropsSold);
};
// Hide market
self.hide = function () {
self.visible = false;
};
// Update crop listings based on ready crops
self.updateListings = function () {
// Clear current listings
while (listingsContainer.children.length > 0) {
listingsContainer.children[0].destroy();
}
// Initialize listing counts
var listings = {};
var yPos = 0;
var spacing = 200;
// Count ready crops by type
plots.forEach(function (plot) {
if (plot.state === PlotState.READY) {
var type = plot.cropType;
if (!listings[type]) {
listings[type] = {
count: 1,
info: CropType.getInfo(type)
};
} else {
listings[type].count++;
}
}
});
// Create listing for each crop type
var listingCount = 0;
for (var cropType in listings) {
var listing = self.createListing(cropType, listings[cropType]);
listing.y = yPos;
listingsContainer.addChild(listing);
yPos += spacing;
listingCount++;
}
// Show message if no crops ready
if (listingCount === 0) {
var noItems = new Text2("No crops ready to sell!", {
size: 50,
fill: 0xFFFFFF
});
noItems.anchor.set(0.5, 0);
listingsContainer.addChild(noItems);
}
};
// Create individual listing
self.createListing = function (cropType, data) {
var container = new Container();
var info = data.info;
var count = data.count;
// Calculate price boosts from kitchen upgrades
var priceMultiplier = 1.0;
var upgradeText = "";
if (hasOven && (cropType == CropType.CARROT || cropType == CropType.CORN)) {
priceMultiplier += 0.5;
upgradeText = " (Oven Bonus)";
}
if (hasBlender && cropType == CropType.TOMATO) {
priceMultiplier += 0.75;
upgradeText = " (Blender Bonus)";
}
if (hasFishingRod) {
priceMultiplier += 0.2;
if (upgradeText === "") upgradeText = " (Fishing Bonus)";
}
// Add seasonal pricing bonuses
var seasonalBonus = 0;
var seasonText = "";
// Check if current weather is a preferred season for this crop type
if (info.bestSeasons && info.bestSeasons.includes(currentWeather)) {
seasonalBonus = 0.3; // 30% bonus for best seasons
seasonText = getWeatherName(currentWeather) + " Season Bonus!";
}
// Check if current weather is a detrimental season for this crop
else if (info.worstSeasons && info.worstSeasons.includes(currentWeather)) {
seasonalBonus = -0.2; // 20% penalty for worst seasons
seasonText = getWeatherName(currentWeather) + " Season Penalty";
}
// Apply seasonal bonus
priceMultiplier += seasonalBonus;
// Add seasonal text to upgrade text if it exists
if (seasonText) {
if (upgradeText) {
upgradeText += " + " + seasonText;
} else {
upgradeText = " (" + seasonText + ")";
}
}
var totalValue = Math.floor(count * info.sellPrice * priceMultiplier);
// Crop icon
var icon = LK.getAsset(info.shape, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
icon.x = -550;
container.addChild(icon);
// Crop info
var nameText = new Text2(info.name + " x" + count + upgradeText, {
size: 50,
fill: 0xFFFFFF
});
nameText.anchor.set(0, 0.5);
nameText.x = -400;
container.addChild(nameText);
// Value
var valueText = new Text2("$" + totalValue, {
size: 50,
fill: 0xFFFF00
});
valueText.anchor.set(0, 0.5);
valueText.x = 100;
container.addChild(valueText);
// Sell button
var sellButton = LK.getAsset('marketButton', {
width: 200,
height: 100,
anchorX: 0.5,
anchorY: 0.5
});
sellButton.x = 500;
container.addChild(sellButton);
var sellText = new Text2("Sell", {
size: 40,
fill: 0xFFFFFF
});
sellText.anchor.set(0.5);
sellText.x = 500;
container.addChild(sellText);
// Sell button interaction
sellButton.down = function (x, y, obj) {
tween(sellButton, {
alpha: 0.7
}, {
duration: 100
});
};
sellButton.up = function (x, y, obj) {
tween(sellButton, {
alpha: 1
}, {
duration: 100
});
// Sell this crop type
var soldCount = 0;
plots.forEach(function (plot) {
if (plot.state === PlotState.READY && plot.cropType == cropType) {
plot.reset();
soldCount++;
}
});
// Award money and update stats
if (soldCount > 0) {
// Calculate price boosts from kitchen upgrades
var priceMultiplier = 1.0;
var upgradeBonus = "";
if (hasOven && (cropType == CropType.CARROT || cropType == CropType.CORN)) {
priceMultiplier += 0.5;
upgradeBonus = " (Oven Bonus)";
}
if (hasBlender && cropType == CropType.TOMATO) {
priceMultiplier += 0.75;
upgradeBonus = " (Blender Bonus)";
}
if (hasFishingRod) {
priceMultiplier += 0.2;
if (upgradeBonus === "") upgradeBonus = " (Fishing Bonus)";
}
var totalEarnings = Math.floor(soldCount * info.sellPrice * priceMultiplier);
money += totalEarnings;
storage.cropsSold += soldCount;
storage.money = money;
updateMoneyDisplay();
// Show feedback
var sellMessage = new Text2("Sold " + soldCount + " " + info.name + " for $" + totalEarnings + "!" + upgradeBonus, {
size: 60,
fill: 0xFFFF00
});
sellMessage.anchor.set(0.5);
sellMessage.x = 0;
sellMessage.y = 300;
container.addChild(sellMessage);
// Animate and remove
tween(sellMessage, {
alpha: 0,
y: 200
}, {
duration: 2000,
onFinish: function onFinish() {
sellMessage.destroy();
self.updateListings();
self.statsText.setText("Total crops sold: " + storage.cropsSold);
}
});
LK.getSound('sell').play();
}
};
return container;
};
// Add a close button that appears at the bottom left of the market panel
var closeButton = new CloseButton();
closeButton.x = -700;
closeButton.y = 800;
closeButton.onClose = function () {
self.hide();
};
self.addChild(closeButton);
return self;
});
var MarketButton = Container.expand(function () {
var self = Container.call(this);
var button = self.attachAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2("Market", {
size: 50,
fill: 0xFFFFFF
});
label.anchor.set(0.5);
self.addChild(label);
self.down = function (x, y, obj) {
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
// Open market panel
marketPanel.show();
};
return self;
});
var Plot = Container.expand(function () {
var self = Container.call(this);
self.state = PlotState.EMPTY;
self.cropType = CropType.NONE;
self.growthProgress = 0;
self.growthTotal = 0;
self.needsWater = false;
self.isWet = false;
// Create soil
var soil = self.attachAsset('soil', {
anchorX: 0.5,
anchorY: 0.5
});
self.soil = soil;
// Growth indicator (invisible initially)
var seedling = self.attachAsset('seedling', {
anchorX: 0.5,
anchorY: 1.0,
y: 50,
visible: false
});
self.seedling = seedling;
self.plant = function (cropType) {
if (self.state !== PlotState.EMPTY || money < CropType.getInfo(cropType).seedCost) {
return false;
}
money -= CropType.getInfo(cropType).seedCost;
updateMoneyDisplay();
self.cropType = cropType;
self.state = PlotState.SEEDED;
self.growthProgress = 0;
self.growthTotal = CropType.getInfo(cropType).growthTime * 60; // Convert to frames
self.needsWater = true;
self.seedling.visible = true;
self.seedling.height = 30; // Small at first
LK.getSound('plant').play();
return true;
};
self.water = function () {
if (self.state !== PlotState.SEEDED && self.state !== PlotState.GROWING) {
return false;
}
self.isWet = true;
self.needsWater = false;
self.soil.texture = LK.getAsset('wetSoil', {}).texture;
// Reset drying timeout
self.dryTimer = LK.setTimeout(function () {
self.isWet = false;
self.needsWater = true;
self.soil.texture = LK.getAsset('soil', {}).texture;
}, 5000); // Soil stays wet for 5 seconds
LK.getSound('water').play();
return true;
};
self.harvest = function () {
if (self.state !== PlotState.READY) {
return false;
}
money += CropType.getInfo(self.cropType).sellPrice;
storage.cropsSold++;
updateMoneyDisplay();
self.reset();
LK.getSound('harvest').play();
return true;
};
self.reset = function () {
self.state = PlotState.EMPTY;
self.cropType = CropType.NONE;
self.growthProgress = 0;
self.growthTotal = 0;
self.needsWater = false;
self.isWet = false;
self.soil.texture = LK.getAsset('soil', {}).texture;
self.seedling.visible = false;
if (self.dryTimer) {
LK.clearTimeout(self.dryTimer);
}
};
self.update = function () {
// Growth based on weather and watering status
if (self.state === PlotState.SEEDED || self.state === PlotState.GROWING) {
// Base growth happens only if plant is watered (except for specific weather effects handled elsewhere)
if (self.isWet) {
self.growthProgress++;
// Apply weather modifiers to crop appearance
if (currentWeather === WeatherType.WINTER) {
// Plants look slightly wilted in winter
self.seedling.tint = 0xCCCCCC; // Grayish
} else if (currentWeather === WeatherType.SPRING) {
// Plants look extra vibrant in spring
self.seedling.tint = 0xFFFFFF; // Normal bright color
} else {
// Reset tint for other weather
self.seedling.tint = 0xFFFFFF;
}
}
// Update crop appearance based on growth progress
var growthPercentage = self.growthProgress / self.growthTotal;
if (growthPercentage < 0.3) {
self.state = PlotState.SEEDED;
self.seedling.height = 30 + growthPercentage * 100;
} else if (growthPercentage < 1) {
self.state = PlotState.GROWING;
// If we just entered growing state, change the shape
if (self.seedling.texture !== LK.getAsset(CropType.getInfo(self.cropType).shape, {}).texture) {
self.seedling.texture = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).texture;
self.seedling.width = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).width;
self.seedling.height = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).height * growthPercentage;
} else {
self.seedling.height = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).height * growthPercentage;
}
} else {
// Fully grown
self.state = PlotState.READY;
self.seedling.height = LK.getAsset(CropType.getInfo(self.cropType).shape, {}).height;
self.seedling.tint = 0xFFFFFF; // Reset tint on ready crops
// Make it bounce a little to show it's ready
tween(self.seedling, {
y: 45
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.seedling, {
y: 50
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
}
};
// Handle interaction
self.down = function (x, y, obj) {
// Selection effect
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
if (selectedTool === 'seed') {
if (selectedCropType !== CropType.NONE) {
self.plant(selectedCropType);
}
} else if (selectedTool === 'water') {
self.water();
} else if (selectedTool === 'harvest') {
self.harvest();
}
};
return self;
});
var RestartButton = Container.expand(function () {
var self = Container.call(this);
// Create restart button background
var button = self.attachAsset('marketButton', {
width: 300,
height: 150,
anchorX: 0.5,
anchorY: 0.5
});
// Add restart label
var label = new Text2("Restart", {
size: 50,
fill: 0xFFFFFF
});
label.anchor.set(0.5);
self.addChild(label);
// Button interaction
self.down = function (x, y, obj) {
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
// Reset all storage values to default
storage.money = 15;
storage.cropsSold = 0;
storage.fieldsUnlocked = 9;
storage.seedQualityLevel = 0;
storage.animalPens = 0;
storage.hasOven = false;
storage.hasBlender = false;
storage.hasFishingRod = false;
// Clean up UI elements to prevent text overlap
if (marketPanel && marketPanel.listingsContainer) {
while (marketPanel.listingsContainer.children.length > 0) {
marketPanel.listingsContainer.children[0].destroy();
}
}
if (upgradesPanel && upgradesPanel.upgradesContainer) {
while (upgradesPanel.upgradesContainer.children.length > 0) {
upgradesPanel.upgradesContainer.children[0].destroy();
}
}
// Reset the game
LK.showYouWin();
};
return self;
});
var ToolButton = Container.expand(function (toolType, shape) {
var self = Container.call(this);
self.toolType = toolType;
var button = self.attachAsset(shape, {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2(toolType.charAt(0).toUpperCase() + toolType.slice(1), {
size: 30,
fill: 0xFFFFFF
});
label.anchor.set(0.5);
self.addChild(label);
self.setSelected = function (isSelected) {
button.alpha = isSelected ? 1.0 : 0.7;
if (isSelected) {
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
} else {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
};
self.down = function (x, y, obj) {
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
// Update selected tool
if (self.toolType === 'seed') {
openCropSelection();
} else {
selectedTool = self.toolType;
selectedCropType = CropType.NONE;
updateToolButtons();
}
};
return self;
});
var Upgrade = Container.expand(function (upgradeType) {
var self = Container.call(this);
var upgradeInfo = getUpgradeInfo(upgradeType);
self.upgradeType = upgradeType;
// Create button
var button = self.attachAsset('marketButton', {
width: 400,
height: 150,
anchorX: 0.5,
anchorY: 0.5
});
// Title
var title = new Text2(upgradeInfo.name, {
size: 40,
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0);
title.y = -50;
self.addChild(title);
// Price
var priceText = new Text2("$" + upgradeInfo.cost, {
size: 35,
fill: 0xFFFF00
});
priceText.anchor.set(0.5, 0);
priceText.y = 10;
self.addChild(priceText);
// Handle interaction
self.down = function (x, y, obj) {
tween(self, {
alpha: 0.7
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
alpha: 1
}, {
duration: 100
});
// Check if player can afford the upgrade
if (money >= upgradeInfo.cost) {
// Apply upgrade
money -= upgradeInfo.cost;
updateMoneyDisplay();
if (upgradeType === "newField") {
addNewField();
} else if (upgradeType === "newAnimal") {
addNewAnimalPen();
} else if (upgradeType === "betterSeeds") {
improveSeedQuality();
} else if (upgradeType === "oven") {
storage.hasOven = true;
hasOven = true;
showKitchenUpgradeEffect("Oven");
} else if (upgradeType === "blender") {
storage.hasBlender = true;
hasBlender = true;
showKitchenUpgradeEffect("Blender");
} else if (upgradeType === "fishingRod") {
storage.hasFishingRod = true;
hasFishingRod = true;
showKitchenUpgradeEffect("Fishing Rod");
}
// Show success message
var successMsg = new Text2("Upgrade purchased!", {
size: 50,
fill: 0x00FF00
});
successMsg.anchor.set(0.5);
successMsg.x = 0;
successMsg.y = 200;
self.parent.addChild(successMsg);
tween(successMsg, {
alpha: 0,
y: 150
}, {
duration: 1500,
onFinish: function onFinish() {
successMsg.destroy();
}
});
// Update upgrades display
upgradesPanel.updateUpgrades();
} else {
// Show insufficient funds message
var errorMsg = new Text2("Not enough money!", {
size: 50,
fill: 0xFF0000
});
errorMsg.anchor.set(0.5);
errorMsg.x = 0;
errorMsg.y = 200;
self.parent.addChild(errorMsg);
tween(errorMsg, {
alpha: 0,
y: 150
}, {
duration: 1500,
onFinish: function onFinish() {
errorMsg.destroy();
}
});
}
};
return self;
});
var UpgradesPanel = Container.expand(function () {
var self = Container.call(this);
self.visible = false;
// Panel background
var background = LK.getAsset('soil', {
width: 1500,
height: 1800,
anchorX: 0.5,
anchorY: 0.5
});
background.alpha = 0.9;
self.addChild(background);
// Title
var title = new Text2("Upgrades", {
size: 100,
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0);
title.y = -800;
self.addChild(title);
// Close button
var closeButton = new CloseButton();
closeButton.x = 700;
closeButton.y = -800;
closeButton.onClose = function () {
self.hide();
};
self.addChild(closeButton);
// Container for upgrade options
var upgradesContainer = new Container();
upgradesContainer.y = -500;
self.addChild(upgradesContainer);
self.upgradesContainer = upgradesContainer;
// Add close button
var closeButton = new CloseButton();
closeButton.x = -700;
closeButton.y = 800;
closeButton.onClose = function () {
self.hide();
};
self.addChild(closeButton);
// Show upgrades panel
self.show = function () {
self.visible = true;
self.updateUpgrades();
};
// Hide upgrades panel
self.hide = function () {
self.visible = false;
};
// Update available upgrades
self.updateUpgrades = function () {
// Clear current upgrades
while (upgradesContainer.children.length > 0) {
upgradesContainer.children[0].destroy();
}
var yPos = 0;
var spacing = 200;
// Add "New Field" upgrade if not at maximum
if (storage.fieldsUnlocked < 12) {
var fieldUpgrade = new Upgrade("newField");
fieldUpgrade.y = yPos;
upgradesContainer.addChild(fieldUpgrade);
yPos += spacing;
}
// Add "New Animal" upgrade if not at maximum
if (animalPens.length < 3) {
var animalUpgrade = new Upgrade("newAnimal");
animalUpgrade.y = yPos;
upgradesContainer.addChild(animalUpgrade);
yPos += spacing;
}
// Add "Better Seeds" upgrade if not at maximum level
if (storage.seedQualityLevel < 3) {
var seedUpgrade = new Upgrade("betterSeeds");
seedUpgrade.y = yPos;
upgradesContainer.addChild(seedUpgrade);
yPos += spacing;
}
// Add kitchen upgrades
if (!storage.hasOven) {
var ovenUpgrade = new Upgrade("oven");
ovenUpgrade.y = yPos;
upgradesContainer.addChild(ovenUpgrade);
yPos += spacing;
}
if (!storage.hasBlender) {
var blenderUpgrade = new Upgrade("blender");
blenderUpgrade.y = yPos;
upgradesContainer.addChild(blenderUpgrade);
yPos += spacing;
}
if (!storage.hasFishingRod) {
var fishingRodUpgrade = new Upgrade("fishingRod");
fishingRodUpgrade.y = yPos;
upgradesContainer.addChild(fishingRodUpgrade);
yPos += spacing;
}
// Show message if no upgrades available
if (upgradesContainer.children.length === 0) {
var noUpgrades = new Text2("All upgrades purchased!", {
size: 50,
fill: 0xFFFFFF
});
noUpgrades.anchor.set(0.5, 0);
upgradesContainer.addChild(noUpgrades);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var PlotState = {
EMPTY: 0,
SEEDED: 1,
GROWING: 2,
READY: 3
};
// Weather types
var WeatherType = {
SUNNY: 0,
RAINY: 1,
WINTER: 2,
THUNDERSTORM: 3,
SPRING: 4
};
// Animal types
var AnimalType = {
CHICKEN: 1,
PIG: 2,
COW: 3
};
// Get animal information
function getAnimalInfo(type) {
switch (type) {
case AnimalType.CHICKEN:
return {
name: "Chicken",
productionTime: 30,
// seconds
productValue: 15,
cost: 100,
color: 0xFFFFFF
};
case AnimalType.PIG:
return {
name: "Pig",
productionTime: 45,
// seconds
productValue: 35,
cost: 250,
color: 0xFFB6C1
};
case AnimalType.COW:
return {
name: "Cow",
productionTime: 60,
// seconds
productValue: 60,
cost: 500,
color: 0x8B4513
};
default:
return {
name: "None",
productionTime: 0,
productValue: 0,
cost: 0,
color: 0xFFFFFF
};
}
}
// Upgrade definitions
function getUpgradeInfo(type) {
switch (type) {
case "newField":
return {
name: "New Field",
cost: 100 + (storage.fieldsUnlocked - 9) * 50,
description: "Expand your farm with a new field"
};
case "newAnimal":
return {
name: "New Animal Pen",
cost: 150 + animalPens.length * 100,
description: "Add a new animal pen to your farm"
};
case "betterSeeds":
return {
name: "Better Seeds (" + (storage.seedQualityLevel + 1) + "/3)",
cost: 200 + storage.seedQualityLevel * 150,
description: "Improve crop yield by 25%"
};
case "oven":
return {
name: "Oven",
cost: 300,
description: "Bake goods to sell for higher prices"
};
case "blender":
return {
name: "Blender",
cost: 400,
description: "Create smoothies from your fruits"
};
case "fishingRod":
return {
name: "Fishing Rod",
cost: 350,
description: "Catch fish to sell at the market"
};
default:
return {
name: "Unknown",
cost: 0,
description: ""
};
}
}
var CropType = {
NONE: 0,
CARROT: 1,
CORN: 2,
TOMATO: 3,
getInfo: function getInfo(type) {
switch (type) {
case CropType.CARROT:
return {
name: "Carrot",
growthTime: 35,
// in seconds for demo
seedCost: 5,
sellPrice: 10 + storage.seedQualityLevel * 3,
shape: 'carrot',
// Seasonal preferences
bestSeasons: [WeatherType.WINTER, WeatherType.SPRING],
worstSeasons: [WeatherType.THUNDERSTORM]
};
case CropType.CORN:
return {
name: "Corn",
growthTime: 45,
// in seconds for demo
seedCost: 10,
sellPrice: 25 + storage.seedQualityLevel * 6,
shape: 'corn',
// Seasonal preferences
bestSeasons: [WeatherType.SUNNY, WeatherType.SPRING],
worstSeasons: [WeatherType.WINTER]
};
case CropType.TOMATO:
return {
name: "Tomato",
growthTime: 55,
// in seconds for demo
seedCost: 15,
sellPrice: 40 + storage.seedQualityLevel * 10,
shape: 'tomato',
// Seasonal preferences
bestSeasons: [WeatherType.SUNNY, WeatherType.RAINY],
worstSeasons: [WeatherType.WINTER, WeatherType.THUNDERSTORM]
};
default:
return {
name: "None",
growthTime: 0,
seedCost: 0,
sellPrice: 0,
shape: null,
bestSeasons: [],
worstSeasons: []
};
}
}
};
var plots = [];
var animalPens = [];
var toolButtons = {};
var cropSelectionPanel;
var marketPanel;
var upgradesPanel;
var moneyDisplay;
var money = storage.money;
var selectedTool = 'seed';
var selectedCropType = CropType.NONE;
var hasOven = storage.hasOven;
var hasBlender = storage.hasBlender;
var hasFishingRod = storage.hasFishingRod;
var restartButton;
var currentWeather = WeatherType.SUNNY;
var weatherEffects = {};
var weatherContainer;
var weatherLabel;
var weatherTimer = 0;
var weatherDuration = 600; // 10 seconds at 60fps
// Initialize the farm layout
function initializeFarm() {
var plotSize = 220; // Size of each plot including margin
var gridSize = 3; // 3x3 grid
var startX = (2048 - plotSize * gridSize) / 2 + plotSize / 2;
var startY = 600; // Start plots below the top UI area
// Create plots in a grid
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
var plot = new Plot();
plot.x = startX + col * plotSize;
plot.y = startY + row * plotSize;
// Check if unlocked
if (row * gridSize + col < storage.fieldsUnlocked) {
game.addChild(plot);
plots.push(plot);
}
}
}
}
// Create UI
function createUI() {
// Money display
moneyDisplay = new Text2("$" + money, {
size: 70,
fill: 0xFFFF00
});
moneyDisplay.anchor.set(0, 0);
moneyDisplay.x = 150;
moneyDisplay.y = 50;
LK.gui.top.addChild(moneyDisplay);
// Title
var titleText = new Text2("Harvest Tycoon", {
size: 100,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 50;
LK.gui.addChild(titleText);
// Create tool buttons
var buttonSize = 120;
var buttonSpacing = buttonSize * 1.2;
var buttonStartX = 2048 - buttonSize - 50; // Right side of screen with some margin
var buttonY = 2732 - buttonSize - 50; // Bottom of screen with some margin
// Harvest button (rightmost)
toolButtons.harvest = new ToolButton('harvest', 'harvestButton');
toolButtons.harvest.x = buttonStartX;
toolButtons.harvest.y = buttonY;
game.addChild(toolButtons.harvest);
// Water button (middle)
toolButtons.water = new ToolButton('water', 'waterButton');
toolButtons.water.x = buttonStartX - buttonSpacing;
toolButtons.water.y = buttonY;
game.addChild(toolButtons.water);
// Seed button (leftmost of the three)
toolButtons.seed = new ToolButton('seed', 'seedButton');
toolButtons.seed.x = buttonStartX - buttonSpacing * 2;
toolButtons.seed.y = buttonY;
game.addChild(toolButtons.seed);
// Market button (to sell all ready crops)
var marketButton = new MarketButton();
marketButton.x = 2048 - 200;
marketButton.y = 200;
game.addChild(marketButton);
// Upgrades button
var upgradesButton = new Container();
var upgradeButtonBg = LK.getAsset('marketButton', {
width: 300,
height: 150,
anchorX: 0.5,
anchorY: 0.5
});
upgradesButton.addChild(upgradeButtonBg);
var upgradesLabel = new Text2("Upgrades", {
size: 50,
fill: 0xFFFFFF
});
upgradesLabel.anchor.set(0.5);
upgradesButton.addChild(upgradesLabel);
upgradesButton.x = 2048 - 200;
upgradesButton.y = 400;
game.addChild(upgradesButton);
// Handle upgrades button interaction
upgradesButton.down = function (x, y, obj) {
tween(upgradesButton, {
alpha: 0.7
}, {
duration: 100
});
};
upgradesButton.up = function (x, y, obj) {
tween(upgradesButton, {
alpha: 1
}, {
duration: 100
});
// Open upgrades panel
upgradesPanel.show();
};
// Create crop selection panel (initially hidden)
cropSelectionPanel = new Container();
cropSelectionPanel.visible = false;
game.addChild(cropSelectionPanel);
// Create market panel (initially hidden)
marketPanel = new Market();
marketPanel.x = 2048 / 2;
marketPanel.y = 2732 / 2;
game.addChild(marketPanel);
// Create upgrades panel (initially hidden)
upgradesPanel = new UpgradesPanel();
upgradesPanel.x = 2048 / 2;
upgradesPanel.y = 2732 / 2;
game.addChild(upgradesPanel);
// Initialize animal pens if any
initializeAnimalPens();
// Clear previous UI elements if they exist before adding restart button
if (LK.gui.children) {
for (var i = LK.gui.children.length - 1; i >= 0; i--) {
if (LK.gui.children[i] instanceof Text2) {
LK.gui.children[i].destroy();
}
}
}
// Add restart button
restartButton = new RestartButton();
restartButton.x = 200;
restartButton.y = 400;
game.addChild(restartButton);
// Panel background
var panelBg = LK.getAsset('soil', {
width: 500,
height: 200,
anchorX: 0.5,
anchorY: 0.5
});
panelBg.alpha = 0.8;
cropSelectionPanel.addChild(panelBg);
// Add close button to crop selection panel
var cropPanelCloseButton = new CloseButton();
cropPanelCloseButton.x = -230;
cropPanelCloseButton.y = 80;
cropPanelCloseButton.onClose = function () {
cropSelectionPanel.visible = false;
};
cropSelectionPanel.addChild(cropPanelCloseButton);
// Add crop buttons
var cropButtonX = -150;
var cropButtonY = 0;
var cropButtonSpacing = 150;
var carrotButton = new CropButton(CropType.CARROT);
carrotButton.x = cropButtonX;
carrotButton.y = cropButtonY;
cropSelectionPanel.addChild(carrotButton);
var cornButton = new CropButton(CropType.CORN);
cornButton.x = cropButtonX + cropButtonSpacing;
cornButton.y = cropButtonY;
cropSelectionPanel.addChild(cornButton);
var tomatoButton = new CropButton(CropType.TOMATO);
tomatoButton.x = cropButtonX + cropButtonSpacing * 2;
tomatoButton.y = cropButtonY;
cropSelectionPanel.addChild(tomatoButton);
// Position the panel
cropSelectionPanel.x = 2048 / 2;
cropSelectionPanel.y = 400;
// Set initial tool button states
updateToolButtons();
}
// Update the money display
function updateMoneyDisplay() {
moneyDisplay.setText("$" + money);
storage.money = money;
}
// Open crop selection panel
function openCropSelection() {
cropSelectionPanel.visible = true;
selectedTool = 'seed';
updateToolButtons();
}
// Update tool button highlighting
function updateToolButtons() {
for (var tool in toolButtons) {
toolButtons[tool].setSelected(tool === selectedTool);
}
}
// Initialize animal pens
function initializeAnimalPens() {
// Position animal pens to the right of the farm
var penStartX = 1700;
var penStartY = 1000;
var penSpacing = 300;
// Create animal pens from storage
for (var i = 0; i < storage.animalPens; i++) {
addAnimalPenAt(penStartX, penStartY + i * penSpacing, getNextAnimalType(i));
}
}
// Get appropriate animal type based on index
function getNextAnimalType(index) {
if (index === 0) return AnimalType.CHICKEN;
if (index === 1) return AnimalType.PIG;
return AnimalType.COW;
}
// Add a new field when upgraded
function addNewField() {
// Find the next unlocked position
var plotSize = 220;
var gridSize = 4; // Expanded to 4x3 grid
var startX = (2048 - plotSize * gridSize) / 2 + plotSize / 2;
var startY = 600;
var unlocked = storage.fieldsUnlocked;
storage.fieldsUnlocked++; // Increment unlocked count
// Calculate position
var row = Math.floor(unlocked / 3);
var col = unlocked % 3;
// Create new plot
var plot = new Plot();
plot.x = startX + col * plotSize;
plot.y = startY + row * plotSize;
game.addChild(plot);
plots.push(plot);
// Show effect
tween(plot, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 0
});
tween(plot, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500
});
}
// Add a new animal pen when upgraded
function addNewAnimalPen() {
var penStartX = 1700;
var penStartY = 1000;
var penSpacing = 300;
var animalType = getNextAnimalType(animalPens.length);
var pen = addAnimalPenAt(penStartX, penStartY + animalPens.length * penSpacing, animalType);
storage.animalPens++;
// Show effect
tween(pen, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 0
});
tween(pen, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500
});
return pen;
}
// Helper function to add animal pen at specific position
function addAnimalPenAt(x, y, animalType) {
var pen = new AnimalPen(animalType);
pen.x = x;
pen.y = y;
game.addChild(pen);
animalPens.push(pen);
return pen;
}
// Improve seed quality when upgraded
function improveSeedQuality() {
storage.seedQualityLevel++;
// Show effect on all plots
plots.forEach(function (plot) {
tween(plot, {
alpha: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(plot, {
alpha: 1
}, {
duration: 200
});
}
});
});
}
// Show kitchen upgrade effect
function showKitchenUpgradeEffect(upgradeName) {
// Create a large notification
var notification = new Container();
game.addChild(notification);
// Background
var bg = LK.getAsset('soil', {
width: 800,
height: 300,
anchorX: 0.5,
anchorY: 0.5
});
bg.alpha = 0.9;
notification.addChild(bg);
// Title
var title = new Text2(upgradeName + " Purchased!", {
size: 60,
fill: 0xFFFF00
});
title.anchor.set(0.5, 0);
title.y = -100;
notification.addChild(title);
// Description
var desc = new Text2("You can now use your " + upgradeName + " to earn more!", {
size: 40,
fill: 0xFFFFFF
});
desc.anchor.set(0.5, 0);
desc.y = 0;
notification.addChild(desc);
// Position notification
notification.x = 2048 / 2;
notification.y = 2732 / 2;
// Add close button
var notificationCloseButton = new CloseButton();
notificationCloseButton.x = 380;
notificationCloseButton.y = -120;
notificationCloseButton.onClose = function () {
tween(notification, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
onFinish: function onFinish() {
notification.destroy();
}
});
};
notification.addChild(notificationCloseButton);
// Animation
notification.alpha = 0;
notification.scale.set(0.5);
tween(notification, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 3000);
}
});
}
// Initialize weather system
function initializeWeather() {
// Create container for weather effects
weatherContainer = new Container();
game.addChild(weatherContainer);
// Create weather label
weatherLabel = new Text2("Sunny Day", {
size: 60,
fill: 0xFFFFFF
});
weatherLabel.anchor.set(0, 0);
weatherLabel.x = 150;
weatherLabel.y = 150;
LK.gui.top.addChild(weatherLabel);
// Initialize weather effects for each type
initializeWeatherEffects();
// Set initial weather
changeWeather(WeatherType.SUNNY);
}
// Initialize weather effect particles for each weather type
function initializeWeatherEffects() {
// Sunny
weatherEffects[WeatherType.SUNNY] = new Container();
var sun = LK.getAsset('centerCircle', {
width: 200,
height: 200,
anchorX: 0.5,
anchorY: 0.5
});
sun.tint = 0xFFFF00;
sun.x = 200;
sun.y = 200;
weatherEffects[WeatherType.SUNNY].addChild(sun);
// Rainy
weatherEffects[WeatherType.RAINY] = new Container();
for (var i = 0; i < 50; i++) {
var raindrop = LK.getAsset('seedling', {
width: 10,
height: 40,
anchorX: 0.5,
anchorY: 0.5
});
raindrop.tint = 0x1E90FF;
raindrop.alpha = 0.7;
raindrop.x = Math.random() * 2048;
raindrop.y = Math.random() * 1000;
raindrop.speedY = 15 + Math.random() * 10;
raindrop.update = function () {
this.y += this.speedY;
if (this.y > 2732) {
this.y = -50;
this.x = Math.random() * 2048;
}
};
weatherEffects[WeatherType.RAINY].addChild(raindrop);
}
// Winter
weatherEffects[WeatherType.WINTER] = new Container();
for (var i = 0; i < 50; i++) {
var snowflake = LK.getAsset('centerCircle', {
width: 10,
height: 10,
anchorX: 0.5,
anchorY: 0.5
});
snowflake.tint = 0xFFFFFF;
snowflake.alpha = 0.8;
snowflake.x = Math.random() * 2048;
snowflake.y = Math.random() * 1000;
snowflake.speedY = 2 + Math.random() * 3;
snowflake.speedX = Math.random() * 2 - 1;
snowflake.update = function () {
this.y += this.speedY;
this.x += this.speedX;
if (this.y > 2732) {
this.y = -50;
this.x = Math.random() * 2048;
}
};
weatherEffects[WeatherType.WINTER].addChild(snowflake);
}
// Thunderstorm
weatherEffects[WeatherType.THUNDERSTORM] = new Container();
// Add rain like rainy weather
for (var i = 0; i < 70; i++) {
var raindrop = LK.getAsset('seedling', {
width: 10,
height: 40,
anchorX: 0.5,
anchorY: 0.5
});
raindrop.tint = 0x1E90FF;
raindrop.alpha = 0.7;
raindrop.x = Math.random() * 2048;
raindrop.y = Math.random() * 1000;
raindrop.speedY = 20 + Math.random() * 15;
raindrop.update = function () {
this.y += this.speedY;
if (this.y > 2732) {
this.y = -50;
this.x = Math.random() * 2048;
}
};
weatherEffects[WeatherType.THUNDERSTORM].addChild(raindrop);
}
// Lightning effect will be handled separately
// Spring
weatherEffects[WeatherType.SPRING] = new Container();
for (var i = 0; i < 30; i++) {
var flower = LK.getAsset('centerCircle', {
width: 15,
height: 15,
anchorX: 0.5,
anchorY: 0.5
});
flower.tint = 0xFF69B4; // Pink flowers
flower.alpha = 0.8;
flower.x = Math.random() * 2048;
flower.y = Math.random() * 1000;
flower.speedY = 1 + Math.random() * 2;
flower.speedX = Math.random() * 4 - 2;
flower.update = function () {
this.y += this.speedY;
this.x += this.speedX;
if (this.y > 2732) {
this.y = -50;
this.x = Math.random() * 2048;
}
};
weatherEffects[WeatherType.SPRING].addChild(flower);
}
}
// Change weather to specified type
function changeWeather(weatherType) {
// Remove current weather effects
while (weatherContainer.children.length > 0) {
weatherContainer.removeChild(weatherContainer.children[0]);
}
// Apply new weather effects
weatherContainer.addChild(weatherEffects[weatherType]);
// Change background color based on weather
switch (weatherType) {
case WeatherType.SUNNY:
game.setBackgroundColor(0x87CEEB); // Sky blue
weatherLabel.setText("Sunny Day");
break;
case WeatherType.RAINY:
game.setBackgroundColor(0x708090); // Slate gray
weatherLabel.setText("Rainy Day");
break;
case WeatherType.WINTER:
game.setBackgroundColor(0xE0FFFF); // Light cyan
weatherLabel.setText("Winter Day");
break;
case WeatherType.THUNDERSTORM:
game.setBackgroundColor(0x4B4B4B); // Dark gray
weatherLabel.setText("Thunderstorm");
break;
case WeatherType.SPRING:
game.setBackgroundColor(0x98FB98); // Pale green
weatherLabel.setText("Spring Day");
break;
}
// Apply weather effects to crops
applyWeatherEffectsToCrops(weatherType);
// Reset weather timer
weatherTimer = 0;
// If thunderstorm, schedule random lightning
if (weatherType === WeatherType.THUNDERSTORM) {
scheduleLightning();
}
}
// Apply weather effects to all crops
function applyWeatherEffectsToCrops(weatherType) {
plots.forEach(function (plot) {
switch (weatherType) {
case WeatherType.RAINY:
// Rainy weather automatically waters all plants
if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) {
plot.water();
// Rainy weather boosts growth for all crops
plot.growthProgress += 2;
}
break;
case WeatherType.WINTER:
// Winter significantly slows growth and may damage plants
if (plot.isWet) {
plot.isWet = false;
plot.needsWater = true;
plot.soil.texture = LK.getAsset('soil', {}).texture;
}
// Winter slows down growth significantly
if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) {
plot.growthProgress = Math.max(0, plot.growthProgress - 1);
// 5% chance to damage crops in winter
if (Math.random() < 0.05) {
plot.growthProgress = Math.max(0, plot.growthProgress - 120);
// Show freeze effect
showFreezeEffect(plot);
}
}
break;
case WeatherType.THUNDERSTORM:
// Thunderstorm waters plants but may damage some
if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) {
plot.water();
// 15% chance of crop damage
if (Math.random() < 0.15) {
plot.growthProgress = Math.max(0, plot.growthProgress - 120); // Set back 2 seconds of growth
showLightningDamageEffect(plot);
} else {
// If not damaged, thunderstorms provide extra nutrients (growth boost)
plot.growthProgress += 3;
}
}
break;
case WeatherType.SPRING:
// Spring significantly speeds up growth for all plants
if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) {
if (plot.isWet) {
plot.growthProgress += 5; // Extra growth in spring - best for growth
showSpringBoostEffect(plot);
}
}
break;
case WeatherType.SUNNY:
// Sunny day provides moderate growth but dries soil faster
if (plot.state === PlotState.SEEDED || plot.state === PlotState.GROWING) {
if (plot.isWet) {
plot.growthProgress += 3; // Good growth in sunny weather
// Soil dries faster in sunny weather
if (Math.random() < 0.05) {
plot.isWet = false;
plot.needsWater = true;
plot.soil.texture = LK.getAsset('soil', {}).texture;
if (plot.dryTimer) {
LK.clearTimeout(plot.dryTimer);
}
}
}
}
break;
}
});
}
// Schedule random lightning flashes for thunderstorm
function scheduleLightning() {
var delay = 1000 + Math.random() * 5000; // Random delay between 1-6 seconds
LK.setTimeout(function () {
if (currentWeather === WeatherType.THUNDERSTORM) {
// Flash the screen
LK.effects.flashScreen(0xFFFFFF, 100);
// Schedule next lightning
scheduleLightning();
}
}, delay);
}
// Show lightning damage effect on a plot
function showLightningDamageEffect(plot) {
// Create lightning strike visual effect
var lightning = LK.getAsset('seedling', {
width: 20,
height: 150,
anchorX: 0.5,
anchorY: 1.0
});
lightning.tint = 0xFFFF00; // Yellow
lightning.alpha = 0.8;
lightning.x = 0;
lightning.y = 0;
plot.addChild(lightning);
// Create damage text
var damageText = new Text2("-2s", {
size: 40,
fill: 0xFF0000
});
damageText.anchor.set(0.5);
damageText.y = -80;
plot.addChild(damageText);
// Animate and remove
tween(lightning, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
lightning.destroy();
}
});
tween(damageText, {
y: -120,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
damageText.destroy();
}
});
}
// Show freeze effect on a plot
function showFreezeEffect(plot) {
// Create freeze visual effect
var frost = LK.getAsset('centerCircle', {
width: 200,
height: 200,
anchorX: 0.5,
anchorY: 0.5
});
frost.tint = 0xA5F2F3; // Light blue
frost.alpha = 0.5;
plot.addChild(frost);
// Create damage text
var damageText = new Text2("Frozen!", {
size: 30,
fill: 0xA5F2F3
});
damageText.anchor.set(0.5);
damageText.y = -50;
plot.addChild(damageText);
// Animate and remove
tween(frost, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
frost.destroy();
}
});
tween(damageText, {
y: -80,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
damageText.destroy();
}
});
}
// Show spring boost effect
function showSpringBoostEffect(plot) {
if (Math.random() < 0.1) {
// Only show occasionally to avoid too many effects
// Create growth visual effect
var growthEffect = LK.getAsset('centerCircle', {
width: 50,
height: 50,
anchorX: 0.5,
anchorY: 0.5
});
growthEffect.tint = 0x00FF00; // Green
growthEffect.alpha = 0.5;
growthEffect.y = -20;
plot.addChild(growthEffect);
// Animate and remove
tween(growthEffect, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
growthEffect.destroy();
}
});
}
}
// Get readable weather name from weather type
function getWeatherName(weatherType) {
switch (weatherType) {
case WeatherType.SUNNY:
return "Sunny";
case WeatherType.RAINY:
return "Rainy";
case WeatherType.WINTER:
return "Winter";
case WeatherType.THUNDERSTORM:
return "Thunderstorm";
case WeatherType.SPRING:
return "Spring";
default:
return "Unknown";
}
}
// Update weather effects
function updateWeather() {
if (weatherContainer && weatherContainer.children.length > 0) {
var effects = weatherContainer.children[0];
for (var i = 0; i < effects.children.length; i++) {
var effect = effects.children[i];
if (effect.update) {
effect.update();
}
}
}
// Check for automatic weather change
weatherTimer++;
if (weatherTimer > weatherDuration) {
// 20% chance to change weather each time period elapses
if (Math.random() < 0.2) {
var newWeather = Math.floor(Math.random() * 5);
if (newWeather !== currentWeather) {
currentWeather = newWeather;
changeWeather(currentWeather);
}
}
weatherTimer = 0;
}
}
// Initialize game
initializeFarm();
createUI();
initializeWeather();
// Play background music
LK.playMusic('farmMusic');
// Game update loop
game.update = function () {
// Update all plots
for (var i = 0; i < plots.length; i++) {
plots[i].update();
}
// Update all animal pens
for (var i = 0; i < animalPens.length; i++) {
animalPens[i].update();
}
// Update weather
updateWeather();
};
Carrot 2d pixilated topdown. In-Game asset. 2d. High contrast. No shadows
Button blank lime 2d pixilated topdown. In-Game asset. 2d. High contrast. No shadows
Square yellow button 2d pixilated topdown. In-Game asset. 2d. High contrast. No shadows
Soil 2d pixilated topdown. In-Game asset. 2d. High contrast. No shadows
Corn 2d pixilated topdown. In-Game asset. 2d. High contrast. No shadows
Tomato 2d pixilated topdown. In-Game asset. 2d. High contrast. No shadows