Code edit (1 edits merged)
Please save this source code
User prompt
change it so that the plots that are unlocked are the center two and not on the outside of the farm
User prompt
Move the plots button over to the right just a little bit more
User prompt
Can you move the plots button to the bottom left of the farm plots
User prompt
remove the restart button
User prompt
Set up the farm so that players begin with only 2 unlocked plots of farmland, which they can use immediately for planting and harvesting. The rest of the farm plots should be locked and visually indicated as unavailable. Add a system where players can unlock additional plots one at a time by spending 200 coins per plot. When a player has at least 200 coins and clicks on a locked plot, prompt them to confirm the purchase; if they confirm, deduct 200 coins and unlock that plot for use. Update the UI to show the number of unlocked plots and the player’s current coin balance. Make sure this system works seamlessly with the existing planting, tilling, and harvesting mechanics. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
restart the game
Code edit (1 edits merged)
Please save this source code
User prompt
give me 500 coins so I can try everything
User prompt
increase the text size of all the uis its way to small to read
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'statusText.style.fill = 0x00FF00;' Line Number: 1074
User prompt
Please fix the bug: 'TypeError: Cannot use 'in' operator to search for 'y' in null' in or related to this line: 'tween(cropGraphic, {' Line Number: 311
User prompt
restart the game
Code edit (1 edits merged)
Please save this source code
User prompt
Move the town button to the bottom right corner of the farm
User prompt
Add a tooltip feature to the game. When the player hovers the mouse over any planted crop on the farm, a small informational box (tooltip) should appear near the cursor. This tooltip should display two pieces of information: the current water level of the crop (e.g., 'Low', 'Medium', 'High') and the time remaining until the crop is fully grown (e.g., '2 days'). For example, hovering over a tomato plant might show 'Water Level: Medium' and 'Time Till Grown: 3 days'. This feature should be implemented for all six crops: wheat, corn, tomato, carrot, potato, and strawberry. The tooltip should be visible only while the mouse is over the crop and should disappear when the mouse moves away. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Generate sound effects for actions: tilling (shovel sound), planting (rustle), watering (splash), harvesting (pluck)
User prompt
Generate sprites for each crop at three growth stages: seed, growing, mature. Generate sprites for tools: Hoe, Shovel, Water Bucket, Seed Bag, Irrigation System, etc.
User prompt
Prompt: “The irrigation system automatically waters crops in a 3x3 area. The auto-tilling tool tills multiple cells at once.” Details: Ensure interactions are intuitive, with visual feedback (e.g., soil changing appearance when tilled)
User prompt
With the seed bag selected, clicking on a tilled cell opens a menu to choose from six crop seeds to plant
User prompt
Add a town interface accessible via a button, containing Tool Shop, Seed Shop, and Market.” Details: The town serves as a hub for economic interactions.
User prompt
Add tools to the player’s inventory: Hoe (tills soil), Shovel (digs holes), Water Bucket (waters plants), Seed Bag (plants seeds). Include advanced tools: Irrigation System, Better Harvesting Tools, Auto-Tilling Tool.” Details: Basic tools are available from the start; advanced tools are unlocked through purchases ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Add six crop types: Wheat, Corn, Tomato, Carrot, Potato, Strawberry. Each has growth stages: seed, growing, mature, with specific growth times and water needs. Wheat- 2 days, corn 3 days, tomato 4 days, carrot 3 days, potato 5 days, and strawberry 6 days
User prompt
Action: Use Upit’s drag-and-drop editor to create a farm grid. Prompt: “Create a 10x10 grid for the farm where each cell represents a plot of land that can be tilled, planted, watered, and harvested.” Details: Ensure each grid cell can change states (e.g., untilled, tilled, planted, watered, mature) based on player actions.
Code edit (1 edits merged)
Please save this source code
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
coins: 0,
unlockedSeeds: ["wheat", "corn", "tomato", "carrot", "potato", "strawberry"],
unlockedTools: {}
});
/****
* Classes
****/
var CoinDisplay = Container.expand(function () {
var self = Container.call(this);
var coinIcon = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
x: -60
});
var coinText = new Text2("0", {
size: 50,
fill: 0xFFFFFF
});
coinText.anchor.set(0, 0.5);
coinText.x = -30;
self.addChild(coinText);
self.updateCoins = function (amount) {
coinText.setText(amount.toString());
};
return self;
});
var FarmPlot = Container.expand(function () {
var self = Container.call(this);
self.state = PlotState.EMPTY;
self.growthTimer = 0;
self.seedType = null;
var soilGraphic = self.attachAsset('soil', {
anchorX: 0.5,
anchorY: 0.5
});
var cropGraphic = null;
self.till = function () {
if (self.state === PlotState.EMPTY) {
self.state = PlotState.TILLED;
soilGraphic.destroy();
soilGraphic = self.attachAsset('tilled_soil', {
anchorX: 0.5,
anchorY: 0.5
});
LK.getSound('till').play();
return true;
}
return false;
};
self.plant = function (seedType) {
if (self.state === PlotState.TILLED) {
self.state = PlotState.SEEDED;
self.seedType = seedType;
if (cropGraphic) {
cropGraphic.destroy();
}
// Use the seed asset with a small tint variation based on seed type
var seedAsset = cropGraphic = self.attachAsset('seed', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
});
// Apply different tint based on seed type
switch (seedType) {
case SeedType.WHEAT:
seedAsset.tint = 0xF5DEB3; // Wheat color
break;
case SeedType.CORN:
seedAsset.tint = 0xFFF44F; // Corn color
break;
case SeedType.TOMATO:
seedAsset.tint = 0xFF6347; // Tomato color
break;
case SeedType.CARROT:
seedAsset.tint = 0xFFA500; // Carrot color
break;
case SeedType.POTATO:
seedAsset.tint = 0xA0522D; // Potato color
break;
case SeedType.STRAWBERRY:
seedAsset.tint = 0xFF3366; // Strawberry color
break;
}
LK.getSound('plant').play();
return true;
}
return false;
};
self.water = function () {
if (self.state === PlotState.SEEDED) {
self.state = PlotState.WATERED;
self.growthTimer = 0;
var waterDroplet = self.attachAsset('water_drop', {
anchorX: 0.5,
anchorY: 0.5,
y: -50,
alpha: 0.8
});
tween(waterDroplet, {
alpha: 0
}, {
duration: 1500,
onFinish: function onFinish() {
waterDroplet.destroy();
}
});
LK.getSound('water').play();
return true;
}
return false;
};
self.grow = function () {
// Get crop configuration based on seed type
var cropConfig = CropConfig[self.seedType] || CropConfig.carrot;
var growthTime = cropConfig.growthTime;
// Calculate growth stage thresholds
var stage1Time = growthTime * 0.25; // 25% of total growth time
var stage2Time = growthTime * 0.5; // 50% of total growth time
var stage3Time = growthTime * 0.75; // 75% of total growth time
var harvestTime = growthTime; // 100% of total growth time
if (self.state === PlotState.WATERED) {
self.growthTimer++;
if (self.growthTimer >= stage1Time) {
self.state = PlotState.GROWING1;
if (cropGraphic) {
cropGraphic.destroy();
}
cropGraphic = self.attachAsset('crop_stage1', {
anchorX: 0.5,
anchorY: 1.0,
y: 0
});
}
} else if (self.state === PlotState.GROWING1) {
self.growthTimer++;
if (self.growthTimer >= stage2Time) {
self.state = PlotState.GROWING2;
if (cropGraphic) {
cropGraphic.destroy();
}
cropGraphic = self.attachAsset('crop_stage2', {
anchorX: 0.5,
anchorY: 1.0,
y: 0
});
}
} else if (self.state === PlotState.GROWING2) {
self.growthTimer++;
if (self.growthTimer >= stage3Time) {
self.state = PlotState.GROWING3;
if (cropGraphic) {
cropGraphic.destroy();
}
cropGraphic = self.attachAsset('crop_stage3', {
anchorX: 0.5,
anchorY: 1.0,
y: 0
});
}
} else if (self.state === PlotState.GROWING3) {
self.growthTimer++;
if (self.growthTimer >= harvestTime) {
self.state = PlotState.READY;
if (cropGraphic) {
cropGraphic.destroy();
}
cropGraphic = self.attachAsset('harvest_ready', {
anchorX: 0.5,
anchorY: 1.0,
y: 0
});
// Add bouncing animation for ready crops
tween(cropGraphic, {
y: -10
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cropGraphic, {
y: 0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (cropGraphic && cropGraphic.parent) {
self.bounceAnimation();
}
}
});
}
});
}
}
};
self.bounceAnimation = function () {
if (self.state === PlotState.READY && cropGraphic && cropGraphic.parent) {
tween(cropGraphic, {
y: -10
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cropGraphic, {
y: 0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (cropGraphic && cropGraphic.parent) {
self.bounceAnimation();
}
}
});
}
});
}
};
self.harvest = function () {
if (self.state === PlotState.READY) {
var harvestValue = 0;
if (self.seedType && CropConfig[self.seedType]) {
harvestValue = CropConfig[self.seedType].value;
} else {
harvestValue = 3; // Default value if seedType is invalid
}
self.reset();
LK.getSound('harvest').play();
return harvestValue;
}
return 0;
};
self.reset = function () {
self.state = PlotState.EMPTY;
self.growthTimer = 0;
self.seedType = null;
if (cropGraphic) {
cropGraphic.destroy();
cropGraphic = null;
}
if (soilGraphic) {
soilGraphic.destroy();
}
soilGraphic = self.attachAsset('soil', {
anchorX: 0.5,
anchorY: 0.5
});
};
self.down = function (x, y, obj) {
var toolAction = false;
// Handle both basic and advanced tools
switch (currentTool) {
case ToolType.HOE:
case "Auto-Tilling Tool":
toolAction = self.till();
// If using auto-tiller and action succeeded, till adjacent plots
if (toolAction && currentTool === "Auto-Tilling Tool") {
// Find nearby plots
var nearbyPlots = findNearbyPlots(self, 1);
nearbyPlots.forEach(function (plot) {
plot.till();
});
}
break;
case ToolType.SEEDS:
toolAction = self.plant(selectedSeedType);
break;
case ToolType.WATER:
case "Irrigation System":
toolAction = self.water();
// If using irrigation system and action succeeded, water adjacent plots
if (toolAction && currentTool === "Irrigation System") {
// Find nearby plots
var nearbyPlots = findNearbyPlots(self, 1);
nearbyPlots.forEach(function (plot) {
plot.water();
});
}
break;
case ToolType.HARVEST:
case "Better Harvesting Tools":
var harvestValue = self.harvest();
if (harvestValue > 0) {
toolAction = true;
// Give bonus yield if using better harvesting tools
if (currentTool === "Better Harvesting Tools") {
harvestValue = Math.floor(harvestValue * 1.5); // 50% bonus
}
addCoins(harvestValue);
}
break;
case ToolType.SHOVEL:
// Shovel resets the plot to empty state
if (self.state !== PlotState.EMPTY) {
self.reset();
toolAction = true;
}
break;
}
if (toolAction) {
// Visual feedback
LK.effects.flashObject(self, 0xFFFFFF, 300);
}
};
self.update = function () {
if (self.state >= PlotState.WATERED && self.state < PlotState.READY) {
self.grow();
}
};
return self;
});
var SeedSelector = Container.expand(function () {
var self = Container.call(this);
// Create background
var background = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 1.5,
tint: 0x8b5a2b,
alpha: 0.8
});
self.addChild(background);
// Title
var titleText = new Text2("Select Seed", {
size: 40,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.y = -70;
self.addChild(titleText);
// Create seed buttons
var seedButtons = [];
var seedTypes = [{
type: SeedType.WHEAT,
name: "Wheat",
color: 0xF5DEB3
}, {
type: SeedType.CORN,
name: "Corn",
color: 0xFFF44F
}, {
type: SeedType.TOMATO,
name: "Tomato",
color: 0xFF6347
}, {
type: SeedType.CARROT,
name: "Carrot",
color: 0xFFA500
}, {
type: SeedType.POTATO,
name: "Potato",
color: 0xA0522D
}, {
type: SeedType.STRAWBERRY,
name: "Strawberry",
color: 0xFF3366
}];
var buttonSize = 60;
var spacing = 80;
var startX = -(spacing * (seedTypes.length - 1)) / 2;
seedTypes.forEach(function (seedInfo, index) {
var button = new Container();
// Seed visual
var seedVisual = LK.getAsset('seed', {
anchorX: 0.5,
anchorY: 0.5,
tint: seedInfo.color
});
button.addChild(seedVisual);
// Seed name
var nameText = new Text2(seedInfo.name, {
size: 25,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0);
nameText.y = 40;
button.addChild(nameText);
// Growth time text
var growthDays = CropConfig[seedInfo.type].growthTime / (60 * 60);
var growthText = new Text2(growthDays + " days", {
size: 18,
fill: 0xCCCCCC
});
growthText.anchor.set(0.5, 0);
growthText.y = 70;
button.addChild(growthText);
// Position button
button.x = startX + index * spacing;
button.y = 0;
button.interactive = true;
// Selection highlight
var highlight = LK.getAsset('seed', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFF00,
alpha: 0
});
button.addChildAt(highlight, 0);
// Set button data
button.seedType = seedInfo.type;
button.highlight = highlight;
// Add to container and array
self.addChild(button);
seedButtons.push(button);
// Button event
button.down = function (x, y, obj) {
selectedSeedType = button.seedType;
updateSelectedSeed();
};
});
// Update visual selection
function updateSelectedSeed() {
seedButtons.forEach(function (button) {
if (button.seedType === selectedSeedType) {
button.highlight.alpha = 0.3;
} else {
button.highlight.alpha = 0;
}
});
}
// Close button
var closeButton = new Container();
var closeVisual = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFF5555
});
closeButton.addChild(closeVisual);
var closeText = new Text2("X", {
size: 40,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.x = background.width / 2 - 30;
closeButton.y = -background.height / 2 + 30;
self.addChild(closeButton);
// Close event
closeButton.down = function (x, y, obj) {
self.visible = false;
};
self.show = function () {
self.visible = true;
updateSelectedSeed();
};
// Initialize with default selection
updateSelectedSeed();
return self;
});
var Tool = Container.expand(function (toolType, isAdvanced, toolData) {
var self = Container.call(this);
self.toolType = toolType;
self.isAdvanced = isAdvanced || false;
self.toolData = toolData || null;
// Determine which asset to use
var assetId = self.isAdvanced && self.toolData ? self.toolData.icon : ToolType.HOE === toolType ? 'tool_hoe' : ToolType.SEEDS === toolType ? 'tool_seeds' : ToolType.WATER === toolType ? 'tool_water' : ToolType.HARVEST === toolType ? 'tool_harvest' : 'tool_hoe';
var toolGraphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Apply tint if it's an advanced tool with tint
if (self.isAdvanced && self.toolData && self.toolData.tint) {
toolGraphic.tint = self.toolData.tint;
}
// Create tool name label
var toolName = new Text2(self.isAdvanced && self.toolData ? self.toolData.name : ToolType.HOE === toolType ? "Hoe" : ToolType.SEEDS === toolType ? "Seeds" : ToolType.WATER === toolType ? "Water" : ToolType.HARVEST === toolType ? "Harvest" : "Tool", {
size: 20,
fill: 0xFFFFFF
});
toolName.anchor.set(0.5, 0);
toolName.y = 80;
self.addChild(toolName);
// Add lock icon or price for locked tools
self.lockIcon = null;
self.priceText = null;
self.updateLockStatus = function () {
// Remove existing lock/price if any
if (self.lockIcon) {
self.lockIcon.destroy();
self.lockIcon = null;
}
if (self.priceText) {
self.priceText.destroy();
self.priceText = null;
}
// If it's an advanced tool and not unlocked, show lock or price
if (self.isAdvanced && self.toolData && !self.toolData.unlocked) {
// Show price
self.priceText = new Text2(self.toolData.price.toString(), {
size: 24,
fill: 0xFFDD00
});
self.priceText.anchor.set(0.5, 0);
self.priceText.y = -70;
self.addChild(self.priceText);
// Dim the tool
toolGraphic.alpha = 0.5;
} else {
toolGraphic.alpha = 1;
}
};
// Highlight border when selected
var selectedBorder = null;
self.setSelected = function (selected) {
if (selected) {
if (!selectedBorder) {
selectedBorder = new Container();
var borderSize = 10;
var borderAsset = LK.getAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFFF00,
alpha: 0.5
});
selectedBorder.addChild(borderAsset);
self.addChildAt(selectedBorder, 0);
}
} else {
if (selectedBorder) {
selectedBorder.destroy();
selectedBorder = null;
}
}
};
self.down = function (x, y, obj) {
// If it's a locked advanced tool, try to purchase
if (self.isAdvanced && self.toolData && !self.toolData.unlocked) {
if (coins >= self.toolData.price) {
// Purchase the tool
coins -= self.toolData.price;
storage.coins = coins;
coinDisplay.updateCoins(coins);
self.toolData.unlocked = true;
// Save unlocked status
var unlockedTools = storage.unlockedTools || {};
unlockedTools[self.toolData.name] = true;
storage.unlockedTools = unlockedTools;
// Update visuals
self.updateLockStatus();
// Show success animation
LK.effects.flashObject(self, 0x00FF00, 500);
} else {
// Not enough coins
LK.effects.flashObject(self, 0xFF0000, 500);
}
} else {
// Normal tool selection
selectTool(self.isAdvanced ? self.toolData.name : self.toolType);
}
};
// Initialize lock/price display
if (self.isAdvanced) {
self.updateLockStatus();
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game variables
var PlotState = {
EMPTY: 0,
TILLED: 1,
SEEDED: 2,
WATERED: 3,
GROWING1: 4,
GROWING2: 5,
GROWING3: 6,
READY: 7
};
// Tool configurations
var ToolConfig = {
// Basic tools (available from start)
basic: {
HOE: {
name: "Hoe",
description: "Tills soil for planting",
icon: 'tool_hoe',
unlocked: true
},
SHOVEL: {
name: "Shovel",
description: "Digs holes in the soil",
icon: 'tool_hoe',
tint: 0x666666,
unlocked: true
},
WATER: {
name: "Water Bucket",
description: "Waters your plants",
icon: 'tool_water',
unlocked: true
},
SEEDS: {
name: "Seed Bag",
description: "Plants seeds in tilled soil",
icon: 'tool_seeds',
unlocked: true
},
HARVEST: {
name: "Harvest Tool",
description: "Harvests mature crops",
icon: 'tool_harvest',
unlocked: true
}
},
// Advanced tools (unlocked through purchases)
advanced: {
IRRIGATION: {
name: "Irrigation System",
description: "Waters multiple plots at once",
icon: 'tool_water',
tint: 0x00AAFF,
price: 100,
unlocked: false
},
BETTER_HARVEST: {
name: "Better Harvesting Tools",
description: "Harvest crops faster with bonus yields",
icon: 'tool_harvest',
tint: 0xFFAA00,
price: 150,
unlocked: false
},
AUTO_TILLER: {
name: "Auto-Tilling Tool",
description: "Tills multiple plots at once",
icon: 'tool_hoe',
tint: 0xAA00FF,
price: 200,
unlocked: false
}
}
};
var ToolType = {
HOE: 0,
SEEDS: 1,
WATER: 2,
HARVEST: 3,
SHOVEL: 4,
IRRIGATION: 5,
BETTER_HARVEST: 6,
AUTO_TILLER: 7
};
var SeedType = {
WHEAT: "wheat",
CORN: "corn",
TOMATO: "tomato",
CARROT: "carrot",
POTATO: "potato",
STRAWBERRY: "strawberry"
};
// Crop configuration with growth times in ticks (60 ticks = 1 second)
var CropConfig = {
wheat: {
growthTime: 2 * 60 * 60,
// 2 days (2 min in game time)
value: 4
},
corn: {
growthTime: 3 * 60 * 60,
// 3 days (3 min in game time)
value: 7
},
tomato: {
growthTime: 4 * 60 * 60,
// 4 days (4 min in game time)
value: 10
},
carrot: {
growthTime: 3 * 60 * 60,
// 3 days (3 min in game time)
value: 6
},
potato: {
growthTime: 5 * 60 * 60,
// 5 days (5 min in game time)
value: 12
},
strawberry: {
growthTime: 6 * 60 * 60,
// 6 days (6 min in game time)
value: 15
}
};
var farmPlots = [];
var tools = [];
var currentTool = ToolType.HOE;
var gameWidth = 2048;
var gameHeight = 2732;
var gridSize = 10;
var plotSize = 180;
var plotSpacing = 10;
var coins = storage.coins || 0;
var coinDisplay;
var selectedSeedType = SeedType.CARROT; // Default selected seed
// Create game title
var titleText = new Text2("Harvest Haven", {
size: 100,
fill: 0x006400
});
titleText.anchor.set(0.5, 0);
titleText.x = gameWidth / 2;
titleText.y = 30;
game.addChild(titleText);
// Create farm grid
function createFarmGrid() {
var gridWidth = gridSize;
var gridHeight = gridSize;
var startX = (gameWidth - (plotSize * gridWidth + plotSpacing * (gridWidth - 1))) / 2;
var startY = 200;
for (var row = 0; row < gridHeight; row++) {
for (var col = 0; col < gridWidth; col++) {
var plot = new FarmPlot();
plot.x = startX + col * (plotSize + plotSpacing) + plotSize / 2;
plot.y = startY + row * (plotSize + plotSpacing) + plotSize / 2;
farmPlots.push(plot);
game.addChild(plot);
}
}
}
// Create tool selection panel
function createToolPanel() {
var toolbarY = gameHeight - 120;
var toolSpacing = 130;
// Load unlocked tools from storage
var unlockedTools = storage.unlockedTools || {};
// Update tool configs with saved unlock status
Object.keys(ToolConfig.advanced).forEach(function (key) {
if (unlockedTools[ToolConfig.advanced[key].name]) {
ToolConfig.advanced[key].unlocked = true;
}
});
// Create basic tools panel
var basicToolCount = Object.keys(ToolConfig.basic).length;
var startX = (gameWidth - toolSpacing * basicToolCount) / 2 + 65;
// Add basic tools
Object.keys(ToolConfig.basic).forEach(function (key, i) {
var toolData = ToolConfig.basic[key];
var tool = new Tool(ToolType[key], false, toolData);
tool.x = startX + i * toolSpacing;
tool.y = toolbarY;
tools.push(tool);
game.addChild(tool);
});
// Add "Advanced Tools" label
var advLabel = new Text2("Advanced Tools", {
size: 30,
fill: 0xFFFFFF
});
advLabel.anchor.set(0.5, 0.5);
advLabel.x = gameWidth / 2;
advLabel.y = toolbarY - 150;
game.addChild(advLabel);
// Create advanced tools panel
var advancedToolCount = Object.keys(ToolConfig.advanced).length;
startX = (gameWidth - toolSpacing * advancedToolCount) / 2 + 65;
var advToolbarY = toolbarY - 220;
// Add advanced tools
Object.keys(ToolConfig.advanced).forEach(function (key, i) {
var toolData = ToolConfig.advanced[key];
var tool = new Tool(ToolType[key], true, toolData);
tool.x = startX + i * toolSpacing;
tool.y = advToolbarY;
tools.push(tool);
game.addChild(tool);
});
// Set initial selected tool
selectTool(currentTool);
// Add panel backgrounds
var basicPanelBackground = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: gameWidth / 200,
scaleY: 2,
tint: 0x4b0082,
alpha: 0.5
});
basicPanelBackground.x = gameWidth / 2;
basicPanelBackground.y = toolbarY;
game.addChildAt(basicPanelBackground, 0);
var advPanelBackground = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: gameWidth / 200,
scaleY: 2,
tint: 0x4b0082,
alpha: 0.5
});
advPanelBackground.x = gameWidth / 2;
advPanelBackground.y = advToolbarY;
game.addChildAt(advPanelBackground, 0);
// Add seed selector button next to seeds tool
var seedButton = tools.find(function (tool) {
return !tool.isAdvanced && tool.toolType === ToolType.SEEDS;
});
var seedSelectButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: 0x8b5a2b
});
seedSelectButton.x = seedButton.x + 60;
seedSelectButton.y = toolbarY;
game.addChild(seedSelectButton);
var arrowText = new Text2("▼", {
size: 40,
fill: 0xFFFFFF
});
arrowText.anchor.set(0.5, 0.5);
arrowText.x = seedSelectButton.x;
arrowText.y = toolbarY;
game.addChild(arrowText);
// Create seed selector
var seedSelector = new SeedSelector();
seedSelector.x = gameWidth / 2;
seedSelector.y = toolbarY - 200;
seedSelector.visible = false;
game.addChild(seedSelector);
// Seed selector button event
seedSelectButton.interactive = true;
seedSelectButton.down = function (x, y, obj) {
seedSelector.show();
};
}
// Create coin display
function createCoinDisplay() {
coinDisplay = new CoinDisplay();
coinDisplay.x = gameWidth - 100;
coinDisplay.y = 80;
coinDisplay.updateCoins(coins);
game.addChild(coinDisplay);
}
// Add coins to player's balance
function addCoins(amount) {
coins += amount;
storage.coins = coins;
// Update display
coinDisplay.updateCoins(coins);
// Show floating coin animation
for (var i = 0; i < amount; i++) {
var coin = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Random starting position near cursor
coin.x = 200 + Math.random() * 100;
coin.y = 200 + Math.random() * 100;
game.addChild(coin);
// Animate coin floating up and towards coin display
tween(coin, {
x: coinDisplay.x,
y: coinDisplay.y,
alpha: 0.8,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut,
onFinish: function onFinish() {
coin.destroy();
// Flash coin display
LK.effects.flashObject(coinDisplay, 0xFFFF00, 300);
}
});
}
}
// Find plots near a given plot within a specified radius
function findNearbyPlots(centerPlot, radius) {
var nearby = [];
// Calculate approximate grid position of centerPlot
var plotSize = 180;
var plotSpacing = 10;
var totalSize = plotSize + plotSpacing;
farmPlots.forEach(function (plot) {
if (plot === centerPlot) {
return;
} // Skip the center plot
// Calculate distance (using squared distance for efficiency)
var dx = plot.x - centerPlot.x;
var dy = plot.y - centerPlot.y;
var distanceSquared = dx * dx + dy * dy;
// Compare with radius (converted to pixels)
var radiusPixels = totalSize * radius + plotSize / 2;
if (distanceSquared <= radiusPixels * radiusPixels) {
nearby.push(plot);
}
});
return nearby;
}
function selectTool(toolType) {
currentTool = toolType;
// Update tool visuals
for (var i = 0; i < tools.length; i++) {
var isSelected = false;
if (typeof toolType === "string") {
// For advanced tools which use string names
isSelected = tools[i].isAdvanced && tools[i].toolData && tools[i].toolData.name === toolType;
} else {
// For basic tools which use ToolType enum
isSelected = !tools[i].isAdvanced && tools[i].toolType === toolType;
}
tools[i].setSelected(isSelected);
}
}
// Initialize game
createFarmGrid();
createToolPanel();
createCoinDisplay();
// Play background music
LK.playMusic('farm_music', {
fade: {
start: 0,
end: 0.3,
duration: 2000
}
});
// Game update loop
game.update = function () {
// Update all plots
for (var i = 0; i < farmPlots.length; i++) {
// Farm plots have their own update method called by LK engine
}
};
// Game input handling
var lastTouchPosition = {
x: 0,
y: 0
};
game.down = function (x, y, obj) {
lastTouchPosition.x = x;
lastTouchPosition.y = y;
};
game.move = function (x, y, obj) {
lastTouchPosition.x = x;
lastTouchPosition.y = y;
};
game.up = function (x, y, obj) {
// We don't need to do anything special here
}; ===================================================================
--- original.js
+++ change.js
@@ -3,9 +3,10 @@
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
coins: 0,
- unlockedSeeds: ["wheat", "corn", "tomato", "carrot", "potato", "strawberry"]
+ unlockedSeeds: ["wheat", "corn", "tomato", "carrot", "potato", "strawberry"],
+ unlockedTools: {}
});
/****
* Classes
@@ -251,25 +252,56 @@
});
};
self.down = function (x, y, obj) {
var toolAction = false;
+ // Handle both basic and advanced tools
switch (currentTool) {
case ToolType.HOE:
+ case "Auto-Tilling Tool":
toolAction = self.till();
+ // If using auto-tiller and action succeeded, till adjacent plots
+ if (toolAction && currentTool === "Auto-Tilling Tool") {
+ // Find nearby plots
+ var nearbyPlots = findNearbyPlots(self, 1);
+ nearbyPlots.forEach(function (plot) {
+ plot.till();
+ });
+ }
break;
case ToolType.SEEDS:
toolAction = self.plant(selectedSeedType);
break;
case ToolType.WATER:
+ case "Irrigation System":
toolAction = self.water();
+ // If using irrigation system and action succeeded, water adjacent plots
+ if (toolAction && currentTool === "Irrigation System") {
+ // Find nearby plots
+ var nearbyPlots = findNearbyPlots(self, 1);
+ nearbyPlots.forEach(function (plot) {
+ plot.water();
+ });
+ }
break;
case ToolType.HARVEST:
+ case "Better Harvesting Tools":
var harvestValue = self.harvest();
if (harvestValue > 0) {
toolAction = true;
+ // Give bonus yield if using better harvesting tools
+ if (currentTool === "Better Harvesting Tools") {
+ harvestValue = Math.floor(harvestValue * 1.5); // 50% bonus
+ }
addCoins(harvestValue);
}
break;
+ case ToolType.SHOVEL:
+ // Shovel resets the plot to empty state
+ if (self.state !== PlotState.EMPTY) {
+ self.reset();
+ toolAction = true;
+ }
+ break;
}
if (toolAction) {
// Visual feedback
LK.effects.flashObject(self, 0xFFFFFF, 300);
@@ -424,30 +456,60 @@
// Initialize with default selection
updateSelectedSeed();
return self;
});
-var Tool = Container.expand(function (toolType) {
+var Tool = Container.expand(function (toolType, isAdvanced, toolData) {
var self = Container.call(this);
self.toolType = toolType;
- var assetId;
- switch (toolType) {
- case ToolType.HOE:
- assetId = 'tool_hoe';
- break;
- case ToolType.SEEDS:
- assetId = 'tool_seeds';
- break;
- case ToolType.WATER:
- assetId = 'tool_water';
- break;
- case ToolType.HARVEST:
- assetId = 'tool_harvest';
- break;
- }
+ self.isAdvanced = isAdvanced || false;
+ self.toolData = toolData || null;
+ // Determine which asset to use
+ var assetId = self.isAdvanced && self.toolData ? self.toolData.icon : ToolType.HOE === toolType ? 'tool_hoe' : ToolType.SEEDS === toolType ? 'tool_seeds' : ToolType.WATER === toolType ? 'tool_water' : ToolType.HARVEST === toolType ? 'tool_harvest' : 'tool_hoe';
var toolGraphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
+ // Apply tint if it's an advanced tool with tint
+ if (self.isAdvanced && self.toolData && self.toolData.tint) {
+ toolGraphic.tint = self.toolData.tint;
+ }
+ // Create tool name label
+ var toolName = new Text2(self.isAdvanced && self.toolData ? self.toolData.name : ToolType.HOE === toolType ? "Hoe" : ToolType.SEEDS === toolType ? "Seeds" : ToolType.WATER === toolType ? "Water" : ToolType.HARVEST === toolType ? "Harvest" : "Tool", {
+ size: 20,
+ fill: 0xFFFFFF
+ });
+ toolName.anchor.set(0.5, 0);
+ toolName.y = 80;
+ self.addChild(toolName);
+ // Add lock icon or price for locked tools
+ self.lockIcon = null;
+ self.priceText = null;
+ self.updateLockStatus = function () {
+ // Remove existing lock/price if any
+ if (self.lockIcon) {
+ self.lockIcon.destroy();
+ self.lockIcon = null;
+ }
+ if (self.priceText) {
+ self.priceText.destroy();
+ self.priceText = null;
+ }
+ // If it's an advanced tool and not unlocked, show lock or price
+ if (self.isAdvanced && self.toolData && !self.toolData.unlocked) {
+ // Show price
+ self.priceText = new Text2(self.toolData.price.toString(), {
+ size: 24,
+ fill: 0xFFDD00
+ });
+ self.priceText.anchor.set(0.5, 0);
+ self.priceText.y = -70;
+ self.addChild(self.priceText);
+ // Dim the tool
+ toolGraphic.alpha = 0.5;
+ } else {
+ toolGraphic.alpha = 1;
+ }
+ };
// Highlight border when selected
var selectedBorder = null;
self.setSelected = function (selected) {
if (selected) {
@@ -472,10 +534,37 @@
}
}
};
self.down = function (x, y, obj) {
- selectTool(self.toolType);
+ // If it's a locked advanced tool, try to purchase
+ if (self.isAdvanced && self.toolData && !self.toolData.unlocked) {
+ if (coins >= self.toolData.price) {
+ // Purchase the tool
+ coins -= self.toolData.price;
+ storage.coins = coins;
+ coinDisplay.updateCoins(coins);
+ self.toolData.unlocked = true;
+ // Save unlocked status
+ var unlockedTools = storage.unlockedTools || {};
+ unlockedTools[self.toolData.name] = true;
+ storage.unlockedTools = unlockedTools;
+ // Update visuals
+ self.updateLockStatus();
+ // Show success animation
+ LK.effects.flashObject(self, 0x00FF00, 500);
+ } else {
+ // Not enough coins
+ LK.effects.flashObject(self, 0xFF0000, 500);
+ }
+ } else {
+ // Normal tool selection
+ selectTool(self.isAdvanced ? self.toolData.name : self.toolType);
+ }
};
+ // Initialize lock/price display
+ if (self.isAdvanced) {
+ self.updateLockStatus();
+ }
return self;
});
/****
@@ -498,13 +587,81 @@
GROWING2: 5,
GROWING3: 6,
READY: 7
};
+// Tool configurations
+var ToolConfig = {
+ // Basic tools (available from start)
+ basic: {
+ HOE: {
+ name: "Hoe",
+ description: "Tills soil for planting",
+ icon: 'tool_hoe',
+ unlocked: true
+ },
+ SHOVEL: {
+ name: "Shovel",
+ description: "Digs holes in the soil",
+ icon: 'tool_hoe',
+ tint: 0x666666,
+ unlocked: true
+ },
+ WATER: {
+ name: "Water Bucket",
+ description: "Waters your plants",
+ icon: 'tool_water',
+ unlocked: true
+ },
+ SEEDS: {
+ name: "Seed Bag",
+ description: "Plants seeds in tilled soil",
+ icon: 'tool_seeds',
+ unlocked: true
+ },
+ HARVEST: {
+ name: "Harvest Tool",
+ description: "Harvests mature crops",
+ icon: 'tool_harvest',
+ unlocked: true
+ }
+ },
+ // Advanced tools (unlocked through purchases)
+ advanced: {
+ IRRIGATION: {
+ name: "Irrigation System",
+ description: "Waters multiple plots at once",
+ icon: 'tool_water',
+ tint: 0x00AAFF,
+ price: 100,
+ unlocked: false
+ },
+ BETTER_HARVEST: {
+ name: "Better Harvesting Tools",
+ description: "Harvest crops faster with bonus yields",
+ icon: 'tool_harvest',
+ tint: 0xFFAA00,
+ price: 150,
+ unlocked: false
+ },
+ AUTO_TILLER: {
+ name: "Auto-Tilling Tool",
+ description: "Tills multiple plots at once",
+ icon: 'tool_hoe',
+ tint: 0xAA00FF,
+ price: 200,
+ unlocked: false
+ }
+ }
+};
var ToolType = {
HOE: 0,
SEEDS: 1,
WATER: 2,
- HARVEST: 3
+ HARVEST: 3,
+ SHOVEL: 4,
+ IRRIGATION: 5,
+ BETTER_HARVEST: 6,
+ AUTO_TILLER: 7
};
var SeedType = {
WHEAT: "wheat",
CORN: "corn",
@@ -584,40 +741,88 @@
}
// Create tool selection panel
function createToolPanel() {
var toolbarY = gameHeight - 120;
- var toolSpacing = 160;
- var startX = (gameWidth - toolSpacing * 4) / 2 + 80;
- for (var i = 0; i < 4; i++) {
- var tool = new Tool(i);
+ var toolSpacing = 130;
+ // Load unlocked tools from storage
+ var unlockedTools = storage.unlockedTools || {};
+ // Update tool configs with saved unlock status
+ Object.keys(ToolConfig.advanced).forEach(function (key) {
+ if (unlockedTools[ToolConfig.advanced[key].name]) {
+ ToolConfig.advanced[key].unlocked = true;
+ }
+ });
+ // Create basic tools panel
+ var basicToolCount = Object.keys(ToolConfig.basic).length;
+ var startX = (gameWidth - toolSpacing * basicToolCount) / 2 + 65;
+ // Add basic tools
+ Object.keys(ToolConfig.basic).forEach(function (key, i) {
+ var toolData = ToolConfig.basic[key];
+ var tool = new Tool(ToolType[key], false, toolData);
tool.x = startX + i * toolSpacing;
tool.y = toolbarY;
tools.push(tool);
game.addChild(tool);
- }
+ });
+ // Add "Advanced Tools" label
+ var advLabel = new Text2("Advanced Tools", {
+ size: 30,
+ fill: 0xFFFFFF
+ });
+ advLabel.anchor.set(0.5, 0.5);
+ advLabel.x = gameWidth / 2;
+ advLabel.y = toolbarY - 150;
+ game.addChild(advLabel);
+ // Create advanced tools panel
+ var advancedToolCount = Object.keys(ToolConfig.advanced).length;
+ startX = (gameWidth - toolSpacing * advancedToolCount) / 2 + 65;
+ var advToolbarY = toolbarY - 220;
+ // Add advanced tools
+ Object.keys(ToolConfig.advanced).forEach(function (key, i) {
+ var toolData = ToolConfig.advanced[key];
+ var tool = new Tool(ToolType[key], true, toolData);
+ tool.x = startX + i * toolSpacing;
+ tool.y = advToolbarY;
+ tools.push(tool);
+ game.addChild(tool);
+ });
// Set initial selected tool
selectTool(currentTool);
- // Add panel background
- var panelBackground = LK.getAsset('button', {
+ // Add panel backgrounds
+ var basicPanelBackground = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: gameWidth / 200,
scaleY: 2,
tint: 0x4b0082,
alpha: 0.5
});
- panelBackground.x = gameWidth / 2;
- panelBackground.y = toolbarY;
- game.addChildAt(panelBackground, 0);
+ basicPanelBackground.x = gameWidth / 2;
+ basicPanelBackground.y = toolbarY;
+ game.addChildAt(basicPanelBackground, 0);
+ var advPanelBackground = LK.getAsset('button', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: gameWidth / 200,
+ scaleY: 2,
+ tint: 0x4b0082,
+ alpha: 0.5
+ });
+ advPanelBackground.x = gameWidth / 2;
+ advPanelBackground.y = advToolbarY;
+ game.addChildAt(advPanelBackground, 0);
// Add seed selector button next to seeds tool
+ var seedButton = tools.find(function (tool) {
+ return !tool.isAdvanced && tool.toolType === ToolType.SEEDS;
+ });
var seedSelectButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: 0x8b5a2b
});
- seedSelectButton.x = startX + ToolType.SEEDS * toolSpacing + 60;
+ seedSelectButton.x = seedButton.x + 60;
seedSelectButton.y = toolbarY;
game.addChild(seedSelectButton);
var arrowText = new Text2("▼", {
size: 40,
@@ -680,13 +885,44 @@
}
});
}
}
+// Find plots near a given plot within a specified radius
+function findNearbyPlots(centerPlot, radius) {
+ var nearby = [];
+ // Calculate approximate grid position of centerPlot
+ var plotSize = 180;
+ var plotSpacing = 10;
+ var totalSize = plotSize + plotSpacing;
+ farmPlots.forEach(function (plot) {
+ if (plot === centerPlot) {
+ return;
+ } // Skip the center plot
+ // Calculate distance (using squared distance for efficiency)
+ var dx = plot.x - centerPlot.x;
+ var dy = plot.y - centerPlot.y;
+ var distanceSquared = dx * dx + dy * dy;
+ // Compare with radius (converted to pixels)
+ var radiusPixels = totalSize * radius + plotSize / 2;
+ if (distanceSquared <= radiusPixels * radiusPixels) {
+ nearby.push(plot);
+ }
+ });
+ return nearby;
+}
function selectTool(toolType) {
currentTool = toolType;
// Update tool visuals
for (var i = 0; i < tools.length; i++) {
- tools[i].setSelected(i === toolType);
+ var isSelected = false;
+ if (typeof toolType === "string") {
+ // For advanced tools which use string names
+ isSelected = tools[i].isAdvanced && tools[i].toolData && tools[i].toolData.name === toolType;
+ } else {
+ // For basic tools which use ToolType enum
+ isSelected = !tools[i].isAdvanced && tools[i].toolType === toolType;
+ }
+ tools[i].setSelected(isSelected);
}
}
// Initialize game
createFarmGrid();
carrot seed. In-Game asset. 2d. High contrast. No shadows
farming hoe. In-Game asset. 2d. High contrast. No shadows
harvesting tool. In-Game asset. 2d. High contrast. No shadows
Irrigation tool. In-Game asset. 2d. High contrast. No shadows
watering can. In-Game asset. 2d. High contrast. No shadows
shovel. In-Game asset. 2d. High contrast. No shadows
Seed bag. In-Game asset. 2d. High contrast. No shadows
Auto harvester. In-Game asset. 2d. High contrast. No shadows
Auto Tiller. In-Game asset. 2d. High contrast. No shadows
water drop. In-Game asset. 2d. High contrast. No shadows
money sign. In-Game asset. 2d. High contrast. No shadows
corn seed. In-Game asset. 2d. High contrast. No shadows
carrot in dirt. In-Game asset. 2d. High contrast. No shadows
Carrot growing in dirt. In-Game asset. 2d. High contrast. No shadows
corn stage 2 growth. In-Game asset. 2d. High contrast. No shadows
Corn growth stage final. In-Game asset. 2d. High contrast. No shadows
Potato seed. In-Game asset. 2d. High contrast. No shadows
Potato growth stage 2. In-Game asset. 2d. High contrast. No shadows
potato growth stage final. In-Game asset. 2d. High contrast. No shadows
Wheat growing stage 2. In-Game asset. 2d. High contrast. No shadows
Wheat growth stage final. In-Game asset. 2d. High contrast. No shadows