User prompt
Optimize the game to run smoother and reduce lag. Improve performance so it doesn’t freeze or slow down.
User prompt
Add a sickle to the player’s hand. Include a hitting (attack) animation for the sickle.
User prompt
Add a sickle to the player’s hand.
User prompt
Add background music to the game. Upload the music as an asset in the music section. The music should play continuously (loop).
User prompt
Add background music to the game. Upload the music as an asset in the music section. The music should play continuously (loop).
User prompt
The mission goal is to reach 250,000 money.
User prompt
Make the mission bar a little smaller. Place it on the left side of the center part of the screen.
User prompt
Add a "Missions" title on the right side of the screen. Show a mission bar under it. The mission is to reach 100,000 money. When the player passes 100,000 money, end the game with a "You Win!" message. Put the mission bar at the top of the missions area.
User prompt
Add a money currency for the player to reach. If the player passes 150,000 money, the game ends with a "You Win!" message. Show the money amount on the right side of the screen, next to the currency. Make it look different and simple. Label it as "Mission".
User prompt
delete ✅ Add logic to detect unlocking of 4th area and start 1-minute win timer ✅ Cancel win timer if game is reset (defensive, optional best practice)
User prompt
After the player unlocks the 4th (last) area, wait 1 minute, then show the "You Win!" message and end the game.
User prompt
Each time the zombie comes, the damage (or cost) should increase. For example: First time: it takes 500 gold Second time: 1000 gold Third time: 2000 gold And so on. It multiplies each time.
User prompt
The zombie should spawn 40 seconds after the player starts the game.
User prompt
When the zombie spawns and the player touches (kills) it, the zombie should respawn again after 40 seconds.
User prompt
The zombie should spawn every 45 seconds and repeat in a loop.
User prompt
The zombie should appear every 50 seconds and repeat in a loop.
User prompt
The zombie should come from the left side.
User prompt
I will add the assets myself. zombi
User prompt
When the player clicks the zombie, the zombie dies.
User prompt
I will add the assets myself. The zombie will have 2 different assets. When the zombie touches the player, the player loses 500 gold.
User prompt
A zombie comes toward the player. The player must hit the zombie with a sickle. If the player hits, the zombie dies. If the player misses, the zombie takes 1000 gold from the player.
User prompt
Make the bird move a little faster. Also, the bird should appear every 3 minutes.
User prompt
"Rooster_1", "Rooster_2", "Rooster_3", and "Rooster_4" should appear 40 seconds after the player starts the game. Then they should keep repeating again and again in order.
User prompt
The message will say: "Game controls: Use mouse to move. For mobile, tap to move."
User prompt
Make the message really big. The current size is too small.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Animal = Container.expand(function () { var self = Container.call(this); self.animalAsset = null; self.setAnimalImage = function (imageId) { if (self.animalAsset) { self.animalAsset.destroy(); } self.animalAsset = self.attachAsset(imageId, { anchorX: 0.5, anchorY: 0.5 }); }; return self; }); // Bird class var Bird = Container.expand(function () { var self = Container.call(this); // Create the bird asset var birdAsset = self.attachAsset('Bird', { anchorX: 0.5, anchorY: 0.5, alpha: 1, scaleX: 0.8, scaleY: 0.8 }); // Variables for movement self.speed = 1.0; // Faster than clouds self.lifeTime = 3000; // 50 seconds at 60fps self.lifeCounter = 0; // Track how long bird has been visible self.flyHeight = 0; // Vertical position offset for flying pattern // Initialize bird self.init = function () { self.lifeCounter = 0; self.alpha = 1; // Start movement animation using tween self.startMoving(); }; // Start the left to right movement with slight up/down wave pattern self.startMoving = function () { // Move bird to the right side of screen var targetX = 2048 + birdAsset.width / 2; // Move past right edge // Create the movement tween tween(self, { x: targetX }, { duration: 20000, // Faster than clouds - 20 seconds to cross screen easing: tween.linear }); }; // Update function called every frame self.update = function () { // Increment life counter self.lifeCounter++; // Create a small wavy flight pattern self.y = self.y + Math.sin(self.lifeCounter * 0.03) * 1.5; // If bird has reached the right edge of the screen if (self.x >= 2048 + birdAsset.width / 2) { // Stop any existing tweens on this bird tween.stop(self); // Fade out animation tween(self, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Remove bird from game self.destroy(); } }); } }; return self; }); // CarrotSlot class for area 2 var CarrotSlot = Container.expand(function () { var self = Container.call(this); self.slotAsset = self.attachAsset('carrot', { anchorX: 0.5, anchorY: 1 }); var sproutAsset = self.attachAsset('sprout', { anchorX: 0.5, anchorY: 1, alpha: 0, scaleX: 0.5, scaleY: 0.5 }); self.harvested = false; self.regrowTime = 1800; // 30 seconds at 60fps self.regrowCounter = 0; self.fieldIndex = 1; // Area 2 self.regrowing = false; // Show/hide carrot and handle regrow animation self.setHarvested = function (harvested) { self.harvested = harvested; if (harvested) { // Hide carrot with animation tween(self.slotAsset, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); // Show sprout with animation sproutAsset.alpha = 1; sproutAsset.scaleX = 0.1; sproutAsset.scaleY = 0.1; // Animate sprout appearing tween(sproutAsset, { scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); self.regrowCounter = self.regrowTime; self.regrowing = true; } else { // Show carrot with animation tween(self.slotAsset, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeIn }); // Hide sprout with animation tween(sproutAsset, { alpha: 0 }, { duration: 300, easing: tween.easeIn }); self.regrowing = false; } }; // Regrow logic self.update = function () { if (self.harvested && self.regrowing) { if (self.regrowCounter > 0) { // Animate sprout growing to carrot size var t = 1 - self.regrowCounter / self.regrowTime; sproutAsset.scaleX = 0.5 + 0.5 * t; sproutAsset.scaleY = 0.5 + 0.5 * t; self.regrowCounter--; } if (self.regrowCounter <= 0) { // Sprout is now full size, switch back to carrot and allow harvest again sproutAsset.scaleX = 1; sproutAsset.scaleY = 1; self.setHarvested(false); } } }; // For hit detection self.isHarvestable = function () { return !self.harvested; }; return self; }); // Cloud class var Cloud = Container.expand(function () { var self = Container.call(this); // Create the cloud asset var cloudAsset = self.attachAsset('cloud', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 // Semi-transparent clouds }); // Variables for movement self.speed = 0.2; // Very slow speed for smooth movement self.lifeTime = 6000; // 100 seconds at 60fps - longer lifetime self.lifeCounter = 0; // Track how long cloud has been visible self.layer = 0; // Layer for visual depth (0 = front, 1 = back) // Initialize cloud self.init = function () { self.lifeCounter = 0; self.alpha = 1; // Apply layer-specific settings if (self.layer === 1) { // Back layer cloud (slightly smaller and more transparent) self.scale.set(0.8, 0.8); self.alpha = 0.7; } // Start movement animation using tween self.startMoving(); }; // Start the left to right movement only self.startMoving = function () { // Move cloud to the right side of screen var targetX = 2048 + cloudAsset.width / 2; // Move past right edge // Create the movement tween tween(self, { x: targetX }, { duration: 60000, // Slower movement - 60 seconds to cross screen easing: tween.linear }); }; // Update function called every frame self.update = function () { // Increment life counter self.lifeCounter++; // Track lastX for edge detection if (typeof self.lastX === "undefined") self.lastX = self.x; // If cloud has just reached the right edge of the screen (crossed this frame) if (self.lastX < 2048 + cloudAsset.width / 2 && self.x >= 2048 + cloudAsset.width / 2) { // Stop any existing tweens on this cloud tween.stop(self); // Fade out animation tween(self, { alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Remove cloud from game self.destroy(); } }); } // Update lastX for next frame self.lastX = self.x; }; return self; }); // EggplantSlot class for area 4 var EggplantSlot = Container.expand(function () { var self = Container.call(this); self.slotAsset = self.attachAsset('eggplant', { anchorX: 0.5, anchorY: 1 }); var sproutAsset = self.attachAsset('sprout', { anchorX: 0.5, anchorY: 1, alpha: 0, scaleX: 0.5, scaleY: 0.5 }); self.harvested = false; self.regrowTime = 1800; // 30 seconds at 60fps self.regrowCounter = 0; self.fieldIndex = 3; // Area 4 self.regrowing = false; // Show/hide eggplant and handle regrow animation self.setHarvested = function (harvested) { self.harvested = harvested; if (harvested) { // Hide eggplant with animation tween(self.slotAsset, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); // Show sprout with animation sproutAsset.alpha = 1; sproutAsset.scaleX = 0.1; sproutAsset.scaleY = 0.1; // Animate sprout appearing tween(sproutAsset, { scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); self.regrowCounter = self.regrowTime; self.regrowing = true; } else { // Show eggplant with animation tween(self.slotAsset, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeIn }); // Hide sprout with animation tween(sproutAsset, { alpha: 0 }, { duration: 300, easing: tween.easeIn }); self.regrowing = false; } }; // Regrow logic self.update = function () { if (self.harvested && self.regrowing) { if (self.regrowCounter > 0) { // Animate sprout growing to eggplant size var t = 1 - self.regrowCounter / self.regrowTime; sproutAsset.scaleX = 0.5 + 0.5 * t; sproutAsset.scaleY = 0.5 + 0.5 * t; self.regrowCounter--; } if (self.regrowCounter <= 0) { // Sprout is now full size, switch back to eggplant and allow harvest again sproutAsset.scaleX = 1; sproutAsset.scaleY = 1; self.setHarvested(false); } } }; // For hit detection self.isHarvestable = function () { return !self.harvested; }; return self; }); // Farmer class var Farmer = Container.expand(function () { var self = Container.call(this); // Create animation frames var idleFrame = self.attachAsset('farmer', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }); // Frame 2 (running) var runningFrame = self.attachAsset('farmer_walk', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Frame 3 (right step) var rightStepFrame = self.attachAsset('farmer_walk', { anchorX: 0.5, anchorY: 0.5, alpha: 0, rotation: 0.1 }); self.speed = 18; // px per move self.targetX = self.x; self.targetY = self.y; self.moving = false; self.lastMoving = false; self.animationTimer = 0; self.animationFrame = 0; self.frameTime = 18; // 0.3 seconds at 60fps // Animation frame switching self.switchToFrame = function (frameNum) { idleFrame.alpha = 0; runningFrame.alpha = 0; rightStepFrame.alpha = 0; if (frameNum === 0) { // Idle idleFrame.alpha = 1; } else if (frameNum === 1) { // Running runningFrame.alpha = 1; } else if (frameNum === 2) { // Right step rightStepFrame.alpha = 1; } }; // Move farmer towards target self.update = function () { // Track movement direction and update image if (self.moving) { var dx = self.targetX - self.x; // Check if moving right or left if (dx > 0) { // Moving right - use player_right asset idleFrame.scaleX = 1; runningFrame.scaleX = 1; rightStepFrame.scaleX = 1; // Switch to player_right image if (self.currentAsset !== idleFrame || idleFrame.texture !== LK.getAsset('player_right', {}).texture) { if (self.currentAsset) { self.currentAsset.alpha = 0; } var rightAsset = LK.getAsset('player_right', { anchorX: 0.5, anchorY: 0.5 }); rightAsset.alpha = 1; self.addChild(rightAsset); self.currentAsset = rightAsset; } } else if (dx < 0) { // Moving left - use player_left asset idleFrame.scaleX = -1; runningFrame.scaleX = -1; rightStepFrame.scaleX = -1; // Switch to player_left image if (self.currentAsset !== idleFrame || idleFrame.texture !== LK.getAsset('player_left', {}).texture) { if (self.currentAsset) { self.currentAsset.alpha = 0; } var leftAsset = LK.getAsset('player_left', { anchorX: 0.5, anchorY: 0.5 }); leftAsset.alpha = 1; self.addChild(leftAsset); self.currentAsset = leftAsset; } } // Animation handling self.animationTimer++; if (self.animationTimer >= self.frameTime) { self.animationTimer = 0; self.animationFrame = self.animationFrame === 1 ? 2 : 1; // Toggle between frames 1 and 2 self.switchToFrame(self.animationFrame); } } else if (!self.moving && self.lastMoving) { // Just stopped moving - switch to idle self.switchToFrame(0); } self.lastMoving = self.moving; if (!self.moving) return; var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.speed) { self.x = self.targetX; self.y = self.targetY; self.moving = false; // Switch to idle frame when stopping self.switchToFrame(0); } else { self.x += self.speed * dx / dist; self.y += self.speed * dy / dist; } }; // Set movement target self.moveTo = function (x, y) { self.targetX = x; self.targetY = y; // Start movement if (!self.moving) { self.moving = true; self.animationFrame = 1; self.animationTimer = 0; self.switchToFrame(self.animationFrame); } }; // Attach sickle to farmer's hand var sickle = self.attachAsset('sickle', { anchorX: 0.2, // hand position, left side of ellipse anchorY: 0.7, // slightly below center x: 0, y: 30 }); sickle.alpha = 1; // Add attack animation for sickle self.attack = function () { tween(sickle, { rotation: Math.PI * 2 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { sickle.rotation = 0; } }); }; return self; }); // Field class var Field = Container.expand(function () { var self = Container.call(this); self.index = 0; // 0-3 self.locked = false; self.lockCost = 0; self.lockNode = null; self.fenceNodes = []; self.wheats = []; self.unlockBtn = null; // Draw fences - Empty implementation to eliminate fences self.drawFences = function (x, y, w, h) { self.fenceNodes = []; // No fences or gates are created }; // Place wheat self.placeWheats = function (x, y, w, h, count) { self.wheats = []; // Define grid size var rows = 5; var cols = 10; // Choose vegetable asset per area var vegAssetId = 'wheat'; if (self.index === 1) vegAssetId = 'carrot'; if (self.index === 2) vegAssetId = 'tomato'; if (self.index === 3) vegAssetId = 'eggplant'; // Fallback if asset not found, use wheat if (!LK.assets || !LK.assets[vegAssetId]) vegAssetId = 'wheat'; // Calculate asset size for spacing (use wheat size as reference for all) var vegAsset = LK.getAsset('wheat', { anchorX: 0.5, anchorY: 1 }); var wheatW = vegAsset.width; var wheatH = vegAsset.height; // Padding from fences var padX = 60; var padY = 60; // Compute available area for wheat grid var gridW = w - 2 * padX; var gridH = h - 2 * padY; // Compute spacing between wheat plants var spacingX = (gridW - wheatW) / (cols - 1); var spacingY = (gridH - wheatH) / (rows - 1); // Place appropriate vegetable in grid based on field index for (var row = 0; row < rows; ++row) { for (var col = 0; col < cols; ++col) { var wx = x + padX + col * spacingX + wheatW / 2; var wy = y + padY + row * spacingY + wheatH; var veg; // Create appropriate vegetable based on area/field index if (self.index === 1) { veg = new CarrotSlot(); } else if (self.index === 2) { veg = new TomatoSlot(); } else if (self.index === 3) { veg = new EggplantSlot(); } else { veg = new Wheat(); veg.fieldIndex = self.index; veg.vegAssetId = vegAssetId; veg.setVegAsset && veg.setVegAsset(vegAssetId); } veg.x = wx; veg.y = wy; self.addChild(veg); self.wheats.push(veg); } } }; // Lock overlay self.showLock = function (centerX, centerY) { if (self.lockNode) return; self.lockNode = LK.getAsset('lock', { anchorX: 0.5, anchorY: 0.5, x: centerX, y: centerY }); self.addChild(self.lockNode); // Unlock text var unlockTxt = new Text2('Unlock\n$' + self.lockCost, { size: 60, fill: "#fff" }); unlockTxt.anchor.set(0.5, 0.5); unlockTxt.x = centerX; unlockTxt.y = centerY + 70; self.unlockBtn = unlockTxt; self.addChild(unlockTxt); }; self.hideLock = function () { if (self.lockNode) { self.lockNode.destroy(); self.lockNode = null; } if (self.unlockBtn) { self.unlockBtn.destroy(); self.unlockBtn = null; } }; return self; }); // Rooster class with 4-frame animation cycling smoothly var Rooster = Container.expand(function () { var self = Container.call(this); // Animation frame asset ids var frameIds = ['rooster_1', 'rooster_2', 'rooster_3', 'rooster_4']; self.roosterFrames = []; self.currentFrame = 0; self.frameTimer = 0; self.frameInterval = 10; // ~0.16s per frame at 60fps (smooth) // Attach all frames, only show the first for (var i = 0; i < frameIds.length; ++i) { var frame = self.attachAsset(frameIds[i], { anchorX: 0.5, anchorY: 0.5, alpha: i === 0 ? 1 : 0 }); self.roosterFrames.push(frame); } // Animation update self.update = function () { self.frameTimer++; if (self.frameTimer >= self.frameInterval) { // Hide current frame self.roosterFrames[self.currentFrame].alpha = 0; // Advance to next frame self.currentFrame = (self.currentFrame + 1) % self.roosterFrames.length; // Show new frame self.roosterFrames[self.currentFrame].alpha = 1; self.frameTimer = 0; } }; return self; }); // TomatoSlot class for area 3 var TomatoSlot = Container.expand(function () { var self = Container.call(this); self.slotAsset = self.attachAsset('tomato', { anchorX: 0.5, anchorY: 1 }); var sproutAsset = self.attachAsset('sprout', { anchorX: 0.5, anchorY: 1, alpha: 0, scaleX: 0.5, scaleY: 0.5 }); self.harvested = false; self.regrowTime = 1800; // 30 seconds at 60fps self.regrowCounter = 0; self.fieldIndex = 2; // Area 3 self.regrowing = false; // Show/hide tomato and handle regrow animation self.setHarvested = function (harvested) { self.harvested = harvested; if (harvested) { // Hide tomato with animation tween(self.slotAsset, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); // Show sprout with animation sproutAsset.alpha = 1; sproutAsset.scaleX = 0.1; sproutAsset.scaleY = 0.1; // Animate sprout appearing tween(sproutAsset, { scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); self.regrowCounter = self.regrowTime; self.regrowing = true; } else { // Show tomato with animation tween(self.slotAsset, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeIn }); // Hide sprout with animation tween(sproutAsset, { alpha: 0 }, { duration: 300, easing: tween.easeIn }); self.regrowing = false; } }; // Regrow logic self.update = function () { if (self.harvested && self.regrowing) { if (self.regrowCounter > 0) { // Animate sprout growing to tomato size var t = 1 - self.regrowCounter / self.regrowTime; sproutAsset.scaleX = 0.5 + 0.5 * t; sproutAsset.scaleY = 0.5 + 0.5 * t; self.regrowCounter--; } if (self.regrowCounter <= 0) { // Sprout is now full size, switch back to tomato and allow harvest again sproutAsset.scaleX = 1; sproutAsset.scaleY = 1; self.setHarvested(false); } } }; // For hit detection self.isHarvestable = function () { return !self.harvested; }; return self; }); // Wheat class var Wheat = Container.expand(function () { var self = Container.call(this); self.vegAssetId = 'wheat'; self.wheatAsset = self.attachAsset('wheat', { anchorX: 0.5, anchorY: 1 }); var sproutAsset = self.attachAsset('sprout', { anchorX: 0.5, anchorY: 1, alpha: 0, scaleX: 0.5, scaleY: 0.5 }); self.harvested = false; self.regrowTime = 1800; // 30 seconds at 60fps self.regrowCounter = 0; self.fieldIndex = 0; // which field this wheat belongs to self.regrowing = false; self.removeAfter = 0; // Change vegetable asset if needed self.setVegAsset = function (assetId) { if (self.wheatAsset) { self.wheatAsset.destroy(); } self.vegAssetId = assetId || 'wheat'; // Only allow wheat, carrot, tomato, eggplant var validAssets = { wheat: 1, carrot: 1, tomato: 1, eggplant: 1 }; if (!validAssets[self.vegAssetId]) self.vegAssetId = 'wheat'; self.wheatAsset = self.attachAsset(self.vegAssetId, { anchorX: 0.5, anchorY: 1 }); // Make sure sprout is on top self.removeChild(sproutAsset); self.addChild(sproutAsset); }; // Show/hide wheat and handle regrow animation self.setHarvested = function (harvested) { self.harvested = harvested; if (harvested) { // Hide wheat, show sprout if (self.wheatAsset) { // Animate wheat harvesting with tween tween(self.wheatAsset, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); } // Show and animate sprout growing from nothing sproutAsset.alpha = 1; sproutAsset.scaleX = 0.1; sproutAsset.scaleY = 0.1; // Animate sprout appearing tween(sproutAsset, { scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeOut }); self.regrowCounter = self.regrowTime; self.regrowing = true; } else { // Show wheat/veg, hide sprout with animation if (self.wheatAsset) { tween(self.wheatAsset, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeIn }); } // Fade out sprout tween(sproutAsset, { alpha: 0 }, { duration: 300, easing: tween.easeIn }); self.regrowing = false; } }; // Regrow logic and removal after 5 seconds self.update = function () { if (self.harvested && self.regrowing) { if (self.regrowCounter > 0) { // Animate sprout growing to wheat/veg size var t = 1 - self.regrowCounter / self.regrowTime; sproutAsset.scaleX = 0.5 + 0.5 * t; sproutAsset.scaleY = 0.5 + 0.5 * t; self.regrowCounter--; } if (self.regrowCounter <= 0) { // Sprout is now full size, switch back to wheat/veg and allow harvest again sproutAsset.scaleX = 1; sproutAsset.scaleY = 1; self.setHarvested(false); } } }; // For hit detection self.isHarvestable = function () { return !self.harvested; }; return self; }); var Zombie = Container.expand(function () { var self = Container.call(this); // Create the zombie frames (two different assets) var zombieFrame1 = self.attachAsset('zombie_1', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }); var zombieFrame2 = self.attachAsset('zombie_2', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Animation variables self.currentFrame = 0; self.frameTimer = 0; self.frameInterval = 15; // Frame switch interval self.speed = 2; // Movement speed self.lastX = 0; // Track previous X for collision detection self.lastY = 0; // Track previous Y for collision detection self.lastWasIntersecting = false; // Track previous intersection state self.isDead = false; // Track if zombie is dead // Handle click/tap on zombie self.down = function (x, y, obj) { // Mark zombie as clicked and initiate death sequence if (!self.isDead) { self.isDead = true; // Flash zombie yellow to indicate hit LK.effects.flashObject(self, 0xFFFF00, 300); // Death animation - fade out and scale down tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { // Remove zombie from game self.destroy(); // Create new zombie after a 40s delay LK.setTimeout(createZombie, 40000); } }); // Prevent event from bubbling to game (stop farmer movement) return true; } }; // Zombie animation and movement self.update = function () { // Don't update if dead if (self.isDead) return; // Save previous position for collision detection self.lastX = self.x; self.lastY = self.y; // Frame animation self.frameTimer++; if (self.frameTimer >= self.frameInterval) { // Toggle between frames self.currentFrame = self.currentFrame === 0 ? 1 : 0; // Show current frame zombieFrame1.alpha = self.currentFrame === 0 ? 1 : 0; zombieFrame2.alpha = self.currentFrame === 1 ? 1 : 0; self.frameTimer = 0; } // Move zombie toward the farmer if (farmer) { var dx = farmer.x - self.x; var dy = farmer.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > self.speed) { self.x += self.speed * dx / dist; self.y += self.speed * dy / dist; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4caf50 // Grass green }); /**** * Game Code ****/ // Area 4 // Area 3 // Area 2 // Lock icon (ellipse, gray) // Sickle (ellipse, yellow) // House (box) // Farmer (box) // Wheat (ellipse) // Field fence (rectangle) // --- Game constants --- // Rooster animation frames (replace id values with your own image ids) var FIELD_W = 900; var FIELD_H = 900; var FIELD_GAP = 120; // Increased gap to move fences further from center var FIELD_COUNT = 4; var WHEAT_PER_FIELD = 10; // Area unlock prices and reward multipliers var FIELD_LOCK_COSTS = [0, 20000, 40000, 60000]; // Area 1 open, others locked var FIELD_REWARD_MULT = [1, 2, 3, 4]; // Area 1=1x, 2=2x, 3=3x, 4=4x // --- Area constants --- // Define the distance from center for all areas (equal distance) var AREA_DISTANCE = 600; // Create an array to hold the areas var areas = []; var animals = []; // --- Game state --- var fields = []; var farmer = null; var money = 0; var moneyTxt = null; var sickle = null; var dragging = false; var dragOffsetX = 0; var dragOffsetY = 0; var unlockFieldIndex = -1; var playerMovementBlockedByUIClick = false; // Flag to indicate UI handled the click // --- Layout calculation --- // Fields: 2x2 grid, with house in center // [0][1] // [2][3] var fieldPositions = [{ x: 0, y: 0 }, // top-left { x: FIELD_W + FIELD_GAP, y: 0 }, // top-right { x: 0, y: FIELD_H + FIELD_GAP }, // bottom-left { x: FIELD_W + FIELD_GAP, y: FIELD_H + FIELD_GAP } // bottom-right ]; // Center everything in game area var totalW = FIELD_W * 2 + FIELD_GAP; var totalH = FIELD_H * 2 + FIELD_GAP; var offsetX = Math.floor((2048 - totalW) / 2); var offsetY = Math.floor((2732 - totalH) / 2); // --- Create fields --- for (var i = 0; i < FIELD_COUNT; ++i) { var f = new Field(); f.index = i; f.locked = FIELD_LOCK_COSTS[i] > 0; f.lockCost = FIELD_LOCK_COSTS[i]; var pos = fieldPositions[i]; var fx = offsetX + pos.x; var fy = offsetY + pos.y; // Skip drawing fences f.placeWheats(fx, fy, FIELD_W, FIELD_H, WHEAT_PER_FIELD); if (f.locked) { // Center of field f.showLock(fx + FIELD_W / 2, fy + FIELD_H / 2); } game.addChild(f); fields.push(f); } // Center reference point for positions var centerX = offsetX + FIELD_W; var centerY = offsetY + FIELD_H - 250; // --- Create farmer --- farmer = new Farmer(); farmer.x = centerX; farmer.y = centerY - 120; // Start at center area game.addChild(farmer); // --- Create sickle (attached to farmer's hand) --- sickle = LK.getAsset('sickle', { anchorX: 0.2, // hand position, left side of ellipse anchorY: 0.7, // slightly below center x: 0, y: 30 }); sickle.alpha = 1; // --- Money display --- moneyTxt = new Text2('$0', { size: 100, fill: "#fff" }); moneyTxt.anchor.set(0.5, 0); LK.gui.top.addChild(moneyTxt); // --- Information message on right side --- // Create the info message text var infoMsgTxt = new Text2('Game controls: Use mouse to move.\nFor mobile, tap to move.', { size: 80, fill: "#fff" }); infoMsgTxt.anchor.set(1, 0.5); // Right align, vertically centered // Position at right side, vertically centered (avoid top 100px for menu) infoMsgTxt.x = 2048 - 40; // 40px padding from right edge infoMsgTxt.y = 2732 / 2; game.addChild(infoMsgTxt); // Hide after 30 seconds (1800 frames at 60fps) LK.setTimeout(function () { if (infoMsgTxt && infoMsgTxt.parent) { infoMsgTxt.destroy(); } }, 30000); // --- Missions UI --- // "Missions" title var missionsTitle = new Text2('Missions', { size: 90, fill: "#fff" }); missionsTitle.anchor.set(0, 0); // Left align, top // Place on the left side of the center part of the screen var missionAreaX = 180; // 180px from left edge, safe from menu var missionAreaY = 120; // Below top menu area missionsTitle.x = missionAreaX; missionsTitle.y = missionAreaY; game.addChild(missionsTitle); // Mission bar background (smaller, left side) var missionBarBg = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0, x: missionAreaX, y: missionsTitle.y + missionsTitle.height + 18, scaleX: 2.2, scaleY: 0.5, alpha: 0.25 }); game.addChild(missionBarBg); // Mission bar fill (progress) var missionBarFill = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0, x: missionAreaX, y: missionsTitle.y + missionsTitle.height + 18, scaleX: 0, // Will be set dynamically scaleY: 0.5, tint: 0xFFD700, // Gold color alpha: 0.85 }); game.addChild(missionBarFill); // Mission text var missionText = new Text2('Reach $100,000', { size: 60, fill: "#fff" }); missionText.anchor.set(0, 0); missionText.x = missionAreaX + 10; missionText.y = missionBarBg.y + missionBarBg.height + 8; game.addChild(missionText); // Store for update var missionBarMaxWidth = 200; // px, visually (not used, but kept for reference) var missionBarFillMaxScale = 2.2; // --- Helper: update money display --- function updateMoneyDisplay() { moneyTxt.setText('$' + money); // --- Missions progress update --- if (typeof missionBarFill !== "undefined") { // Clamp progress between 0 and 1 var progress = Math.max(0, Math.min(1, money / 100000)); missionBarFill.scaleX = missionBarFillMaxScale * progress; } // --- Mission complete: You Win! --- if (money >= 100000 && !game._missionWinShown) { game._missionWinShown = true; LK.showYouWin(); } } // --- Helper: unlock field if enough money --- function tryUnlockField(fieldIdx) { var f = fields[fieldIdx]; if (!f.locked) return; if (money >= f.lockCost) { money -= f.lockCost; updateMoneyDisplay(); f.locked = false; f.hideLock(); // Flash field green for (var i = 0; i < f.fenceNodes.length; ++i) { LK.effects.flashObject(f.fenceNodes[i], 0x00ff00, 600); } } else { // Not enough money, flash red LK.effects.flashScreen(0xff0000, 400); } } // --- Touch/mouse handling --- var lastDownX = 0, lastDownY = 0; var harvestMode = false; var harvestWheat = null; // Helper: find harvestable vegetable under (x, y) in unlocked fields function findHarvestableWheat(x, y) { for (var i = 0; i < fields.length; ++i) { var f = fields[i]; if (f.locked) continue; for (var j = 0; j < f.wheats.length; ++j) { var w = f.wheats[j]; if (w.isHarvestable()) { // Use bounding box for hit var wx = w.x, wy = w.y; var ww = 60, wh = 80; if (x >= wx - ww / 2 && x <= wx + ww / 2 && y >= wy - wh && y <= wy) { return w; } } } } return null; } // Helper: find locked field under (x, y) function findLockedField(x, y) { for (var i = 0; i < fields.length; ++i) { var f = fields[i]; if (!f.locked) continue; // Use field area var pos = fieldPositions[i]; var fx = offsetX + pos.x; var fy = offsetY + pos.y; if (x >= fx && x <= fx + FIELD_W && y >= fy && y <= fy + FIELD_H) { return i; } } return -1; } // --- Game event handlers --- // Move farmer or harvest wheat game.down = function (x, y, obj) { // If UI handled this click, do nothing for game movement. if (playerMovementBlockedByUIClick) { playerMovementBlockedByUIClick = false; // Reset flag for next input return; } // Shop system completely removed // No shopButton references needed anymore // Continue with normal game control flow // No shop button checks needed // lastDownX = x; lastDownY = y; // Check if tapping on locked field unlock button var lockedIdx = findLockedField(x, y); if (lockedIdx >= 0) { var f = fields[lockedIdx]; // If tap is near lock icon or unlock text var centerX = offsetX + fieldPositions[lockedIdx].x + FIELD_W / 2; var centerY = offsetY + fieldPositions[lockedIdx].y + FIELD_H / 2; var dist = Math.sqrt((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY)); if (dist < 120) { tryUnlockField(lockedIdx); return; } } // Check for wheat var w = findHarvestableWheat(x, y); if (w) { harvestMode = true; harvestWheat = w; // Change player to face forward during harvest // Switch to player_down for harvesting if (farmer.currentAsset) { farmer.currentAsset.alpha = 0; } var playerDown = LK.getAsset('player_down', { anchorX: 0.5, anchorY: 0.5 }); playerDown.alpha = 1; farmer.addChild(playerDown); farmer.currentAsset = playerDown; // Trigger sickle attack animation farmer.attack(); // Show harvest animation effect var harvestEffect = LK.getAsset('sprout', { anchorX: 0.5, anchorY: 0.5, x: w.x, y: w.y - 50, alpha: 0.8, scaleX: 2, scaleY: 2 }); game.addChild(harvestEffect); // Animate the harvest effect tween(harvestEffect, { alpha: 0, y: harvestEffect.y - 100 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { harvestEffect.destroy(); } }); // Harvest w.setHarvested(true); var reward = 100 * (FIELD_REWARD_MULT[w.fieldIndex] || 1); money += reward; updateMoneyDisplay(); // Flash wheat LK.effects.flashObject(w, 0xffff00, 300); // No setHarvested(false) here; regrow/removal handled in Wheat.update harvestMode = false; harvestWheat = null; return; } // Move farmer with animation farmer.moveTo(x, y); dragging = true; dragOffsetX = x - farmer.x; dragOffsetY = y - farmer.y; }; // Drag farmer game.move = function (x, y, obj) { // If UI interaction blocked the start of a drag, this helps. if (playerMovementBlockedByUIClick) { // Flag will be reset by the next 'down' event, or could be reset here if necessary, // but typically 'move' follows a 'down' that wasn't blocked. return; } // Shop system completely removed // if (dragging) { farmer.moveTo(x - dragOffsetX, y - dragOffsetY); } if (harvestMode && harvestWheat) { sickle.x = x; sickle.y = y; } }; // End drag/harvest game.up = function (x, y, obj) { // If UI interaction blocked the 'down' event, 'up' should also be controlled. if (playerMovementBlockedByUIClick) { playerMovementBlockedByUIClick = false; // Reset flag here as well return; } // Shop system completely removed // // dragging = false; harvestMode = false; harvestWheat = null; }; // --- Main update loop --- // Defensive: If game is reset, clear win timer game.update = function () { // Update farmer farmer.update(); // Update wheat regrow for (var i = 0; i < fields.length; ++i) { var f = fields[i]; f.wheats.forEach(function (wheat) { wheat.update(); }); } // Update clouds for (var i = 0; i < clouds.length; i++) { clouds[i].update(); } // Update birds for (var i = 0; i < birds.length; i++) { birds[i].update(); } }; // --- Create areas and place animals --- // Calculate center of game screen var gameWidth = 2048; var gameHeight = 2732; var gameCenterX = gameWidth / 2; var gameCenterY = gameHeight / 2; // Create the four areas at equal distances from center // Area_Left var areaLeft = new Container(); areaLeft.x = gameCenterX - AREA_DISTANCE; areaLeft.y = gameCenterY; areaLeft.name = "Area_Left"; game.addChild(areaLeft); areas.push(areaLeft); // Area_Right var areaRight = new Container(); areaRight.x = gameCenterX + AREA_DISTANCE; areaRight.y = gameCenterY; areaRight.name = "Area_Right"; game.addChild(areaRight); areas.push(areaRight); // Area_Top var areaTop = new Container(); areaTop.x = gameCenterX; areaTop.y = gameCenterY - AREA_DISTANCE; areaTop.name = "Area_Top"; game.addChild(areaTop); areas.push(areaTop); // Area_Bottom var areaBottom = new Container(); areaBottom.x = gameCenterX; areaBottom.y = gameCenterY + AREA_DISTANCE; areaBottom.name = "Area_Bottom"; game.addChild(areaBottom); areas.push(areaBottom); // Place animals in the areas // Animal_Right at bottom right of screen var animalRight = new Animal(); animalRight.setAnimalImage('animal_right'); animalRight.name = "Animal_Right"; // Place at bottom right, accounting for anchor (0.5, 0.5) and asset size var animalRightAsset = LK.getAsset('animal_right', { anchorX: 0.5, anchorY: 0.5 }); animalRight.x = gameWidth - animalRightAsset.width / 2 - 10; // 10px padding from right animalRight.y = gameHeight - animalRightAsset.height / 2 - 10; // 10px padding from bottom game.addChild(animalRight); animals.push(animalRight); // Area_Bottom has no animal // --- Create clouds --- var clouds = []; // Create two clouds at different positions function createClouds() { // Remove any existing clouds for (var i = 0; i < clouds.length; i++) { clouds[i].destroy(); } clouds = []; // Cloud width for calculations var cloudWidth = 500; // Create first cloud (front layer) var cloud1 = new Cloud(); cloud1.x = -cloudWidth / 2; // Start from off-screen left cloud1.y = 180; // Higher position near the top cloud1.layer = 0; // Front layer - this will be in front cloud1.init(); // Initialize movement and timing game.addChild(cloud1); clouds.push(cloud1); // Create second cloud (back layer) var cloud2 = new Cloud(); cloud2.x = -cloudWidth / 2 - 200; // Start more separated from first cloud cloud2.y = 280; // Position below first cloud with more separation cloud2.layer = 1; // Back layer - this will be behind cloud2.init(); // Initialize movement and timing game.addChild(cloud2); clouds.push(cloud2); // Schedule creation of new clouds after these disappear LK.setTimeout(createClouds, 61000); // 61 seconds to ensure smooth transition } // Start creating clouds createClouds(); // Shop system completely removed // --- Create zombie --- var zombie = null; var zombieDamageTimer = 0; // Timer to prevent continuous damage var zombieDamageAmount = 500; // Initial zombie damage/cost var zombieAppearCount = 0; // How many times zombie has appeared // --- Create birds --- var birds = []; // Create a bird that starts at the top, flies across, disappears, and restarts in a loop function createBird() { // Remove any existing birds that might be stuck for (var i = 0; i < birds.length; i++) { birds[i].destroy(); } birds = []; // Bird asset for size var tempBirdAsset = LK.getAsset('Bird', { anchorX: 0.5, anchorY: 0.5 }); var birdWidth = tempBirdAsset.width; var birdHeight = tempBirdAsset.height; // Start at the top of the screen, just off the left edge var bird = new Bird(); bird.x = -birdWidth / 2; bird.y = birdHeight / 2 + 20; // 20px padding from the very top bird.init(); game.addChild(bird); birds.push(bird); // Set up a watcher to restart the bird after 60 seconds (3600 ticks at 60fps) bird._birdLoopCheck = function () { // Only restart if bird is gone (destroyed) if (!bird.parent) { LK.setTimeout(createBird, 60000); // 60 seconds delay before next bird } else { LK.setTimeout(bird._birdLoopCheck, 200); // Check again in 200ms } }; LK.setTimeout(bird._birdLoopCheck, 200); } // Start creating birds after 1 minute (60000 ms) LK.setTimeout(createBird, 60000); // Play background music in a loop LK.playMusic('backgroundMusic', { loop: true }); // --- Initial money display --- updateMoneyDisplay(); // --- Place trees at corners --- // Tree size var treeWidth = 400; var treeHeight = 532; // Top left corner tree var topLeftTree = LK.getAsset('tree', { anchorX: 0.5, anchorY: 0.5, x: offsetX / 2, y: offsetY / 2 }); game.addChild(topLeftTree); // Top right corner tree var topRightTree = LK.getAsset('tree', { anchorX: 0.5, anchorY: 0.5, x: 2048 - offsetX / 2, y: offsetY / 2 }); game.addChild(topRightTree); // Bottom left corner tree var bottomLeftTree = LK.getAsset('tree', { anchorX: 0.5, anchorY: 0.5, x: offsetX / 2, y: 2732 - offsetY / 2 }); game.addChild(bottomLeftTree); // Bottom right corner tree var bottomRightTree = LK.getAsset('tree', { anchorX: 0.5, anchorY: 0.5, x: 2048 - offsetX / 2, y: 2732 - offsetY / 2 }); game.addChild(bottomRightTree); // --- Place trees at middle sides aligned with corner trees --- // Tree to the left of center var leftCenterTree = LK.getAsset('tree', { anchorX: 0.5, anchorY: 0.5, x: offsetX / 2, y: topRightTree.y }); game.addChild(leftCenterTree); // Tree to the right of center var rightCenterTree = LK.getAsset('tree', { anchorX: 0.5, anchorY: 0.5, x: 2048 - offsetX / 2, y: topRightTree.y }); game.addChild(rightCenterTree); // --- Add Rooster that moves left-to-right, disappears at right edge, reappears after 40s and repeats --- var rooster = null; var roosterTimeout = null; function spawnRooster() { // Remove any existing rooster rooster.destroy(); rooster = new Rooster(); // Start at the left center of the screen rooster.y = 2732 / 2; rooster.x = rooster.roosterFrames[0].width / 2 + 10; game.addChild(rooster); // Rooster path: left-to-right, horizontally centered var roosterStartX = rooster.roosterFrames[0].width / 2 + 10; var roosterEndX = 2048 - rooster.roosterFrames[0].width / 2 - 10; var roosterSpeed = 1; // px per frame, very slow movement rooster.targetX = roosterEndX; rooster.direction = 1; // 1: moving right rooster.updateRoosterMovement = function () { // Track lastX for edge detection if (typeof rooster.lastX === "undefined") rooster.lastX = rooster.x; // Move only horizontally in the center var dx = rooster.targetX - rooster.x; var dist = Math.abs(dx); if (dist < roosterSpeed) { rooster.x = rooster.targetX; } else { rooster.x += roosterSpeed * (dx > 0 ? 1 : -1); } // Call animation update if (typeof rooster.update === "function") { rooster.update(); } // Check if rooster just reached the right edge (disappear trigger) if (rooster.lastX < roosterEndX && rooster.x >= roosterEndX) { // Fade out and destroy, then respawn after 40s tween(rooster, { alpha: 0 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { if (rooster && rooster.parent) { rooster.destroy(); } roosterTimeout = LK.setTimeout(spawnRooster, 40000); // 40 seconds } }); } // Update lastX for next frame rooster.lastX = rooster.x; }; } // Add rooster update to main game loop var oldGameUpdate = game.update; game.update = function () { if (typeof oldGameUpdate === "function") oldGameUpdate(); if (rooster && rooster.parent && typeof rooster.updateRoosterMovement === "function") { rooster.updateRoosterMovement(); } // Update zombie if (zombie && zombie.parent) { zombie.update(); // Collision detection with player (only triggers on state change) var isIntersecting = zombie.intersects(farmer); // Check if we just started intersecting if (!zombie.lastWasIntersecting && isIntersecting && zombieDamageTimer <= 0) { // Zombie just touched the player, deduct gold money = Math.max(0, money - zombieDamageAmount); updateMoneyDisplay(); // Flash both zombie and farmer red LK.effects.flashObject(zombie, 0xff0000, 500); LK.effects.flashObject(farmer, 0xff0000, 500); // Set cooldown timer to prevent continuous damage (3 second cooldown) zombieDamageTimer = 180; } // Update intersection state zombie.lastWasIntersecting = isIntersecting; // Update damage cooldown timer if (zombieDamageTimer > 0) { zombieDamageTimer--; } } }; // Create the zombie function createZombie() { // Remove existing zombie if it exists zombie.destroy(); // Create new zombie zombie = new Zombie(); // Position zombie off-screen to the left zombie.x = -100; zombie.y = 2732 / 2; // Initialize tracking variables zombie.lastX = zombie.x; zombie.lastY = zombie.y; zombie.lastWasIntersecting = false; game.addChild(zombie); // Increase zombie damage each time it spawns zombieAppearCount++; if (zombieAppearCount === 1) { zombieDamageAmount = 500; } else { zombieDamageAmount = zombieDamageAmount * 2; } } // Start the first rooster and create zombie spawnRooster(); // Delay the first zombie spawn by 40 seconds after game start LK.setTimeout(createZombie, 40000); // Zombie respawn is now handled after being killed by the player;
===================================================================
--- original.js
+++ change.js
@@ -1289,23 +1289,19 @@
farmer.update();
// Update wheat regrow
for (var i = 0; i < fields.length; ++i) {
var f = fields[i];
- for (var j = 0; j < f.wheats.length; ++j) {
- f.wheats[j].update();
- }
+ f.wheats.forEach(function (wheat) {
+ wheat.update();
+ });
}
// Update clouds
for (var i = 0; i < clouds.length; i++) {
- if (clouds[i] && clouds[i].parent) {
- clouds[i].update();
- }
+ clouds[i].update();
}
// Update birds
for (var i = 0; i < birds.length; i++) {
- if (birds[i] && birds[i].parent) {
- birds[i].update();
- }
+ birds[i].update();
}
};
// --- Create areas and place animals ---
// Calculate center of game screen
@@ -1362,11 +1358,9 @@
// Create two clouds at different positions
function createClouds() {
// Remove any existing clouds
for (var i = 0; i < clouds.length; i++) {
- if (clouds[i] && clouds[i].parent) {
- clouds[i].destroy();
- }
+ clouds[i].destroy();
}
clouds = [];
// Cloud width for calculations
var cloudWidth = 500;
@@ -1402,11 +1396,9 @@
// Create a bird that starts at the top, flies across, disappears, and restarts in a loop
function createBird() {
// Remove any existing birds that might be stuck
for (var i = 0; i < birds.length; i++) {
- if (birds[i] && birds[i].parent) {
- birds[i].destroy();
- }
+ birds[i].destroy();
}
birds = [];
// Bird asset for size
var tempBirdAsset = LK.getAsset('Bird', {
@@ -1498,11 +1490,9 @@
var rooster = null;
var roosterTimeout = null;
function spawnRooster() {
// Remove any existing rooster
- if (rooster && rooster.parent) {
- rooster.destroy();
- }
+ rooster.destroy();
rooster = new Rooster();
// Start at the left center of the screen
rooster.y = 2732 / 2;
rooster.x = rooster.roosterFrames[0].width / 2 + 10;
@@ -1581,11 +1571,9 @@
};
// Create the zombie
function createZombie() {
// Remove existing zombie if it exists
- if (zombie && zombie.parent) {
- zombie.destroy();
- }
+ zombie.destroy();
// Create new zombie
zombie = new Zombie();
// Position zombie off-screen to the left
zombie.x = -100;