Code edit (2 edits merged)
Please save this source code
User prompt
Not sure why, but when adding mishnu harvesting rate funstionality to human and zombie, they can no longer be harvested. please fix
Code edit (2 edits merged)
Please save this source code
User prompt
For our text animation when booster is picked up, make it so that the canvas and the text appear in the center of the view port.
Code edit (13 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: canvas is undefined' in or related to this line: 'canvas.x = self.x;' Line Number: 188
Code edit (1 edits merged)
Please save this source code
User prompt
Boosters need to appear bigger. The whole thing looks too small, adjust the size make it bigger
User prompt
My boosters are still not spawning in when mishnu snax (dog food) increase by 1, can you fix this?
User prompt
Ensure game.update processes the boosters
User prompt
Please fix the bug: 'uiLayer is undefined' in or related to this line: 'var factory = uiLayer.addChild(new Factory());' Line Number: 728
User prompt
Ensure the factory instance is initialized before referencing it in the code. same with ui layer, lets simply move the booster class after these are defined
User prompt
Please fix the bug: 'factory is undefined' in or related to this line: 'var originalIncreaseDogFood = factory.startProcessing;' Line Number: 724
Code edit (1 edits merged)
Please save this source code
User prompt
Instead of saying dog food: in our game in the ui, it will say Mishnu Snax: We can keep dog food internally but the display will say Mishnu Snax: for the player
User prompt
for some reason the innerhealthbar is not receiving the grey tint flash on zombie hit. can you solve this
User prompt
Please fix the bug: 'Timeout.tick error: target is undefined' in or related to this line: 'return target.tint = 0xFFFFFF;' Line Number: 779
User prompt
Validate targets in flashGreyMask Function: Modify the function to ensure only valid objects with a tint property are processed. I need the grey mask to flash when mishnu gets hit over mishnu, the harvest radius, and the innerHealthbar. I tried to create a helper function for this as you can see. I suggested above maybe a way to fix this, maybe you have a better way.
User prompt
Please fix the bug: 'Timeout.tick error: target is undefined' in or related to this line: 'return target.tint = tintColor;' Line Number: 786
Code edit (2 edits merged)
Please save this source code
User prompt
a delay of.2 seconds on the bark sound
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Timeout.tick error: self is undefined' in or related to this line: 'self.removeChild(hitSpark);' Line Number: 684
User prompt
Please fix the bug: 'TypeError: self is undefined' in or related to this line: 'hitSpark.x = self.x + Math.cos(angle) * radius;' Line Number: 672
User prompt
Please fix the bug: 'TypeError: self is undefined' in or related to this line: 'var hitSpark = self.attachAsset('HitSpark', {' Line Number: 660
/**** 
* Classes
****/ 
// Blood Splash Class
var BloodSplash = Container.expand(function (x, y, isFinal) {
	var self = Container.call(this);
	var bloodGraphics = self.attachAsset('Blood_Splash_1', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0,
		rotation: Math.random() * Math.PI * 2,
		scaleX: 0,
		scaleY: 0
	});
	self.x = x;
	self.y = y;
	var growSpeed = isFinal ? 0.1 : 0.05;
	self.update = function () {
		bloodGraphics.alpha += 0.05;
		bloodGraphics.scaleX += growSpeed;
		bloodGraphics.scaleY += growSpeed;
		if (bloodGraphics && bloodGraphics.alpha >= 1) {
			game.removeChild(self);
		}
	};
	return self;
});
var Booster = Container.expand(function (type) {
	var self = Container.call(this);
	// Randomly assign a color
	var colors = [{
		color: 0x80FF80,
		effect: 'increaseHealth',
		text: '+1 Health'
	},
	// Green
	{
		color: 0xFF8080,
		effect: 'increaseHarvestSpeed',
		text: '+10% Harvest Speed'
	},
	// Red
	{
		color: 0x8080FF,
		effect: 'increaseMaxCargo',
		text: '+5 Max Cargo'
	},
	// Blue
	{
		color: 0xFFFF80,
		effect: 'increaseMovementSpeed',
		text: '+10% Movement Speed'
	},
	// Yellow
	{
		color: 0xBF80BF,
		effect: 'increaseProductionSpeed',
		text: '+10% Production Speed'
	},
	// Purple
	{
		color: 0xA0A0A0,
		effect: 'fillCargo',
		text: 'Cargo Filled!'
	} // Grey
	];
	var selected = colors[Math.floor(Math.random() * colors.length)];
	// Sparkle effect container
	var sparkleContainer = new Container();
	self.addChild(sparkleContainer); // Add sparkles first
	// Attach booster graphics
	var boosterGraphics = self.attachAsset('Booster', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: selected.color,
		scaleX: 1.5,
		// Increased size
		scaleY: 1.5 // Increased size
	});
	// Start position (bottom-middle of the screen)
	self.x = 2048 / 2;
	self.y = 2432 - 200;
	// Target position (random on the screen with boundaries)
	var margin = 150; // Boundary margin for safe landing
	var targetX = margin + Math.random() * (2048 - 2 * margin);
	var targetY = margin + Math.random() * (2432 - 300 - 2 * margin);
	// Rotation and sparkle effects
	var rotationSpeed = 0.01;
	function emitSparkles() {
		var angle = Math.random() * Math.PI * 2; // Random angle around the booster
		var distance = boosterGraphics.width / 2 + 10; // Distance from the center
		var sparkle = sparkleContainer.attachAsset('Stars', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: Math.random() * 2 + 0.3,
			// Larger spark sizes
			scaleY: Math.random() * 2 + 0.3,
			alpha: 0.2,
			tint: 0xFFFFFF,
			x: Math.cos(angle) * distance,
			y: Math.sin(angle) * distance
		});
		var lifetime = Math.random() * 400 + 200;
		var elapsed = 0;
		var interval = LK.setInterval(function () {
			elapsed += 16;
			sparkle.y -= 0.5; // Subtle upward motion
			sparkle.alpha = Math.max(0, 1 - elapsed / lifetime); // Gradual fade-out
			if (elapsed >= lifetime) {
				LK.clearInterval(interval);
				sparkleContainer.removeChild(sparkle);
			}
		}, 16);
	}
	// Propulsion animation
	var elapsedTime = 0;
	var duration = 1000; // 1 second to land
	LK.getSound('woosh').play();
	self.update = function () {
		elapsedTime += 16;
		var t = Math.min(1, elapsedTime / duration);
		self.x = (1 - t) * (2048 / 2) + t * targetX;
		self.y = (1 - t) * (2432 - 200) + t * targetY - 100 * Math.sin(t * Math.PI); // Arc-like motion
		if (t >= 1) {
			LK.getSound('can').play();
			self.update = function () {
				boosterGraphics.rotation += rotationSpeed;
				emitSparkles();
			};
		}
	};
	// Handle pickup and apply effect
	self.pickUp = function () {
		// Play pickup sound
		LK.getSound('Booster_Sound').play();
		// Floating text with canvas
		var canvas = self.attachAsset('Booster_Text_Canvas', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1.5,
			scaleY: 1,
			alpha: 1
		});
		var floatingText = new Text2(selected.text, {
			size: 80,
			// Large size
			fill: 0xFFFFFF,
			// White color
			align: 'center'
		});
		floatingText.anchor.set(0.5, 0.5);
		// Set initial position (higher above booster)
		var textYOffset = 150; // Higher spawn point
		canvas.x = 2048 / 2;
		canvas.y = 2732 / 2;
		floatingText.x = canvas.x;
		floatingText.y = canvas.y;
		game.addChild(canvas); // Add canvas first for layering
		game.addChild(floatingText); // Add text on top
		// Animate text and canvas together
		var elapsed = 0;
		var textDuration = 1000; // 1 second
		var fadeInterval = LK.setInterval(function () {
			elapsed += 16;
			canvas.y -= 1.5; // Move upward slightly faster
			floatingText.y -= 1.5;
			canvas.alpha = Math.max(0, 1 - elapsed / textDuration); // Fade out
			floatingText.alpha = Math.max(0, 1 - elapsed / textDuration); // Fade out
			if (elapsed >= textDuration) {
				LK.clearInterval(fadeInterval);
				game.removeChild(canvas);
				game.removeChild(floatingText);
			}
		}, 16);
		// Apply effect based on booster type
		switch (selected.effect) {
			case 'increaseHealth':
				if (globalHealthBar.currentHealth < globalHealthBar.maxHealth) {
					globalHealthBar.setHealth(globalHealthBar.currentHealth + 1);
				}
				break;
			case 'increaseHarvestSpeed':
				mishnu.harvestSpeed = mishnu.harvestSpeed * 1.1; // Increase by 10%
				break;
			case 'increaseMaxCargo':
				mishnu.cargoMax = Math.round(mishnu.cargoMax + 5); // Increase by 5 and round to nearest whole number
				break;
			case 'increaseMovementSpeed':
				mishnu.speed = mishnu.speed * 1.1; // Increase by 10%
				break;
			case 'increaseProductionSpeed':
				factory.processInterval = Math.max(1000, factory.processInterval * 0.9); // Increase speed by 10%
				break;
			case 'fillCargo':
				mishnu.humansHarvested = mishnu.cargoMax;
				break;
			default:
				console.error('Unknown booster effect:', selected.effect);
		}
		// Quick removal effect for booster
		var fadeOutInterval = LK.setInterval(function () {
			boosterGraphics.alpha -= 0.1;
			if (boosterGraphics.alpha <= 0) {
				LK.clearInterval(fadeOutInterval);
				game.removeChild(self);
			}
		}, 16);
	};
	return self;
});
// Factory Class
var Factory = Container.expand(function () {
	var self = Container.call(this);
	var factoryGraphics = self.attachAsset('Factory', {
		anchorX: 0.5,
		anchorY: 0.5,
		zIndex: 3
	});
	self.x = 950;
	self.y = 2432 - 100; // Position factory in the text box area
	self.meat = 0;
	self.dogFood = 0;
	self.processing = false;
	self.processInterval = null;
	self.rumbleTimer = 0; // Timer for rumble effect
	self.level = 1; // Current level
	self.nextLevelRequirement = 5; // Starting requirement for level 2
	// Start processing meat into dog food
	self.startProcessing = function () {
		if (!self.processing && self.meat >= 5) {
			self.processing = true;
			LK.getSound('Factory_Operation').play({
				loop: true
			});
			self.processInterval = LK.setInterval(function () {
				if (self.meat >= 5) {
					self.meat -= 5;
					self.dogFood++;
					updateFactoryText();
					checkLevelProgression(); // Check if the next level is reached
					spawnZombies(1, maxZombiesOnScreen); // Spawn a zombie when dog food is produced
					spawnBooster(); // Spawn a booster when dog food is produced
				} else {
					self.stopProcessing();
				}
			}, 5000);
		}
	};
	// Stop processing
	self.stopProcessing = function () {
		if (self.processing) {
			self.processing = false;
			LK.clearInterval(self.processInterval);
			LK.getSound('Factory_Operation').stop();
		}
	};
	// Update the factory
	self.update = function () {
		// Check for Mishnu depositing cargo
		if (mishnu.humansHarvested > 0 && self.intersects(mishnu)) {
			// Mishnu deposits cargo
			self.meat += mishnu.humansHarvested;
			mishnu.humansHarvested = 0;
			LK.getSound('Factory_Deposit').play(); // Play deposit sound
			updateFactoryText();
			self.startProcessing();
		}
		// Add rumble effect when processing
		if (self.processing) {
			self.rumbleTimer += 16; // Assume 16ms per frame
			if (self.rumbleTimer >= 100) {
				// Rumble every 100ms
				factoryGraphics.x = Math.random() * 6 - 3; // Horizontal rumble
				factoryGraphics.y = Math.random() * 6 - 3; // Vertical rumble
				self.rumbleTimer = 0;
			}
		} else {
			// Reset position when not processing
			factoryGraphics.x = 0;
			factoryGraphics.y = 0;
		}
		// Stop processing if out of meat
		if (self.meat < 5 && self.processing) {
			self.stopProcessing();
		}
	};
	function triggerLevelTextShake() {
		var shakeIntensity = 5; // Maximum shake offset in pixels
		var shakeDuration = 500; // Duration of the shake in milliseconds
		var elapsedTime = 0; // Tracks elapsed time
		var originalX = factoryText.x; // Save the original x position
		var originalY = factoryText.y; // Save the original y position
		// Function to perform shaking
		var shakeInterval = LK.setInterval(function () {
			if (elapsedTime >= shakeDuration) {
				LK.clearInterval(shakeInterval);
				factoryText.x = originalX; // Reset to original position
				factoryText.y = originalY;
				return;
			}
			// Apply random offset for shaking
			factoryText.x = originalX + (Math.random() * shakeIntensity * 2 - shakeIntensity);
			factoryText.y = originalY + (Math.random() * shakeIntensity * 2 - shakeIntensity);
			elapsedTime += 16; // Assume 16ms per frame (60 FPS)
		}, 16);
	}
	function checkLevelProgression() {
		if (self.dogFood >= self.nextLevelRequirement) {
			self.level++;
			LK.getSound('Level_Up').play(); // Play level-up sound
			self.nextLevelRequirement += Math.round(self.nextLevelRequirement * 0.75); // Increase requirement by 75%
			// Reset spawn counter and calculate new spawn limit
			humansSpawnedThisLevel = 0;
			humanSpawnLimit = self.nextLevelRequirement * 5;
			// Trigger level-up animation
			triggerLevelTextShake();
			updateFactoryText();
			spawnZombies(1, maxZombiesOnScreen); // Spawn a zombie when leveling up
		}
	}
});
// GlobalHealthBar Class
var GlobalHealthBar = Container.expand(function (initialHealth, maxHealth) {
	var self = Container.call(this);
	self.currentHealth = initialHealth;
	self.maxHealth = maxHealth;
	// Define frame dimensions if dynamic retrieval isn't available
	var frameWidth = LK.getAsset('LK_Health_Bar', {}).width;
	// Create filler (health bar inner part)
	var filler = self.attachAsset('LK_Inner_Health_Bar', {
		anchorX: 0,
		// Anchor to the left
		anchorY: 0.5,
		// Center vertically
		x: -frameWidth / 2,
		// Align with the outer frame
		// Start from the left edge of the frame
		y: 0,
		// Center vertically
		scaleX: 1 // Fully filled initially
	});
	// Create frame (health bar outer part)
	var frame = self.attachAsset('LK_Health_Bar', {
		anchorX: 0.5,
		// Center horizontally
		anchorY: 0.5,
		// Center vertically
		x: 0,
		// Centered relative to the container
		y: 0 // Center vertically
	});
	// Update the visual representation of the health bar
	self.updateHealth = function () {
		// Ensure filler width matches current health
		filler.scaleX = Math.max(0, self.currentHealth / self.maxHealth); // Scale proportionally
	};
	// Change health value
	self.setHealth = function (newHealth) {
		self.currentHealth = Math.max(0, Math.min(newHealth, self.maxHealth)); // Clamp between 0 and maxHealth
		self.updateHealth();
	};
	// Change maximum health and adjust health proportionally
	self.setMaxHealth = function (newMaxHealth) {
		var healthRatio = self.currentHealth / self.maxHealth;
		self.maxHealth = Math.max(1, newMaxHealth); // Ensure at least 1 max health
		self.currentHealth = Math.min(self.currentHealth, self.maxHealth);
		self.updateHealth();
	};
	// Initialize the health bar
	self.setHealth(initialHealth);
	return self;
});
// Declare healthBar globally for accessibility
// Assuming initial and max health are both 100
// Class for Mishnu's harvest radius
var HarvestRadius = Container.expand(function () {
	var self = Container.call(this);
	var radiusGraphics = self.attachAsset('radius', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 10,
		scaleY: 10
	});
	self.radiusSize = 300; // Effective radius size
	var rotationSpeed = 0.001; // Extremely slow rotation speed
	self.update = function () {
		self.x = mishnu.x;
		self.y = mishnu.y;
		// Apply slow rotation to the radius
		radiusGraphics.rotation += rotationSpeed;
	};
	return self;
});
// Class for Humans
var Human = Container.expand(function () {
	var self = Container.call(this);
	var humanGraphics = self.attachAsset('human', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var bloodSplashes = [];
	self.speedX = (Math.random() * 2 - 1) * 2;
	self.speedY = (Math.random() * 2 - 1) * 2;
	self.isBeingHarvested = false;
	self.inRadiusStartTime = null;
	self.currentAgonySound = null;
	self.currentCrunchSound = null;
	self.yellStarted = false; // Tracks if the yell has started
	self.yellShouldPlay = Math.random() < 1 / 3; // 1-in-3 chance for yelling
	self.crunchShouldPlay = Math.random() < 1 / 6; // 1-in-3 chance for crunch sound
	self.flashTimer = 0; // Timer for red flashing
	self.flashInterval = 500; // Initial interval for flashing
	self.update = function () {
		// Escape logic
		self.x += self.speedX;
		self.y += self.speedY;
		// Keep humans within the viewport margins
		var margin = 50;
		var bottomMargin = 300; // Extra margin for bottom text box
		if (self.x <= margin) {
			self.x = margin;
			self.speedX *= -1;
		} else if (self.x >= 2048 - margin) {
			self.x = 2048 - margin;
			self.speedX *= -1;
		}
		if (self.y <= margin) {
			self.y = margin;
			self.speedY *= -1;
		} else if (self.y >= 2432 - margin) {
			// Ensure humans respect new boundary height
			self.y = 2432 - margin;
			self.speedY *= -1;
		}
		// Check distance to Mishnu
		var dx = self.x - mishnu.x;
		var dy = self.y - mishnu.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (mishnu.humansHarvested >= mishnu.cargoMax * 1.5) {
			// Stop all sounds when cargo exceeds 150% capacity
			if (self.currentAgonySound !== null) {
				fadeOutSound(self.currentAgonySound, 500);
			}
			if (self.currentCrunchSound) {
				self.currentCrunchSound.stop();
			}
			self.isBeingHarvested = false;
			humanGraphics.tint = 0xFFFFFF; // Reset flashing
			return;
		}
		if (distance < radius.radiusSize - 2) {
			if (!self.isBeingHarvested) {
				self.isBeingHarvested = true;
				self.inRadiusStartTime = Date.now();
				self.flashTimer = 0;
				bloodSplashes = [];
				self.yellStarted = false;
				// Play crunch sound if applicable
				if (self.crunchShouldPlay) {
					self.currentCrunchSound = getRandomSound(['Dog_Crunch', 'Dog_Crunch_2', 'Dog_Crunch_3']);
					self.currentCrunchSound.volume = 0.3;
					self.currentCrunchSound.play();
				}
			} else {
				// Calculate vibration intensity based on time in the radius
				var elapsedTime = Date.now() - self.inRadiusStartTime;
				var intensity = Math.min(1, elapsedTime / 3000); // Max intensity at 3 seconds
				// Add vibration effect
				humanGraphics.x = Math.random() * intensity * 10 - intensity * 5;
				humanGraphics.y = Math.random() * intensity * 10 - intensity * 5;
				// Escape logic during vibration
				var runSpeed = 2; // Speed humans try to escape the radius
				self.x += dx / distance * runSpeed;
				self.y += dy / distance * runSpeed;
				// Flash red effect
				self.flashTimer += 16; // Assume a fixed delta of 16ms per frame
				if (self.flashTimer >= self.flashInterval) {
					self.flashTimer = 0;
					humanGraphics.tint = humanGraphics.tint === 0xFFFFFF ? 0xFF0000 : 0xFFFFFF;
					// Emit blood splash
					var bloodSplash = game.addChild(new BloodSplash(self.x, self.y));
					bloodSplashes.push(bloodSplash);
				}
				// Increase flash frequency closer to harvest
				self.flashInterval = Math.max(100, 500 - elapsedTime / 3000 * 400);
				// Start agony yell after 1 second of harvesting
				if (elapsedTime > 1000 && !self.yellStarted && self.yellShouldPlay) {
					self.yellStarted = true;
					self.currentAgonySound = getRandomSound(['Agony_Yell_1', 'Agony_Yell_2', 'Agony_Yell_3', 'Agony_Yell_4', 'Agony_Yell_5', 'Agony_Yell_6', 'Agony_Yell_7', 'Agony_Yell_8', 'Agony_Yell_9']);
					self.currentAgonySound.volume = 0.3;
					self.currentAgonySound.play();
				}
				if (elapsedTime >= 3000) {
					// Harvest after 3 seconds
					if (mishnu.humansHarvested < mishnu.cargoMax * 1.5) {
						game.removeChild(self); // Remove human from the game
						humans.splice(humans.indexOf(self), 1); // Remove from array
						mishnu.humansHarvested++;
						// Stop yelling abruptly
						if (self.currentAgonySound) {
							self.currentAgonySound.stop();
						}
						// Play ding and squish sounds on harvest
						LK.getSound('Ding_1').play();
						getRandomSound(['Squish_1', 'Squish_2', 'Squish_3', 'Squish_4']).play();
						// Final blood splashes
						for (var i = 0; i < 10; i++) {
							var bloodSplash = game.addChild(new BloodSplash(self.x, self.y, true));
							bloodSplashes.push(bloodSplash);
						}
					}
				}
			}
		} else {
			// Reset harvesting state if outside the radius
			if (self.isBeingHarvested) {
				if (self.currentAgonySound && self.yellStarted) {
					self.currentAgonySound.loop = false;
				}
				if (self.currentCrunchSound) {
					self.currentCrunchSound.stop();
				}
			}
			self.isBeingHarvested = false;
			self.inRadiusStartTime = null;
			self.flashTimer = 0;
			humanGraphics.tint = 0xFFFFFF; // Reset flashing
			bloodSplashes.forEach(function (splash) {
				game.removeChild(splash);
			});
		}
	};
	return self;
});
// Class for Mishnu
var Mishnu = Container.expand(function () {
	var self = Container.call(this);
	var mishnuGraphics = self.attachAsset('mishnu', {
		anchorX: 0.5,
		anchorY: 0.5,
		zIndex: 1
	});
	self.speed = 4;
	self.humansHarvested = 0;
	self.cargoMax = 10;
	self.targetX = 2048 / 2;
	self.targetY = 2432 - 200;
	self.update = function () {
		var dx = self.targetX - self.x;
		var dy = self.targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Adjust speed based on cargo
		if (self.humansHarvested > self.cargoMax) {
			var overCapacityFactor = (self.humansHarvested - self.cargoMax) / (self.cargoMax * 0.5);
			self.speed = Math.max(1, 4 - 3 * overCapacityFactor); // Minimum speed of 1
		} else {
			self.speed = 4; // Full speed
		}
		if (distance > 0) {
			self.x += dx / distance * self.speed;
			self.y += dy / distance * self.speed;
		}
		// Keep Mishnu within viewport margins
		var margin = 50;
		var bottomMargin = 300; // Extra margin for bottom text box
		self.x = Math.max(margin, Math.min(2048 - margin, self.x));
		self.y = Math.max(margin, Math.min(2432 - bottomMargin, self.y));
	};
	// Create and position the health bar at the top center of the viewport
	globalHealthBar.x = 1820; // Center horizontally
	globalHealthBar.y = 2560; // Position at the top center
	uiLayer.addChild(globalHealthBar); // Add to the UI layer to ensure visibility
	return self;
});
var Zombie = Container.expand(function () {
	var self = Container.call(this);
	// Add the zombie graphics
	var zombieGraphics = self.attachAsset('Zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	zombieGraphics.tint = 0x007e94; // Blue tint for the mask
	// Attributes
	self.speed = 2;
	self.harvestTime = 4000; // Time (ms) in radius to get harvested
	self.attackCooldown = 3000; // Cooldown (ms) between attacks
	self.lastAttackTime = 0; // Tracks the last attack time
	self.state = 'roaming'; // Initial state
	self.targetX = Math.random() * 2048; // Random initial roaming target
	self.targetY = Math.random() * 2432;
	self.inRadiusStartTime = null; // Time zombie entered Mishnu's radius
	var agonySound = null;
	var harvestSoundPlayed = false;
	// Helper function: Generate a random roaming target
	function setRandomTarget() {
		self.targetX = Math.random() * 2048;
		self.targetY = Math.random() * 2432;
	}
	// Helper function: Move to a target
	function moveToTarget(targetX, targetY) {
		var speedMultiplier = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
		var dx = targetX - self.x;
		var dy = targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance > 1) {
			self.x += dx / distance * self.speed * speedMultiplier;
			self.y += dy / distance * self.speed * speedMultiplier;
		} else {
			setRandomTarget();
		}
	}
	// Add sparkles
	function emitStars() {
		var sparkle = self.attachAsset('Stars', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: Math.random() * 0.3 + 0.1,
			scaleY: Math.random() * 0.3 + 0.1,
			alpha: 1,
			tint: 0xFFFFFF // White sparkles
		});
		// Position sparkles randomly around the zombie
		var angle = Math.random() * Math.PI * 2;
		var radius = zombieGraphics.width / 2 + 10;
		sparkle.x = Math.cos(angle) * radius;
		sparkle.y = Math.sin(angle) * radius;
		var lifetime = Math.random() * 400 + 200;
		var elapsed = 0;
		var interval = LK.setInterval(function () {
			elapsed += 16; // Assume 16ms per frame
			sparkle.y -= 0.5; // Subtle upward motion
			sparkle.alpha = Math.max(0, 1 - elapsed / lifetime); // Gradual fade-out
			if (elapsed >= lifetime) {
				LK.clearInterval(interval);
				self.removeChild(sparkle);
			}
		}, 16);
	}
	// Periodically emit sparkles
	LK.setInterval(emitStars, 300);
	// Add blood splashes
	function addBloodSplashes() {
		var isFinal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
		var count = isFinal ? 10 : 1;
		for (var i = 0; i < count; i++) {
			var bloodSplash = game.addChild(new BloodSplash(self.x, self.y, isFinal));
		}
	}
	// Update behavior
	self.update = function () {
		var dx = mishnu.x - self.x;
		var dy = mishnu.y - self.y;
		var distanceToMishnu = Math.sqrt(dx * dx + dy * dy);
		switch (self.state) {
			case 'roaming':
				// Wandering logic
				moveToTarget(self.targetX, self.targetY);
				// Enter Mishnu's radius
				if (distanceToMishnu < radius.radiusSize) {
					self.state = 'attacking';
					self.inRadiusStartTime = Date.now();
					// Play agony sound (1-in-3 chance)
					if (Math.random() < 1 / 2) {
						agonySound = getRandomSound(['GiggleMan_1', 'GiggleMan_2', 'GiggleMan_3', 'GiggleMan_4']);
						agonySound.volume = 0.3;
						agonySound.play();
					}
				}
				break;
			case 'attacking':
				// Attack logic
				moveToTarget(mishnu.x, mishnu.y, 1.5);
				if (distanceToMishnu < radius.radiusSize) {
					var elapsedTime = Date.now() - self.inRadiusStartTime;
					// Harvest if in radius for the required time
					if (elapsedTime >= self.harvestTime) {
						self.state = 'harvested';
						game.removeChild(self);
						zombies.splice(zombies.indexOf(self), 1);
						mishnu.humansHarvested += 2;
						// Play harvest sounds
						if (!harvestSoundPlayed) {
							LK.getSound('Ding_1').play();
							getRandomSound(['Squish_1', 'Squish_2', 'Squish_3', 'Squish_4']).play();
							harvestSoundPlayed = true;
						}
						addBloodSplashes(true);
						return;
					}
					// Attack Mishnu if close
					if (distanceToMishnu < 50 && Date.now() - self.lastAttackTime > self.attackCooldown) {
						globalHealthBar.setHealth(globalHealthBar.currentHealth - 1);
						self.lastAttackTime = Date.now();
						self.state = 'fleeing';
						// Set flee target
						var fleeAngle = Math.random() * Math.PI * 2;
						self.targetX = mishnu.x + Math.cos(fleeAngle) * (radius.radiusSize + 50);
						self.targetY = mishnu.y + Math.sin(fleeAngle) * (radius.radiusSize + 50);
						addBloodSplashes();
						// Flash grey mask on Mishnu, radius, and health bar
						flashGreyMask([mishnu, radius, globalHealthBar], 400, 3);
						LK.getSound('Hit').play(); // Play "Hit" sound
						LK.setTimeout(function () {
							LK.getSound('Bark').play(); // Play "Bark" sound
						}, 200); // Delay of 0.2 seconds
					}
				} else {
					// Outside radius, return to roaming
					self.state = 'roaming';
					setRandomTarget();
				}
				break;
			case 'fleeing':
				// Flee logic
				moveToTarget(self.targetX, self.targetY, 2);
				if (distanceToMishnu > radius.radiusSize + 50) {
					// Successfully fled, return to roaming
					self.state = 'roaming';
					setRandomTarget();
				} else if (distanceToMishnu < radius.radiusSize) {
					// If Mishnu keeps the zombie in the radius, reset harvest timer
					if (!self.inRadiusStartTime) {
						self.inRadiusStartTime = Date.now();
					}
					var elapsedTime = Date.now() - self.inRadiusStartTime;
					if (elapsedTime >= self.harvestTime) {
						self.state = 'harvested';
						game.removeChild(self);
						zombies.splice(zombies.indexOf(self), 1);
						mishnu.humansHarvested += 2;
						// Play harvest sounds
						if (!harvestSoundPlayed) {
							LK.getSound('Ding_1').play();
							getRandomSound(['Squish_1', 'Squish_2', 'Squish_3', 'Squish_4']).play();
							harvestSoundPlayed = true;
						}
						addBloodSplashes(true);
						return;
					}
				}
				break;
			case 'harvested':
				// Zombie is removed after harvesting
				break;
			default:
				console.error("Zombie in unknown state: ".concat(self.state));
				self.state = 'roaming';
				setRandomTarget();
				break;
		}
	};
	// Set initial target
	setRandomTarget();
	return self;
});
/**** 
* Initialize Game
****/ 
// Modify game logic to include zombie spawning
// Declare healthBar globally for accessibility
var game = new LK.Game({
	backgroundColor: 0x1d1d1d
});
/**** 
* Game Code
****/ 
// Booster spawning logic
// Booster spawning logic
// Declare healthBar globally for accessibility
// Modify game logic to include zombie spawning
var boosters = [];
function spawnBooster() {
	var booster = new Booster();
	boosters.push(booster);
	game.addChild(booster);
}
// Integrate boosters with Mishnu Snax increase
var uiLayer = new Container();
uiLayer.zIndex = 10; // Ensure it's above the background and mask
game.addChild(uiLayer);
var factory = uiLayer.addChild(new Factory());
var originalIncreaseDogFood = factory.startProcessing;
factory.startProcessing = function () {
	originalIncreaseDogFood.call(factory);
	spawnBooster(); // Spawn a booster every time dog food increases
};
// Mishnu pickup logic
function checkBoosterPickup() {
	boosters.forEach(function (booster) {
		var dx = booster.x - mishnu.x;
		var dy = booster.y - mishnu.y;
		if (Math.sqrt(dx * dx + dy * dy) < 50) {
			booster.pickUp();
			boosters.splice(boosters.indexOf(booster), 1);
		}
	});
}
// Add to game update loop
var originalGameUpdate = game.update;
game.update = function () {
	originalGameUpdate.call(this);
	boosters.forEach(function (booster) {
		booster.update();
	});
	checkBoosterPickup();
};
var globalHealthBar = new GlobalHealthBar(100, 100);
function spawnZombies(count, maxZombiesOnScreen) {
	for (var i = 0; i < count; i++) {
		if (zombies.length >= maxZombiesOnScreen) {
			break;
		}
		var spawnEdge = Math.floor(Math.random() * 3); // 0: top, 1: left, 2: right
		var spawnX, spawnY;
		switch (spawnEdge) {
			case 0:
				spawnX = Math.random() * 2048;
				spawnY = -50;
				break;
			case 1:
				spawnX = -50;
				spawnY = Math.random() * (2432 - 300);
				break;
			case 2:
				spawnX = 2048 + 50;
				spawnY = Math.random() * (2432 - 300);
				break;
		}
		var newZombie = new Zombie();
		newZombie.x = spawnX;
		newZombie.y = spawnY;
		zombies.push(newZombie);
		game.addChild(newZombie);
	}
}
// Initialize zombies
var zombies = [];
var zombieSpawnCooldown = 3000; // Time (ms) between zombie spawn attempts
var zombieSpawnElapsedTime = 0;
var maxZombiesOnScreen = 10;
// Update game loop to handle zombies
var originalGameUpdate = game.update;
game.update = function () {
	originalGameUpdate.call(this);
	// Update zombies
	zombies.forEach(function (zombie) {
		zombie.update();
	});
	// Spawn zombies if needed
	zombieSpawnElapsedTime += 16; // Assume 16ms per frame
	if (zombieSpawnElapsedTime >= zombieSpawnCooldown && zombies.length < maxZombiesOnScreen) {
		spawnZombies(1, maxZombiesOnScreen); // Spawn one zombie at a time
		zombieSpawnElapsedTime = 0;
	}
	// Ensure zombie count does not exceed maximum
	if (zombies.length > maxZombiesOnScreen) {
		while (zombies.length > maxZombiesOnScreen) {
			var zombieToRemove = zombies.pop();
			game.removeChild(zombieToRemove);
		}
	}
};
var isMusicPlaying = {
	'Music_Level_1_4': false,
	'Music_Level_1_5': false
};
// Update factory text
function updateFactoryText() {
	factoryText.setText("Level: " + factory.level + "\nMeat: " + factory.meat + "\nMishnu Snax: " + factory.dogFood + "\nNext level at: " + factory.nextLevelRequirement);
}
// Function to randomly select a sound from a list
;
// Add a UI layer to ensure factory is rendered above the background and mask
var uiLayer = new Container();
uiLayer.zIndex = 10; // Ensure it's above the background and mask
game.addChild(uiLayer);
// Create and position the health bar at the top center of the viewport
var globalHealthBar = new GlobalHealthBar(5, 5); // Initialize with initial and max health of 5
globalHealthBar.x = 1820; // Center horizontally
globalHealthBar.y = 2560; // Position at the top center
// Add text label 'Health' above the global health bar
var healthLabel = new Text2('Health', {
	size: 50,
	fill: 0xFFFFFF
});
healthLabel.anchor.set(0.5, 1);
healthLabel.x = globalHealthBar.x;
healthLabel.y = globalHealthBar.y - 60; // Position above the health bar
uiLayer.addChild(healthLabel);
uiLayer.addChild(globalHealthBar); // Add to the UI layer to ensure visibility
// Add the factory to the UI layer
var factory = uiLayer.addChild(new Factory());
// Initialize factory text
var factoryText = new Text2('Meat: 0\nMishnu Snax: 0\nNext level at: ', {
	size: 50,
	fill: 0xFFFFFF,
	align: 'left'
});
factoryText.anchor.set(0, 1);
LK.gui.bottomLeft.addChild(factoryText);
var nextLevel = 100; // Placeholder for next level goal
// Function to randomly spawn a human at the edges of the viewport
function spawnHumans(count, maxHumansOnScreen) {
	for (var i = 0; i < count; i++) {
		// Ensure we don't exceed maxHumansOnScreen
		if (humans.length >= maxHumansOnScreen) {
			break;
		}
		// Randomly select a spawn edge (excluding the bottom)
		var spawnEdge = Math.floor(Math.random() * 3); // 0: top, 1: left, 2: right
		var spawnX, spawnY;
		switch (spawnEdge) {
			case 0:
				// Top
				spawnX = Math.random() * 2048;
				spawnY = -50; // Just outside the top boundary
				break;
			case 1:
				// Left
				spawnX = -50; // Just outside the left boundary
				spawnY = Math.random() * (2432 - 300); // Exclude bottom UI area
				break;
			case 2:
				// Right
				spawnX = 2048 + 50; // Just outside the right boundary
				spawnY = Math.random() * (2432 - 300); // Exclude bottom UI area
				break;
		}
		// Create a new human and add it to the game
		var newHuman = new Human();
		newHuman.x = spawnX;
		newHuman.y = spawnY;
		humans.push(newHuman);
		game.addChild(newHuman);
	}
}
// Update game loop
var originalUpdate = game.update;
game.update = function () {
	originalUpdate.call(this);
	// Update factory
	factory.update();
	// Check for level progression
	if (factory.dogFood >= nextLevel) {
		// Handle level progression logic here
		nextLevel += 100; // Example: increase next level goal
		updateFactoryText();
	}
};
function flashGreyMask(targets, duration, flashes) {
	var flashInterval = duration / (flashes * 2); // Time for each flash on/off
	var flashCount = 0;
	var interval = LK.setInterval(function () {
		if (flashCount >= flashes * 2) {
			// End the flashing effect
			targets.forEach(function (target) {
				if (target && typeof target.tint !== 'undefined') {
					target.tint = 0xFFFFFF;
				}
			}); // Reset tint
			LK.clearInterval(interval);
		} else {
			var isOn = flashCount % 2 === 0; // Toggle between grey and normal
			var tintColor = isOn ? 0x808080 : 0xFFFFFF; // Grey tint or original
			targets.forEach(function (target) {
				if (target && typeof target.tint !== 'undefined') {
					target.tint = tintColor;
				}
			}); // Apply tint
			flashCount++;
		}
	}, flashInterval);
}
function getRandomSound(soundList) {
	return LK.getSound(soundList[Math.floor(Math.random() * soundList.length)]);
}
// Function to fade out a sound
function fadeOutSound(sound, duration) {
	var initialVolume = sound.volume;
	var fadeStep = initialVolume / (duration / 100);
	var fadeInterval = LK.setInterval(function () {
		if (sound.volume > 0) {
			sound.volume = Math.max(0, sound.volume - fadeStep);
		} else {
			LK.clearInterval(fadeInterval);
			sound.stop();
		}
	}, 100);
}
var radius = game.addChild(new HarvestRadius());
var mishnu = game.addChild(new Mishnu());
mishnu.x = 2048 / 2;
mishnu.y = 2432 - 200;
radius.x = mishnu.x;
radius.y = mishnu.y;
// Initialize humans
var humans = [];
for (var i = 0; i < 50; i++) {
	var human = new Human();
	human.x = Math.random() * 2048;
	human.y = Math.random() * (2432 - 100);
	humans.push(human);
	game.addChild(human);
	var humansSpawnedThisLevel = 0; // Tracks how many humans have spawned in the current level
	var humanSpawnLimit = factory.nextLevelRequirement * 7; // Set minimum spawn limit to nextLevelRequirement * 7 
}
var spawnCooldown = 20; // Reduced time (in ms) between spawn attempts for faster spawning
var spawnElapsedTime = 0; // Tracks time elapsed since the last spawn attempt
// Play looping Dog Panting sound
LK.getSound('Dog_panting').play({
	loop: true
});
// Handle mouse movement
game.move = function (x, y, obj) {
	mishnu.targetX = x;
	mishnu.targetY = y;
};
// Display cargo count
var cargoText = new Text2('Cargo: 0 / 10', {
	size: 50,
	fill: 0xFFFFFF
});
cargoText.anchor.set(1, 1);
LK.gui.bottomRight.addChild(cargoText);
// Music alternation logic
var currentMusic = 'Music_Level_1_5';
game.update = function () {
	humans.forEach(function (human) {
		human.update();
	});
	mishnu.update();
	zombies.forEach(function (zombie) {
		zombie.update();
	});
	radius.update();
	boosters.forEach(function (booster) {
		booster.update();
	});
	checkBoosterPickup();
	// Calculate dynamic minimum and maximum humans on screen
	var minHumansOnScreen = Math.max((factory.nextLevelRequirement - factory.dogFood) * 7, 20); // Ensure a minimum of 20
	var maxHumansOnScreen = Math.ceil(minHumansOnScreen * 1.5); // Scale max to 150% of min
	// Ensure minimum number of humans on screen
	if (humans.length < minHumansOnScreen) {
		spawnElapsedTime += 16; // Assume 16ms per frame
		if (spawnElapsedTime >= spawnCooldown) {
			spawnHumans(minHumansOnScreen - humans.length, maxHumansOnScreen); // Pass the maxHumansOnScreen value
			spawnElapsedTime = 0; // Reset spawn elapsed time
		}
	}
	// Cap the number of humans to maxHumansOnScreen
	if (humans.length > maxHumansOnScreen) {
		// Remove excess humans from the game
		while (humans.length > maxHumansOnScreen) {
			var humanToRemove = humans.pop();
			game.removeChild(humanToRemove);
		}
	}
	// Update cargo text
	var textColor = mishnu.humansHarvested > mishnu.cargoMax ? 0xFF0000 : 0xFFFFFF;
	if (cargoText.fill !== textColor) {
		LK.gui.bottomRight.removeChild(cargoText);
		cargoText = new Text2('Cargo: ' + mishnu.humansHarvested + ' / ' + mishnu.cargoMax, {
			size: 50,
			fill: textColor
		});
		cargoText.anchor.set(1, 1);
		LK.gui.bottomRight.addChild(cargoText);
	} else {
		cargoText.setText('Cargo: ' + mishnu.humansHarvested + ' / ' + mishnu.cargoMax);
	}
	// Play Music_Level_1_4 in a loop
	if (!isMusicPlaying['Music_Level_1_4']) {
		LK.playMusic('Music_Level_1_4', {
			loop: true
		});
		isMusicPlaying['Music_Level_1_4'] = true; // Track music state
	}
	// Play Music_Level_1_5 in a loop
	if (!isMusicPlaying['Music_Level_1_5']) {
		LK.playMusic('Music_Level_1_5', {
			loop: true
		});
		isMusicPlaying['Music_Level_1_5'] = true; // Track music state
	}
	// Update factory
	factory.update();
}; ===================================================================
--- original.js
+++ change.js
@@ -79,11 +79,12 @@
 	});
 	// Start position (bottom-middle of the screen)
 	self.x = 2048 / 2;
 	self.y = 2432 - 200;
-	// Target position (random on the screen)
-	var targetX = Math.random() * 2048;
-	var targetY = Math.random() * (2432 - 300);
+	// Target position (random on the screen with boundaries)
+	var margin = 150; // Boundary margin for safe landing
+	var targetX = margin + Math.random() * (2048 - 2 * margin);
+	var targetY = margin + Math.random() * (2432 - 300 - 2 * margin);
 	// Rotation and sparkle effects
 	var rotationSpeed = 0.01;
 	function emitSparkles() {
 		var angle = Math.random() * Math.PI * 2; // Random angle around the booster
@@ -148,24 +149,25 @@
 			align: 'center'
 		});
 		floatingText.anchor.set(0.5, 0.5);
 		// Set initial position (higher above booster)
-		canvas.x = self.x;
-		canvas.y = self.y - 100; // Higher spawn point
+		var textYOffset = 150; // Higher spawn point
+		canvas.x = 2048 / 2;
+		canvas.y = 2732 / 2;
 		floatingText.x = canvas.x;
 		floatingText.y = canvas.y;
 		game.addChild(canvas); // Add canvas first for layering
 		game.addChild(floatingText); // Add text on top
 		// Animate text and canvas together
 		var elapsed = 0;
-		var duration = 1000; // 1 second
+		var textDuration = 1000; // 1 second
 		var fadeInterval = LK.setInterval(function () {
 			elapsed += 16;
 			canvas.y -= 1.5; // Move upward slightly faster
 			floatingText.y -= 1.5;
-			canvas.alpha = Math.max(0, 1 - elapsed / duration); // Fade out
-			floatingText.alpha = Math.max(0, 1 - elapsed / duration); // Fade out
-			if (elapsed >= duration) {
+			canvas.alpha = Math.max(0, 1 - elapsed / textDuration); // Fade out
+			floatingText.alpha = Math.max(0, 1 - elapsed / textDuration); // Fade out
+			if (elapsed >= textDuration) {
 				LK.clearInterval(fadeInterval);
 				game.removeChild(canvas);
 				game.removeChild(floatingText);
 			}
@@ -763,12 +765,12 @@
 
 /**** 
 * Game Code
 ****/ 
-// Modify game logic to include zombie spawning
-// Declare healthBar globally for accessibility
 // Booster spawning logic
 // Booster spawning logic
+// Declare healthBar globally for accessibility
+// Modify game logic to include zombie spawning
 var boosters = [];
 function spawnBooster() {
 	var booster = new Booster();
 	boosters.push(booster);
:quality(85)/https://cdn.frvr.ai/67931b63cc7b408db741b640.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6793257acc7b408db741b67f.png%3F3) 
 blurry texture background 4k black and white
:quality(85)/https://cdn.frvr.ai/67940b273e37286b7983d505.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6794359a3e37286b7983d6a4.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67951abd3e37286b7983d840.png%3F3) 
 can of Dog Food. Game asset. 3d clipart. Blank background. High contrast. No shadows..
:quality(85)/https://cdn.frvr.ai/679521c13e37286b7983d863.png%3F3) 
 black capsule. Game asset. 3d clipart. Blank background. High contrast. No shadows..
:quality(85)/https://cdn.frvr.ai/6795ad3fd63d184aa47a9eb4.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6796df81690fa8a090669abd.png%3F3) 
 woman in short shorts. mobile game art. pixel art. full body. front facing. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6797c2cd2e20f9214f6db0f9.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6797c4512e20f9214f6db110.png%3F3) 
 laser beam cartoon game asset. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6797f7e2f6fe7a86a4b91b59.png%3F3) 
 bone. clipart. cartoon. Blank background. High contrast. No shadows..
:quality(85)/https://cdn.frvr.ai/6797f91bf6fe7a86a4b91b87.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67986eed43c5680ce8057f5e.png%3F3) 
 Game Over. Red game letters, dripping. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/67c96bde9febb78ebd21db3e.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67c9788bb2f53263695b0230.png%3F3) 
 Dog_panting
Sound effect
Agony_Yell_1
Sound effect
Music_Level_1_5
Music
Music_Level_1_4
Music
Agony_Yell_2
Sound effect
Agony_Yell_3
Sound effect
Agony_Yell_4
Sound effect
Agony_Yell_5
Sound effect
Agony_Yell_6
Sound effect
Agony_Yell_7
Sound effect
Dog_Crunch
Sound effect
Dog_Crunch_2
Sound effect
Dog_Crunch_3
Sound effect
Ding_1
Sound effect
Squish_1
Sound effect
Squish_2
Sound effect
Squish_4
Sound effect
Squish_3
Sound effect
Factory_Deposit
Sound effect
Factory_Operation
Sound effect
Level_Up
Sound effect
Bark
Sound effect
Hit
Sound effect
Agony_Yell_8
Sound effect
Agony_Yell_9
Sound effect
GiggleMan_1
Sound effect
GiggleMan_2
Sound effect
GiggleMan_3
Sound effect
GiggleMan_4
Sound effect
Booster_Sound
Sound effect
Can
Sound effect
woosh
Sound effect
Agony_Yell_10
Sound effect
Bark_2
Sound effect
Bark_3
Sound effect
laser
Sound effect
searing
Sound effect
laser_2
Sound effect
Laser_3
Sound effect
Laser_4
Sound effect
Boss_Hit
Sound effect
Boss_Hit_2
Sound effect
Boss_Hit_3
Sound effect
GiggleMan_5
Sound effect
GiggleMan_6
Sound effect
hip_hop_loop
Sound effect