User prompt
la ventana de upgrade esta fatal distribuida dejala igual de bien que la de tienda, sin que nada se pise entre si
User prompt
Please fix the bug: 'speedBtn is not defined' in or related to this line: 'speedBtn.addChild(speedBtnText);' Line Number: 1355
User prompt
deja mas margen entre todo en upgrade
User prompt
deja mas margen entre los items de arriba y abajo que se pisan entre ellos y lo mismo con los precios y nombres
User prompt
arregla la composicion de los items en upgrades que no se solapen entre ellos y que queden bien ordenados y visibles
User prompt
sube los precios de los upgrades y haz un par nuevos y que se desbloqueen progresivamente llegando a X niveles
User prompt
deja el juego como si empezaramos desde cero ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
baja un poco la sandia uvas trufa y orquidea para dejar margen arriba con los botones de compra
User prompt
deja mas margen entre las imagenes letras y precios de la tienda
User prompt
haz que en vez de poner monedas en la tienda ponga $
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'value')' in or related to this line: 'var sellPrice = Math.floor(cropData[cropType].value * 0.8); // 80% of original value' Line Number: 844
User prompt
haz las letras un poco mas grandes
User prompt
baja mas los botones y centra mas arriba todo lo de la tienda que quede centrado en el panel
User prompt
y en la fila de abajo de la tienda pon el boton de comprar abajo de los items
User prompt
haz los nombres, el precio y las imagenes de la tienda mas grandes
User prompt
haz las letras y los items de la tienda mas grandes
User prompt
quita los marcos de la hotbar de la tienda y añade el pecio y el nombre de cada item
User prompt
Deja mas margen entre las filas
User prompt
Ahora baja y centra los items
User prompt
Pon el texto de comprar semillas mas arriba y en la fila de arriba los botones por encima de lo items
User prompt
Centralo algo mas a la derecha sin pisar el boton de vender
User prompt
En la tienda centra todas las plantas para que no sobresalgan del panel
User prompt
Pero a la derecha del todo de la barra
User prompt
Pon el número de experiencia en la misma posicion pero arriba de la barra de XP
User prompt
Centra la hotbar para que se vean todas las plantas nuevas
/****
* 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 = -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: 40,
fill: 0xFFFFFF
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
// More Plots Upgrade
var plotUpgradeContainer = new Container();
plotUpgradeContainer.x = -450; // Left column positioning
plotUpgradeContainer.y = -120; // Top row positioning - moved up for more margin
self.addChild(plotUpgradeContainer);
var plotIcon = plotUpgradeContainer.addChild(LK.getAsset('farmPlot', {
anchorX: 0.5,
anchorY: 0.5
}));
var plotTitle = new Text2('MÁS PARCELAS', {
size: 35,
fill: 0x000000
});
plotTitle.anchor.set(0.5, 0.5);
plotTitle.x = 0;
plotTitle.y = 130; // Moved down for more margin
plotUpgradeContainer.addChild(plotTitle);
var plotPrice = new Text2('$500', {
size: 40,
fill: 0x000000
});
plotPrice.anchor.set(0.5, 0.5);
plotPrice.x = 0;
plotPrice.y = -130; // Moved up for more margin
plotUpgradeContainer.addChild(plotPrice);
var plotBtn = plotUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 200 //{bw} // Moved down for more margin
}));
var plotBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
plotBtnText.anchor.set(0.5, 0.5);
plotBtn.addChild(plotBtnText);
// Speed Upgrade
var speedUpgradeContainer = new Container();
speedUpgradeContainer.x = 0; // Center column positioning
speedUpgradeContainer.y = -120; // Top row positioning - moved up for more margin
self.addChild(speedUpgradeContainer);
var speedIcon = speedUpgradeContainer.addChild(LK.getAsset('seedling', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
}));
var speedTitle = new Text2('VELOCIDAD', {
size: 35,
fill: 0x000000
});
speedTitle.anchor.set(0.5, 0.5);
speedTitle.x = 0;
speedTitle.y = 130; // Moved down for more margin
speedUpgradeContainer.addChild(speedTitle);
var speedPrice = new Text2('$300', {
size: 40,
fill: 0x000000
});
speedPrice.anchor.set(0.5, 0.5);
speedPrice.x = 0;
speedPrice.y = -130; // Moved up for more margin
speedUpgradeContainer.addChild(speedPrice);
var speedBtn = speedUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 200 //{bw} // Moved down for more margin
}));
var speedBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
speedBtnText.anchor.set(0.5, 0.5);
speedBtn.addChild(speedBtnText);
// Sprinkler Upgrade
var sprinklerUpgradeContainer = new Container();
sprinklerUpgradeContainer.x = 450; // Right column positioning
sprinklerUpgradeContainer.y = -120; // Top row positioning - moved up for more margin
self.addChild(sprinklerUpgradeContainer);
var sprinklerIcon = sprinklerUpgradeContainer.addChild(LK.getAsset('sprinkler', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
var sprinklerTitle = new Text2('ASPERSOR', {
size: 35,
fill: 0x000000
});
sprinklerTitle.anchor.set(0.5, 0.5);
sprinklerTitle.x = 0;
sprinklerTitle.y = 130; // Moved down for more margin
sprinklerUpgradeContainer.addChild(sprinklerTitle);
var sprinklerPrice = new Text2('$1500', {
size: 40,
fill: 0x000000
});
sprinklerPrice.anchor.set(0.5, 0.5);
sprinklerPrice.x = 0;
sprinklerPrice.y = -130; // Moved up for more margin
sprinklerUpgradeContainer.addChild(sprinklerPrice);
var sprinklerBtn = sprinklerUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 200 //{bw} // Moved down for more margin
}));
var sprinklerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
sprinklerBtnText.anchor.set(0.5, 0.5);
sprinklerBtn.addChild(sprinklerBtnText);
// Companion Upgrade - moved to lower right
var companionUpgradeContainer = new Container();
companionUpgradeContainer.x = -450; // Left column positioning
companionUpgradeContainer.y = 120; // Middle row positioning - moved down for more margin
self.addChild(companionUpgradeContainer);
var companionIcon = companionUpgradeContainer.addChild(LK.getAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
var companionTitle = new Text2('COMPAÑERO', {
size: 35,
fill: 0x000000
});
companionTitle.anchor.set(0.5, 0.5);
companionTitle.x = 0;
companionTitle.y = 130; // Moved down for more margin
companionUpgradeContainer.addChild(companionTitle);
var companionPrice = new Text2('$3000', {
size: 40,
fill: 0x000000
});
companionPrice.anchor.set(0.5, 0.5);
companionPrice.x = 0;
companionPrice.y = -130; // Moved up for more margin
companionUpgradeContainer.addChild(companionPrice);
var companionBtn = companionUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 200 //{bw} // Moved down for more margin
}));
var companionBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
companionBtnText.anchor.set(0.5, 0.5);
companionBtn.addChild(companionBtnText);
// Super Fertilizer Upgrade - unlocked at level 15
var fertilizerUpgradeContainer = new Container();
fertilizerUpgradeContainer.x = 0; // Center column positioning
fertilizerUpgradeContainer.y = 120; // Middle row positioning - moved down for more margin
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: 35,
fill: 0x000000
});
fertilizerTitle.anchor.set(0.5, 0.5);
fertilizerTitle.x = 0;
fertilizerTitle.y = 130; // Moved down for more margin
fertilizerUpgradeContainer.addChild(fertilizerTitle);
var fertilizerPrice = new Text2('$5000', {
size: 40,
fill: 0x000000
});
fertilizerPrice.anchor.set(0.5, 0.5);
fertilizerPrice.x = 0;
fertilizerPrice.y = -130; // Moved up for more margin
fertilizerUpgradeContainer.addChild(fertilizerPrice);
var fertilizerBtn = fertilizerUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 200 //{bw} // Moved down for more margin
}));
var fertilizerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
fertilizerBtnText.anchor.set(0.5, 0.5);
fertilizerBtn.addChild(fertilizerBtnText);
// Mega Harvester Upgrade - unlocked at level 25
var harvesterUpgradeContainer = new Container();
harvesterUpgradeContainer.x = 450; // Right column positioning
harvesterUpgradeContainer.y = 120; // Middle row positioning - moved down for more margin
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: 35,
fill: 0x000000
});
harvesterTitle.anchor.set(0.5, 0.5);
harvesterTitle.x = 0;
harvesterTitle.y = 130; // Moved down for more margin
harvesterUpgradeContainer.addChild(harvesterTitle);
var harvesterPrice = new Text2('$12000', {
size: 40,
fill: 0x000000
});
harvesterPrice.anchor.set(0.5, 0.5);
harvesterPrice.x = 0;
harvesterPrice.y = -130; // Moved up for more margin
harvesterUpgradeContainer.addChild(harvesterPrice);
var harvesterBtn = harvesterUpgradeContainer.addChild(LK.getAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 200 //{bw} // Moved down for more margin
}));
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();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1282,8 +1282,30 @@
anchorY: 0.5,
scaleX: 2,
scaleY: 2
}));
+ var speedTitle = new Text2('VELOCIDAD', {
+ size: 35,
+ fill: 0x000000
+ });
+ speedTitle.anchor.set(0.5, 0.5);
+ speedTitle.x = 0;
+ speedTitle.y = 130; // Moved down for more margin
+ speedUpgradeContainer.addChild(speedTitle);
+ var speedPrice = new Text2('$300', {
+ size: 40,
+ fill: 0x000000
+ });
+ speedPrice.anchor.set(0.5, 0.5);
+ speedPrice.x = 0;
+ speedPrice.y = -130; // Moved up for more margin
+ speedUpgradeContainer.addChild(speedPrice);
+ var speedBtn = speedUpgradeContainer.addChild(LK.getAsset('buyButton', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 200 //{bw} // Moved down for more margin
+ }));
var speedBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
@@ -1299,8 +1321,30 @@
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
+ var sprinklerTitle = new Text2('ASPERSOR', {
+ size: 35,
+ fill: 0x000000
+ });
+ sprinklerTitle.anchor.set(0.5, 0.5);
+ sprinklerTitle.x = 0;
+ sprinklerTitle.y = 130; // Moved down for more margin
+ sprinklerUpgradeContainer.addChild(sprinklerTitle);
+ var sprinklerPrice = new Text2('$1500', {
+ size: 40,
+ fill: 0x000000
+ });
+ sprinklerPrice.anchor.set(0.5, 0.5);
+ sprinklerPrice.x = 0;
+ sprinklerPrice.y = -130; // Moved up for more margin
+ sprinklerUpgradeContainer.addChild(sprinklerPrice);
+ var sprinklerBtn = sprinklerUpgradeContainer.addChild(LK.getAsset('buyButton', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 200 //{bw} // Moved down for more margin
+ }));
var sprinklerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
@@ -1316,8 +1360,30 @@
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
+ var companionTitle = new Text2('COMPAÑERO', {
+ size: 35,
+ fill: 0x000000
+ });
+ companionTitle.anchor.set(0.5, 0.5);
+ companionTitle.x = 0;
+ companionTitle.y = 130; // Moved down for more margin
+ companionUpgradeContainer.addChild(companionTitle);
+ var companionPrice = new Text2('$3000', {
+ size: 40,
+ fill: 0x000000
+ });
+ companionPrice.anchor.set(0.5, 0.5);
+ companionPrice.x = 0;
+ companionPrice.y = -130; // Moved up for more margin
+ companionUpgradeContainer.addChild(companionPrice);
+ var companionBtn = companionUpgradeContainer.addChild(LK.getAsset('buyButton', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 200 //{bw} // Moved down for more margin
+ }));
var companionBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
@@ -1334,8 +1400,30 @@
scaleX: 1.2,
scaleY: 1.2,
tint: 0x00FF00
}));
+ var fertilizerTitle = new Text2('FERTILIZANTE', {
+ size: 35,
+ fill: 0x000000
+ });
+ fertilizerTitle.anchor.set(0.5, 0.5);
+ fertilizerTitle.x = 0;
+ fertilizerTitle.y = 130; // Moved down for more margin
+ fertilizerUpgradeContainer.addChild(fertilizerTitle);
+ var fertilizerPrice = new Text2('$5000', {
+ size: 40,
+ fill: 0x000000
+ });
+ fertilizerPrice.anchor.set(0.5, 0.5);
+ fertilizerPrice.x = 0;
+ fertilizerPrice.y = -130; // Moved up for more margin
+ fertilizerUpgradeContainer.addChild(fertilizerPrice);
+ var fertilizerBtn = fertilizerUpgradeContainer.addChild(LK.getAsset('buyButton', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 200 //{bw} // Moved down for more margin
+ }));
var fertilizerBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
@@ -1352,8 +1440,30 @@
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFD700
}));
+ var harvesterTitle = new Text2('COSECHADOR', {
+ size: 35,
+ fill: 0x000000
+ });
+ harvesterTitle.anchor.set(0.5, 0.5);
+ harvesterTitle.x = 0;
+ harvesterTitle.y = 130; // Moved down for more margin
+ harvesterUpgradeContainer.addChild(harvesterTitle);
+ var harvesterPrice = new Text2('$12000', {
+ size: 40,
+ fill: 0x000000
+ });
+ harvesterPrice.anchor.set(0.5, 0.5);
+ harvesterPrice.x = 0;
+ harvesterPrice.y = -130; // Moved up for more margin
+ harvesterUpgradeContainer.addChild(harvesterPrice);
+ var harvesterBtn = harvesterUpgradeContainer.addChild(LK.getAsset('buyButton', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 200 //{bw} // Moved down for more margin
+ }));
var harvesterBtnText = new Text2('COMPRAR', {
size: 20,
fill: 0xFFFFFF
});
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