/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BuyPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like inventory panel
self.addChild(panelBg);
var titleText = new Text2('COMPRAR SEMILLAS', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -280;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// Switch to sell panel button
var sellPanelBtn = self.addChild(LK.getAsset('sellButton', {
anchorX: 0.5,
anchorY: 0.5,
x: -700,
y: 200
}));
var sellPanelBtnText = new Text2('VENDER', {
size: 30,
fill: 0xFFFFFF
});
sellPanelBtnText.anchor.set(0.5, 0.5);
sellPanelBtn.addChild(sellPanelBtnText);
// Seed shop items
var seedItems = [{
name: 'Semillas de Lechuga',
type: 'crop1',
price: 5
}, {
name: 'Semillas de Tomate',
type: 'crop2',
price: 10
}, {
name: 'Semillas de Maíz',
type: 'crop3',
price: 20
}, {
name: 'Semillas de Calabaza',
type: 'crop4',
price: 50
}, {
name: 'Semillas de Sandía',
type: 'crop5',
price: 85
}, {
name: 'Semillas de Uvas',
type: 'crop6',
price: 150
}, {
name: 'Semillas de Trufa',
type: 'crop7',
price: 280
}, {
name: 'Semillas de Orquídea',
type: 'crop8',
price: 450
}];
var buyItems = [];
seedItems.forEach(function (item, index) {
var row = Math.floor(index / 4);
var col = index % 4;
var shopItem = new ShopItem(item.type, item.price, false);
shopItem.x = -300 + col * 200; // Better centered positioning
// Move second row items (watermelon, grapes, truffle, orchid) down more
if (row === 1) {
shopItem.y = -150 + row * 250 + 50; // Add extra 50px margin for second row
} else {
shopItem.y = -150 + row * 250; // Keep first row position unchanged
}
self.addChild(shopItem);
buyItems.push(shopItem);
shopItem.button.down = function (x, y, obj) {
if (coins >= item.price) {
coins -= item.price;
if (!seeds[item.type]) {
seeds[item.type] = 0;
}
seeds[item.type] += 5;
// Award XP for buying seeds (1 XP per purchase)
addXP(1);
LK.getSound('purchase').play();
updateUI();
}
};
});
sellPanelBtn.down = function (x, y, obj) {
self.visible = false;
sellPanel.visible = true;
sellPanel.updateSellSection();
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isBuyPanelOpen = false;
};
return self;
});
var FarmPlot = Container.expand(function () {
var self = Container.call(this);
var plotGraphics = self.attachAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5
});
self.cropType = null;
self.plantTime = 0;
self.growthStage = 0;
self.currentCrop = null;
self.isEmpty = true;
self.isReady = false;
self.isMutated = false; //{mutation_prop}
self.plantCrop = function (cropType) {
if (!self.isEmpty) return false;
self.cropType = cropType;
self.plantTime = LK.ticks;
self.growthStage = 0;
self.isEmpty = false;
self.isReady = false;
// Check for mutation with skill bonus
var mutationChance = MUTATION_CHANCE + getMutationChanceBonus();
self.isMutated = Math.random() < mutationChance;
// Create seedling
self.currentCrop = self.addChild(LK.getAsset('seedling', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
}));
// Apply mutation visual effect to seedling if mutated
if (self.isMutated) {
//{mutation_seedling_start}
tween(self.currentCrop, {
//{mutation_seedling_tween1}
tint: 0xFF69B4 //{mutation_seedling_tint1}
}, {
//{mutation_seedling_config1}
duration: 250,
//{mutation_seedling_duration1}
easing: tween.easeInOut //{mutation_seedling_easing1}
}); //{mutation_seedling_end1}
tween(self.currentCrop, {
//{mutation_seedling_tween2}
tint: 0x32CD32 //{mutation_seedling_tint2}
}, {
//{mutation_seedling_config2}
duration: 250,
//{mutation_seedling_duration2}
easing: tween.easeInOut //{mutation_seedling_easing2}
}); //{mutation_seedling_end2}
} //{mutation_seedling_end}
LK.getSound('plant').play();
// Award XP for planting based on crop type
var plantingXP = 0;
if (cropType === 'crop1') plantingXP = 2; // Lettuce: 2 XP
else if (cropType === 'crop2') plantingXP = 5; // Tomato: 5 XP
else if (cropType === 'crop3') plantingXP = 8; // Corn: 8 XP
else if (cropType === 'crop4') plantingXP = 12; // Pumpkin: 12 XP
else if (cropType === 'crop5') plantingXP = 18; // Watermelon: 18 XP
else if (cropType === 'crop6') plantingXP = 25; // Grapes: 25 XP
else if (cropType === 'crop7') plantingXP = 35; // Truffle: 35 XP
else if (cropType === 'crop8') plantingXP = 50; // Orchid: 50 XP
addXP(plantingXP);
return true;
};
self.harvestCrop = function () {
if (!self.isReady) return null;
var baseValue = cropData[self.cropType].value;
var baseXP = 5;
var harvestedCrop = {
type: self.cropType,
value: self.isMutated ? Math.floor(baseValue * MUTATION_VALUE_MULTIPLIER) : baseValue,
isMutated: self.isMutated
};
// Remove crop visual
if (self.currentCrop) {
self.currentCrop.destroy();
self.currentCrop = null;
}
// Reset plot
self.cropType = null;
self.plantTime = 0;
self.growthStage = 0;
self.isEmpty = true;
self.isReady = false;
var wasMutated = self.isMutated; //{mutation_was_mutated}
self.isMutated = false; //{mutation_reset}
LK.getSound('harvest').play();
// Award XP for harvesting (more XP for mutations)
var xpReward = wasMutated ? Math.floor(baseXP * MUTATION_XP_MULTIPLIER) : baseXP;
addXP(xpReward);
return harvestedCrop;
};
self.update = function () {
if (self.isEmpty || !self.cropType) return;
var elapsed = LK.ticks - self.plantTime;
var growthTime = cropData[self.cropType].growthTime;
if (elapsed >= growthTime && !self.isReady) {
// Crop is ready
self.isReady = true;
if (self.currentCrop) {
self.currentCrop.destroy();
}
self.currentCrop = self.addChild(LK.getAsset(self.cropType, {
anchorX: 0.5,
anchorY: 0.5,
y: -20
}));
// Apply mutation effects if this crop is mutated
if (self.isMutated) {
//{mutation_scale_y}
// Start multicolor animation for mutated crops
var startMutationColorCycle = function startMutationColorCycle() {
//{mutation_color_cycle_start}
var colors = [0xFF69B4, 0x32CD32, 0xFF4500, 0x9932CC, 0xFFD700, 0x00CED1]; //{mutation_colors}
var currentColorIndex = 0; //{mutation_color_index}
function cycleMutationColors() {
//{mutation_cycle_function}
if (self.currentCrop && self.isMutated && self.isReady) {
//{mutation_cycle_check}
tween(self.currentCrop, {
//{mutation_cycle_tween}
tint: colors[currentColorIndex] //{mutation_cycle_tint}
}, {
//{mutation_cycle_config}
duration: 800,
//{mutation_cycle_duration}
easing: tween.easeInOut,
//{mutation_cycle_easing}
onFinish: function onFinish() {
//{mutation_cycle_finish}
currentColorIndex = (currentColorIndex + 1) % colors.length; //{mutation_cycle_increment}
LK.setTimeout(cycleMutationColors, 200); //{mutation_cycle_timeout}
} //{mutation_cycle_finish_end}
}); //{mutation_cycle_tween_end}
} //{mutation_cycle_check_end}
} //{mutation_cycle_function_end}
cycleMutationColors(); //{mutation_start_cycle}
}; //{mutation_color_cycle_end}
//{mutation_grown_start}
// Make mutated crops larger
self.currentCrop.scaleX = 1.5; //{mutation_scale_x}
self.currentCrop.scaleY = 1.5;
startMutationColorCycle(); //{mutation_start_color_cycle}
} //{mutation_grown_end}
// Add glow effect for ready crops
tween(self.currentCrop, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeInOut
});
tween(self.currentCrop, {
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.currentCrop && self.isReady) {
tween(self.currentCrop, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeInOut
});
tween(self.currentCrop, {
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.currentCrop && self.isReady) {
self.update();
}
}
});
}
}
});
} else if (elapsed < growthTime && elapsed > growthTime * 0.5 && self.growthStage === 0) {
// Half grown
self.growthStage = 1;
if (self.currentCrop) {
tween(self.currentCrop, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300
});
}
}
};
self.down = function (x, y, obj) {
if (self.isReady) {
var harvest = self.harvestCrop();
if (harvest) {
// Add to inventory (separate mutated crops)
var inventoryKey = harvest.isMutated ? harvest.type + '_mutated' : harvest.type; //{mutation_inventory_key}
if (!inventory[inventoryKey]) {
inventory[inventoryKey] = 0;
}
inventory[inventoryKey]++;
updateUI();
}
} else if (self.isEmpty && selectedSeed && seeds[selectedSeed] > 0) {
if (self.plantCrop(selectedSeed)) {
seeds[selectedSeed]--;
updateUI();
}
}
};
return self;
});
var HotbarSlot = Container.expand(function (seedType, index) {
var self = Container.call(this);
self.seedType = seedType;
self.index = index;
self.isSelected = false;
var slotBg = self.attachAsset('hotbarSlot', {
anchorX: 0.5,
anchorY: 0.5
});
self.selectedBg = self.addChild(LK.getAsset('hotbarSlotSelected', {
anchorX: 0.5,
anchorY: 0.5
}));
self.selectedBg.visible = false;
// Add seed visual
if (seedType) {
var seedVisual = self.addChild(LK.getAsset(seedType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
}
// Add count text
self.countText = new Text2('0', {
size: 30,
fill: 0xFFFFFF
});
self.countText.anchor.set(0.5, 0.5);
self.countText.x = 0;
self.countText.y = 40;
self.addChild(self.countText);
self.updateCount = function (count) {
self.countText.setText(count.toString());
self.alpha = count > 0 ? 1.0 : 0.5;
};
self.setSelected = function (selected) {
self.isSelected = selected;
self.selectedBg.visible = selected;
if (selected) {
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeInOut
});
} else {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeInOut
});
}
};
self.down = function (x, y, obj) {
if (seeds[self.seedType] > 0) {
selectedSeed = self.seedType;
updateHotbar();
}
};
return self;
});
var InventoryItem = Container.expand(function (itemType, count, isHarvested) {
var self = Container.call(this);
// Item icon without background frame - larger size
var itemIcon = self.addChild(LK.getAsset(itemType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
// Count text below the icon
self.countText = new Text2(count.toString(), {
size: 35,
fill: 0x000000,
fontStyle: 'bold'
});
self.countText.anchor.set(0.5, 0.5);
self.countText.x = 0;
self.countText.y = 70;
self.addChild(self.countText);
self.updateCount = function (newCount) {
self.countText.setText(newCount.toString());
self.alpha = newCount > 0 ? 1.0 : 0.5;
};
return self;
});
var InventoryPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like shop and upgrades panels
self.addChild(panelBg);
var titleText = new Text2('INVENTARIO', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -200;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
self.inventoryTexts = [];
self.updateInventory = function () {
// Clear existing items
self.inventoryTexts.forEach(function (item) {
item.destroy();
});
self.inventoryTexts = [];
// Create grid layout - wider spacing for larger items
var itemsPerRow = 4;
var itemSpacing = 220;
var currentRow = 0;
var currentCol = 0;
// Adjust positioning for horizontal layout with proper margins within background
var startX = -400; // Adjust left margin to stay within background
var startY = 80;
// Show seeds
Object.keys(seeds).forEach(function (seedType) {
if (seeds[seedType] > 0) {
var item = new InventoryItem(seedType, seeds[seedType], false);
item.x = startX + currentCol * itemSpacing;
item.y = startY;
item.updateCount(seeds[seedType]);
self.addChild(item);
self.inventoryTexts.push(item);
currentCol++;
}
});
// Show harvested crops
Object.keys(inventory).forEach(function (cropType) {
if (inventory[cropType] > 0) {
// Skip mutated crops here - they'll be handled separately
if (cropType.endsWith('_mutated')) return;
var item = new InventoryItem(cropType, inventory[cropType], true);
item.x = startX + currentCol * itemSpacing;
item.y = startY;
item.updateCount(inventory[cropType]);
self.addChild(item);
self.inventoryTexts.push(item);
currentCol++;
}
});
// Show mutated crops separately
Object.keys(inventory).forEach(function (inventoryKey) {
if (inventory[inventoryKey] > 0 && inventoryKey.endsWith('_mutated')) {
var baseCropType = inventoryKey.replace('_mutated', '');
var item = new InventoryItem(baseCropType, inventory[inventoryKey], true);
item.x = startX + currentCol * itemSpacing;
item.y = startY;
item.updateCount(inventory[inventoryKey]);
// Make mutated crops larger and add special visual effects
item.scaleX = 1.2;
item.scaleY = 1.2;
// Add mutated indicator text
var mutatedLabel = new Text2('¡MUTACIÓN!', {
size: 25,
fill: 0xFF1493,
fontStyle: 'bold'
});
mutatedLabel.anchor.set(0.5, 0.5);
mutatedLabel.x = 0;
mutatedLabel.y = -40;
item.addChild(mutatedLabel);
self.addChild(item);
self.inventoryTexts.push(item);
currentCol++;
}
});
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isInventoryOpen = false;
};
return self;
});
var Minion = Container.expand(function () {
var self = Container.call(this);
// Create minion visual using character asset
var minionGraphics = self.attachAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
self.targetPlot = null;
self.isMoving = false;
self.harvestTimer = 0;
// Find next ready crop to harvest
self.findNextTarget = function () {
var readyPlots = farmPlots.filter(function (plot) {
return plot.isReady;
});
if (readyPlots.length > 0) {
// Find closest ready plot
var closestPlot = readyPlots[0];
var minDistance = Math.abs(self.x - closestPlot.x) + Math.abs(self.y - closestPlot.y);
readyPlots.forEach(function (plot) {
var distance = Math.abs(self.x - plot.x) + Math.abs(self.y - plot.y);
if (distance < minDistance) {
minDistance = distance;
closestPlot = plot;
}
});
return closestPlot;
}
return null;
};
// Move to target plot
self.moveToPlot = function (plot) {
if (self.isMoving || !plot) return;
self.isMoving = true;
self.targetPlot = plot;
// Calculate movement duration based on distance
var distance = Math.sqrt(Math.pow(plot.x - self.x, 2) + Math.pow(plot.y - self.y, 2));
var duration = Math.max(500, distance * 2); // Minimum 0.5 seconds
// Animate movement to plot
tween(self, {
x: plot.x,
y: plot.y
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isMoving = false;
self.harvestCrop();
}
});
// Add walking animation - slight bouncing
tween(minionGraphics, {
scaleY: 1.4
}, {
duration: 200,
easing: tween.easeInOut
});
tween(minionGraphics, {
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeInOut
});
};
// Harvest crop at current location
self.harvestCrop = function () {
if (self.targetPlot && self.targetPlot.isReady) {
var harvest = self.targetPlot.harvestCrop();
if (harvest) {
// Add to inventory (separate mutated crops)
var inventoryKey = harvest.isMutated ? harvest.type + '_mutated' : harvest.type; //{mutation_minion_key}
if (!inventory[inventoryKey]) {
inventory[inventoryKey] = 0;
}
inventory[inventoryKey]++;
// Show harvested crop above minion's head
var harvestedCropDisplay = self.addChild(LK.getAsset(harvest.type, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -80,
scaleX: 0.8,
scaleY: 0.8
}));
// Animate the harvested crop display
tween(harvestedCropDisplay, {
y: -120,
alpha: 0.7
}, {
duration: 800,
easing: tween.easeOut
});
tween(harvestedCropDisplay, {
alpha: 0
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
harvestedCropDisplay.destroy();
}
});
// Add harvest animation - flash green
tween(minionGraphics, {
tint: 0x00ff00
}, {
duration: 300,
easing: tween.easeInOut
});
tween(minionGraphics, {
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeInOut
});
updateUI();
}
}
self.targetPlot = null;
};
// Wander around the farm when there's nothing to harvest
self.wanderAround = function () {
if (self.isMoving || farmPlots.length === 0) return;
// Pick a random farm plot to visit
var randomIndex = Math.floor(Math.random() * farmPlots.length);
var randomPlot = farmPlots[randomIndex];
if (randomPlot) {
self.isMoving = true;
// Calculate movement duration based on distance
var distance = Math.sqrt(Math.pow(randomPlot.x - self.x, 2) + Math.pow(randomPlot.y - self.y, 2));
var duration = Math.max(1000, distance * 3); // Slower wandering movement
// Animate movement to random plot
tween(self, {
x: randomPlot.x,
y: randomPlot.y
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isMoving = false;
}
});
// Add walking animation - slight bouncing
tween(minionGraphics, {
scaleY: 1.4
}, {
duration: 200,
easing: tween.easeInOut
});
tween(minionGraphics, {
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeInOut
});
}
};
self.update = function () {
// Only act if not currently moving
if (!self.isMoving) {
self.harvestTimer++;
// Look for crops to harvest every 60 ticks (1 second)
if (self.harvestTimer >= 60) {
self.harvestTimer = 0;
var nextTarget = self.findNextTarget();
if (nextTarget) {
self.moveToPlot(nextTarget);
} else {
// No crops to harvest, wander around
self.wanderAround();
}
}
}
};
return self;
});
var SellPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like inventory panel
self.addChild(panelBg);
var titleText = new Text2('VENDER CULTIVOS', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -200;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// Switch to buy panel button
var buyPanelBtn = self.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: -700,
y: 200
}));
var buyPanelBtnText = new Text2('COMPRAR', {
size: 30,
fill: 0xFFFFFF
});
buyPanelBtnText.anchor.set(0.5, 0.5);
buyPanelBtn.addChild(buyPanelBtnText);
// Sell all button
var sellAllBtn = self.addChild(LK.getAsset('sellAllButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 200
}));
var sellAllBtnText = new Text2('VENDER TODO', {
size: 35,
fill: 0xFFFFFF
});
sellAllBtnText.anchor.set(0.5, 0.5);
sellAllBtn.addChild(sellAllBtnText);
// Initialize sell texts array
self.sellTexts = [];
self.updateSellSection = function () {
// Clear existing sell items
self.sellTexts.forEach(function (item) {
item.destroy();
});
self.sellTexts = [];
// Create grid layout for sell items
var itemsPerRow = 4;
var itemSpacing = 180;
var currentRow = 0;
var currentCol = 0;
var startX = -300;
var startY = 80;
// Show harvested crops for selling (exclude mutated crops here)
Object.keys(inventory).forEach(function (cropType) {
if (inventory[cropType] > 0 && !cropType.endsWith('_mutated')) {
var sellPrice = Math.floor(cropData[cropType].value * 0.8); // 80% of original value
var sellItem = new ShopItem(cropType, sellPrice, true, inventory[cropType]);
sellItem.x = -400 + currentCol * 400;
sellItem.y = startY + currentRow * 250;
self.addChild(sellItem);
self.sellTexts.push(sellItem);
sellItem.button.down = function (x, y, obj) {
if (inventory[cropType] > 0) {
inventory[cropType]--;
coins += sellPrice;
// Award XP for selling crops (4 XP per sale)
addXP(4);
// Animate coin icon when selling crop
animateCoins(true);
LK.getSound('purchase').play();
updateUI();
self.updateSellSection();
}
};
currentCol++;
if (currentCol >= itemsPerRow) {
currentCol = 0;
currentRow++;
}
}
});
// Show mutated crops for selling (if any)
Object.keys(inventory).forEach(function (cropType) {
//{mutation_sell_start}
var mutatedKey = cropType + '_mutated'; //{mutation_sell_key}
if (inventory[mutatedKey] > 0) {
//{mutation_sell_check}
var baseSellPrice = Math.floor(cropData[cropType].value * 0.8); //{mutation_sell_base}
var mutatedSellPrice = Math.floor(baseSellPrice * MUTATION_VALUE_MULTIPLIER); //{mutation_sell_price}
var sellItem = new ShopItem(cropType, mutatedSellPrice, true, inventory[mutatedKey]); //{mutation_sell_item}
sellItem.x = -400 + currentCol * 400; //{mutation_sell_x}
sellItem.y = startY + currentRow * 250; //{mutation_sell_y}
// Make mutated crops larger and add special visual effects
sellItem.scaleX = 1.2; //{mutation_sell_scale_x}
sellItem.scaleY = 1.2; //{mutation_sell_scale_y}
// Add mutated indicator text
var mutatedLabel = new Text2('¡MUTACIÓN!', {
//{mutation_sell_label}
size: 25,
//{mutation_sell_label_size}
fill: 0xFF1493,
//{mutation_sell_label_color}
fontStyle: 'bold' //{mutation_sell_label_style}
}); //{mutation_sell_label_end}
mutatedLabel.anchor.set(0.5, 0.5); //{mutation_sell_label_anchor}
mutatedLabel.x = 0; //{mutation_sell_label_x}
mutatedLabel.y = -150; //{mutation_sell_label_y}
sellItem.addChild(mutatedLabel); //{mutation_sell_label_add}
self.addChild(sellItem); //{mutation_sell_add}
self.sellTexts.push(sellItem); //{mutation_sell_push}
sellItem.button.down = function (x, y, obj) {
//{mutation_sell_handler}
if (inventory[mutatedKey] > 0) {
//{mutation_sell_handler_check}
inventory[mutatedKey]--; //{mutation_sell_handler_decrement}
coins += mutatedSellPrice; //{mutation_sell_handler_coins}
// Award more XP for selling mutated crops
addXP(Math.floor(4 * MUTATION_XP_MULTIPLIER)); //{mutation_sell_handler_xp}
// Animate coin icon when selling mutated crop
animateCoins(true); //{mutation_sell_handler_animate}
LK.getSound('purchase').play(); //{mutation_sell_handler_sound}
updateUI(); //{mutation_sell_handler_ui}
self.updateSellSection(); //{mutation_sell_handler_update}
} //{mutation_sell_handler_end}
}; //{mutation_sell_handler_close}
currentCol++; //{mutation_sell_col}
if (currentCol >= itemsPerRow) {
//{mutation_sell_row_check}
currentCol = 0; //{mutation_sell_col_reset}
currentRow++; //{mutation_sell_row_increment}
} //{mutation_sell_row_end}
} //{mutation_sell_check_end}
}); //{mutation_sell_end}
};
sellAllBtn.down = function (x, y, obj) {
var totalEarnings = 0;
var totalSoldItems = 0;
Object.keys(inventory).forEach(function (cropType) {
if (inventory[cropType] > 0 && !cropType.endsWith('_mutated')) {
var sellPrice = Math.floor(cropData[cropType].value * 0.8);
totalEarnings += sellPrice * inventory[cropType];
totalSoldItems += inventory[cropType];
inventory[cropType] = 0;
}
// Also sell mutated versions
var mutatedKey = cropType + '_mutated'; //{mutation_sellall_key}
if (inventory[mutatedKey] > 0) {
//{mutation_sellall_check}
var baseSellPrice = Math.floor(cropData[cropType].value * 0.8); //{mutation_sellall_base}
var mutatedSellPrice = Math.floor(baseSellPrice * MUTATION_VALUE_MULTIPLIER); //{mutation_sellall_price}
totalEarnings += mutatedSellPrice * inventory[mutatedKey]; //{mutation_sellall_earnings}
totalSoldItems += inventory[mutatedKey] * MUTATION_XP_MULTIPLIER; // Count mutated items with XP multiplier
inventory[mutatedKey] = 0; //{mutation_sellall_reset}
} //{mutation_sellall_end}
});
if (totalEarnings > 0) {
coins += totalEarnings;
// Award XP for selling all crops (4 XP per item sold)
addXP(4 * totalSoldItems);
// Animate coin icon when selling all crops
animateCoins(true);
LK.getSound('purchase').play();
updateUI();
self.updateSellSection();
}
};
buyPanelBtn.down = function (x, y, obj) {
self.visible = false;
buyPanel.visible = true;
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isSellPanelOpen = false;
};
return self;
});
var ShopItem = Container.expand(function (itemType, price, isSellItem, count) {
var self = Container.call(this);
// Item icon (no background frame)
var itemIcon = self.addChild(LK.getAsset(itemType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
// Item name text
var itemNames = {
'crop1': 'Lechuga',
'crop2': 'Tomate',
'crop3': 'Maíz',
'crop4': 'Calabaza',
'crop5': 'Sandía',
'crop6': 'Uvas',
'crop7': 'Trufa',
'crop8': 'Orquídea'
};
var nameText = new Text2(itemNames[itemType] || itemType, {
size: 38,
fill: 0x000000,
fontStyle: 'bold'
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 0;
nameText.y = 80;
self.addChild(nameText);
// Price text
var priceText = new Text2('$' + price, {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
priceText.anchor.set(0.5, 0.5);
priceText.x = 0;
priceText.y = 120;
self.addChild(priceText);
// Button
var buttonAsset = isSellItem ? 'sellButton' : 'buyButton';
var button = self.addChild(LK.getAsset(buttonAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180
}));
var buttonText = new Text2(isSellItem ? 'VENDER' : 'COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
button.addChild(buttonText);
self.button = button;
self.itemType = itemType;
self.price = price;
self.isSellItem = isSellItem;
self.updateCount = function (newCount) {
self.alpha = newCount > 0 ? 1.0 : 0.3;
};
return self;
});
var SkillTreePanel = Container.expand(function () {
var self = Container.call(this);
// Create background panel
var panelBg = LK.getAsset('upgradesPanel', {
anchorX: 0.5,
anchorY: 0.5
});
panelBg.scale.set(1.5, 0.8);
self.addChild(panelBg);
var titleText = new Text2('ÁRBOL DE HABILIDADES', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -280;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -300
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// Available attribute points display
self.attributePointsText = new Text2('', {
size: 40,
fill: 0x000000,
fontStyle: 'bold'
});
self.attributePointsText.anchor.set(0.5, 0.5);
self.attributePointsText.x = 0;
self.attributePointsText.y = -220;
self.addChild(self.attributePointsText);
// Skill categories
var skills = [{
name: 'VELOCIDAD DE CRECIMIENTO',
description: 'Reduce el tiempo de crecimiento',
icon: 'seedling',
maxLevel: 5,
x: -400,
y: -100
}, {
name: 'VALOR DE CULTIVOS',
description: 'Aumenta el valor de venta',
icon: 'coinIcon',
maxLevel: 5,
x: 0,
y: -100
}, {
name: 'PROBABILIDAD MUTACIÓN',
description: 'Aumenta chance de mutación',
icon: 'crop1',
maxLevel: 5,
x: 400,
y: -100
}, {
name: 'GANANCIA XP',
description: 'Más experiencia por acción',
icon: 'character',
maxLevel: 5,
x: -200,
y: 100
}, {
name: 'EFICIENCIA HERRAMIENTAS',
description: 'Mejores efectos de herramientas',
icon: 'sprinkler',
maxLevel: 5,
x: 200,
y: 100
}];
self.skillContainers = [];
skills.forEach(function (skill, index) {
var skillContainer = new Container();
skillContainer.x = skill.x;
skillContainer.y = skill.y;
self.addChild(skillContainer);
// Skill icon
var skillIcon = skillContainer.addChild(LK.getAsset(skill.icon, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
}));
// Skill name
var skillName = new Text2(skill.name, {
size: 25,
fill: 0x000000,
fontStyle: 'bold'
});
skillName.anchor.set(0.5, 0.5);
skillName.x = 0;
skillName.y = 60;
skillContainer.addChild(skillName);
// Skill description
var skillDesc = new Text2(skill.description, {
size: 18,
fill: 0x666666
});
skillDesc.anchor.set(0.5, 0.5);
skillDesc.x = 0;
skillDesc.y = 85;
skillContainer.addChild(skillDesc);
// Level display
var levelText = new Text2('0/' + skill.maxLevel, {
size: 30,
fill: 0x000000,
fontStyle: 'bold'
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 0;
levelText.y = -60;
skillContainer.addChild(levelText);
// Upgrade button
var upgradeBtn = skillContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 110
}));
var upgradeBtnText = new Text2('+', {
size: 30,
fill: 0xFFFFFF,
fontStyle: 'bold'
});
upgradeBtnText.anchor.set(0.5, 0.5);
upgradeBtn.addChild(upgradeBtnText);
// Store references
skill.container = skillContainer;
skill.levelText = levelText;
skill.upgradeBtn = upgradeBtn;
skill.upgradeBtnText = upgradeBtnText;
skill.currentLevel = skillLevels[index] || 0;
// Button handler
upgradeBtn.down = function (x, y, obj) {
if (attributePoints > 0 && skill.currentLevel < skill.maxLevel) {
attributePoints--;
skill.currentLevel++;
skillLevels[index] = skill.currentLevel;
// Apply skill effect
applySkillEffect(index, skill.currentLevel);
// Update storage
storage.attributePoints = attributePoints;
storage.skillLevels = skillLevels;
LK.getSound('purchase').play();
self.updateSkillDisplay();
}
};
self.skillContainers.push(skill);
});
self.updateSkillDisplay = function () {
self.attributePointsText.setText('Puntos Disponibles: ' + attributePoints);
self.skillContainers.forEach(function (skill) {
skill.levelText.setText(skill.currentLevel + '/' + skill.maxLevel);
// Update button state
if (attributePoints > 0 && skill.currentLevel < skill.maxLevel) {
skill.upgradeBtn.alpha = 1.0;
skill.upgradeBtnText.setText('+');
} else {
skill.upgradeBtn.alpha = 0.5;
skill.upgradeBtnText.setText(skill.currentLevel >= skill.maxLevel ? 'MAX' : '+');
}
});
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isSkillTreeOpen = false;
};
return self;
});
var Sprinkler = Container.expand(function () {
var self = Container.call(this);
// Create sprinkler visual using dedicated sprinkler asset
var sprinklerGraphics = self.attachAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
// Add pulsing animation to show it's working
function startSprinklerAnimation() {
tween(sprinklerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.8
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(sprinklerGraphics, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 1.0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
startSprinklerAnimation();
}
}
});
}
});
}
startSprinklerAnimation();
// Accelerate all crops every 5 seconds (300 ticks)
self.accelerationTimer = 0;
self.update = function () {
self.accelerationTimer++;
if (self.accelerationTimer >= 300) {
// Every 5 seconds
self.accelerationTimer = 0;
// Accelerate all growing crops by 30 seconds (1800 ticks)
farmPlots.forEach(function (plot) {
if (!plot.isEmpty && !plot.isReady) {
plot.plantTime -= 1800; // Reduce by 30 seconds
}
});
// Flash effect when accelerating
tween(sprinklerGraphics, {
tint: 0x00FF00
}, {
duration: 200,
easing: tween.easeInOut
});
tween(sprinklerGraphics, {
tint: 0x4169E1
}, {
duration: 200,
easing: tween.easeInOut
});
}
};
return self;
});
var UpgradesPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('upgradesPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like inventory panel
self.addChild(panelBg);
var titleText = new Text2('MEJORAS', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -280;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// More Plots Upgrade - Top row, left position
var plotUpgradeContainer = new Container();
plotUpgradeContainer.x = -400; // Better centered positioning like shop
plotUpgradeContainer.y = -150; // Top row positioning
self.addChild(plotUpgradeContainer);
var plotIcon = plotUpgradeContainer.addChild(LK.getAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5
}));
var plotTitle = new Text2('MÁS PARCELAS', {
size: 28,
fill: 0x000000
});
plotTitle.anchor.set(0.5, 0.5);
plotTitle.x = 0;
plotTitle.y = 80; // Better spacing from icon
plotUpgradeContainer.addChild(plotTitle);
var plotPrice = new Text2('$500', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
plotPrice.anchor.set(0.5, 0.5);
plotPrice.x = 0;
plotPrice.y = 120; // Below title
plotUpgradeContainer.addChild(plotPrice);
var plotBtn = plotUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var plotBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
plotBtnText.anchor.set(0.5, 0.5);
plotBtn.addChild(plotBtnText);
// Speed Upgrade - Top row, second position
var speedUpgradeContainer = new Container();
speedUpgradeContainer.x = -100; // Center-left positioning
speedUpgradeContainer.y = -150; // Top row positioning
self.addChild(speedUpgradeContainer);
var speedIcon = speedUpgradeContainer.addChild(LK.getAsset('seedling', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
var speedTitle = new Text2('VELOCIDAD', {
size: 28,
fill: 0x000000
});
speedTitle.anchor.set(0.5, 0.5);
speedTitle.x = 0;
speedTitle.y = 80; // Better spacing from icon
speedUpgradeContainer.addChild(speedTitle);
var speedPrice = new Text2('$300', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
speedPrice.anchor.set(0.5, 0.5);
speedPrice.x = 0;
speedPrice.y = 120; // Below title
speedUpgradeContainer.addChild(speedPrice);
var speedBtn = speedUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var speedBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
speedBtnText.anchor.set(0.5, 0.5);
speedBtn.addChild(speedBtnText);
// Sprinkler Upgrade - Top row, third position
var sprinklerUpgradeContainer = new Container();
sprinklerUpgradeContainer.x = 200; // Center-right positioning
sprinklerUpgradeContainer.y = -150; // Top row positioning
self.addChild(sprinklerUpgradeContainer);
var sprinklerIcon = sprinklerUpgradeContainer.addChild(LK.getAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
}));
var sprinklerTitle = new Text2('ASPERSOR', {
size: 28,
fill: 0x000000
});
sprinklerTitle.anchor.set(0.5, 0.5);
sprinklerTitle.x = 0;
sprinklerTitle.y = 80; // Better spacing from icon
sprinklerUpgradeContainer.addChild(sprinklerTitle);
var sprinklerPrice = new Text2('$1500', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
sprinklerPrice.anchor.set(0.5, 0.5);
sprinklerPrice.x = 0;
sprinklerPrice.y = 120; // Below title
sprinklerUpgradeContainer.addChild(sprinklerPrice);
var sprinklerBtn = sprinklerUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var sprinklerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
sprinklerBtnText.anchor.set(0.5, 0.5);
sprinklerBtn.addChild(sprinklerBtnText);
// Companion Upgrade - Top row, fourth position
var companionUpgradeContainer = new Container();
companionUpgradeContainer.x = 500; // Right positioning
companionUpgradeContainer.y = -150; // Top row positioning
self.addChild(companionUpgradeContainer);
var companionIcon = companionUpgradeContainer.addChild(LK.getAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
}));
var companionTitle = new Text2('COMPAÑERO', {
size: 28,
fill: 0x000000
});
companionTitle.anchor.set(0.5, 0.5);
companionTitle.x = 0;
companionTitle.y = 80; // Better spacing from icon
companionUpgradeContainer.addChild(companionTitle);
var companionPrice = new Text2('$3000', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
companionPrice.anchor.set(0.5, 0.5);
companionPrice.x = 0;
companionPrice.y = 120; // Below title
companionUpgradeContainer.addChild(companionPrice);
var companionBtn = companionUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var companionBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
companionBtnText.anchor.set(0.5, 0.5);
companionBtn.addChild(companionBtnText);
// Super Fertilizer Upgrade - Bottom row, left position (unlocked at level 15)
var fertilizerUpgradeContainer = new Container();
fertilizerUpgradeContainer.x = -200; // Left-center positioning for bottom row
fertilizerUpgradeContainer.y = 100; // Bottom row positioning - moved up from previous position
self.addChild(fertilizerUpgradeContainer);
var fertilizerIcon = fertilizerUpgradeContainer.addChild(LK.getAsset('crop3', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0x00FF00
}));
var fertilizerTitle = new Text2('FERTILIZANTE', {
size: 28,
fill: 0x000000
});
fertilizerTitle.anchor.set(0.5, 0.5);
fertilizerTitle.x = 0;
fertilizerTitle.y = 80; // Better spacing from icon
fertilizerUpgradeContainer.addChild(fertilizerTitle);
var fertilizerPrice = new Text2('$5000', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
fertilizerPrice.anchor.set(0.5, 0.5);
fertilizerPrice.x = 0;
fertilizerPrice.y = 120; // Below title
fertilizerUpgradeContainer.addChild(fertilizerPrice);
var fertilizerBtn = fertilizerUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var fertilizerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
fertilizerBtnText.anchor.set(0.5, 0.5);
fertilizerBtn.addChild(fertilizerBtnText);
// Mega Harvester Upgrade - Bottom row, right position (unlocked at level 25)
var harvesterUpgradeContainer = new Container();
harvesterUpgradeContainer.x = 200; // Right-center positioning for bottom row
harvesterUpgradeContainer.y = 100; // Bottom row positioning - moved up from previous position
self.addChild(harvesterUpgradeContainer);
var harvesterIcon = harvesterUpgradeContainer.addChild(LK.getAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFD700
}));
var harvesterTitle = new Text2('COSECHADOR', {
size: 28,
fill: 0x000000
});
harvesterTitle.anchor.set(0.5, 0.5);
harvesterTitle.x = 0;
harvesterTitle.y = 80; // Better spacing from icon
harvesterUpgradeContainer.addChild(harvesterTitle);
var harvesterPrice = new Text2('$12000', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
harvesterPrice.anchor.set(0.5, 0.5);
harvesterPrice.x = 0;
harvesterPrice.y = 120; // Below title
harvesterUpgradeContainer.addChild(harvesterPrice);
var harvesterBtn = harvesterUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var harvesterBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
harvesterBtnText.anchor.set(0.5, 0.5);
harvesterBtn.addChild(harvesterBtnText);
// Update upgrade button states based on level requirements
self.updateUpgradeAvailability = function () {
// Super Fertilizer - unlocked at level 15
if (level < 15) {
fertilizerUpgradeContainer.alpha = 0.5;
fertilizerBtn.alpha = 0.3;
fertilizerBtnText.setText('BLOQUEADO');
} else if (hasSuperFertilizer) {
fertilizerBtn.alpha = 0.5;
fertilizerBtnText.setText('COMPRADO');
} else {
fertilizerUpgradeContainer.alpha = 1.0;
fertilizerBtn.alpha = 1.0;
fertilizerBtnText.setText('COMPRAR');
}
// Mega Harvester - unlocked at level 25
if (level < 25) {
harvesterUpgradeContainer.alpha = 0.5;
harvesterBtn.alpha = 0.3;
harvesterBtnText.setText('BLOQUEADO');
} else if (hasMegaHarvester) {
harvesterBtn.alpha = 0.5;
harvesterBtnText.setText('COMPRADO');
} else {
harvesterUpgradeContainer.alpha = 1.0;
harvesterBtn.alpha = 1.0;
harvesterBtnText.setText('COMPRAR');
}
};
// Button handlers
plotBtn.down = function (x, y, obj) {
if (coins >= 500 && totalPlots < 64) {
// Max 64 plots (4 grids of 4x4)
coins -= 500;
updateUI();
// Close upgrades panel
self.visible = false;
isUpgradesPanelOpen = false;
// Enter plot selection mode
isPlotSelectionMode = true;
createPlotSelectionOverlay();
}
};
speedBtn.down = function (x, y, obj) {
if (coins >= 300) {
coins -= 300;
// Accelerate all growing crops
farmPlots.forEach(function (plot) {
if (!plot.isEmpty && !plot.isReady) {
plot.plantTime -= 300; // Reduce by 5 seconds (double the effect)
}
});
// Award XP for speed upgrade (12 XP)
addXP(12);
LK.getSound('purchase').play();
updateUI();
}
};
fertilizerBtn.down = function (x, y, obj) {
if (coins >= 5000 && level >= 15 && !hasSuperFertilizer) {
coins -= 5000;
hasSuperFertilizer = true;
// Permanently increase mutation chance by 20%
MUTATION_CHANCE += 0.20;
// Award XP for fertilizer upgrade (100 XP)
addXP(100);
LK.getSound('purchase').play();
updateUI();
self.updateUpgradeAvailability();
// Flash screen green for fertilizer upgrade
LK.effects.flashScreen(0x00FF00, 1000);
}
};
harvesterBtn.down = function (x, y, obj) {
if (coins >= 12000 && level >= 25 && !hasMegaHarvester) {
coins -= 12000;
hasMegaHarvester = true;
// Permanently increase crop value multiplier by 50%
MUTATION_VALUE_MULTIPLIER += 0.5;
// Award XP for harvester upgrade (200 XP)
addXP(200);
LK.getSound('purchase').play();
updateUI();
self.updateUpgradeAvailability();
// Flash screen gold for harvester upgrade
LK.effects.flashScreen(0xFFD700, 1200);
}
};
// Update sprinkler button appearance based on current state
self.updateSprinklerButton = function () {
if (hasSprinkler) {
sprinklerBtn.alpha = 0.5;
sprinklerBtnText.setText('COMPRADO');
} else {
sprinklerBtn.alpha = 1.0;
sprinklerBtnText.setText('COMPRAR');
}
};
// Update companion button appearance based on current state
self.updateCompanionButton = function () {
if (hasCompanion) {
companionBtn.alpha = 0.5;
companionBtnText.setText('COMPRADO');
} else {
companionBtn.alpha = 1.0;
companionBtnText.setText('COMPRAR');
}
};
// Initialize button states
self.updateSprinklerButton();
self.updateCompanionButton();
sprinklerBtn.down = function (x, y, obj) {
if (coins >= 1500 && !hasSprinkler) {
coins -= 1500;
hasSprinkler = true;
self.updateSprinklerButton();
// Award XP for sprinkler upgrade (50 XP)
addXP(50);
LK.getSound('purchase').play();
updateUI();
// Create sprinkler in the middle of all plots
sprinkler = new Sprinkler();
sprinkler.x = mainGridCenterX; // Center of main plot grid
sprinkler.y = mainGridCenterY; // Center of main plot grid
sprinkler.zIndex = 50; // Render above plots but below UI
game.addChild(sprinkler);
// Close upgrades panel after purchase
self.visible = false;
isUpgradesPanelOpen = false;
}
};
companionBtn.down = function (x, y, obj) {
if (coins >= 3000 && !hasCompanion) {
coins -= 3000;
hasCompanion = true;
self.updateCompanionButton();
// Award XP for companion upgrade (100 XP)
addXP(100);
LK.getSound('purchase').play();
updateUI();
// Create minion when companion is purchased
minion = new Minion();
minion.x = 1024; // Start at center
minion.y = 1200; // Above the farm plots
minion.zIndex = 100; // Render above plots but below UI
game.addChild(minion);
}
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isUpgradesPanelOpen = false;
};
// Initialize upgrade states
self.updateUpgradeAvailability();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Add background image
var backgroundImage = game.addChild(LK.getAsset('gameBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
backgroundImage.zIndex = -2000; // Ensure it's behind everything
// Game data
var cropData = {
'crop1': {
name: 'Lechuga',
growthTime: 300,
value: 8
},
// 5 seconds
'crop2': {
name: 'Tomate',
growthTime: 600,
value: 18
},
// 10 seconds
'crop3': {
name: 'Maíz',
growthTime: 900,
value: 35
},
// 15 seconds
'crop4': {
name: 'Calabaza',
growthTime: 1200,
value: 75
},
// 20 seconds
'crop5': {
name: 'Sandía',
growthTime: 1500,
value: 120
},
// 25 seconds
'crop6': {
name: 'Uvas',
growthTime: 1800,
value: 200
},
// 30 seconds
'crop7': {
name: 'Trufa',
growthTime: 2400,
value: 350
},
// 40 seconds
'crop8': {
name: 'Orquídea',
growthTime: 3000,
value: 500
} // 50 seconds
};
// Mutation system constants
var MUTATION_CHANCE = 0.15; // 15% chance for mutation
var MUTATION_VALUE_MULTIPLIER = 2.5; // Mutated crops are worth 2.5x more
var MUTATION_XP_MULTIPLIER = 2; // Mutated crops give 2x more XP (double experience)
// Clear all stored game progress - reset to starting values
storage.coins = 100;
storage.seeds = {
'crop1': 10,
'crop2': 0,
'crop3': 0,
'crop4': 0,
'crop5': 0,
'crop6': 0,
'crop7': 0,
'crop8': 0
};
storage.inventory = {};
storage.hasCompanion = false;
storage.hasSprinkler = false;
storage.hasSuperFertilizer = false;
storage.hasMegaHarvester = false;
storage.totalPlots = 16;
storage.level = 1;
storage.xp = 0;
storage.attributePoints = 0;
storage.skillLevels = [0, 0, 0, 0, 0];
// Game state - initialize to starting values
var isStartScreen = true;
var startScreenOverlay = null;
var coins = 100;
var seeds = {
'crop1': 10,
'crop2': 0,
'crop3': 0,
'crop4': 0,
'crop5': 0,
'crop6': 0,
'crop7': 0,
'crop8': 0
};
var inventory = {};
var selectedSeed = 'crop1';
var isBuyPanelOpen = false;
var isSellPanelOpen = false;
var isInventoryOpen = false;
var isUpgradesPanelOpen = false;
var hasCompanion = false;
var companionTimer = 0;
var minion = null;
var hasSprinkler = false;
var sprinkler = null;
var hasSuperFertilizer = false;
var hasMegaHarvester = false;
var level = 1;
var xp = 0;
var attributePoints = 0;
var skillLevels = [0, 0, 0, 0, 0];
var isSkillTreeOpen = false;
var isPlotSelectionMode = false;
var selectedPlotSlot = null;
var plotSelectionOverlay = null;
// No minion at start since companion is not purchased
// UI elements
var coinsContainer = new Container();
coinsContainer.x = 1024; // Position at top center
coinsContainer.y = 150; // Position at top
coinsContainer.zIndex = 400;
game.addChild(coinsContainer);
var coinIcon = coinsContainer.addChild(LK.getAsset('coinIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 40
}));
// Make coinIcon globally accessible for animations
window.coinIcon = coinIcon;
var coinsText = new Text2(coins.toString(), {
size: 120,
fill: 0xFFD700,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 8
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 80;
coinsText.y = 40;
coinsContainer.addChild(coinsText);
// Create seasons and time system
var gameStartTime = Date.now();
var timeMultiplier = 20; // 1 real minute = 20 game minutes (slower time)
var currentSeason = 0; // 0=Primavera, 1=Verano, 2=Otoño, 3=Invierno
var seasonNames = ['Primavera', 'Verano', 'Otoño', 'Invierno'];
var dayOfYear = 1;
var currentYear = 2024;
// Create time/season display container in top-right
var timeContainer = new Container();
timeContainer.x = 1900; // Top-right position (leaving margin from edge)
timeContainer.y = 200; // Top position
timeContainer.zIndex = 500;
game.addChild(timeContainer);
// Add gray background behind time/season display with rounded corners
var timeBackground = timeContainer.addChild(LK.getAsset('fullScreenOverlay', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.25,
scaleY: 0.15,
x: -200,
y: 0,
tint: 0x808080,
alpha: 0.7
}));
// Apply rounded corners by scaling down slightly and using visual rounding effect
tween(timeBackground, {
scaleX: 0.24,
scaleY: 0.14
}, {
duration: 100,
easing: tween.easeInOut
});
timeBackground.zIndex = -1; // Behind the text elements
// Time display
var timeText = new Text2('12:00', {
size: 90,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
timeText.anchor.set(1.0, 0.5);
timeText.x = 0;
timeText.y = -80;
timeContainer.addChild(timeText);
// Date display
var dateText = new Text2('1 Ene 2024', {
size: 80,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 5
});
dateText.anchor.set(1.0, 0.5);
dateText.x = 0;
dateText.y = 0;
timeContainer.addChild(dateText);
// Season display
var seasonText = new Text2('Primavera', {
size: 85,
fill: 0x90EE90,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
seasonText.anchor.set(1.0, 0.5);
seasonText.x = 0;
seasonText.y = 80;
timeContainer.addChild(seasonText);
// Function to update time and season display
function updateTimeAndSeason() {
var elapsedRealTime = Date.now() - gameStartTime;
// Make 1 game minute pass every 3 seconds (3000ms)
var elapsedGameMinutes = Math.floor(elapsedRealTime / 3000);
var elapsedGameHours = Math.floor(elapsedGameMinutes / 60);
// Calculate current time (24-hour cycle)
var currentHour = (12 + elapsedGameHours) % 24; // Start at 12:00
var currentMinute = elapsedGameMinutes % 60;
// Format time display
var hourStr = currentHour < 10 ? '0' + currentHour : currentHour.toString();
var minuteStr = currentMinute < 10 ? '0' + currentMinute : currentMinute.toString();
timeText.setText(hourStr + ':' + minuteStr);
// Calculate current day (new day every 24 game hours)
var totalGameDays = Math.floor(elapsedGameHours / 24);
var currentDayOfYear = (dayOfYear + totalGameDays - 1) % 365 + 1;
var currentGameYear = currentYear + Math.floor((dayOfYear + totalGameDays - 1) / 365);
// Calculate season (each season lasts ~91 days)
var seasonIndex = Math.floor((currentDayOfYear - 1) / 91) % 4;
if (seasonIndex !== currentSeason) {
currentSeason = seasonIndex;
// Update season color
var seasonColors = [0x90EE90, 0xFFD700, 0xFF8C00, 0x87CEEB]; // Spring, Summer, Autumn, Winter
seasonText.tint = seasonColors[currentSeason];
}
// Format date display
var monthNames = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'];
var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var remainingDays = currentDayOfYear;
var month = 0;
while (remainingDays > daysInMonth[month] && month < 11) {
remainingDays -= daysInMonth[month];
month++;
}
dateText.setText(remainingDays + ' ' + monthNames[month] + ' ' + currentGameYear);
seasonText.setText(seasonNames[currentSeason]);
}
// Create skill points counter container in top-left
var skillPointsContainer = new Container();
skillPointsContainer.x = 200; // Top-left position (avoiding platform menu)
skillPointsContainer.y = 150; // Same height as coins counter
skillPointsContainer.zIndex = 400;
game.addChild(skillPointsContainer);
// Skill points icon
var skillPointIcon = skillPointsContainer.addChild(LK.getAsset('skillPointIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 40,
scaleX: 1.5,
scaleY: 1.5
}));
// Skill points text
var skillPointsText = new Text2(attributePoints.toString(), {
size: 120,
fill: 0xFFD700,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 8
});
skillPointsText.anchor.set(0.5, 0.5);
skillPointsText.x = 320;
skillPointsText.y = 40;
skillPointsContainer.addChild(skillPointsText);
// Create XP progress bar container
var xpContainer = new Container();
xpContainer.x = 1024; // Center horizontally
xpContainer.y = 2450; // Below tab buttons - moved a little lower
xpContainer.zIndex = 400;
game.addChild(xpContainer);
// XP progress bar background
var xpBarBg = xpContainer.addChild(LK.getAsset('inventoryPanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.14,
scaleY: 0.15
}));
// XP progress bar fill
var xpBarFill = xpContainer.addChild(LK.getAsset('inventoryPanel', {
anchorX: 0,
anchorY: 0.5,
scaleX: 1.14,
scaleY: 0.15,
x: -1024,
tint: 0x0000ff
}));
// Level text
var levelText = new Text2('Nivel ' + level, {
size: 90,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 2,
dropShadowDistance: 2,
stroke: 0x000000,
strokeThickness: 8
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 0;
levelText.y = -10;
xpContainer.addChild(levelText);
// XP text
var xpText = new Text2('', {
size: 70,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 2,
dropShadowDistance: 2,
stroke: 0x000000,
strokeThickness: 3
});
xpText.anchor.set(1.0, 0.5);
xpText.x = 1024;
xpText.y = -50;
xpContainer.addChild(xpText);
// Create horizontal tabs container positioned above coins
var tabsContainer = new Container();
tabsContainer.x = 1024;
tabsContainer.y = 2300; // Position above coins text - moved higher
tabsContainer.zIndex = 500; // Ensure tabs render above coins
game.addChild(tabsContainer);
// Shop button
var shopBtn = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var shopBtnText = new Text2('TIENDA', {
size: 35,
fill: 0xFFFFFF
});
shopBtnText.anchor.set(0.5, 0.5);
shopBtn.addChild(shopBtnText);
shopBtn.x = -300;
shopBtn.y = 0;
tabsContainer.addChild(shopBtn);
// Inventory button
var invBtn = LK.getAsset('inventoryButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var invBtnText = new Text2('INVENTARIO', {
size: 30,
fill: 0xFFFFFF
});
invBtnText.anchor.set(0.5, 0.5);
invBtn.addChild(invBtnText);
invBtn.x = 0;
invBtn.y = 0;
tabsContainer.addChild(invBtn);
// Upgrades button
var upgradesBtn = LK.getAsset('upgradesButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var upgradesBtnText = new Text2('MEJORAS', {
size: 30,
fill: 0xFFFFFF
});
upgradesBtnText.anchor.set(0.5, 0.5);
upgradesBtn.addChild(upgradesBtnText);
upgradesBtn.x = 300;
upgradesBtn.y = 0;
tabsContainer.addChild(upgradesBtn);
// Skill tree arrow button
var skillTreeArrowBtn = LK.getAsset('skillTreeArrow', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 3.0
});
skillTreeArrowBtn.x = 1024;
skillTreeArrowBtn.y = 2150;
skillTreeArrowBtn.zIndex = 500;
game.addChild(skillTreeArrowBtn);
// Arrow symbol inside button
var arrowText = new Text2('→', {
size: 50,
fill: 0x000000,
fontStyle: 'bold'
});
arrowText.anchor.set(0.5, 0.5);
skillTreeArrowBtn.addChild(arrowText);
// Create farm plots in 4x4 grid
var farmPlots = [];
var totalPlots = 16; // Always start with 16 plots (4x4)
var plotSpacingX = 140;
var plotSpacingY = 100;
var plotMargin = 30; // Margin between plot groups
// Calculate center position for the main 4x4 grid
var mainGridCenterX = 1024; // Center of screen
var mainGridCenterY = 900; // Positioned to avoid UI overlap
// Calculate starting position for centered 4x4 grid
var mainStartX = mainGridCenterX - 3 * plotSpacingX / 2;
var mainStartY = mainGridCenterY - 3 * plotSpacingY / 2;
function createPlotAtPosition(x, y) {
var plot = new FarmPlot();
plot.x = x;
plot.y = y;
game.addChild(plot);
farmPlots.push(plot);
}
function createPlotSelectionOverlay() {
plotSelectionOverlay = new Container();
plotSelectionOverlay.zIndex = 800;
game.addChild(plotSelectionOverlay);
// Semi-transparent background
var overlay = plotSelectionOverlay.addChild(LK.getAsset('fullScreenOverlay', {
anchorX: 0,
anchorY: 0,
alpha: 0.7
}));
// Title text
var titleText = new Text2('ELIGE DÓNDE COLOCAR LA NUEVA PARCELA', {
size: 80,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
plotSelectionOverlay.addChild(titleText);
// Instructions text
var instructionsText = new Text2('TOCA UN ESPACIO VACÍO PARA COLOCAR LA PARCELA', {
size: 60,
fill: 0xFFD700,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 2,
stroke: 0x000000,
strokeThickness: 4
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 400;
plotSelectionOverlay.addChild(instructionsText);
// Cancel button
var cancelBtn = plotSelectionOverlay.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2400
}));
var cancelBtnText = new Text2('CANCELAR', {
size: 30,
fill: 0xFFFFFF
});
cancelBtnText.anchor.set(0.5, 0.5);
cancelBtn.addChild(cancelBtnText);
// Create selection slots for each potential plot position
createPlotSelectionSlots();
// Cancel button handler
cancelBtn.down = function (x, y, obj) {
if (plotSelectionOverlay) {
plotSelectionOverlay.destroy();
plotSelectionOverlay = null;
}
isPlotSelectionMode = false;
selectedPlotSlot = null;
coins += 100; // Refund the money
updateUI();
};
return plotSelectionOverlay;
}
function createPlotSelectionSlots() {
if (!plotSelectionOverlay) return;
// Create visual slots for all possible plot positions
var slotsCreated = 0;
var maxSlots = 64; // Maximum possible plots
// Main 4x4 grid slots
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = mainStartX + col * plotSpacingX;
var slotY = mainStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
// Check if this position already has a plot
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
// Right 4x4 grid slots
var rightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var rightStartY = mainStartY;
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = rightStartX + col * plotSpacingX;
var slotY = rightStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
// Bottom-left 4x4 grid slots
var bottomLeftStartX = mainStartX;
var bottomLeftStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = bottomLeftStartX + col * plotSpacingX;
var slotY = bottomLeftStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
// Bottom-right 4x4 grid slots
var bottomRightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var bottomRightStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = bottomRightStartX + col * plotSpacingX;
var slotY = bottomRightStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
}
function createPlotSelectionSlot(x, y, index, hasPlot) {
if (!plotSelectionOverlay) return;
var slot = new Container();
slot.x = x;
slot.y = y;
slot.zIndex = 10;
plotSelectionOverlay.addChild(slot);
if (hasPlot) {
// Show existing plot (darker/disabled)
var existingPlotVisual = slot.addChild(LK.getAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
tint: 0x666666
}));
} else {
// Show empty slot (can be selected)
var emptySlotVisual = slot.addChild(LK.getAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7,
tint: 0x00FF00
}));
// Add pulsing animation to available slots
tween(emptySlotVisual, {
alpha: 0.4,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(emptySlotVisual, {
alpha: 0.7,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (emptySlotVisual.parent) {
createPlotSelectionSlot(x, y, index, hasPlot);
}
}
});
}
});
// Make empty slot clickable
slot.down = function (slotX, slotY, obj) {
if (!hasPlot && isPlotSelectionMode) {
// Place the new plot here
createPlotAtPosition(x, y);
totalPlots++;
storage.totalPlots = totalPlots;
// Close selection overlay
if (plotSelectionOverlay) {
plotSelectionOverlay.destroy();
plotSelectionOverlay = null;
}
isPlotSelectionMode = false;
selectedPlotSlot = null;
// Award XP for buying plot upgrade (15 XP)
addXP(15);
LK.getSound('purchase').play();
updateUI();
}
};
}
}
function repositionAllPlots() {
// Clear existing plots
farmPlots.forEach(function (plot) {
plot.destroy();
});
farmPlots = [];
var plotsCreated = 0;
// Main 4x4 grid (center)
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(mainStartX + col * plotSpacingX, mainStartY + row * plotSpacingY);
plotsCreated++;
}
}
// Right 4x4 grid (if more than 16 plots)
if (totalPlots > 16) {
var rightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var rightStartY = mainStartY;
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(rightStartX + col * plotSpacingX, rightStartY + row * plotSpacingY);
plotsCreated++;
}
}
}
// Bottom-left 4x4 grid (if more than 32 plots)
if (totalPlots > 32) {
var bottomLeftStartX = mainStartX;
var bottomLeftStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(bottomLeftStartX + col * plotSpacingX, bottomLeftStartY + row * plotSpacingY);
plotsCreated++;
}
}
}
// Bottom-right 4x4 grid (if more than 48 plots)
if (totalPlots > 48) {
var bottomRightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var bottomRightStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(bottomRightStartX + col * plotSpacingX, bottomRightStartY + row * plotSpacingY);
plotsCreated++;
}
}
}
// Ensure all farm plots render below interface panels
farmPlots.forEach(function (plot) {
plot.zIndex = -1000;
});
}
// Initialize farm plots
repositionAllPlots();
// Buy and sell panels - positioned as horizontal scroll above coins
var buyPanel = new BuyPanel();
buyPanel.x = 1024;
buyPanel.y = 1800;
buyPanel.visible = false;
buyPanel.zIndex = 600;
game.addChild(buyPanel);
var sellPanel = new SellPanel();
sellPanel.x = 1024;
sellPanel.y = 1800;
sellPanel.visible = false;
sellPanel.zIndex = 600;
game.addChild(sellPanel);
var inventoryPanel = new InventoryPanel();
inventoryPanel.x = 1024;
inventoryPanel.y = 1800;
inventoryPanel.visible = false;
inventoryPanel.zIndex = 600;
game.addChild(inventoryPanel);
var upgradesPanel = new UpgradesPanel();
upgradesPanel.x = 1024;
upgradesPanel.y = 1800;
upgradesPanel.visible = false;
upgradesPanel.zIndex = 600;
game.addChild(upgradesPanel);
var skillTreePanel = new SkillTreePanel();
skillTreePanel.x = 1024;
skillTreePanel.y = 1600;
skillTreePanel.visible = false;
skillTreePanel.zIndex = 700;
game.addChild(skillTreePanel);
// Apply skill effects based on current levels
function applySkillEffect(skillIndex, level) {
switch (skillIndex) {
case 0:
// Growth Speed - reduce growth time
break;
case 1:
// Crop Value - increase sell price
break;
case 2:
// Mutation Chance - increase mutation probability
break;
case 3:
// XP Gain - multiply XP rewards
break;
case 4:
// Tool Efficiency - enhance sprinkler/companion
break;
}
}
// Calculate skill multipliers
function getGrowthSpeedMultiplier() {
var level = skillLevels[0] || 0;
return 1 - level * 0.1; // 10% faster per level
}
function getCropValueMultiplier() {
var level = skillLevels[1] || 0;
return 1 + level * 0.15; // 15% more value per level
}
function getMutationChanceBonus() {
var level = skillLevels[2] || 0;
return level * 0.05; // 5% more chance per level
}
function getXPMultiplier() {
var level = skillLevels[3] || 0;
return 1 + level * 0.2; // 20% more XP per level
}
function getToolEfficiencyMultiplier() {
var level = skillLevels[4] || 0;
return 1 + level * 0.25; // 25% better tools per level
}
// Button event handlers
shopBtn.down = function (x, y, obj) {
if (!isInventoryOpen && !isSellPanelOpen && !isUpgradesPanelOpen) {
buyPanel.visible = true;
isBuyPanelOpen = true;
}
};
invBtn.down = function (x, y, obj) {
if (!isBuyPanelOpen && !isSellPanelOpen && !isUpgradesPanelOpen) {
inventoryPanel.visible = true;
inventoryPanel.updateInventory();
isInventoryOpen = true;
}
};
upgradesBtn.down = function (x, y, obj) {
if (!isBuyPanelOpen && !isSellPanelOpen && !isInventoryOpen) {
upgradesPanel.visible = true;
upgradesPanel.updateUpgradeAvailability();
isUpgradesPanelOpen = true;
}
};
skillTreeArrowBtn.down = function (x, y, obj) {
if (!isBuyPanelOpen && !isSellPanelOpen && !isInventoryOpen && !isUpgradesPanelOpen) {
skillTreePanel.visible = true;
skillTreePanel.updateSkillDisplay();
isSkillTreeOpen = true;
}
};
// Create hotbar
var hotbarSlots = [];
var hotbarContainer = new Container();
hotbarContainer.x = 1024;
hotbarContainer.y = 2600;
hotbarContainer.zIndex = 400;
game.addChild(hotbarContainer);
// Create hotbar slots for each seed type
var seedTypes = ['crop1', 'crop2', 'crop3', 'crop4', 'crop5', 'crop6', 'crop7', 'crop8'];
seedTypes.forEach(function (seedType, index) {
var slot = new HotbarSlot(seedType, index);
slot.x = (index - 3.5) * 180; // Center all 8 slots around container center
slot.y = 0;
hotbarContainer.addChild(slot);
hotbarSlots.push(slot);
});
function updateHotbar() {
hotbarSlots.forEach(function (slot) {
var count = seeds[slot.seedType] || 0;
slot.updateCount(count);
slot.setSelected(slot.seedType === selectedSeed);
});
}
// Initialize hotbar
updateHotbar();
// Initialize XP bar
updateXPBar();
// Hide UI elements during start screen
function setUIVisibility(visible) {
coinsContainer.visible = visible;
timeContainer.visible = visible;
xpContainer.visible = visible;
tabsContainer.visible = visible;
hotbarContainer.visible = visible;
skillTreeArrowBtn.visible = visible;
skillPointsContainer.visible = visible;
}
// Initially hide UI elements
setUIVisibility(false);
// Remove old seed selection behavior - hotbar handles it now
game.down = function (x, y, obj) {
// Hotbar slots handle their own clicks now
};
var lastCoins = coins; // Track last coins value for animation detection
// Calculate XP needed for a specific level
function getXPForLevel(targetLevel) {
if (targetLevel === 1) return 0;
if (targetLevel === 2) return 20; // First level only needs 20 XP
return Math.floor(100 * Math.pow(1.5, targetLevel - 2));
}
// Get current level's XP requirement
function getCurrentLevelXP() {
return getXPForLevel(level);
}
// Get next level's XP requirement
function getNextLevelXP() {
return getXPForLevel(level + 1);
}
// Add XP and handle level ups
function addXP(amount) {
var multipliedAmount = Math.floor(amount * getXPMultiplier());
xp += multipliedAmount;
// Check for level up
var nextLevelXP = getNextLevelXP();
if (xp >= nextLevelXP) {
level++;
// Award attribute points every 5 levels
if (level % 5 === 0) {
attributePoints += 5;
// Flash screen purple for attribute points
LK.effects.flashScreen(0x9932CC, 1000);
} else {
// Flash screen gold for regular level up
LK.effects.flashScreen(0xFFD700, 800);
}
// Animate XP bar
tween(xpContainer, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.easeOut
});
tween(xpContainer, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 400,
easing: tween.easeInOut
});
}
updateXPBar();
}
// Update XP progress bar visual
function updateXPBar() {
var currentLevelXP = getCurrentLevelXP();
var nextLevelXP = getNextLevelXP();
var progressXP = xp - currentLevelXP;
var levelXPRange = nextLevelXP - currentLevelXP;
var progress = Math.min(progressXP / levelXPRange, 1.0);
// Update bar fill using scaleX to match background thickness exactly
xpBarFill.scaleX = 1.14 * progress;
xpBarFill.scaleY = 0.15; // Match background scaleY exactly
// Update texts
levelText.setText('Nivel ' + level);
xpText.setText(progressXP + '/' + levelXPRange + ' XP');
}
function animateCoins(increase) {
if (increase) {
// Animate for coin increase (green pulse and scale up)
tween(window.coinIcon, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0x00ff00
}, {
duration: 200,
easing: tween.easeOut
});
tween(window.coinIcon, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeInOut
});
} else {
// Animate for coin decrease (red pulse and slight shrink)
tween(window.coinIcon, {
scaleX: 0.8,
scaleY: 0.8,
tint: 0xff0000
}, {
duration: 200,
easing: tween.easeOut
});
tween(window.coinIcon, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeInOut
});
}
}
function updateUI() {
// Store current text before updating
var currentText = coinsText.text;
var newText = coins.toString();
// Update the coins text
coinsText.setText(newText);
// Update skill points text
skillPointsText.setText(attributePoints.toString());
updateHotbar();
updateXPBar();
// Check if the displayed text actually changed and animate accordingly
if (currentText !== newText) {
if (coins > lastCoins) {
animateCoins(true); // Coins increased
} else if (coins < lastCoins) {
animateCoins(false); // Coins decreased
}
}
lastCoins = coins; // Update last coins value
// Save progress
storage.coins = coins;
storage.seeds = seeds;
storage.inventory = inventory;
storage.hasCompanion = hasCompanion;
storage.hasSprinkler = hasSprinkler;
storage.hasSuperFertilizer = hasSuperFertilizer;
storage.hasMegaHarvester = hasMegaHarvester;
storage.level = level;
storage.xp = xp;
storage.attributePoints = attributePoints;
storage.skillLevels = skillLevels;
}
// Initialize sprinkler if already purchased
if (hasSprinkler && !sprinkler) {
sprinkler = new Sprinkler();
sprinkler.x = mainGridCenterX;
sprinkler.y = mainGridCenterY;
sprinkler.zIndex = 50;
game.addChild(sprinkler);
}
// Create start screen
function createStartScreen() {
startScreenOverlay = new Container();
startScreenOverlay.zIndex = 1000;
game.addChild(startScreenOverlay);
// Semi-transparent background
var overlay = startScreenOverlay.addChild(LK.getAsset('fullScreenOverlay', {
anchorX: 0,
anchorY: 0,
alpha: 0.8
}));
// Game title
var titleText = new Text2('Harvest Haven', {
size: 200,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 8,
dropShadowDistance: 6,
stroke: 0x000000,
strokeThickness: 16
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
startScreenOverlay.addChild(titleText);
// Instructions text
var instructionsText = new Text2('TOCA PARA COMENZAR', {
size: 120,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 1400;
startScreenOverlay.addChild(instructionsText);
// Enhanced pulsing animation for instructions - alpha, scale, and color effects
function startPulsingAnimation() {
// First phase: fade out and scale up with color change
tween(instructionsText, {
alpha: 0.5,
scaleX: 1.15,
scaleY: 1.15,
tint: 0xFFD700
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Second phase: fade in and scale down with bounce effect
tween(instructionsText, {
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFFFFF
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Small pause before next cycle
LK.setTimeout(function () {
if (isStartScreen && instructionsText.parent) {
// Restart pulsing animation
startPulsingAnimation();
}
}, 300);
}
});
}
});
}
startPulsingAnimation();
// Add click handler to overlay
overlay.down = function (x, y, obj) {
if (isStartScreen) {
isStartScreen = false;
startScreenOverlay.destroy();
startScreenOverlay = null;
// Show UI elements when entering game
setUIVisibility(true);
}
};
}
// Initialize start screen
createStartScreen();
game.update = function () {
// Skip game updates during start screen
if (isStartScreen) {
return;
}
// Update all farm plots
farmPlots.forEach(function (plot) {
// Plot update is called automatically
});
// Minion handles harvesting automatically through its own update method
// Update time and season display every 30 ticks (0.5 seconds)
if (LK.ticks % 30 === 0) {
updateTimeAndSeason();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BuyPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like inventory panel
self.addChild(panelBg);
var titleText = new Text2('COMPRAR SEMILLAS', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -280;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// Switch to sell panel button
var sellPanelBtn = self.addChild(LK.getAsset('sellButton', {
anchorX: 0.5,
anchorY: 0.5,
x: -700,
y: 200
}));
var sellPanelBtnText = new Text2('VENDER', {
size: 30,
fill: 0xFFFFFF
});
sellPanelBtnText.anchor.set(0.5, 0.5);
sellPanelBtn.addChild(sellPanelBtnText);
// Seed shop items
var seedItems = [{
name: 'Semillas de Lechuga',
type: 'crop1',
price: 5
}, {
name: 'Semillas de Tomate',
type: 'crop2',
price: 10
}, {
name: 'Semillas de Maíz',
type: 'crop3',
price: 20
}, {
name: 'Semillas de Calabaza',
type: 'crop4',
price: 50
}, {
name: 'Semillas de Sandía',
type: 'crop5',
price: 85
}, {
name: 'Semillas de Uvas',
type: 'crop6',
price: 150
}, {
name: 'Semillas de Trufa',
type: 'crop7',
price: 280
}, {
name: 'Semillas de Orquídea',
type: 'crop8',
price: 450
}];
var buyItems = [];
seedItems.forEach(function (item, index) {
var row = Math.floor(index / 4);
var col = index % 4;
var shopItem = new ShopItem(item.type, item.price, false);
shopItem.x = -300 + col * 200; // Better centered positioning
// Move second row items (watermelon, grapes, truffle, orchid) down more
if (row === 1) {
shopItem.y = -150 + row * 250 + 50; // Add extra 50px margin for second row
} else {
shopItem.y = -150 + row * 250; // Keep first row position unchanged
}
self.addChild(shopItem);
buyItems.push(shopItem);
shopItem.button.down = function (x, y, obj) {
if (coins >= item.price) {
coins -= item.price;
if (!seeds[item.type]) {
seeds[item.type] = 0;
}
seeds[item.type] += 5;
// Award XP for buying seeds (1 XP per purchase)
addXP(1);
LK.getSound('purchase').play();
updateUI();
}
};
});
sellPanelBtn.down = function (x, y, obj) {
self.visible = false;
sellPanel.visible = true;
sellPanel.updateSellSection();
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isBuyPanelOpen = false;
};
return self;
});
var FarmPlot = Container.expand(function () {
var self = Container.call(this);
var plotGraphics = self.attachAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5
});
self.cropType = null;
self.plantTime = 0;
self.growthStage = 0;
self.currentCrop = null;
self.isEmpty = true;
self.isReady = false;
self.isMutated = false; //{mutation_prop}
self.plantCrop = function (cropType) {
if (!self.isEmpty) return false;
self.cropType = cropType;
self.plantTime = LK.ticks;
self.growthStage = 0;
self.isEmpty = false;
self.isReady = false;
// Check for mutation with skill bonus
var mutationChance = MUTATION_CHANCE + getMutationChanceBonus();
self.isMutated = Math.random() < mutationChance;
// Create seedling
self.currentCrop = self.addChild(LK.getAsset('seedling', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
}));
// Apply mutation visual effect to seedling if mutated
if (self.isMutated) {
//{mutation_seedling_start}
tween(self.currentCrop, {
//{mutation_seedling_tween1}
tint: 0xFF69B4 //{mutation_seedling_tint1}
}, {
//{mutation_seedling_config1}
duration: 250,
//{mutation_seedling_duration1}
easing: tween.easeInOut //{mutation_seedling_easing1}
}); //{mutation_seedling_end1}
tween(self.currentCrop, {
//{mutation_seedling_tween2}
tint: 0x32CD32 //{mutation_seedling_tint2}
}, {
//{mutation_seedling_config2}
duration: 250,
//{mutation_seedling_duration2}
easing: tween.easeInOut //{mutation_seedling_easing2}
}); //{mutation_seedling_end2}
} //{mutation_seedling_end}
LK.getSound('plant').play();
// Award XP for planting based on crop type
var plantingXP = 0;
if (cropType === 'crop1') plantingXP = 2; // Lettuce: 2 XP
else if (cropType === 'crop2') plantingXP = 5; // Tomato: 5 XP
else if (cropType === 'crop3') plantingXP = 8; // Corn: 8 XP
else if (cropType === 'crop4') plantingXP = 12; // Pumpkin: 12 XP
else if (cropType === 'crop5') plantingXP = 18; // Watermelon: 18 XP
else if (cropType === 'crop6') plantingXP = 25; // Grapes: 25 XP
else if (cropType === 'crop7') plantingXP = 35; // Truffle: 35 XP
else if (cropType === 'crop8') plantingXP = 50; // Orchid: 50 XP
addXP(plantingXP);
return true;
};
self.harvestCrop = function () {
if (!self.isReady) return null;
var baseValue = cropData[self.cropType].value;
var baseXP = 5;
var harvestedCrop = {
type: self.cropType,
value: self.isMutated ? Math.floor(baseValue * MUTATION_VALUE_MULTIPLIER) : baseValue,
isMutated: self.isMutated
};
// Remove crop visual
if (self.currentCrop) {
self.currentCrop.destroy();
self.currentCrop = null;
}
// Reset plot
self.cropType = null;
self.plantTime = 0;
self.growthStage = 0;
self.isEmpty = true;
self.isReady = false;
var wasMutated = self.isMutated; //{mutation_was_mutated}
self.isMutated = false; //{mutation_reset}
LK.getSound('harvest').play();
// Award XP for harvesting (more XP for mutations)
var xpReward = wasMutated ? Math.floor(baseXP * MUTATION_XP_MULTIPLIER) : baseXP;
addXP(xpReward);
return harvestedCrop;
};
self.update = function () {
if (self.isEmpty || !self.cropType) return;
var elapsed = LK.ticks - self.plantTime;
var growthTime = cropData[self.cropType].growthTime;
if (elapsed >= growthTime && !self.isReady) {
// Crop is ready
self.isReady = true;
if (self.currentCrop) {
self.currentCrop.destroy();
}
self.currentCrop = self.addChild(LK.getAsset(self.cropType, {
anchorX: 0.5,
anchorY: 0.5,
y: -20
}));
// Apply mutation effects if this crop is mutated
if (self.isMutated) {
//{mutation_scale_y}
// Start multicolor animation for mutated crops
var startMutationColorCycle = function startMutationColorCycle() {
//{mutation_color_cycle_start}
var colors = [0xFF69B4, 0x32CD32, 0xFF4500, 0x9932CC, 0xFFD700, 0x00CED1]; //{mutation_colors}
var currentColorIndex = 0; //{mutation_color_index}
function cycleMutationColors() {
//{mutation_cycle_function}
if (self.currentCrop && self.isMutated && self.isReady) {
//{mutation_cycle_check}
tween(self.currentCrop, {
//{mutation_cycle_tween}
tint: colors[currentColorIndex] //{mutation_cycle_tint}
}, {
//{mutation_cycle_config}
duration: 800,
//{mutation_cycle_duration}
easing: tween.easeInOut,
//{mutation_cycle_easing}
onFinish: function onFinish() {
//{mutation_cycle_finish}
currentColorIndex = (currentColorIndex + 1) % colors.length; //{mutation_cycle_increment}
LK.setTimeout(cycleMutationColors, 200); //{mutation_cycle_timeout}
} //{mutation_cycle_finish_end}
}); //{mutation_cycle_tween_end}
} //{mutation_cycle_check_end}
} //{mutation_cycle_function_end}
cycleMutationColors(); //{mutation_start_cycle}
}; //{mutation_color_cycle_end}
//{mutation_grown_start}
// Make mutated crops larger
self.currentCrop.scaleX = 1.5; //{mutation_scale_x}
self.currentCrop.scaleY = 1.5;
startMutationColorCycle(); //{mutation_start_color_cycle}
} //{mutation_grown_end}
// Add glow effect for ready crops
tween(self.currentCrop, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeInOut
});
tween(self.currentCrop, {
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.currentCrop && self.isReady) {
tween(self.currentCrop, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeInOut
});
tween(self.currentCrop, {
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.currentCrop && self.isReady) {
self.update();
}
}
});
}
}
});
} else if (elapsed < growthTime && elapsed > growthTime * 0.5 && self.growthStage === 0) {
// Half grown
self.growthStage = 1;
if (self.currentCrop) {
tween(self.currentCrop, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300
});
}
}
};
self.down = function (x, y, obj) {
if (self.isReady) {
var harvest = self.harvestCrop();
if (harvest) {
// Add to inventory (separate mutated crops)
var inventoryKey = harvest.isMutated ? harvest.type + '_mutated' : harvest.type; //{mutation_inventory_key}
if (!inventory[inventoryKey]) {
inventory[inventoryKey] = 0;
}
inventory[inventoryKey]++;
updateUI();
}
} else if (self.isEmpty && selectedSeed && seeds[selectedSeed] > 0) {
if (self.plantCrop(selectedSeed)) {
seeds[selectedSeed]--;
updateUI();
}
}
};
return self;
});
var HotbarSlot = Container.expand(function (seedType, index) {
var self = Container.call(this);
self.seedType = seedType;
self.index = index;
self.isSelected = false;
var slotBg = self.attachAsset('hotbarSlot', {
anchorX: 0.5,
anchorY: 0.5
});
self.selectedBg = self.addChild(LK.getAsset('hotbarSlotSelected', {
anchorX: 0.5,
anchorY: 0.5
}));
self.selectedBg.visible = false;
// Add seed visual
if (seedType) {
var seedVisual = self.addChild(LK.getAsset(seedType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
}
// Add count text
self.countText = new Text2('0', {
size: 30,
fill: 0xFFFFFF
});
self.countText.anchor.set(0.5, 0.5);
self.countText.x = 0;
self.countText.y = 40;
self.addChild(self.countText);
self.updateCount = function (count) {
self.countText.setText(count.toString());
self.alpha = count > 0 ? 1.0 : 0.5;
};
self.setSelected = function (selected) {
self.isSelected = selected;
self.selectedBg.visible = selected;
if (selected) {
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeInOut
});
} else {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeInOut
});
}
};
self.down = function (x, y, obj) {
if (seeds[self.seedType] > 0) {
selectedSeed = self.seedType;
updateHotbar();
}
};
return self;
});
var InventoryItem = Container.expand(function (itemType, count, isHarvested) {
var self = Container.call(this);
// Item icon without background frame - larger size
var itemIcon = self.addChild(LK.getAsset(itemType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
// Count text below the icon
self.countText = new Text2(count.toString(), {
size: 35,
fill: 0x000000,
fontStyle: 'bold'
});
self.countText.anchor.set(0.5, 0.5);
self.countText.x = 0;
self.countText.y = 70;
self.addChild(self.countText);
self.updateCount = function (newCount) {
self.countText.setText(newCount.toString());
self.alpha = newCount > 0 ? 1.0 : 0.5;
};
return self;
});
var InventoryPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like shop and upgrades panels
self.addChild(panelBg);
var titleText = new Text2('INVENTARIO', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -200;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
self.inventoryTexts = [];
self.updateInventory = function () {
// Clear existing items
self.inventoryTexts.forEach(function (item) {
item.destroy();
});
self.inventoryTexts = [];
// Create grid layout - wider spacing for larger items
var itemsPerRow = 4;
var itemSpacing = 220;
var currentRow = 0;
var currentCol = 0;
// Adjust positioning for horizontal layout with proper margins within background
var startX = -400; // Adjust left margin to stay within background
var startY = 80;
// Show seeds
Object.keys(seeds).forEach(function (seedType) {
if (seeds[seedType] > 0) {
var item = new InventoryItem(seedType, seeds[seedType], false);
item.x = startX + currentCol * itemSpacing;
item.y = startY;
item.updateCount(seeds[seedType]);
self.addChild(item);
self.inventoryTexts.push(item);
currentCol++;
}
});
// Show harvested crops
Object.keys(inventory).forEach(function (cropType) {
if (inventory[cropType] > 0) {
// Skip mutated crops here - they'll be handled separately
if (cropType.endsWith('_mutated')) return;
var item = new InventoryItem(cropType, inventory[cropType], true);
item.x = startX + currentCol * itemSpacing;
item.y = startY;
item.updateCount(inventory[cropType]);
self.addChild(item);
self.inventoryTexts.push(item);
currentCol++;
}
});
// Show mutated crops separately
Object.keys(inventory).forEach(function (inventoryKey) {
if (inventory[inventoryKey] > 0 && inventoryKey.endsWith('_mutated')) {
var baseCropType = inventoryKey.replace('_mutated', '');
var item = new InventoryItem(baseCropType, inventory[inventoryKey], true);
item.x = startX + currentCol * itemSpacing;
item.y = startY;
item.updateCount(inventory[inventoryKey]);
// Make mutated crops larger and add special visual effects
item.scaleX = 1.2;
item.scaleY = 1.2;
// Add mutated indicator text
var mutatedLabel = new Text2('¡MUTACIÓN!', {
size: 25,
fill: 0xFF1493,
fontStyle: 'bold'
});
mutatedLabel.anchor.set(0.5, 0.5);
mutatedLabel.x = 0;
mutatedLabel.y = -40;
item.addChild(mutatedLabel);
self.addChild(item);
self.inventoryTexts.push(item);
currentCol++;
}
});
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isInventoryOpen = false;
};
return self;
});
var Minion = Container.expand(function () {
var self = Container.call(this);
// Create minion visual using character asset
var minionGraphics = self.attachAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
self.targetPlot = null;
self.isMoving = false;
self.harvestTimer = 0;
// Find next ready crop to harvest
self.findNextTarget = function () {
var readyPlots = farmPlots.filter(function (plot) {
return plot.isReady;
});
if (readyPlots.length > 0) {
// Find closest ready plot
var closestPlot = readyPlots[0];
var minDistance = Math.abs(self.x - closestPlot.x) + Math.abs(self.y - closestPlot.y);
readyPlots.forEach(function (plot) {
var distance = Math.abs(self.x - plot.x) + Math.abs(self.y - plot.y);
if (distance < minDistance) {
minDistance = distance;
closestPlot = plot;
}
});
return closestPlot;
}
return null;
};
// Move to target plot
self.moveToPlot = function (plot) {
if (self.isMoving || !plot) return;
self.isMoving = true;
self.targetPlot = plot;
// Calculate movement duration based on distance
var distance = Math.sqrt(Math.pow(plot.x - self.x, 2) + Math.pow(plot.y - self.y, 2));
var duration = Math.max(500, distance * 2); // Minimum 0.5 seconds
// Animate movement to plot
tween(self, {
x: plot.x,
y: plot.y
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isMoving = false;
self.harvestCrop();
}
});
// Add walking animation - slight bouncing
tween(minionGraphics, {
scaleY: 1.4
}, {
duration: 200,
easing: tween.easeInOut
});
tween(minionGraphics, {
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeInOut
});
};
// Harvest crop at current location
self.harvestCrop = function () {
if (self.targetPlot && self.targetPlot.isReady) {
var harvest = self.targetPlot.harvestCrop();
if (harvest) {
// Add to inventory (separate mutated crops)
var inventoryKey = harvest.isMutated ? harvest.type + '_mutated' : harvest.type; //{mutation_minion_key}
if (!inventory[inventoryKey]) {
inventory[inventoryKey] = 0;
}
inventory[inventoryKey]++;
// Show harvested crop above minion's head
var harvestedCropDisplay = self.addChild(LK.getAsset(harvest.type, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -80,
scaleX: 0.8,
scaleY: 0.8
}));
// Animate the harvested crop display
tween(harvestedCropDisplay, {
y: -120,
alpha: 0.7
}, {
duration: 800,
easing: tween.easeOut
});
tween(harvestedCropDisplay, {
alpha: 0
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
harvestedCropDisplay.destroy();
}
});
// Add harvest animation - flash green
tween(minionGraphics, {
tint: 0x00ff00
}, {
duration: 300,
easing: tween.easeInOut
});
tween(minionGraphics, {
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeInOut
});
updateUI();
}
}
self.targetPlot = null;
};
// Wander around the farm when there's nothing to harvest
self.wanderAround = function () {
if (self.isMoving || farmPlots.length === 0) return;
// Pick a random farm plot to visit
var randomIndex = Math.floor(Math.random() * farmPlots.length);
var randomPlot = farmPlots[randomIndex];
if (randomPlot) {
self.isMoving = true;
// Calculate movement duration based on distance
var distance = Math.sqrt(Math.pow(randomPlot.x - self.x, 2) + Math.pow(randomPlot.y - self.y, 2));
var duration = Math.max(1000, distance * 3); // Slower wandering movement
// Animate movement to random plot
tween(self, {
x: randomPlot.x,
y: randomPlot.y
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isMoving = false;
}
});
// Add walking animation - slight bouncing
tween(minionGraphics, {
scaleY: 1.4
}, {
duration: 200,
easing: tween.easeInOut
});
tween(minionGraphics, {
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeInOut
});
}
};
self.update = function () {
// Only act if not currently moving
if (!self.isMoving) {
self.harvestTimer++;
// Look for crops to harvest every 60 ticks (1 second)
if (self.harvestTimer >= 60) {
self.harvestTimer = 0;
var nextTarget = self.findNextTarget();
if (nextTarget) {
self.moveToPlot(nextTarget);
} else {
// No crops to harvest, wander around
self.wanderAround();
}
}
}
};
return self;
});
var SellPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('shopPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like inventory panel
self.addChild(panelBg);
var titleText = new Text2('VENDER CULTIVOS', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -200;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// Switch to buy panel button
var buyPanelBtn = self.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: -700,
y: 200
}));
var buyPanelBtnText = new Text2('COMPRAR', {
size: 30,
fill: 0xFFFFFF
});
buyPanelBtnText.anchor.set(0.5, 0.5);
buyPanelBtn.addChild(buyPanelBtnText);
// Sell all button
var sellAllBtn = self.addChild(LK.getAsset('sellAllButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 200
}));
var sellAllBtnText = new Text2('VENDER TODO', {
size: 35,
fill: 0xFFFFFF
});
sellAllBtnText.anchor.set(0.5, 0.5);
sellAllBtn.addChild(sellAllBtnText);
// Initialize sell texts array
self.sellTexts = [];
self.updateSellSection = function () {
// Clear existing sell items
self.sellTexts.forEach(function (item) {
item.destroy();
});
self.sellTexts = [];
// Create grid layout for sell items
var itemsPerRow = 4;
var itemSpacing = 180;
var currentRow = 0;
var currentCol = 0;
var startX = -300;
var startY = 80;
// Show harvested crops for selling (exclude mutated crops here)
Object.keys(inventory).forEach(function (cropType) {
if (inventory[cropType] > 0 && !cropType.endsWith('_mutated')) {
var sellPrice = Math.floor(cropData[cropType].value * 0.8); // 80% of original value
var sellItem = new ShopItem(cropType, sellPrice, true, inventory[cropType]);
sellItem.x = -400 + currentCol * 400;
sellItem.y = startY + currentRow * 250;
self.addChild(sellItem);
self.sellTexts.push(sellItem);
sellItem.button.down = function (x, y, obj) {
if (inventory[cropType] > 0) {
inventory[cropType]--;
coins += sellPrice;
// Award XP for selling crops (4 XP per sale)
addXP(4);
// Animate coin icon when selling crop
animateCoins(true);
LK.getSound('purchase').play();
updateUI();
self.updateSellSection();
}
};
currentCol++;
if (currentCol >= itemsPerRow) {
currentCol = 0;
currentRow++;
}
}
});
// Show mutated crops for selling (if any)
Object.keys(inventory).forEach(function (cropType) {
//{mutation_sell_start}
var mutatedKey = cropType + '_mutated'; //{mutation_sell_key}
if (inventory[mutatedKey] > 0) {
//{mutation_sell_check}
var baseSellPrice = Math.floor(cropData[cropType].value * 0.8); //{mutation_sell_base}
var mutatedSellPrice = Math.floor(baseSellPrice * MUTATION_VALUE_MULTIPLIER); //{mutation_sell_price}
var sellItem = new ShopItem(cropType, mutatedSellPrice, true, inventory[mutatedKey]); //{mutation_sell_item}
sellItem.x = -400 + currentCol * 400; //{mutation_sell_x}
sellItem.y = startY + currentRow * 250; //{mutation_sell_y}
// Make mutated crops larger and add special visual effects
sellItem.scaleX = 1.2; //{mutation_sell_scale_x}
sellItem.scaleY = 1.2; //{mutation_sell_scale_y}
// Add mutated indicator text
var mutatedLabel = new Text2('¡MUTACIÓN!', {
//{mutation_sell_label}
size: 25,
//{mutation_sell_label_size}
fill: 0xFF1493,
//{mutation_sell_label_color}
fontStyle: 'bold' //{mutation_sell_label_style}
}); //{mutation_sell_label_end}
mutatedLabel.anchor.set(0.5, 0.5); //{mutation_sell_label_anchor}
mutatedLabel.x = 0; //{mutation_sell_label_x}
mutatedLabel.y = -150; //{mutation_sell_label_y}
sellItem.addChild(mutatedLabel); //{mutation_sell_label_add}
self.addChild(sellItem); //{mutation_sell_add}
self.sellTexts.push(sellItem); //{mutation_sell_push}
sellItem.button.down = function (x, y, obj) {
//{mutation_sell_handler}
if (inventory[mutatedKey] > 0) {
//{mutation_sell_handler_check}
inventory[mutatedKey]--; //{mutation_sell_handler_decrement}
coins += mutatedSellPrice; //{mutation_sell_handler_coins}
// Award more XP for selling mutated crops
addXP(Math.floor(4 * MUTATION_XP_MULTIPLIER)); //{mutation_sell_handler_xp}
// Animate coin icon when selling mutated crop
animateCoins(true); //{mutation_sell_handler_animate}
LK.getSound('purchase').play(); //{mutation_sell_handler_sound}
updateUI(); //{mutation_sell_handler_ui}
self.updateSellSection(); //{mutation_sell_handler_update}
} //{mutation_sell_handler_end}
}; //{mutation_sell_handler_close}
currentCol++; //{mutation_sell_col}
if (currentCol >= itemsPerRow) {
//{mutation_sell_row_check}
currentCol = 0; //{mutation_sell_col_reset}
currentRow++; //{mutation_sell_row_increment}
} //{mutation_sell_row_end}
} //{mutation_sell_check_end}
}); //{mutation_sell_end}
};
sellAllBtn.down = function (x, y, obj) {
var totalEarnings = 0;
var totalSoldItems = 0;
Object.keys(inventory).forEach(function (cropType) {
if (inventory[cropType] > 0 && !cropType.endsWith('_mutated')) {
var sellPrice = Math.floor(cropData[cropType].value * 0.8);
totalEarnings += sellPrice * inventory[cropType];
totalSoldItems += inventory[cropType];
inventory[cropType] = 0;
}
// Also sell mutated versions
var mutatedKey = cropType + '_mutated'; //{mutation_sellall_key}
if (inventory[mutatedKey] > 0) {
//{mutation_sellall_check}
var baseSellPrice = Math.floor(cropData[cropType].value * 0.8); //{mutation_sellall_base}
var mutatedSellPrice = Math.floor(baseSellPrice * MUTATION_VALUE_MULTIPLIER); //{mutation_sellall_price}
totalEarnings += mutatedSellPrice * inventory[mutatedKey]; //{mutation_sellall_earnings}
totalSoldItems += inventory[mutatedKey] * MUTATION_XP_MULTIPLIER; // Count mutated items with XP multiplier
inventory[mutatedKey] = 0; //{mutation_sellall_reset}
} //{mutation_sellall_end}
});
if (totalEarnings > 0) {
coins += totalEarnings;
// Award XP for selling all crops (4 XP per item sold)
addXP(4 * totalSoldItems);
// Animate coin icon when selling all crops
animateCoins(true);
LK.getSound('purchase').play();
updateUI();
self.updateSellSection();
}
};
buyPanelBtn.down = function (x, y, obj) {
self.visible = false;
buyPanel.visible = true;
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isSellPanelOpen = false;
};
return self;
});
var ShopItem = Container.expand(function (itemType, price, isSellItem, count) {
var self = Container.call(this);
// Item icon (no background frame)
var itemIcon = self.addChild(LK.getAsset(itemType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
// Item name text
var itemNames = {
'crop1': 'Lechuga',
'crop2': 'Tomate',
'crop3': 'Maíz',
'crop4': 'Calabaza',
'crop5': 'Sandía',
'crop6': 'Uvas',
'crop7': 'Trufa',
'crop8': 'Orquídea'
};
var nameText = new Text2(itemNames[itemType] || itemType, {
size: 38,
fill: 0x000000,
fontStyle: 'bold'
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 0;
nameText.y = 80;
self.addChild(nameText);
// Price text
var priceText = new Text2('$' + price, {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
priceText.anchor.set(0.5, 0.5);
priceText.x = 0;
priceText.y = 120;
self.addChild(priceText);
// Button
var buttonAsset = isSellItem ? 'sellButton' : 'buyButton';
var button = self.addChild(LK.getAsset(buttonAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180
}));
var buttonText = new Text2(isSellItem ? 'VENDER' : 'COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
button.addChild(buttonText);
self.button = button;
self.itemType = itemType;
self.price = price;
self.isSellItem = isSellItem;
self.updateCount = function (newCount) {
self.alpha = newCount > 0 ? 1.0 : 0.3;
};
return self;
});
var SkillTreePanel = Container.expand(function () {
var self = Container.call(this);
// Create background panel
var panelBg = LK.getAsset('upgradesPanel', {
anchorX: 0.5,
anchorY: 0.5
});
panelBg.scale.set(1.5, 0.8);
self.addChild(panelBg);
var titleText = new Text2('ÁRBOL DE HABILIDADES', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -280;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -300
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// Available attribute points display
self.attributePointsText = new Text2('', {
size: 40,
fill: 0x000000,
fontStyle: 'bold'
});
self.attributePointsText.anchor.set(0.5, 0.5);
self.attributePointsText.x = 0;
self.attributePointsText.y = -220;
self.addChild(self.attributePointsText);
// Skill categories
var skills = [{
name: 'VELOCIDAD DE CRECIMIENTO',
description: 'Reduce el tiempo de crecimiento',
icon: 'seedling',
maxLevel: 5,
x: -400,
y: -100
}, {
name: 'VALOR DE CULTIVOS',
description: 'Aumenta el valor de venta',
icon: 'coinIcon',
maxLevel: 5,
x: 0,
y: -100
}, {
name: 'PROBABILIDAD MUTACIÓN',
description: 'Aumenta chance de mutación',
icon: 'crop1',
maxLevel: 5,
x: 400,
y: -100
}, {
name: 'GANANCIA XP',
description: 'Más experiencia por acción',
icon: 'character',
maxLevel: 5,
x: -200,
y: 100
}, {
name: 'EFICIENCIA HERRAMIENTAS',
description: 'Mejores efectos de herramientas',
icon: 'sprinkler',
maxLevel: 5,
x: 200,
y: 100
}];
self.skillContainers = [];
skills.forEach(function (skill, index) {
var skillContainer = new Container();
skillContainer.x = skill.x;
skillContainer.y = skill.y;
self.addChild(skillContainer);
// Skill icon
var skillIcon = skillContainer.addChild(LK.getAsset(skill.icon, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
}));
// Skill name
var skillName = new Text2(skill.name, {
size: 25,
fill: 0x000000,
fontStyle: 'bold'
});
skillName.anchor.set(0.5, 0.5);
skillName.x = 0;
skillName.y = 60;
skillContainer.addChild(skillName);
// Skill description
var skillDesc = new Text2(skill.description, {
size: 18,
fill: 0x666666
});
skillDesc.anchor.set(0.5, 0.5);
skillDesc.x = 0;
skillDesc.y = 85;
skillContainer.addChild(skillDesc);
// Level display
var levelText = new Text2('0/' + skill.maxLevel, {
size: 30,
fill: 0x000000,
fontStyle: 'bold'
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 0;
levelText.y = -60;
skillContainer.addChild(levelText);
// Upgrade button
var upgradeBtn = skillContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 110
}));
var upgradeBtnText = new Text2('+', {
size: 30,
fill: 0xFFFFFF,
fontStyle: 'bold'
});
upgradeBtnText.anchor.set(0.5, 0.5);
upgradeBtn.addChild(upgradeBtnText);
// Store references
skill.container = skillContainer;
skill.levelText = levelText;
skill.upgradeBtn = upgradeBtn;
skill.upgradeBtnText = upgradeBtnText;
skill.currentLevel = skillLevels[index] || 0;
// Button handler
upgradeBtn.down = function (x, y, obj) {
if (attributePoints > 0 && skill.currentLevel < skill.maxLevel) {
attributePoints--;
skill.currentLevel++;
skillLevels[index] = skill.currentLevel;
// Apply skill effect
applySkillEffect(index, skill.currentLevel);
// Update storage
storage.attributePoints = attributePoints;
storage.skillLevels = skillLevels;
LK.getSound('purchase').play();
self.updateSkillDisplay();
}
};
self.skillContainers.push(skill);
});
self.updateSkillDisplay = function () {
self.attributePointsText.setText('Puntos Disponibles: ' + attributePoints);
self.skillContainers.forEach(function (skill) {
skill.levelText.setText(skill.currentLevel + '/' + skill.maxLevel);
// Update button state
if (attributePoints > 0 && skill.currentLevel < skill.maxLevel) {
skill.upgradeBtn.alpha = 1.0;
skill.upgradeBtnText.setText('+');
} else {
skill.upgradeBtn.alpha = 0.5;
skill.upgradeBtnText.setText(skill.currentLevel >= skill.maxLevel ? 'MAX' : '+');
}
});
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isSkillTreeOpen = false;
};
return self;
});
var Sprinkler = Container.expand(function () {
var self = Container.call(this);
// Create sprinkler visual using dedicated sprinkler asset
var sprinklerGraphics = self.attachAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
// Add pulsing animation to show it's working
function startSprinklerAnimation() {
tween(sprinklerGraphics, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.8
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(sprinklerGraphics, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 1.0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
startSprinklerAnimation();
}
}
});
}
});
}
startSprinklerAnimation();
// Accelerate all crops every 5 seconds (300 ticks)
self.accelerationTimer = 0;
self.update = function () {
self.accelerationTimer++;
if (self.accelerationTimer >= 300) {
// Every 5 seconds
self.accelerationTimer = 0;
// Accelerate all growing crops by 30 seconds (1800 ticks)
farmPlots.forEach(function (plot) {
if (!plot.isEmpty && !plot.isReady) {
plot.plantTime -= 1800; // Reduce by 30 seconds
}
});
// Flash effect when accelerating
tween(sprinklerGraphics, {
tint: 0x00FF00
}, {
duration: 200,
easing: tween.easeInOut
});
tween(sprinklerGraphics, {
tint: 0x4169E1
}, {
duration: 200,
easing: tween.easeInOut
});
}
};
return self;
});
var UpgradesPanel = Container.expand(function () {
var self = Container.call(this);
// Create rounded horizontal background
var panelBg = LK.getAsset('upgradesPanel', {
anchorX: 0.5,
anchorY: 0.5
});
// Make corners rounded by scaling height and applying visual rounding effect
panelBg.scale.set(1.5, 0.6); // Make it wider and more horizontal like inventory panel
self.addChild(panelBg);
var titleText = new Text2('MEJORAS', {
size: 50,
fill: 0x000000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -280;
self.addChild(titleText);
var closeBtn = self.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -250
}));
var closeBtnText = new Text2('X', {
size: 30,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// More Plots Upgrade - Top row, left position
var plotUpgradeContainer = new Container();
plotUpgradeContainer.x = -400; // Better centered positioning like shop
plotUpgradeContainer.y = -150; // Top row positioning
self.addChild(plotUpgradeContainer);
var plotIcon = plotUpgradeContainer.addChild(LK.getAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5
}));
var plotTitle = new Text2('MÁS PARCELAS', {
size: 28,
fill: 0x000000
});
plotTitle.anchor.set(0.5, 0.5);
plotTitle.x = 0;
plotTitle.y = 80; // Better spacing from icon
plotUpgradeContainer.addChild(plotTitle);
var plotPrice = new Text2('$500', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
plotPrice.anchor.set(0.5, 0.5);
plotPrice.x = 0;
plotPrice.y = 120; // Below title
plotUpgradeContainer.addChild(plotPrice);
var plotBtn = plotUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var plotBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
plotBtnText.anchor.set(0.5, 0.5);
plotBtn.addChild(plotBtnText);
// Speed Upgrade - Top row, second position
var speedUpgradeContainer = new Container();
speedUpgradeContainer.x = -100; // Center-left positioning
speedUpgradeContainer.y = -150; // Top row positioning
self.addChild(speedUpgradeContainer);
var speedIcon = speedUpgradeContainer.addChild(LK.getAsset('seedling', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
var speedTitle = new Text2('VELOCIDAD', {
size: 28,
fill: 0x000000
});
speedTitle.anchor.set(0.5, 0.5);
speedTitle.x = 0;
speedTitle.y = 80; // Better spacing from icon
speedUpgradeContainer.addChild(speedTitle);
var speedPrice = new Text2('$300', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
speedPrice.anchor.set(0.5, 0.5);
speedPrice.x = 0;
speedPrice.y = 120; // Below title
speedUpgradeContainer.addChild(speedPrice);
var speedBtn = speedUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var speedBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
speedBtnText.anchor.set(0.5, 0.5);
speedBtn.addChild(speedBtnText);
// Sprinkler Upgrade - Top row, third position
var sprinklerUpgradeContainer = new Container();
sprinklerUpgradeContainer.x = 200; // Center-right positioning
sprinklerUpgradeContainer.y = -150; // Top row positioning
self.addChild(sprinklerUpgradeContainer);
var sprinklerIcon = sprinklerUpgradeContainer.addChild(LK.getAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
}));
var sprinklerTitle = new Text2('ASPERSOR', {
size: 28,
fill: 0x000000
});
sprinklerTitle.anchor.set(0.5, 0.5);
sprinklerTitle.x = 0;
sprinklerTitle.y = 80; // Better spacing from icon
sprinklerUpgradeContainer.addChild(sprinklerTitle);
var sprinklerPrice = new Text2('$1500', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
sprinklerPrice.anchor.set(0.5, 0.5);
sprinklerPrice.x = 0;
sprinklerPrice.y = 120; // Below title
sprinklerUpgradeContainer.addChild(sprinklerPrice);
var sprinklerBtn = sprinklerUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var sprinklerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
sprinklerBtnText.anchor.set(0.5, 0.5);
sprinklerBtn.addChild(sprinklerBtnText);
// Companion Upgrade - Top row, fourth position
var companionUpgradeContainer = new Container();
companionUpgradeContainer.x = 500; // Right positioning
companionUpgradeContainer.y = -150; // Top row positioning
self.addChild(companionUpgradeContainer);
var companionIcon = companionUpgradeContainer.addChild(LK.getAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
}));
var companionTitle = new Text2('COMPAÑERO', {
size: 28,
fill: 0x000000
});
companionTitle.anchor.set(0.5, 0.5);
companionTitle.x = 0;
companionTitle.y = 80; // Better spacing from icon
companionUpgradeContainer.addChild(companionTitle);
var companionPrice = new Text2('$3000', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
companionPrice.anchor.set(0.5, 0.5);
companionPrice.x = 0;
companionPrice.y = 120; // Below title
companionUpgradeContainer.addChild(companionPrice);
var companionBtn = companionUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var companionBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
companionBtnText.anchor.set(0.5, 0.5);
companionBtn.addChild(companionBtnText);
// Super Fertilizer Upgrade - Bottom row, left position (unlocked at level 15)
var fertilizerUpgradeContainer = new Container();
fertilizerUpgradeContainer.x = -200; // Left-center positioning for bottom row
fertilizerUpgradeContainer.y = 100; // Bottom row positioning - moved up from previous position
self.addChild(fertilizerUpgradeContainer);
var fertilizerIcon = fertilizerUpgradeContainer.addChild(LK.getAsset('crop3', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0x00FF00
}));
var fertilizerTitle = new Text2('FERTILIZANTE', {
size: 28,
fill: 0x000000
});
fertilizerTitle.anchor.set(0.5, 0.5);
fertilizerTitle.x = 0;
fertilizerTitle.y = 80; // Better spacing from icon
fertilizerUpgradeContainer.addChild(fertilizerTitle);
var fertilizerPrice = new Text2('$5000', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
fertilizerPrice.anchor.set(0.5, 0.5);
fertilizerPrice.x = 0;
fertilizerPrice.y = 120; // Below title
fertilizerUpgradeContainer.addChild(fertilizerPrice);
var fertilizerBtn = fertilizerUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var fertilizerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
fertilizerBtnText.anchor.set(0.5, 0.5);
fertilizerBtn.addChild(fertilizerBtnText);
// Mega Harvester Upgrade - Bottom row, right position (unlocked at level 25)
var harvesterUpgradeContainer = new Container();
harvesterUpgradeContainer.x = 200; // Right-center positioning for bottom row
harvesterUpgradeContainer.y = 100; // Bottom row positioning - moved up from previous position
self.addChild(harvesterUpgradeContainer);
var harvesterIcon = harvesterUpgradeContainer.addChild(LK.getAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFD700
}));
var harvesterTitle = new Text2('COSECHADOR', {
size: 28,
fill: 0x000000
});
harvesterTitle.anchor.set(0.5, 0.5);
harvesterTitle.x = 0;
harvesterTitle.y = 80; // Better spacing from icon
harvesterUpgradeContainer.addChild(harvesterTitle);
var harvesterPrice = new Text2('$12000', {
size: 34,
fill: 0x8B4513,
fontStyle: 'bold'
});
harvesterPrice.anchor.set(0.5, 0.5);
harvesterPrice.x = 0;
harvesterPrice.y = 120; // Below title
harvesterUpgradeContainer.addChild(harvesterPrice);
var harvesterBtn = harvesterUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 180 // Below price
}));
var harvesterBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
harvesterBtnText.anchor.set(0.5, 0.5);
harvesterBtn.addChild(harvesterBtnText);
// Update upgrade button states based on level requirements
self.updateUpgradeAvailability = function () {
// Super Fertilizer - unlocked at level 15
if (level < 15) {
fertilizerUpgradeContainer.alpha = 0.5;
fertilizerBtn.alpha = 0.3;
fertilizerBtnText.setText('BLOQUEADO');
} else if (hasSuperFertilizer) {
fertilizerBtn.alpha = 0.5;
fertilizerBtnText.setText('COMPRADO');
} else {
fertilizerUpgradeContainer.alpha = 1.0;
fertilizerBtn.alpha = 1.0;
fertilizerBtnText.setText('COMPRAR');
}
// Mega Harvester - unlocked at level 25
if (level < 25) {
harvesterUpgradeContainer.alpha = 0.5;
harvesterBtn.alpha = 0.3;
harvesterBtnText.setText('BLOQUEADO');
} else if (hasMegaHarvester) {
harvesterBtn.alpha = 0.5;
harvesterBtnText.setText('COMPRADO');
} else {
harvesterUpgradeContainer.alpha = 1.0;
harvesterBtn.alpha = 1.0;
harvesterBtnText.setText('COMPRAR');
}
};
// Button handlers
plotBtn.down = function (x, y, obj) {
if (coins >= 500 && totalPlots < 64) {
// Max 64 plots (4 grids of 4x4)
coins -= 500;
updateUI();
// Close upgrades panel
self.visible = false;
isUpgradesPanelOpen = false;
// Enter plot selection mode
isPlotSelectionMode = true;
createPlotSelectionOverlay();
}
};
speedBtn.down = function (x, y, obj) {
if (coins >= 300) {
coins -= 300;
// Accelerate all growing crops
farmPlots.forEach(function (plot) {
if (!plot.isEmpty && !plot.isReady) {
plot.plantTime -= 300; // Reduce by 5 seconds (double the effect)
}
});
// Award XP for speed upgrade (12 XP)
addXP(12);
LK.getSound('purchase').play();
updateUI();
}
};
fertilizerBtn.down = function (x, y, obj) {
if (coins >= 5000 && level >= 15 && !hasSuperFertilizer) {
coins -= 5000;
hasSuperFertilizer = true;
// Permanently increase mutation chance by 20%
MUTATION_CHANCE += 0.20;
// Award XP for fertilizer upgrade (100 XP)
addXP(100);
LK.getSound('purchase').play();
updateUI();
self.updateUpgradeAvailability();
// Flash screen green for fertilizer upgrade
LK.effects.flashScreen(0x00FF00, 1000);
}
};
harvesterBtn.down = function (x, y, obj) {
if (coins >= 12000 && level >= 25 && !hasMegaHarvester) {
coins -= 12000;
hasMegaHarvester = true;
// Permanently increase crop value multiplier by 50%
MUTATION_VALUE_MULTIPLIER += 0.5;
// Award XP for harvester upgrade (200 XP)
addXP(200);
LK.getSound('purchase').play();
updateUI();
self.updateUpgradeAvailability();
// Flash screen gold for harvester upgrade
LK.effects.flashScreen(0xFFD700, 1200);
}
};
// Update sprinkler button appearance based on current state
self.updateSprinklerButton = function () {
if (hasSprinkler) {
sprinklerBtn.alpha = 0.5;
sprinklerBtnText.setText('COMPRADO');
} else {
sprinklerBtn.alpha = 1.0;
sprinklerBtnText.setText('COMPRAR');
}
};
// Update companion button appearance based on current state
self.updateCompanionButton = function () {
if (hasCompanion) {
companionBtn.alpha = 0.5;
companionBtnText.setText('COMPRADO');
} else {
companionBtn.alpha = 1.0;
companionBtnText.setText('COMPRAR');
}
};
// Initialize button states
self.updateSprinklerButton();
self.updateCompanionButton();
sprinklerBtn.down = function (x, y, obj) {
if (coins >= 1500 && !hasSprinkler) {
coins -= 1500;
hasSprinkler = true;
self.updateSprinklerButton();
// Award XP for sprinkler upgrade (50 XP)
addXP(50);
LK.getSound('purchase').play();
updateUI();
// Create sprinkler in the middle of all plots
sprinkler = new Sprinkler();
sprinkler.x = mainGridCenterX; // Center of main plot grid
sprinkler.y = mainGridCenterY; // Center of main plot grid
sprinkler.zIndex = 50; // Render above plots but below UI
game.addChild(sprinkler);
// Close upgrades panel after purchase
self.visible = false;
isUpgradesPanelOpen = false;
}
};
companionBtn.down = function (x, y, obj) {
if (coins >= 3000 && !hasCompanion) {
coins -= 3000;
hasCompanion = true;
self.updateCompanionButton();
// Award XP for companion upgrade (100 XP)
addXP(100);
LK.getSound('purchase').play();
updateUI();
// Create minion when companion is purchased
minion = new Minion();
minion.x = 1024; // Start at center
minion.y = 1200; // Above the farm plots
minion.zIndex = 100; // Render above plots but below UI
game.addChild(minion);
}
};
closeBtn.down = function (x, y, obj) {
self.visible = false;
isUpgradesPanelOpen = false;
};
// Initialize upgrade states
self.updateUpgradeAvailability();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Add background image
var backgroundImage = game.addChild(LK.getAsset('gameBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
backgroundImage.zIndex = -2000; // Ensure it's behind everything
// Game data
var cropData = {
'crop1': {
name: 'Lechuga',
growthTime: 300,
value: 8
},
// 5 seconds
'crop2': {
name: 'Tomate',
growthTime: 600,
value: 18
},
// 10 seconds
'crop3': {
name: 'Maíz',
growthTime: 900,
value: 35
},
// 15 seconds
'crop4': {
name: 'Calabaza',
growthTime: 1200,
value: 75
},
// 20 seconds
'crop5': {
name: 'Sandía',
growthTime: 1500,
value: 120
},
// 25 seconds
'crop6': {
name: 'Uvas',
growthTime: 1800,
value: 200
},
// 30 seconds
'crop7': {
name: 'Trufa',
growthTime: 2400,
value: 350
},
// 40 seconds
'crop8': {
name: 'Orquídea',
growthTime: 3000,
value: 500
} // 50 seconds
};
// Mutation system constants
var MUTATION_CHANCE = 0.15; // 15% chance for mutation
var MUTATION_VALUE_MULTIPLIER = 2.5; // Mutated crops are worth 2.5x more
var MUTATION_XP_MULTIPLIER = 2; // Mutated crops give 2x more XP (double experience)
// Clear all stored game progress - reset to starting values
storage.coins = 100;
storage.seeds = {
'crop1': 10,
'crop2': 0,
'crop3': 0,
'crop4': 0,
'crop5': 0,
'crop6': 0,
'crop7': 0,
'crop8': 0
};
storage.inventory = {};
storage.hasCompanion = false;
storage.hasSprinkler = false;
storage.hasSuperFertilizer = false;
storage.hasMegaHarvester = false;
storage.totalPlots = 16;
storage.level = 1;
storage.xp = 0;
storage.attributePoints = 0;
storage.skillLevels = [0, 0, 0, 0, 0];
// Game state - initialize to starting values
var isStartScreen = true;
var startScreenOverlay = null;
var coins = 100;
var seeds = {
'crop1': 10,
'crop2': 0,
'crop3': 0,
'crop4': 0,
'crop5': 0,
'crop6': 0,
'crop7': 0,
'crop8': 0
};
var inventory = {};
var selectedSeed = 'crop1';
var isBuyPanelOpen = false;
var isSellPanelOpen = false;
var isInventoryOpen = false;
var isUpgradesPanelOpen = false;
var hasCompanion = false;
var companionTimer = 0;
var minion = null;
var hasSprinkler = false;
var sprinkler = null;
var hasSuperFertilizer = false;
var hasMegaHarvester = false;
var level = 1;
var xp = 0;
var attributePoints = 0;
var skillLevels = [0, 0, 0, 0, 0];
var isSkillTreeOpen = false;
var isPlotSelectionMode = false;
var selectedPlotSlot = null;
var plotSelectionOverlay = null;
// No minion at start since companion is not purchased
// UI elements
var coinsContainer = new Container();
coinsContainer.x = 1024; // Position at top center
coinsContainer.y = 150; // Position at top
coinsContainer.zIndex = 400;
game.addChild(coinsContainer);
var coinIcon = coinsContainer.addChild(LK.getAsset('coinIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 40
}));
// Make coinIcon globally accessible for animations
window.coinIcon = coinIcon;
var coinsText = new Text2(coins.toString(), {
size: 120,
fill: 0xFFD700,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 8
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 80;
coinsText.y = 40;
coinsContainer.addChild(coinsText);
// Create seasons and time system
var gameStartTime = Date.now();
var timeMultiplier = 20; // 1 real minute = 20 game minutes (slower time)
var currentSeason = 0; // 0=Primavera, 1=Verano, 2=Otoño, 3=Invierno
var seasonNames = ['Primavera', 'Verano', 'Otoño', 'Invierno'];
var dayOfYear = 1;
var currentYear = 2024;
// Create time/season display container in top-right
var timeContainer = new Container();
timeContainer.x = 1900; // Top-right position (leaving margin from edge)
timeContainer.y = 200; // Top position
timeContainer.zIndex = 500;
game.addChild(timeContainer);
// Add gray background behind time/season display with rounded corners
var timeBackground = timeContainer.addChild(LK.getAsset('fullScreenOverlay', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.25,
scaleY: 0.15,
x: -200,
y: 0,
tint: 0x808080,
alpha: 0.7
}));
// Apply rounded corners by scaling down slightly and using visual rounding effect
tween(timeBackground, {
scaleX: 0.24,
scaleY: 0.14
}, {
duration: 100,
easing: tween.easeInOut
});
timeBackground.zIndex = -1; // Behind the text elements
// Time display
var timeText = new Text2('12:00', {
size: 90,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
timeText.anchor.set(1.0, 0.5);
timeText.x = 0;
timeText.y = -80;
timeContainer.addChild(timeText);
// Date display
var dateText = new Text2('1 Ene 2024', {
size: 80,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 5
});
dateText.anchor.set(1.0, 0.5);
dateText.x = 0;
dateText.y = 0;
timeContainer.addChild(dateText);
// Season display
var seasonText = new Text2('Primavera', {
size: 85,
fill: 0x90EE90,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
seasonText.anchor.set(1.0, 0.5);
seasonText.x = 0;
seasonText.y = 80;
timeContainer.addChild(seasonText);
// Function to update time and season display
function updateTimeAndSeason() {
var elapsedRealTime = Date.now() - gameStartTime;
// Make 1 game minute pass every 3 seconds (3000ms)
var elapsedGameMinutes = Math.floor(elapsedRealTime / 3000);
var elapsedGameHours = Math.floor(elapsedGameMinutes / 60);
// Calculate current time (24-hour cycle)
var currentHour = (12 + elapsedGameHours) % 24; // Start at 12:00
var currentMinute = elapsedGameMinutes % 60;
// Format time display
var hourStr = currentHour < 10 ? '0' + currentHour : currentHour.toString();
var minuteStr = currentMinute < 10 ? '0' + currentMinute : currentMinute.toString();
timeText.setText(hourStr + ':' + minuteStr);
// Calculate current day (new day every 24 game hours)
var totalGameDays = Math.floor(elapsedGameHours / 24);
var currentDayOfYear = (dayOfYear + totalGameDays - 1) % 365 + 1;
var currentGameYear = currentYear + Math.floor((dayOfYear + totalGameDays - 1) / 365);
// Calculate season (each season lasts ~91 days)
var seasonIndex = Math.floor((currentDayOfYear - 1) / 91) % 4;
if (seasonIndex !== currentSeason) {
currentSeason = seasonIndex;
// Update season color
var seasonColors = [0x90EE90, 0xFFD700, 0xFF8C00, 0x87CEEB]; // Spring, Summer, Autumn, Winter
seasonText.tint = seasonColors[currentSeason];
}
// Format date display
var monthNames = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'];
var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var remainingDays = currentDayOfYear;
var month = 0;
while (remainingDays > daysInMonth[month] && month < 11) {
remainingDays -= daysInMonth[month];
month++;
}
dateText.setText(remainingDays + ' ' + monthNames[month] + ' ' + currentGameYear);
seasonText.setText(seasonNames[currentSeason]);
}
// Create skill points counter container in top-left
var skillPointsContainer = new Container();
skillPointsContainer.x = 200; // Top-left position (avoiding platform menu)
skillPointsContainer.y = 150; // Same height as coins counter
skillPointsContainer.zIndex = 400;
game.addChild(skillPointsContainer);
// Skill points icon
var skillPointIcon = skillPointsContainer.addChild(LK.getAsset('skillPointIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 40,
scaleX: 1.5,
scaleY: 1.5
}));
// Skill points text
var skillPointsText = new Text2(attributePoints.toString(), {
size: 120,
fill: 0xFFD700,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 8
});
skillPointsText.anchor.set(0.5, 0.5);
skillPointsText.x = 320;
skillPointsText.y = 40;
skillPointsContainer.addChild(skillPointsText);
// Create XP progress bar container
var xpContainer = new Container();
xpContainer.x = 1024; // Center horizontally
xpContainer.y = 2450; // Below tab buttons - moved a little lower
xpContainer.zIndex = 400;
game.addChild(xpContainer);
// XP progress bar background
var xpBarBg = xpContainer.addChild(LK.getAsset('inventoryPanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.14,
scaleY: 0.15
}));
// XP progress bar fill
var xpBarFill = xpContainer.addChild(LK.getAsset('inventoryPanel', {
anchorX: 0,
anchorY: 0.5,
scaleX: 1.14,
scaleY: 0.15,
x: -1024,
tint: 0x0000ff
}));
// Level text
var levelText = new Text2('Nivel ' + level, {
size: 90,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 2,
dropShadowDistance: 2,
stroke: 0x000000,
strokeThickness: 8
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 0;
levelText.y = -10;
xpContainer.addChild(levelText);
// XP text
var xpText = new Text2('', {
size: 70,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 2,
dropShadowDistance: 2,
stroke: 0x000000,
strokeThickness: 3
});
xpText.anchor.set(1.0, 0.5);
xpText.x = 1024;
xpText.y = -50;
xpContainer.addChild(xpText);
// Create horizontal tabs container positioned above coins
var tabsContainer = new Container();
tabsContainer.x = 1024;
tabsContainer.y = 2300; // Position above coins text - moved higher
tabsContainer.zIndex = 500; // Ensure tabs render above coins
game.addChild(tabsContainer);
// Shop button
var shopBtn = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var shopBtnText = new Text2('TIENDA', {
size: 35,
fill: 0xFFFFFF
});
shopBtnText.anchor.set(0.5, 0.5);
shopBtn.addChild(shopBtnText);
shopBtn.x = -300;
shopBtn.y = 0;
tabsContainer.addChild(shopBtn);
// Inventory button
var invBtn = LK.getAsset('inventoryButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var invBtnText = new Text2('INVENTARIO', {
size: 30,
fill: 0xFFFFFF
});
invBtnText.anchor.set(0.5, 0.5);
invBtn.addChild(invBtnText);
invBtn.x = 0;
invBtn.y = 0;
tabsContainer.addChild(invBtn);
// Upgrades button
var upgradesBtn = LK.getAsset('upgradesButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var upgradesBtnText = new Text2('MEJORAS', {
size: 30,
fill: 0xFFFFFF
});
upgradesBtnText.anchor.set(0.5, 0.5);
upgradesBtn.addChild(upgradesBtnText);
upgradesBtn.x = 300;
upgradesBtn.y = 0;
tabsContainer.addChild(upgradesBtn);
// Skill tree arrow button
var skillTreeArrowBtn = LK.getAsset('skillTreeArrow', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 3.0
});
skillTreeArrowBtn.x = 1024;
skillTreeArrowBtn.y = 2150;
skillTreeArrowBtn.zIndex = 500;
game.addChild(skillTreeArrowBtn);
// Arrow symbol inside button
var arrowText = new Text2('→', {
size: 50,
fill: 0x000000,
fontStyle: 'bold'
});
arrowText.anchor.set(0.5, 0.5);
skillTreeArrowBtn.addChild(arrowText);
// Create farm plots in 4x4 grid
var farmPlots = [];
var totalPlots = 16; // Always start with 16 plots (4x4)
var plotSpacingX = 140;
var plotSpacingY = 100;
var plotMargin = 30; // Margin between plot groups
// Calculate center position for the main 4x4 grid
var mainGridCenterX = 1024; // Center of screen
var mainGridCenterY = 900; // Positioned to avoid UI overlap
// Calculate starting position for centered 4x4 grid
var mainStartX = mainGridCenterX - 3 * plotSpacingX / 2;
var mainStartY = mainGridCenterY - 3 * plotSpacingY / 2;
function createPlotAtPosition(x, y) {
var plot = new FarmPlot();
plot.x = x;
plot.y = y;
game.addChild(plot);
farmPlots.push(plot);
}
function createPlotSelectionOverlay() {
plotSelectionOverlay = new Container();
plotSelectionOverlay.zIndex = 800;
game.addChild(plotSelectionOverlay);
// Semi-transparent background
var overlay = plotSelectionOverlay.addChild(LK.getAsset('fullScreenOverlay', {
anchorX: 0,
anchorY: 0,
alpha: 0.7
}));
// Title text
var titleText = new Text2('ELIGE DÓNDE COLOCAR LA NUEVA PARCELA', {
size: 80,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
plotSelectionOverlay.addChild(titleText);
// Instructions text
var instructionsText = new Text2('TOCA UN ESPACIO VACÍO PARA COLOCAR LA PARCELA', {
size: 60,
fill: 0xFFD700,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 3,
dropShadowDistance: 2,
stroke: 0x000000,
strokeThickness: 4
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 400;
plotSelectionOverlay.addChild(instructionsText);
// Cancel button
var cancelBtn = plotSelectionOverlay.addChild(LK.getAsset('closeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2400
}));
var cancelBtnText = new Text2('CANCELAR', {
size: 30,
fill: 0xFFFFFF
});
cancelBtnText.anchor.set(0.5, 0.5);
cancelBtn.addChild(cancelBtnText);
// Create selection slots for each potential plot position
createPlotSelectionSlots();
// Cancel button handler
cancelBtn.down = function (x, y, obj) {
if (plotSelectionOverlay) {
plotSelectionOverlay.destroy();
plotSelectionOverlay = null;
}
isPlotSelectionMode = false;
selectedPlotSlot = null;
coins += 100; // Refund the money
updateUI();
};
return plotSelectionOverlay;
}
function createPlotSelectionSlots() {
if (!plotSelectionOverlay) return;
// Create visual slots for all possible plot positions
var slotsCreated = 0;
var maxSlots = 64; // Maximum possible plots
// Main 4x4 grid slots
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = mainStartX + col * plotSpacingX;
var slotY = mainStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
// Check if this position already has a plot
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
// Right 4x4 grid slots
var rightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var rightStartY = mainStartY;
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = rightStartX + col * plotSpacingX;
var slotY = rightStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
// Bottom-left 4x4 grid slots
var bottomLeftStartX = mainStartX;
var bottomLeftStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = bottomLeftStartX + col * plotSpacingX;
var slotY = bottomLeftStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
// Bottom-right 4x4 grid slots
var bottomRightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var bottomRightStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
var slotX = bottomRightStartX + col * plotSpacingX;
var slotY = bottomRightStartY + row * plotSpacingY;
var slotIndex = slotsCreated;
var hasPlot = farmPlots.some(function (plot) {
return Math.abs(plot.x - slotX) < 10 && Math.abs(plot.y - slotY) < 10;
});
createPlotSelectionSlot(slotX, slotY, slotIndex, hasPlot);
slotsCreated++;
}
}
}
function createPlotSelectionSlot(x, y, index, hasPlot) {
if (!plotSelectionOverlay) return;
var slot = new Container();
slot.x = x;
slot.y = y;
slot.zIndex = 10;
plotSelectionOverlay.addChild(slot);
if (hasPlot) {
// Show existing plot (darker/disabled)
var existingPlotVisual = slot.addChild(LK.getAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
tint: 0x666666
}));
} else {
// Show empty slot (can be selected)
var emptySlotVisual = slot.addChild(LK.getAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7,
tint: 0x00FF00
}));
// Add pulsing animation to available slots
tween(emptySlotVisual, {
alpha: 0.4,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(emptySlotVisual, {
alpha: 0.7,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (emptySlotVisual.parent) {
createPlotSelectionSlot(x, y, index, hasPlot);
}
}
});
}
});
// Make empty slot clickable
slot.down = function (slotX, slotY, obj) {
if (!hasPlot && isPlotSelectionMode) {
// Place the new plot here
createPlotAtPosition(x, y);
totalPlots++;
storage.totalPlots = totalPlots;
// Close selection overlay
if (plotSelectionOverlay) {
plotSelectionOverlay.destroy();
plotSelectionOverlay = null;
}
isPlotSelectionMode = false;
selectedPlotSlot = null;
// Award XP for buying plot upgrade (15 XP)
addXP(15);
LK.getSound('purchase').play();
updateUI();
}
};
}
}
function repositionAllPlots() {
// Clear existing plots
farmPlots.forEach(function (plot) {
plot.destroy();
});
farmPlots = [];
var plotsCreated = 0;
// Main 4x4 grid (center)
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(mainStartX + col * plotSpacingX, mainStartY + row * plotSpacingY);
plotsCreated++;
}
}
// Right 4x4 grid (if more than 16 plots)
if (totalPlots > 16) {
var rightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var rightStartY = mainStartY;
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(rightStartX + col * plotSpacingX, rightStartY + row * plotSpacingY);
plotsCreated++;
}
}
}
// Bottom-left 4x4 grid (if more than 32 plots)
if (totalPlots > 32) {
var bottomLeftStartX = mainStartX;
var bottomLeftStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(bottomLeftStartX + col * plotSpacingX, bottomLeftStartY + row * plotSpacingY);
plotsCreated++;
}
}
}
// Bottom-right 4x4 grid (if more than 48 plots)
if (totalPlots > 48) {
var bottomRightStartX = mainStartX + 4 * plotSpacingX + plotMargin;
var bottomRightStartY = mainStartY + 4 * plotSpacingY + plotMargin;
for (var row = 0; row < 4 && plotsCreated < totalPlots; row++) {
for (var col = 0; col < 4 && plotsCreated < totalPlots; col++) {
createPlotAtPosition(bottomRightStartX + col * plotSpacingX, bottomRightStartY + row * plotSpacingY);
plotsCreated++;
}
}
}
// Ensure all farm plots render below interface panels
farmPlots.forEach(function (plot) {
plot.zIndex = -1000;
});
}
// Initialize farm plots
repositionAllPlots();
// Buy and sell panels - positioned as horizontal scroll above coins
var buyPanel = new BuyPanel();
buyPanel.x = 1024;
buyPanel.y = 1800;
buyPanel.visible = false;
buyPanel.zIndex = 600;
game.addChild(buyPanel);
var sellPanel = new SellPanel();
sellPanel.x = 1024;
sellPanel.y = 1800;
sellPanel.visible = false;
sellPanel.zIndex = 600;
game.addChild(sellPanel);
var inventoryPanel = new InventoryPanel();
inventoryPanel.x = 1024;
inventoryPanel.y = 1800;
inventoryPanel.visible = false;
inventoryPanel.zIndex = 600;
game.addChild(inventoryPanel);
var upgradesPanel = new UpgradesPanel();
upgradesPanel.x = 1024;
upgradesPanel.y = 1800;
upgradesPanel.visible = false;
upgradesPanel.zIndex = 600;
game.addChild(upgradesPanel);
var skillTreePanel = new SkillTreePanel();
skillTreePanel.x = 1024;
skillTreePanel.y = 1600;
skillTreePanel.visible = false;
skillTreePanel.zIndex = 700;
game.addChild(skillTreePanel);
// Apply skill effects based on current levels
function applySkillEffect(skillIndex, level) {
switch (skillIndex) {
case 0:
// Growth Speed - reduce growth time
break;
case 1:
// Crop Value - increase sell price
break;
case 2:
// Mutation Chance - increase mutation probability
break;
case 3:
// XP Gain - multiply XP rewards
break;
case 4:
// Tool Efficiency - enhance sprinkler/companion
break;
}
}
// Calculate skill multipliers
function getGrowthSpeedMultiplier() {
var level = skillLevels[0] || 0;
return 1 - level * 0.1; // 10% faster per level
}
function getCropValueMultiplier() {
var level = skillLevels[1] || 0;
return 1 + level * 0.15; // 15% more value per level
}
function getMutationChanceBonus() {
var level = skillLevels[2] || 0;
return level * 0.05; // 5% more chance per level
}
function getXPMultiplier() {
var level = skillLevels[3] || 0;
return 1 + level * 0.2; // 20% more XP per level
}
function getToolEfficiencyMultiplier() {
var level = skillLevels[4] || 0;
return 1 + level * 0.25; // 25% better tools per level
}
// Button event handlers
shopBtn.down = function (x, y, obj) {
if (!isInventoryOpen && !isSellPanelOpen && !isUpgradesPanelOpen) {
buyPanel.visible = true;
isBuyPanelOpen = true;
}
};
invBtn.down = function (x, y, obj) {
if (!isBuyPanelOpen && !isSellPanelOpen && !isUpgradesPanelOpen) {
inventoryPanel.visible = true;
inventoryPanel.updateInventory();
isInventoryOpen = true;
}
};
upgradesBtn.down = function (x, y, obj) {
if (!isBuyPanelOpen && !isSellPanelOpen && !isInventoryOpen) {
upgradesPanel.visible = true;
upgradesPanel.updateUpgradeAvailability();
isUpgradesPanelOpen = true;
}
};
skillTreeArrowBtn.down = function (x, y, obj) {
if (!isBuyPanelOpen && !isSellPanelOpen && !isInventoryOpen && !isUpgradesPanelOpen) {
skillTreePanel.visible = true;
skillTreePanel.updateSkillDisplay();
isSkillTreeOpen = true;
}
};
// Create hotbar
var hotbarSlots = [];
var hotbarContainer = new Container();
hotbarContainer.x = 1024;
hotbarContainer.y = 2600;
hotbarContainer.zIndex = 400;
game.addChild(hotbarContainer);
// Create hotbar slots for each seed type
var seedTypes = ['crop1', 'crop2', 'crop3', 'crop4', 'crop5', 'crop6', 'crop7', 'crop8'];
seedTypes.forEach(function (seedType, index) {
var slot = new HotbarSlot(seedType, index);
slot.x = (index - 3.5) * 180; // Center all 8 slots around container center
slot.y = 0;
hotbarContainer.addChild(slot);
hotbarSlots.push(slot);
});
function updateHotbar() {
hotbarSlots.forEach(function (slot) {
var count = seeds[slot.seedType] || 0;
slot.updateCount(count);
slot.setSelected(slot.seedType === selectedSeed);
});
}
// Initialize hotbar
updateHotbar();
// Initialize XP bar
updateXPBar();
// Hide UI elements during start screen
function setUIVisibility(visible) {
coinsContainer.visible = visible;
timeContainer.visible = visible;
xpContainer.visible = visible;
tabsContainer.visible = visible;
hotbarContainer.visible = visible;
skillTreeArrowBtn.visible = visible;
skillPointsContainer.visible = visible;
}
// Initially hide UI elements
setUIVisibility(false);
// Remove old seed selection behavior - hotbar handles it now
game.down = function (x, y, obj) {
// Hotbar slots handle their own clicks now
};
var lastCoins = coins; // Track last coins value for animation detection
// Calculate XP needed for a specific level
function getXPForLevel(targetLevel) {
if (targetLevel === 1) return 0;
if (targetLevel === 2) return 20; // First level only needs 20 XP
return Math.floor(100 * Math.pow(1.5, targetLevel - 2));
}
// Get current level's XP requirement
function getCurrentLevelXP() {
return getXPForLevel(level);
}
// Get next level's XP requirement
function getNextLevelXP() {
return getXPForLevel(level + 1);
}
// Add XP and handle level ups
function addXP(amount) {
var multipliedAmount = Math.floor(amount * getXPMultiplier());
xp += multipliedAmount;
// Check for level up
var nextLevelXP = getNextLevelXP();
if (xp >= nextLevelXP) {
level++;
// Award attribute points every 5 levels
if (level % 5 === 0) {
attributePoints += 5;
// Flash screen purple for attribute points
LK.effects.flashScreen(0x9932CC, 1000);
} else {
// Flash screen gold for regular level up
LK.effects.flashScreen(0xFFD700, 800);
}
// Animate XP bar
tween(xpContainer, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.easeOut
});
tween(xpContainer, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 400,
easing: tween.easeInOut
});
}
updateXPBar();
}
// Update XP progress bar visual
function updateXPBar() {
var currentLevelXP = getCurrentLevelXP();
var nextLevelXP = getNextLevelXP();
var progressXP = xp - currentLevelXP;
var levelXPRange = nextLevelXP - currentLevelXP;
var progress = Math.min(progressXP / levelXPRange, 1.0);
// Update bar fill using scaleX to match background thickness exactly
xpBarFill.scaleX = 1.14 * progress;
xpBarFill.scaleY = 0.15; // Match background scaleY exactly
// Update texts
levelText.setText('Nivel ' + level);
xpText.setText(progressXP + '/' + levelXPRange + ' XP');
}
function animateCoins(increase) {
if (increase) {
// Animate for coin increase (green pulse and scale up)
tween(window.coinIcon, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0x00ff00
}, {
duration: 200,
easing: tween.easeOut
});
tween(window.coinIcon, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeInOut
});
} else {
// Animate for coin decrease (red pulse and slight shrink)
tween(window.coinIcon, {
scaleX: 0.8,
scaleY: 0.8,
tint: 0xff0000
}, {
duration: 200,
easing: tween.easeOut
});
tween(window.coinIcon, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeInOut
});
}
}
function updateUI() {
// Store current text before updating
var currentText = coinsText.text;
var newText = coins.toString();
// Update the coins text
coinsText.setText(newText);
// Update skill points text
skillPointsText.setText(attributePoints.toString());
updateHotbar();
updateXPBar();
// Check if the displayed text actually changed and animate accordingly
if (currentText !== newText) {
if (coins > lastCoins) {
animateCoins(true); // Coins increased
} else if (coins < lastCoins) {
animateCoins(false); // Coins decreased
}
}
lastCoins = coins; // Update last coins value
// Save progress
storage.coins = coins;
storage.seeds = seeds;
storage.inventory = inventory;
storage.hasCompanion = hasCompanion;
storage.hasSprinkler = hasSprinkler;
storage.hasSuperFertilizer = hasSuperFertilizer;
storage.hasMegaHarvester = hasMegaHarvester;
storage.level = level;
storage.xp = xp;
storage.attributePoints = attributePoints;
storage.skillLevels = skillLevels;
}
// Initialize sprinkler if already purchased
if (hasSprinkler && !sprinkler) {
sprinkler = new Sprinkler();
sprinkler.x = mainGridCenterX;
sprinkler.y = mainGridCenterY;
sprinkler.zIndex = 50;
game.addChild(sprinkler);
}
// Create start screen
function createStartScreen() {
startScreenOverlay = new Container();
startScreenOverlay.zIndex = 1000;
game.addChild(startScreenOverlay);
// Semi-transparent background
var overlay = startScreenOverlay.addChild(LK.getAsset('fullScreenOverlay', {
anchorX: 0,
anchorY: 0,
alpha: 0.8
}));
// Game title
var titleText = new Text2('Harvest Haven', {
size: 200,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 8,
dropShadowDistance: 6,
stroke: 0x000000,
strokeThickness: 16
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
startScreenOverlay.addChild(titleText);
// Instructions text
var instructionsText = new Text2('TOCA PARA COMENZAR', {
size: 120,
fill: 0xFFFFFF,
fontStyle: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 3,
stroke: 0x000000,
strokeThickness: 6
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 1400;
startScreenOverlay.addChild(instructionsText);
// Enhanced pulsing animation for instructions - alpha, scale, and color effects
function startPulsingAnimation() {
// First phase: fade out and scale up with color change
tween(instructionsText, {
alpha: 0.5,
scaleX: 1.15,
scaleY: 1.15,
tint: 0xFFD700
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Second phase: fade in and scale down with bounce effect
tween(instructionsText, {
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFFFFF
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Small pause before next cycle
LK.setTimeout(function () {
if (isStartScreen && instructionsText.parent) {
// Restart pulsing animation
startPulsingAnimation();
}
}, 300);
}
});
}
});
}
startPulsingAnimation();
// Add click handler to overlay
overlay.down = function (x, y, obj) {
if (isStartScreen) {
isStartScreen = false;
startScreenOverlay.destroy();
startScreenOverlay = null;
// Show UI elements when entering game
setUIVisibility(true);
}
};
}
// Initialize start screen
createStartScreen();
game.update = function () {
// Skip game updates during start screen
if (isStartScreen) {
return;
}
// Update all farm plots
farmPlots.forEach(function (plot) {
// Plot update is called automatically
});
// Minion handles harvesting automatically through its own update method
// Update time and season display every 30 ticks (0.5 seconds)
if (LK.ticks % 30 === 0) {
updateTimeAndSeason();
}
};
buy button. In-Game asset. 2d. High contrast. No shadows
inventory button. In-Game asset. 2d. High contrast. No shadows
shop button. In-Game asset. 2d. High contrast. No shadows
X button. In-Game asset. 2d. High contrast. No shadows
dirt. In-Game asset. 2d. High contrast. No shadows
lechuga. In-Game asset. 2d. High contrast. No shadows
tomate. In-Game asset. 2d. High contrast. No shadows
semilla. In-Game asset. 2d. High contrast. No shadows
sell button. In-Game asset. 2d. High contrast. No shadows
maiz. In-Game asset. 2d. High contrast. No shadows
sell all button. In-Game asset. 2d. High contrast. No shadows
upgrade button. In-Game asset. 2d. High contrast. No shadows
Hotbar slot. In-Game asset. 2d. High contrast. No shadows
Quita el cesped de abajo
Flying minion flower. In-Game asset. 2d. High contrast. No shadows
Aspersor. In-Game asset. 2d. High contrast. No shadows
Que sea verde y hectagonal
Arbol de habilidades botón. In-Game asset. 2d. High contrast. No shadows
calabaza. In-Game asset. 2d. High contrast. No shadows
sandia entera
planta uva. In-Game asset. 2d. High contrast. No shadows
trufa. In-Game asset. 2d. High contrast. No shadows
orquidea. In-Game asset. 2d. High contrast. No shadows