/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Removed plugin import to fix 'Unable to load plugins' error 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; }); // Zombie respawn is now handled after being killed by the player; // IntroScreen class for game intro animation with improved loading var IntroScreen = Container.expand(function () { var self = Container.call(this); // Track loading state self.loadingPhase = 0; // 0=Loading core, 1=Loading intro, 2=Loading game assets, 3=Complete self.animationStarted = false; self.introAssetsLoaded = false; self.gameAssetsLoaded = false; // Create a dark overlay as background var overlay = LK.getAsset('centerCircle', { anchorX: 0, anchorY: 0, scaleX: 30, scaleY: 40, alpha: 1, tint: 0x000000 }); self.addChild(overlay); // Loading text var loadingText = new Text2('Loading Core Assets...', { size: 120, fill: 0xFFFFFF }); loadingText.anchor.set(0.5, 0.5); loadingText.x = 2048 / 2; loadingText.y = 2732 / 2; self.addChild(loadingText); // Animation references var sunriseBackground = null; var introClouds = []; var maleFarmer = null; var femaleFarmer = null; var sproutAsset = null; var wheatAsset = null; var carrotAsset = null; var tomatoAsset = null; var titleText = null; var subtitleText = null; var introZombie = null; var introSickle = null; var startButtonBg = null; var startText = null; // Loading dots animation self.updateLoadingText = function () { if (self.loadingPhase >= 3) { return; } var dots = ''; if (loadingText && loadingText.text) { var baseTxt = ''; if (self.loadingPhase === 0) { baseTxt = 'Loading Core Assets'; } else if (self.loadingPhase === 1) { baseTxt = 'Loading Intro Assets'; } else if (self.loadingPhase === 2) { baseTxt = 'Loading Game Assets'; } if (loadingText.text.indexOf(baseTxt) === 0) { var parts = loadingText.text.split(baseTxt); dots = parts.length > 1 ? parts[1] : ''; } } // Cycle through dot patterns if (dots === '...') { dots = ''; } else if (dots === '') { dots = '.'; } else if (dots === '.') { dots = '..'; } else if (dots === '..') { dots = '...'; } // Update text based on current loading phase var baseTxt = ''; if (self.loadingPhase === 0) { baseTxt = 'Loading Core Assets'; } else if (self.loadingPhase === 1) { baseTxt = 'Loading Intro Assets'; } else if (self.loadingPhase === 2) { baseTxt = 'Loading Game Assets'; } loadingText.setText(baseTxt + dots); // Continue animation until all assets are loaded LK.setTimeout(self.updateLoadingText, 500); }; // Check if intro assets are loaded self.checkIntroAssetsLoaded = function () { if (!self.introAssetsLoaded) { var allAssetsLoaded = true; var testAssets = ['centerCircle', 'cloud']; for (var i = 0; i < testAssets.length; i++) { var testAsset = LK.getAsset(testAssets[i], { anchorX: 0.5, anchorY: 0.5 }); if (!testAsset || !testAsset.width) { allAssetsLoaded = false; break; } } if (allAssetsLoaded) { self.introAssetsLoaded = true; self.loadingPhase = 1; // Now that intro assets are loaded, create the intro elements self.createIntroElements(); // Start loading game assets LK.setTimeout(self.checkGameAssetsLoaded, 100); } else { // Check again in a moment LK.setTimeout(self.checkIntroAssetsLoaded, 100); } } }; // Check if game assets are loaded self.checkGameAssetsLoaded = function () { if (!self.gameAssetsLoaded) { var allAssetsLoaded = true; var testAssets = ['farmer', 'wheat', 'zombie_1', 'tomato', 'carrot', 'eggplant', 'sickle']; for (var i = 0; i < testAssets.length; i++) { var testAsset = LK.getAsset(testAssets[i], { anchorX: 0.5, anchorY: 0.5 }); if (!testAsset || !testAsset.width) { allAssetsLoaded = false; break; } } if (allAssetsLoaded) { self.gameAssetsLoaded = true; self.loadingPhase = 3; // Fade out the loading text tween(loadingText, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { loadingText.destroy(); // Start the intro animation once all loading is complete if (!self.animationStarted) { self.animationStarted = true; self.startAnimation(); } } }); } else { // Update loading phase self.loadingPhase = 2; // Check again in a moment LK.setTimeout(self.checkGameAssetsLoaded, 100); } } }; // Create intro elements once basic assets are loaded self.createIntroElements = function () { // Add a sunrise effect background sunriseBackground = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 30, scaleY: 40, alpha: 0, tint: 0xf5cb6c // Sunrise yellow color }); self.addChild(sunriseBackground); // Create animated clouds for intro introClouds = []; for (var i = 0; i < 3; i++) { var cloudAsset = LK.getAsset('cloud', { anchorX: 0.5, anchorY: 0.5, x: -300 + i * 500, y: 400 + i * 150, alpha: 0, scaleX: 0.8 + i * 0.3, scaleY: 0.8 + i * 0.3 }); self.addChild(cloudAsset); introClouds.push(cloudAsset); } // Create title text titleText = new Text2('FARM HARVESTER', { size: 180, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 2732 / 4; titleText.alpha = 0; self.addChild(titleText); // Create subtitle text subtitleText = new Text2('Grow crops, earn money, expand your farm!', { size: 90, fill: 0xFFFFFF }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 2048 / 2; subtitleText.y = titleText.y + 200; subtitleText.alpha = 0; self.addChild(subtitleText); // Create start text only, no background startText = new Text2('TAP TO START', { size: 100, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); startText.x = 2048 / 2; startText.y = 2732 / 2 + 600; startText.alpha = 0; self.addChild(startText); }; // Start the loading process self.updateLoadingText(); self.checkIntroAssetsLoaded(); // Lazy creation of game assets for intro only when needed self.createGameIntroAssets = function () { // Create male and female farmer for intro animation only when needed if (!maleFarmer) { maleFarmer = LK.getAsset('farmer', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 300, y: 2732 / 2 + 200, scaleX: 1.2, scaleY: 1.2, alpha: 0 }); self.addChild(maleFarmer); } if (!femaleFarmer) { femaleFarmer = LK.getAsset('farmer_walk', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 300, y: 2732 / 2 + 200, scaleX: 1.2, scaleY: 1.2, alpha: 0 }); self.addChild(femaleFarmer); } // Create growing plant animation elements only when needed if (!sproutAsset) { sproutAsset = LK.getAsset('sprout', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2732 / 2 + 400, scaleX: 0.1, scaleY: 0.1, alpha: 0 }); self.addChild(sproutAsset); } if (!wheatAsset) { wheatAsset = LK.getAsset('wheat', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2732 / 2 + 400, scaleX: 0.1, scaleY: 0.1, alpha: 0 }); self.addChild(wheatAsset); } // Create vegetables that will grow from sprout if (!carrotAsset) { carrotAsset = LK.getAsset('carrot', { anchorX: 0.5, anchorY: 1, x: 2048 / 2 - 200, y: 2732 / 2 + 400, scaleX: 0.1, scaleY: 0.1, alpha: 0 }); self.addChild(carrotAsset); } if (!tomatoAsset) { tomatoAsset = LK.getAsset('tomato', { anchorX: 0.5, anchorY: 1, x: 2048 / 2 + 200, y: 2732 / 2 + 400, scaleX: 0.1, scaleY: 0.1, alpha: 0 }); self.addChild(tomatoAsset); } // Add zombie for intro animation if (!introZombie) { introZombie = LK.getAsset('zombie_1', { anchorX: 0.5, anchorY: 0.5, x: 2048 + 300, y: 2732 / 2 + 300, scaleX: 1.2, scaleY: 1.2, alpha: 0 }); self.addChild(introZombie); } // Add sickle for intro animation if (!introSickle) { introSickle = LK.getAsset('sickle', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 - 200, scaleX: 2, scaleY: 2, alpha: 0, rotation: -Math.PI / 4 }); self.addChild(introSickle); } }; // Start animation sequence self.startAnimation = function () { // Make sure assets are loaded before starting animation if (self.loadingPhase < 3) { LK.setTimeout(self.checkGameAssetsLoaded, 100); return; } // Create game assets needed for intro animation self.createGameIntroAssets(); // Fade in sunrise effect tween(sunriseBackground, { alpha: 0.5 }, { duration: 2000, easing: tween.easeOut }); // Animate clouds drifting in for (var i = 0; i < introClouds.length; i++) { (function (index) { var cloud = introClouds[index]; LK.setTimeout(function () { tween(cloud, { alpha: 0.7, x: cloud.x + 400 }, { duration: 4000, easing: tween.easeOut }); }, 500 * index); })(i); } // Fade in and animate farmers running in from sides LK.setTimeout(function () { // Animate male farmer running in from left tween(maleFarmer, { alpha: 1, x: 2048 / 2 - 150 }, { duration: 1500, easing: tween.easeOut }); // Animate female farmer running in from right tween(femaleFarmer, { alpha: 1, x: 2048 / 2 + 150 }, { duration: 1500, easing: tween.easeOut }); }, 1000); // Animate farmers meeting in middle and "planting" sprout LK.setTimeout(function () { // Move farmers to center tween(maleFarmer, { x: 2048 / 2 - 50 }, { duration: 800, easing: tween.easeInOut }); tween(femaleFarmer, { x: 2048 / 2 + 50 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { // Show sprout growing sproutAsset.alpha = 1; tween(sproutAsset, { scaleX: 1, scaleY: 1 }, { duration: 1200, easing: tween.easeOut, onFinish: function onFinish() { // Show wheat growing from sprout wheatAsset.alpha = 1; tween(wheatAsset, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.easeOut }); // Show carrot and tomato growing carrotAsset.alpha = 1; tween(carrotAsset, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.easeOut }); tomatoAsset.alpha = 1; tween(tomatoAsset, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.easeOut }); } }); } }); }, 3000); // Animate zombie coming in from right LK.setTimeout(function () { introZombie.alpha = 1; tween(introZombie, { x: 2048 / 2 + 450 }, { duration: 1500, easing: tween.easeIn }); }, 5000); // Animate sickle appearing and swinging LK.setTimeout(function () { introSickle.alpha = 1; tween(introSickle, { rotation: Math.PI }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(introZombie, { alpha: 0, y: introZombie.y + 100 }, { duration: 500, easing: tween.easeIn }); } }); }, 6000); // Fade in title with a fancy effect LK.setTimeout(function () { titleText.alpha = 0.1; tween(titleText, { alpha: 1, y: titleText.y + 50 }, { duration: 1200, easing: tween.easeOut }); // Flash effect for title var _flashTitle = function flashTitle(count) { if (count <= 0) { return; } tween(titleText, { alpha: 0.7 }, { duration: 100, onFinish: function onFinish() { tween(titleText, { alpha: 1 }, { duration: 100, onFinish: function onFinish() { _flashTitle(count - 1); } }); } }); }; LK.setTimeout(function () { _flashTitle(3); }, 1200); }, 7000); // Fade in subtitle with delay LK.setTimeout(function () { tween(subtitleText, { alpha: 1, y: subtitleText.y + 30 }, { duration: 800, easing: tween.easeOut }); }, 8000); // Fade out animation elements and transition to game UI LK.setTimeout(function () { // Fade out animation elements if (maleFarmer) { tween(maleFarmer, { alpha: 0 }, { duration: 800 }); } if (femaleFarmer) { tween(femaleFarmer, { alpha: 0 }, { duration: 800 }); } if (sproutAsset) { tween(sproutAsset, { alpha: 0 }, { duration: 800 }); } if (wheatAsset) { tween(wheatAsset, { alpha: 0 }, { duration: 800 }); } if (carrotAsset) { tween(carrotAsset, { alpha: 0 }, { duration: 800 }); } if (tomatoAsset) { tween(tomatoAsset, { alpha: 0 }, { duration: 800 }); } if (introSickle) { tween(introSickle, { alpha: 0 }, { duration: 800 }); } // Fade in start text only - startButtonBg is removed tween(startText, { alpha: 1 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { // No need to pulse since startButtonBg is removed } }); }, 9500); }; // Pulse animation for start button (modified to check if element exists) self.startPulse = function () { // Just pulse the start text since background is removed tween(startText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(startText, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.easeInOut, onFinish: self.startPulse }); } }); }; // Handle intro screen tap to start the game self.down = function (x, y, obj) { // Prevent multiple taps if (self._startingGame) { return; } self._startingGame = true; // Play tap animation for text instead tween(startText, { scaleX: 1.2, scaleY: 1.2 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { // Transition to yellow background tween(sunriseBackground, { alpha: 1, tint: 0xf8e9c0 }, { duration: 800, easing: tween.easeOut }); // Fade out all elements if (titleText) { tween(titleText, { alpha: 0 }, { duration: 600 }); } if (subtitleText) { tween(subtitleText, { alpha: 0 }, { duration: 600 }); } tween(startText, { alpha: 0 }, { duration: 600 }); for (var i = 0; i < introClouds.length; i++) { tween(introClouds[i], { alpha: 0 }, { duration: 600 }); } // Fade out entire intro screen with delay LK.setTimeout(function () { tween(self, { alpha: 0 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); // Start/enable actual game startActualGame(); } }); }, 800); } }); return true; // Prevent event bubbling }; 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); // --- Setup actual game start function --- var gameInitialized = false; var introScreen = null; function initializeGameElements() { if (gameInitialized) { return; } // --- 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); } gameInitialized = true; } function startActualGame() { // The assets should already be loaded due to the optimized intro loading process // Initialize game elements if not already done initializeGameElements(); // Set game elements active game.gameActive = true; // Play background music LK.playMusic('backgroundMusic', { loop: true }); // Start game timers and events createClouds(); LK.setTimeout(createBird, 60000); spawnRooster(); LK.setTimeout(createZombie, 40000); } // Create intro screen with enhanced animations introScreen = new IntroScreen(); game.addChild(introScreen); // Set game to inactive until intro completes game.gameActive = false; // Start intro animation sequence introScreen.startAnimation(); // Don't initialize game elements yet - wait for intro to complete // They will be created when the player taps the start button // 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); // Buttons removed to simplify the game interface // --- 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) { // Don't process game inputs if game is not active yet if (!game.gameActive) { 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) { // Don't process game inputs if game is not active yet if (!game.gameActive) { 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) { // Don't process game inputs if game is not active yet if (!game.gameActive) { 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 () { // Only update game elements if game is active (after intro) if (!game.gameActive) { // If there's an intro screen, allow it to animate even while game is inactive if (introScreen && introScreen.parent) { // Still allow intro screen animations to update if (introScreen.updateLoadingText && !introScreen.assetsLoaded) { // Loading animation is handled by setTimeout } } return; } // Update farmer if initialized if (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); // Background music will be played when the game starts after the intro sequence completes // Music playback is now handled in startActualGame() // --- 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 if (rooster && rooster.parent) { 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 if (zombie && zombie.parent) { 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);
===================================================================
--- original.js
+++ change.js