/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigRottenMeat = Container.expand(function () {
var self = Container.call(this);
var meatGraphics = self.attachAsset('rottenMeat', {
anchorX: 0.5,
anchorY: 0.5
});
meatGraphics.scaleX = 2; // Bigger meat
meatGraphics.scaleY = 2;
meatGraphics.tint = 0x00AA00; // Different color
self.lifetime = 300; // 5 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Big bounce effect
var bounce = Math.sin(LK.ticks * 0.1) * 4;
meatGraphics.y = bounce;
};
return self;
});
var BigZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('Big-zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.scaleX = 2.5; // Much bigger than other zombies
zombieGraphics.scaleY = 2.5;
zombieGraphics.tint = 0x4B0082; // Dark purple color for big zombie
self.speed = 0.2; // Very slow movement
self.targetX = 0;
self.targetY = 0;
self.knifeHits = 0; // Track knife hits
self.maxKnifeHits = 5; // Dies after 5 knife hits
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function () {
self.knifeHits++;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.knifeHits >= self.maxKnifeHits) {
return true; // Dies
}
return false; // Still alive
};
return self;
});
var BigZombieNoAI = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('Big-zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.scaleX = 2.5;
zombieGraphics.scaleY = 2.5;
zombieGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function - stationary
return self;
});
var BloodZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x8B0000; // Blood red color
zombieGraphics.scaleX = 1.2;
zombieGraphics.scaleY = 1.2;
self.speed = 2; // Fast when activated
self.targetX = 0;
self.targetY = 0;
self.isActive = false; // Start inactive
self.activate = function () {
self.isActive = true;
self.targetX = player.x;
self.targetY = player.y;
};
self.update = function () {
if (self.isActive) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
};
return self;
});
var BossZombie = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('King-Zombie', {
anchorX: 0.5,
anchorY: 0.5
});
bossGraphics.scaleX = 8; // Massive boss zombie
bossGraphics.scaleY = 8;
bossGraphics.tint = 0x8B0000; // Dark red for boss
self.speed = 0.5; // Slow but deadly
self.targetX = 0;
self.targetY = 0;
self.bulletHits = 0; // Track bullet hits only
self.maxBulletHits = 120; // Dies after 120 bullet hits only
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (type) {
if (type === 'bullet') {
self.bulletHits++;
}
LK.effects.flashObject(self, 0xff0000, 300);
if (self.bulletHits >= self.maxBulletHits) {
return true; // Boss dies
}
return false; // Boss still alive
};
return self;
});
var ChickenJockey = Container.expand(function () {
var self = Container.call(this);
var chickenGraphics = self.attachAsset('Chicken-Jockey', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3; // Faster than zombies
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var ChickenJockeyNoAI = Container.expand(function () {
var self = Container.call(this);
var chickenGraphics = self.attachAsset('Chicken-Jockey', {
anchorX: 0.5,
anchorY: 0.5
});
chickenGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function - stationary
return self;
});
var GreenZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x00FF00; // Green color
zombieGraphics.scaleX = 1.5; // Bigger and stronger
zombieGraphics.scaleY = 1.5;
self.speed = 0.5; // Slow movement
self.targetX = 0;
self.targetY = 0;
self.knifeHits = 0; // Track knife hits
self.maxKnifeHits = 5; // Dies after 5 knife hits
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function () {
self.knifeHits++;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.knifeHits >= self.maxKnifeHits) {
return true; // Dies
}
return false; // Still alive
};
return self;
});
var GroundKnife = Container.expand(function () {
var self = Container.call(this);
var knifeGraphics = self.attachAsset('knife', {
anchorX: 0.5,
anchorY: 0.5
});
knifeGraphics.tint = 0xFF0000; // Blood red knife
// Pulse effect
self.update = function () {
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
knifeGraphics.scaleX = scale;
knifeGraphics.scaleY = scale;
};
return self;
});
var House = Container.expand(function () {
var self = Container.call(this);
var houseGraphics = self.attachAsset('house', {
anchorX: 0.5,
anchorY: 1.0
});
self.safeRadius = 200; // Safe zone around house
return self;
});
var KingZombie = Container.expand(function () {
var self = Container.call(this);
var kingGraphics = self.attachAsset('King-Zombie', {
anchorX: 0.5,
anchorY: 0.5
});
kingGraphics.scaleX = 3; // Larger than other zombies
kingGraphics.scaleY = 3;
kingGraphics.tint = 0x8B008B; // Dark magenta for royalty
self.commandTimer = 0; // Timer for commanding zombies
self.commandCooldown = 300; // 5 seconds between commands
self.health = 50; // King zombies now have health
self.maxHealth = 50;
self.update = function () {
self.commandTimer++;
if (self.commandTimer >= self.commandCooldown) {
self.commandTimer = 0;
// Gather zombies around the king
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < 300) {
// Within command range
// Make zombie come to king and wait
zombie.targetX = self.x + (Math.random() - 0.5) * 100;
zombie.targetY = self.y + (Math.random() - 0.5) * 100;
// After 3 seconds, send them back to attack player
LK.setTimeout(function (zombie) {
if (zombie && zombie.parent) {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
}.bind(null, zombie), 3000);
}
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
return true; // King zombie dies
}
return false; // Still alive
};
return self;
});
var KingZombieNoAI = Container.expand(function () {
var self = Container.call(this);
var kingGraphics = self.attachAsset('King-Zombie', {
anchorX: 0.5,
anchorY: 0.5
});
kingGraphics.scaleX = 3;
kingGraphics.scaleY = 3;
kingGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function and no commands
return self;
});
var Lightning = Container.expand(function () {
var self = Container.call(this);
var lightningGraphics = self.attachAsset('lightning', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 10; // Very short flash
lightningGraphics.alpha = 0.8;
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
};
return self;
});
var Pistol = Container.expand(function () {
var self = Container.call(this);
var pistolGraphics = self.attachAsset('pistol', {
anchorX: 0.5,
anchorY: 0.5
});
self.ammo = 30;
self.lifetime = 300; // 5 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Small rotation animation
pistolGraphics.rotation += 0.02;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 1.0;
self.shielded = false;
self.shieldTime = 0;
self.hasKnife = false;
self.knifeUses = 0;
self.update = function () {
if (self.shielded) {
self.shieldTime--;
if (self.shieldTime <= 0) {
self.shielded = false;
playerGraphics.tint = 0xFFFFFF;
}
}
};
self.takeDamage = function (amount) {
if (immortalMode) return; // Immortal mode blocks all damage
if (!self.shielded) {
self.health -= amount;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0xff0000, 500);
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
}
};
self.activateShield = function () {
self.shielded = true;
self.shieldTime = 300; // 5 seconds at 60fps
playerGraphics.tint = 0x00FFFF;
};
self.activateKnife = function () {
self.hasKnife = true;
self.knifeUses = 5;
playerGraphics.tint = 0xFFFF00;
};
self.useKnife = function () {
if (self.hasKnife && self.knifeUses > 0) {
if (!infiniteKnife) {
self.knifeUses--;
}
LK.getSound('knife').play();
if (self.knifeUses <= 0 && !infiniteKnife) {
self.hasKnife = false;
playerGraphics.tint = 0xFFFFFF;
}
return true;
}
return false;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.tint = 0x00FF00; // Green bullets for player
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 120; // 2 seconds at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = type;
self.lifetime = 600; // 10 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Pulse effect
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
powerUpGraphics.scaleX = scale;
powerUpGraphics.scaleY = scale;
};
return self;
});
var Raindrop = Container.expand(function () {
var self = Container.call(this);
var dropGraphics = self.attachAsset('raindrop', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8 + Math.random() * 4;
self.update = function () {
self.y += self.speed;
// Remove when off screen
if (self.y > 2800) {
self.destroy();
}
};
return self;
});
var RottenMeat = Container.expand(function () {
var self = Container.call(this);
var meatGraphics = self.attachAsset('rottenMeat', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 300; // 5 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Small bounce effect
var bounce = Math.sin(LK.ticks * 0.1) * 2;
meatGraphics.y = bounce;
};
return self;
});
var Soldier = Container.expand(function () {
var self = Container.call(this);
var soldierGraphics = self.attachAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.shootTimer = 0;
self.shootCooldown = 60; // 1 second at 60fps
self.range = 300;
self.update = function () {
self.shootTimer--;
if (self.shootTimer <= 0) {
// Find closest zombie within range
var closestZombie = null;
var closestDistance = Infinity;
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < self.range && distance < closestDistance) {
closestDistance = distance;
closestZombie = zombie;
}
}
if (closestZombie) {
// Shoot at zombie
var bullet = new SoldierBullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = closestZombie.x - self.x;
var dy = closestZombie.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 8;
bullet.velocityY = dy / distance * 8;
}
soldierBullets.push(bullet);
game.addChild(bullet);
LK.getSound('gunshot').play();
self.shootTimer = self.shootCooldown;
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.destroy();
}
};
return self;
});
var SoldierBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 180; // 3 seconds at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
}
};
return self;
});
var StrongZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x8B0000; // Dark red color for strong zombie
zombieGraphics.scaleX = 1.8; // Bigger and more muscular
zombieGraphics.scaleY = 1.8;
self.speed = 0.3; // Very slow movement
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var Tank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('tank', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.targetX = 1024;
self.targetY = 1366;
self.crushRadius = 80;
self.update = function () {
// Move towards center of map
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Crush zombies
for (var z = zombies.length - 1; z >= 0; z--) {
var zombie = zombies[z];
var zombieDistance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (zombieDistance < self.crushRadius) {
LK.setScore(LK.getScore() + 15);
dropRottenMeat(zombie.x, zombie.y);
zombie.destroy();
zombies.splice(z, 1);
}
}
// Check collision with big zombies - tank gets destroyed
for (var bz = 0; bz < bigZombies.length; bz++) {
var bigZombie = bigZombies[bz];
var bigZombieDistance = Math.sqrt(Math.pow(bigZombie.x - self.x, 2) + Math.pow(bigZombie.y - self.y, 2));
if (bigZombieDistance < self.crushRadius) {
// Tank gets destroyed when hitting big zombie
self.destroy();
break;
}
}
};
return self;
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
});
self.isOnFire = false;
self.fireTime = 0;
self.strikeWithLightning = function () {
self.isOnFire = true;
self.fireTime = 300; // 5 seconds at 60fps
treeGraphics.tint = 0xFF4500; // Orange fire color
LK.getSound('lightning').play();
LK.effects.flashObject(self, 0xFFFF00, 200);
};
self.update = function () {
if (self.isOnFire) {
self.fireTime--;
if (self.fireTime <= 0) {
self.isOnFire = false;
treeGraphics.tint = 0xFFFFFF;
}
}
};
return self;
});
var TreeNoAI = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
});
treeGraphics.tint = 0x808080; // Gray color to indicate no AI
// No lightning strike functionality
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var ZombieNoAI = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function - stationary
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E7D32
});
/****
* Game Code
****/
game.setBackgroundColor(0x1B5E20);
var player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
var zombies = [];
var powerUps = [];
var rottenMeats = [];
var houses = [];
var trees = [];
var raindrops = [];
var lightnings = [];
var soldiers = [];
var soldierBullets = [];
var playerBullets = [];
var pistols = [];
var tank = null;
var tankSpawnTimer = 3600; // 1 minute at 60fps
var dragNode = null;
var playerHasPistol = false;
var playerAmmo = 0;
var survivalTime = 0;
var meatCollected = 0;
var hungerLevel = 10; // Start with full hunger
var maxHunger = 10;
var hungerTimer = 0;
var hungerDamageTimer = 0;
var greenZombies = [];
var strongZombies = [];
var bigZombies = [];
var bloodZombies = [];
var groundKnife = null;
var horrorMode = false;
var levelHackCount = 0;
var safeZoneRadius = 200;
var zombieSpawnRate = 120; // Start spawning every 2 seconds
var minZombieSpawnRate = 30; // Fastest spawn rate
var zombieSpeed = 1;
var maxZombieSpeed = 4;
var isRaining = false;
var rainTimer = 0;
var lightningTimer = 0;
var currentLevel = 1;
var levelCompleted = false;
var showingLevelComplete = false;
var levelCompleteMessage = null;
var levelContinueButton = null;
// Cheat system variables
var immortalMode = false;
var levelHackButton = null;
var adminMode = false;
var gameBlocked = false;
var hackMenuVisible = false;
var hackButton = null;
var hackMenuButtons = [];
var zombiesKilled = false;
var rainDeleted = false;
var adminHackCount = 0;
var adminHackButtons = [];
var adminHackVisible = false;
var infiniteKnife = false;
var chickenJockies = [];
var kingZombies = [];
var bossMode = false;
var bossZombie = null;
var bossMessage = null;
var rainToggleEnabled = false;
var zombieSlowEnabled = false;
// UI Elements
var healthTxt = new Text2('Health: 100', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthTxt);
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var timeTxt = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(timeTxt);
var knifeTxt = new Text2('', {
size: 60,
fill: 0xFFFF00
});
knifeTxt.anchor.set(0, 0);
knifeTxt.y = 260; // Position below meat counter
LK.gui.topLeft.addChild(knifeTxt);
var hungerTxt = new Text2('Hunger: 10/10', {
size: 60,
fill: 0x00FF00
});
hungerTxt.anchor.set(0, 0);
hungerTxt.y = 140; // Position below health
LK.gui.topLeft.addChild(hungerTxt);
var meatTxt = new Text2('Meat: 0', {
size: 60,
fill: 0x8B4513
});
meatTxt.anchor.set(0, 0);
meatTxt.y = 200; // Position below hunger bar
LK.gui.topLeft.addChild(meatTxt);
var ammoTxt = new Text2('', {
size: 60,
fill: 0x00FF00
});
ammoTxt.anchor.set(0, 0);
ammoTxt.y = 320; // Position below knife counter
LK.gui.topLeft.addChild(ammoTxt);
// Create hack button
hackButton = new Text2('HACK', {
size: 50,
fill: 0xFF00FF
});
hackButton.anchor.set(1, 0);
hackButton.y = 200;
LK.gui.topRight.addChild(hackButton);
// Create rewind button
var rewindButton = new Text2('REWIND', {
size: 50,
fill: 0x00FFFF
});
rewindButton.anchor.set(1, 0);
rewindButton.y = 260;
LK.gui.topRight.addChild(rewindButton);
// Create rain toggle button
var rainToggleButton = new Text2('Rain: OFF', {
size: 50,
fill: 0x00AAFF
});
rainToggleButton.anchor.set(1, 0);
rainToggleButton.y = 320;
LK.gui.topRight.addChild(rainToggleButton);
// Create zombie slow button
var zombieSlowButton = new Text2('Zombie Speed: Normal', {
size: 50,
fill: 0xFFAA00
});
zombieSlowButton.anchor.set(1, 0);
zombieSlowButton.y = 380;
LK.gui.topRight.addChild(zombieSlowButton);
// Rewind button functionality
rewindButton.down = function () {
if (gameBlocked) return;
// Reset the entire game
resetGame();
};
// Rain toggle button functionality
rainToggleButton.down = function () {
if (gameBlocked) return;
rainToggleEnabled = !rainToggleEnabled;
if (rainToggleEnabled) {
rainToggleButton.setText('Rain: OFF');
rainToggleButton.fill = 0xFF0000;
// Stop current rain
isRaining = false;
rainTimer = 0;
// Remove all existing raindrops
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
} else {
rainToggleButton.setText('Rain: ON');
rainToggleButton.fill = 0x00AAFF;
}
};
// Zombie slow button functionality
zombieSlowButton.down = function () {
if (gameBlocked) return;
zombieSlowEnabled = !zombieSlowEnabled;
if (zombieSlowEnabled) {
zombieSlowButton.setText('Zombie Speed: Slow');
zombieSlowButton.fill = 0x00FF00;
// Slow down all existing zombies
for (var z = 0; z < zombies.length; z++) {
zombies[z].speed = 0.3; // Level 1 speed
}
for (var gz = 0; gz < greenZombies.length; gz++) {
greenZombies[gz].speed = 0.3;
}
for (var sz = 0; sz < strongZombies.length; sz++) {
strongZombies[sz].speed = 0.3;
}
for (var bz = 0; bz < bigZombies.length; bz++) {
bigZombies[bz].speed = 0.3;
}
for (var cj = 0; cj < chickenJockies.length; cj++) {
chickenJockies[cj].speed = 0.3;
}
} else {
zombieSlowButton.setText('Zombie Speed: Normal');
zombieSlowButton.fill = 0xFFAA00;
}
};
function clearAllGameObjects() {
// Destroy all game objects
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
greenZombies[gz].destroy();
}
greenZombies = [];
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
strongZombies[sz].destroy();
}
strongZombies = [];
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
for (var p = powerUps.length - 1; p >= 0; p--) {
powerUps[p].destroy();
}
powerUps = [];
for (var m = rottenMeats.length - 1; m >= 0; m--) {
rottenMeats[m].destroy();
}
rottenMeats = [];
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var t = trees.length - 1; t >= 0; t--) {
trees[t].destroy();
}
trees = [];
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
for (var l = lightnings.length - 1; l >= 0; l--) {
lightnings[l].destroy();
}
lightnings = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
playerBullets[pb].destroy();
}
playerBullets = [];
for (var pi = pistols.length - 1; pi >= 0; pi--) {
pistols[pi].destroy();
}
pistols = [];
if (tank) {
tank.destroy();
tank = null;
}
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
}
chickenJockies = [];
for (var kz = kingZombies.length - 1; kz >= 0; kz--) {
kingZombies[kz].destroy();
}
kingZombies = [];
if (bossZombie) {
bossZombie.destroy();
bossZombie = null;
}
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
bossMode = false;
}
function resetGame() {
// Destroy all game objects except keeping meat count
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
greenZombies[gz].destroy();
}
greenZombies = [];
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
strongZombies[sz].destroy();
}
strongZombies = [];
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
for (var p = powerUps.length - 1; p >= 0; p--) {
powerUps[p].destroy();
}
powerUps = [];
for (var m = rottenMeats.length - 1; m >= 0; m--) {
rottenMeats[m].destroy();
}
rottenMeats = [];
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var t = trees.length - 1; t >= 0; t--) {
trees[t].destroy();
}
trees = [];
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
for (var l = lightnings.length - 1; l >= 0; l--) {
lightnings[l].destroy();
}
lightnings = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
playerBullets[pb].destroy();
}
playerBullets = [];
for (var pi = pistols.length - 1; pi >= 0; pi--) {
pistols[pi].destroy();
}
pistols = [];
if (tank) {
tank.destroy();
tank = null;
}
// Reset player
player.x = 1024;
player.y = 1366;
player.health = 100;
player.hasKnife = false;
player.knifeUses = 0;
player.shielded = false;
player.speed = 1.0;
// Reset all game variables except meatCollected
currentLevel = 1;
levelCompleted = false;
showingLevelComplete = false;
survivalTime = 0;
safeZoneRadius = 200;
zombieSpawnRate = 120;
zombieSpeed = 1;
tankSpawnTimer = 3600;
playerHasPistol = false;
playerAmmo = 0;
isRaining = false;
rainTimer = 0;
lightningTimer = 0;
hungerLevel = 10;
hungerTimer = 0;
hungerDamageTimer = 0;
horrorMode = false;
levelHackCount = 0;
zombiesKilled = false;
rainDeleted = false;
adminHackCount = 0;
adminHackVisible = false;
infiniteKnife = false;
rainToggleEnabled = false;
zombieSlowEnabled = false;
// Reset button states
rainToggleButton.setText('Rain: OFF');
rainToggleButton.fill = 0x00AAFF;
zombieSlowButton.setText('Zombie Speed: Normal');
zombieSlowButton.fill = 0xFFAA00;
// Clean up admin hack buttons
for (var ahb = adminHackButtons.length - 1; ahb >= 0; ahb--) {
adminHackButtons[ahb].destroy();
}
adminHackButtons = [];
for (var bz = bloodZombies.length - 1; bz >= 0; bz--) {
bloodZombies[bz].destroy();
}
bloodZombies = [];
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
}
chickenJockies = [];
for (var kz = kingZombies.length - 1; kz >= 0; kz--) {
kingZombies[kz].destroy();
}
kingZombies = [];
if (groundKnife) {
groundKnife.destroy();
groundKnife = null;
}
if (bossZombie) {
bossZombie.destroy();
bossZombie = null;
}
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
bossMode = false;
// Reset score
LK.setScore(0);
// Spawn initial house and soldiers
spawnHouse();
spawnSoldiers();
// Spawn initial trees
for (var t = 0; t < 8; t++) {
spawnTree();
}
}
// Hack button functionality
hackButton.down = function () {
if (gameBlocked) return;
hackMenuVisible = !hackMenuVisible;
if (hackMenuVisible) {
showHackMenu();
} else {
hideHackMenu();
}
};
// Show hack menu function
function showHackMenu() {
var cheatNames = ['/Immortality', '/Finish the Game', '/Admin', '/Level Hack', '/Kill Zombies and Big Zombies', '/Delete Rain', 'BOSS FIGHT!'];
var colors = [0x00FF00, 0xFF0000, 0xFF8800, 0x8800FF, 0xFF00FF, 0x00FFFF, 0xFF0000];
for (var i = 0; i < cheatNames.length; i++) {
var button = new Text2(cheatNames[i], {
size: 60,
fill: colors[i]
});
button.anchor.set(0.5, 0.5);
button.x = 0;
button.y = -250 + i * 80;
button.cheatType = cheatNames[i].toLowerCase();
button.down = function () {
if (gameBlocked) return;
executeCheat(this.cheatType);
hideHackMenu();
};
hackMenuButtons.push(button);
LK.gui.center.addChild(button);
}
}
// Hide hack menu function
function hideHackMenu() {
for (var i = hackMenuButtons.length - 1; i >= 0; i--) {
hackMenuButtons[i].destroy();
}
hackMenuButtons = [];
hackMenuVisible = false;
}
// Show admin hack menu function
function showAdminHacks() {
var adminCheatNames = ['/level 999', '/give knife', '/summon zombie', '/summon zombie no AI', '/summon big zombie', '/summon big zombie no AI', '/summon tree no AI', '/summon chicken jockey', '/summon King Zombie', '/summon King Zombie no AI', '/Horror Mode!!'];
var adminColors = [0xFF00FF, 0x00FF00, 0xFF0000, 0x808080, 0x8B0000, 0x404040, 0x228B22, 0xFFFF00, 0x8B008B, 0x404040, 0x8B0000];
for (var i = 0; i < adminCheatNames.length; i++) {
var button = new Text2('Admin Hack ' + (i + 1) + ' : ' + adminCheatNames[i], {
size: 50,
fill: adminColors[i]
});
button.anchor.set(0, 1);
button.x = 120;
button.y = -100 - i * 60; // Stack above Level Hack button
button.adminCheatType = adminCheatNames[i].toLowerCase();
button.down = function () {
if (gameBlocked) return;
executeAdminCheat(this.adminCheatType);
};
adminHackButtons.push(button);
LK.gui.bottomLeft.addChild(button);
}
}
// Execute admin cheat function
function executeAdminCheat(cheatType) {
switch (cheatType) {
case '/level 999':
currentLevel = 999;
break;
case '/give knife':
infiniteKnife = true;
player.hasKnife = true;
player.knifeUses = 999;
break;
case '/summon zombie':
var zombie = new Zombie();
zombie.x = player.x + (Math.random() - 0.5) * 200;
zombie.y = player.y + (Math.random() - 0.5) * 200;
zombie.targetX = player.x;
zombie.targetY = player.y;
zombies.push(zombie);
game.addChild(zombie);
break;
case '/summon zombie no ai':
var zombieNoAI = new ZombieNoAI();
zombieNoAI.x = player.x + (Math.random() - 0.5) * 200;
zombieNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(zombieNoAI);
break;
case '/summon big zombie':
var bigZombie = new BigZombie();
bigZombie.x = player.x + (Math.random() - 0.5) * 200;
bigZombie.y = player.y + (Math.random() - 0.5) * 200;
bigZombie.targetX = player.x;
bigZombie.targetY = player.y;
bigZombies.push(bigZombie);
game.addChild(bigZombie);
break;
case '/summon big zombie no ai':
var bigZombieNoAI = new BigZombieNoAI();
bigZombieNoAI.x = player.x + (Math.random() - 0.5) * 200;
bigZombieNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(bigZombieNoAI);
break;
case '/summon tree no ai':
var treeNoAI = new TreeNoAI();
treeNoAI.x = player.x + (Math.random() - 0.5) * 200;
treeNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(treeNoAI);
break;
case '/summon chicken jockey':
var chickenJockey = new ChickenJockey();
chickenJockey.x = player.x + (Math.random() - 0.5) * 200;
chickenJockey.y = player.y + (Math.random() - 0.5) * 200;
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
chickenJockies.push(chickenJockey);
game.addChild(chickenJockey);
break;
case '/summon king zombie':
var kingZombie = new KingZombie();
kingZombie.x = player.x + (Math.random() - 0.5) * 200;
kingZombie.y = player.y + (Math.random() - 0.5) * 200;
kingZombies.push(kingZombie);
game.addChild(kingZombie);
break;
case '/summon king zombie no ai':
var kingZombieNoAI = new KingZombieNoAI();
kingZombieNoAI.x = player.x + (Math.random() - 0.5) * 200;
kingZombieNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(kingZombieNoAI);
break;
case '/horror mode!!':
// Activate horror mode immediately
currentLevel = 1000;
horrorMode = true;
gameBlocked = false;
// Clear everything
clearAllGameObjects();
// Replace hack and rewind buttons with horror message
hackButton.destroy();
rewindButton.destroy();
var horrorMessage = new Text2('I WANT YOU TO DIE', {
size: 80,
fill: 0xFF0000
});
horrorMessage.anchor.set(1, 0);
horrorMessage.y = 200;
LK.gui.topRight.addChild(horrorMessage);
// Spawn blood knife in front of player
groundKnife = new GroundKnife();
groundKnife.x = player.x;
groundKnife.y = player.y - 100;
game.addChild(groundKnife);
// Spawn 30 blood zombies at center position
for (var bz = 0; bz < 30; bz++) {
var bloodZombie = new BloodZombie();
bloodZombie.x = 1024 + (Math.random() - 0.5) * 100;
bloodZombie.y = 1366 + (Math.random() - 0.5) * 100;
bloodZombies.push(bloodZombie);
game.addChild(bloodZombie);
}
// Play scary music
LK.stopMusic();
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.3,
duration: 2000
}
});
break;
}
}
// Execute cheat function
function executeCheat(cheatType) {
switch (cheatType) {
case '/immortality':
immortalMode = true;
break;
case '/level hack':
if (!levelHackButton) {
levelHackButton = new Text2('Level Hack', {
size: 60,
fill: 0xFF0000
});
levelHackButton.anchor.set(0, 1);
levelHackButton.x = 120;
levelHackButton.y = -50;
LK.gui.bottomLeft.addChild(levelHackButton);
levelHackButton.down = function () {
if (gameBlocked) return;
currentLevel++;
levelHackCount++;
// Check for level 1000 horror mode
if (currentLevel >= 1000 && !horrorMode) {
horrorMode = true;
gameBlocked = false; // Unblock game
// Remove STOP message if it exists
var stopElements = LK.gui.center.children;
for (var i = stopElements.length - 1; i >= 0; i--) {
if (stopElements[i].text && stopElements[i].text === 'STOP!') {
stopElements[i].destroy();
}
}
// Clear everything
clearAllGameObjects();
// Replace hack and rewind buttons with horror message
hackButton.destroy();
rewindButton.destroy();
var horrorMessage = new Text2('I WANT YOU TO DIE', {
size: 80,
fill: 0xFF0000
});
horrorMessage.anchor.set(1, 0);
horrorMessage.y = 200;
LK.gui.topRight.addChild(horrorMessage);
// Spawn ground knife
groundKnife = new GroundKnife();
groundKnife.x = 1024;
groundKnife.y = 1366;
game.addChild(groundKnife);
// Spawn 30 blood zombies
for (var bz = 0; bz < 30; bz++) {
var bloodZombie = new BloodZombie();
bloodZombie.x = Math.random() * 1800 + 100;
bloodZombie.y = Math.random() * 2400 + 100;
bloodZombies.push(bloodZombie);
game.addChild(bloodZombie);
}
// Play scary music
LK.stopMusic();
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.3,
duration: 2000
}
});
}
if (currentLevel >= 100 && levelHackCount >= 5) {
gameBlocked = false;
// Remove STOP message
var stopElements = LK.gui.center.children;
for (var i = stopElements.length - 1; i >= 0; i--) {
if (stopElements[i].text && stopElements[i].text === 'STOP!') {
stopElements[i].destroy();
}
}
} else if (currentLevel >= 100) {
gameBlocked = true;
var stopMessage = new Text2('STOP!', {
size: 150,
fill: 0xFF0000
});
stopMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(stopMessage);
}
};
}
break;
case '/admin':
adminMode = true;
adminHackCount++;
if (adminHackCount >= 10 && !adminHackVisible) {
adminHackVisible = true;
showAdminHacks();
}
break;
case '/finish the game':
var finishMessage = new Text2('FINISH!', {
size: 120,
fill: 0x00FF00
});
finishMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(finishMessage);
currentLevel = 3;
LK.setTimeout(function () {
finishMessage.destroy();
}, 3000);
break;
case '/kill zombies and big zombies':
zombiesKilled = true;
// Kill all existing zombies
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
// Kill all existing big zombies
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
break;
case '/delete rain':
rainDeleted = true;
isRaining = false;
rainTimer = 0;
// Remove all existing raindrops
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
break;
case 'boss fight!':
// Activate boss mode immediately
bossMode = true;
currentLevel = 10;
levelCompleted = false;
// Clear EVERYTHING including soldiers and houses
clearAllGameObjects();
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
// Show BOSS FIGHT message
bossMessage = new Text2('BOSS FIGHT!!', {
size: 150,
fill: 0xFF0000
});
bossMessage.anchor.set(0.5, 0);
LK.gui.top.addChild(bossMessage);
// Spawn boss zombie
bossZombie = new BossZombie();
bossZombie.x = 1024;
bossZombie.y = 200;
bossZombie.targetX = player.x;
bossZombie.targetY = player.y;
game.addChild(bossZombie);
break;
}
}
// Spawn initial house
spawnHouse();
function spawnSoldiers() {
for (var h = 0; h < houses.length; h++) {
var house = houses[h];
// Spawn 2-3 soldiers behind each house
var soldierCount = 2 + Math.floor(Math.random() * 2);
for (var s = 0; s < soldierCount; s++) {
var soldier = new Soldier();
soldier.x = house.x + (Math.random() - 0.5) * 150;
soldier.y = house.y + 50 + Math.random() * 50;
soldiers.push(soldier);
game.addChild(soldier);
}
}
}
function spawnTank() {
if (tank) return; // Only one tank at a time
tank = new Tank();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top
tank.x = Math.random() * 2048;
tank.y = -100;
break;
case 1:
// Right
tank.x = 2148;
tank.y = Math.random() * 2732;
break;
case 2:
// Bottom
tank.x = Math.random() * 2048;
tank.y = 2832;
break;
case 3:
// Left
tank.x = -100;
tank.y = Math.random() * 2732;
break;
}
game.addChild(tank);
LK.getSound('tankEngine').play();
}
function spawnPistol() {
var pistol = new Pistol();
pistol.x = Math.random() * (2048 - 100) + 50;
pistol.y = Math.random() * (2732 - 200) + 100;
pistols.push(pistol);
game.addChild(pistol);
}
// Spawn initial soldiers
spawnSoldiers();
function spawnTree() {
var tree = new Tree();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 20) {
tree.x = Math.random() * (2048 - 120) + 60;
tree.y = Math.random() * (2732 - 200) + 150;
validPosition = true;
// Check distance from houses and other trees
for (var h = 0; h < houses.length; h++) {
var distance = Math.sqrt(Math.pow(tree.x - houses[h].x, 2) + Math.pow(tree.y - houses[h].y, 2));
if (distance < 200) {
validPosition = false;
break;
}
}
for (var t = 0; t < trees.length; t++) {
var distance = Math.sqrt(Math.pow(tree.x - trees[t].x, 2) + Math.pow(tree.y - trees[t].y, 2));
if (distance < 100) {
validPosition = false;
break;
}
}
attempts++;
}
trees.push(tree);
game.addChild(tree);
}
function createRain() {
for (var r = 0; r < 1; r++) {
// Reduced from 2 to 1 raindrop per call
var raindrop = new Raindrop();
raindrop.x = Math.random() * 2048;
raindrop.y = -20;
raindrops.push(raindrop);
game.addChild(raindrop);
}
}
function createLightning(x, y) {
var lightning = new Lightning();
lightning.x = x;
lightning.y = y;
lightnings.push(lightning);
game.addChild(lightning);
LK.getSound('thunder').play();
LK.effects.flashScreen(0xFFFFFF, 200);
}
// Spawn initial trees
for (var t = 0; t < 8; t++) {
spawnTree();
}
function spawnZombie() {
var zombie = new Zombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top
zombie.x = Math.random() * 2048;
zombie.y = -50;
break;
case 1:
// Right
zombie.x = 2098;
zombie.y = Math.random() * 2732;
break;
case 2:
// Bottom
zombie.x = Math.random() * 2048;
zombie.y = 2782;
break;
case 3:
// Left
zombie.x = -50;
zombie.y = Math.random() * 2732;
break;
}
zombie.speed = zombieSlowEnabled ? 0.3 : zombieSpeed + Math.random() * 0.5;
zombie.targetX = player.x;
zombie.targetY = player.y;
zombies.push(zombie);
game.addChild(zombie);
}
function spawnPowerUp() {
var types = ['speedBoost', 'shield', 'extraPoints', 'knife'];
var type = types[Math.floor(Math.random() * types.length)];
var powerUp = new PowerUp(type);
powerUp.x = Math.random() * (2048 - 100) + 50;
powerUp.y = Math.random() * (2732 - 200) + 100;
powerUps.push(powerUp);
game.addChild(powerUp);
}
function spawnHouse() {
var house = new House();
// Place houses away from edges and other houses
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 20) {
house.x = Math.random() * (2048 - 300) + 150;
house.y = Math.random() * (2732 - 300) + 200;
validPosition = true;
// Check distance from other houses
for (var h = 0; h < houses.length; h++) {
var distance = Math.sqrt(Math.pow(house.x - houses[h].x, 2) + Math.pow(house.y - houses[h].y, 2));
if (distance < 400) {
validPosition = false;
break;
}
}
attempts++;
}
houses.push(house);
game.addChild(house);
}
function dropRottenMeat(x, y) {
var meat = new RottenMeat();
meat.x = x + (Math.random() - 0.5) * 50;
meat.y = y + (Math.random() - 0.5) * 50;
rottenMeats.push(meat);
game.addChild(meat);
}
function isPlayerInSafeZone() {
for (var h = 0; h < houses.length; h++) {
var distance = Math.sqrt(Math.pow(player.x - houses[h].x, 2) + Math.pow(player.y - houses[h].y, 2));
if (distance < safeZoneRadius) {
return true;
}
}
return false;
}
function handleMove(x, y, obj) {
if (gameBlocked) return; // Block movement when game is blocked
if (horrorMode && groundKnife) return; // Block movement until knife is picked up
if (dragNode) {
// Apply speed multiplier
var targetX = x;
var targetY = y;
// Smooth movement with speed
var dx = targetX - dragNode.x;
var dy = targetY - dragNode.y;
dragNode.x += dx * 0.1 * dragNode.speed;
dragNode.y += dy * 0.1 * dragNode.speed;
// Keep player within bounds
dragNode.x = Math.max(40, Math.min(2008, dragNode.x));
dragNode.y = Math.max(40, Math.min(2692, dragNode.y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Block all input if game is blocked
if (gameBlocked) return;
// Check if player has pistol and ammo
if (playerHasPistol && playerAmmo > 0) {
// Shoot towards touch/click position
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y;
var dx = x - player.x;
var dy = y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 10;
bullet.velocityY = dy / distance * 10;
}
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('gunshot').play();
playerAmmo--;
if (playerAmmo <= 0) {
playerHasPistol = false;
}
} else {
// Normal movement
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
survivalTime++;
// Update score and UI
var timeInSeconds = Math.floor(survivalTime / 60);
var score = Math.floor(survivalTime / 10) + LK.getScore();
var healthText = immortalMode ? 'Health: FOREVER' : 'Health: ' + player.health;
healthTxt.setText(healthText);
// Update knife display separately
if (player.hasKnife && player.knifeUses > 0) {
knifeTxt.setText('Knife: ' + player.knifeUses);
} else {
knifeTxt.setText('');
}
scoreTxt.setText('Level ' + currentLevel + ' - Score: ' + score);
timeTxt.setText('Time: ' + timeInSeconds + 's');
// Increase difficulty over time (more aggressive in higher levels)
if (survivalTime % 600 == 0) {
// Every 10 seconds
var spawnRateDecrease = currentLevel * 3; // More aggressive in higher levels
var speedIncrease = currentLevel * 0.15; // More aggressive in higher levels
if (zombieSpawnRate > minZombieSpawnRate) {
zombieSpawnRate -= spawnRateDecrease;
}
if (zombieSpeed < maxZombieSpeed) {
zombieSpeed += speedIncrease;
}
}
// Spawn zombies (but not in horror mode at level 1000 or after level 200)
if (survivalTime % zombieSpawnRate == 0 && !(horrorMode && currentLevel >= 1000) && currentLevel < 200 && !zombiesKilled) {
spawnZombie();
}
// Block spawning of dev zombies, normal zombies and items in horror mode
if (!horrorMode) {
// Spawn green zombie every 300 score (blocked if zombies killed cheat is active)
var currentScore = Math.floor(survivalTime / 10) + LK.getScore();
if (currentScore > 0 && currentScore % 300 === 0 && survivalTime % 60 === 0 && !zombiesKilled) {
var greenZombie = new GreenZombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
greenZombie.x = Math.random() * 2048;
greenZombie.y = -50;
break;
case 1:
greenZombie.x = 2098;
greenZombie.y = Math.random() * 2732;
break;
case 2:
greenZombie.x = Math.random() * 2048;
greenZombie.y = 2782;
break;
case 3:
greenZombie.x = -50;
greenZombie.y = Math.random() * 2732;
break;
}
greenZombie.targetX = player.x;
greenZombie.targetY = player.y;
greenZombies.push(greenZombie);
game.addChild(greenZombie);
}
// Spawn strong zombie every 200 score
if (currentScore > 0 && currentScore % 200 === 0 && survivalTime % 90 === 0) {
var strongZombie = new StrongZombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
strongZombie.x = Math.random() * 2048;
strongZombie.y = -50;
break;
case 1:
strongZombie.x = 2098;
strongZombie.y = Math.random() * 2732;
break;
case 2:
strongZombie.x = Math.random() * 2048;
strongZombie.y = 2782;
break;
case 3:
strongZombie.x = -50;
strongZombie.y = Math.random() * 2732;
break;
}
strongZombie.targetX = player.x;
strongZombie.targetY = player.y;
strongZombies.push(strongZombie);
game.addChild(strongZombie);
}
// Spawn big zombie at specific score intervals (blocked if zombies killed cheat is active)
var bigZombieScores = [300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600, 3900, 4200, 4500, 4800, 5100, 5400, 5700, 6000, 6300, 6600, 6900, 7200];
for (var i = 0; i < bigZombieScores.length; i++) {
if (currentScore === bigZombieScores[i] && survivalTime % 60 === 0 && !zombiesKilled) {
var bigZombie = new BigZombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
bigZombie.x = Math.random() * 2048;
bigZombie.y = -50;
break;
case 1:
bigZombie.x = 2098;
bigZombie.y = Math.random() * 2732;
break;
case 2:
bigZombie.x = Math.random() * 2048;
bigZombie.y = 2782;
break;
case 3:
bigZombie.x = -50;
bigZombie.y = Math.random() * 2732;
break;
}
bigZombie.targetX = player.x;
bigZombie.targetY = player.y;
bigZombies.push(bigZombie);
game.addChild(bigZombie);
break;
}
}
}
// Spawn chicken jockey at score 2200
if (currentScore === 2200 && survivalTime % 60 === 0 && chickenJockies.length === 0) {
var chickenJockey = new ChickenJockey();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
chickenJockey.x = Math.random() * 2048;
chickenJockey.y = -50;
break;
case 1:
chickenJockey.x = 2098;
chickenJockey.y = Math.random() * 2732;
break;
case 2:
chickenJockey.x = Math.random() * 2048;
chickenJockey.y = 2782;
break;
case 3:
chickenJockey.x = -50;
chickenJockey.y = Math.random() * 2732;
break;
}
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
chickenJockies.push(chickenJockey);
game.addChild(chickenJockey);
}
// Despawn chicken jockey at score 2900
if (currentScore >= 2900 && chickenJockies.length > 0) {
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
chickenJockies.splice(cj, 1);
}
}
// Spawn power-ups occasionally (less frequent in higher levels, blocked in horror mode)
if (!horrorMode) {
var powerUpChance = 0.002 / currentLevel; // Harder in higher levels
if (survivalTime > 300 && Math.random() < powerUpChance && !(horrorMode && currentLevel >= 1000)) {
spawnPowerUp();
}
}
// Update zombie targets
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
// Check if player is in safe zone
var playerInSafeZone = isPlayerInSafeZone();
if (playerInSafeZone) {
// Find closest house edge to target instead of player directly
var closestHouse = null;
var closestDistance = Infinity;
for (var h = 0; h < houses.length; h++) {
var houseDistance = Math.sqrt(Math.pow(player.x - houses[h].x, 2) + Math.pow(player.y - houses[h].y, 2));
if (houseDistance < safeZoneRadius && houseDistance < closestDistance) {
closestDistance = houseDistance;
closestHouse = houses[h];
}
}
if (closestHouse) {
// Target edge of safe zone instead of player
var dx = player.x - closestHouse.x;
var dy = player.y - closestHouse.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
zombie.targetX = closestHouse.x + dx / distance * (safeZoneRadius + 20);
zombie.targetY = closestHouse.y + dy / distance * (safeZoneRadius + 20);
} else {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
} else {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
} else {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
// Check collision with player
if (zombie.intersects(player)) {
if (player.useKnife()) {
// Knife kills zombie and gives points
LK.setScore(LK.getScore() + 10);
dropRottenMeat(zombie.x, zombie.y); // Drop meat when killed
zombie.destroy();
zombies.splice(i, 1);
} else {
// No knife, take damage only if not in safe zone
if (!isPlayerInSafeZone()) {
player.takeDamage(10);
}
zombie.destroy();
zombies.splice(i, 1);
}
continue;
}
// Remove zombies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(zombie.x - player.x, 2) + Math.pow(zombie.y - player.y, 2));
if (distanceFromPlayer > 3000) {
zombie.destroy();
zombies.splice(i, 1);
}
}
// Check power-up collisions
for (var j = powerUps.length - 1; j >= 0; j--) {
var powerUp = powerUps[j];
if (powerUp.intersects(player)) {
LK.getSound('powerup').play();
switch (powerUp.type) {
case 'speedBoost':
player.speed = 1.5;
tween(player, {
speed: 1.0
}, {
duration: 3000
});
break;
case 'shield':
player.activateShield();
break;
case 'extraPoints':
LK.setScore(LK.getScore() + 50);
break;
case 'knife':
player.activateKnife();
break;
}
powerUp.destroy();
powerUps.splice(j, 1);
}
if (powerUp.lifetime <= 0) {
powerUps.splice(j, 1);
}
}
// Update green zombies
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
var greenZombie = greenZombies[gz];
// Update target
greenZombie.targetX = player.x;
greenZombie.targetY = player.y;
// Check collision with player
if (greenZombie.intersects(player)) {
if (player.useKnife()) {
// Knife damages green zombie
if (greenZombie.takeDamage()) {
// Green zombie dies, drop big meat
var bigMeat = new BigRottenMeat();
bigMeat.x = greenZombie.x;
bigMeat.y = greenZombie.y;
rottenMeats.push(bigMeat);
game.addChild(bigMeat);
LK.setScore(LK.getScore() + 50);
greenZombie.destroy();
greenZombies.splice(gz, 1);
}
} else {
// No knife, take big damage only if not in safe zone
if (!isPlayerInSafeZone()) {
player.takeDamage(30);
}
greenZombie.destroy();
greenZombies.splice(gz, 1);
}
continue;
}
// Remove green zombies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(greenZombie.x - player.x, 2) + Math.pow(greenZombie.y - player.y, 2));
if (distanceFromPlayer > 3000) {
greenZombie.destroy();
greenZombies.splice(gz, 1);
}
}
// Update strong zombies
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
var strongZombie = strongZombies[sz];
// Update target
strongZombie.targetX = player.x;
strongZombie.targetY = player.y;
// Check collision with player
if (strongZombie.intersects(player)) {
// Strong zombie always deals 30 damage, no knife defense
if (!isPlayerInSafeZone()) {
player.takeDamage(30);
}
// Drop big rotten meat when hitting player
var bigMeat = new BigRottenMeat();
bigMeat.x = strongZombie.x;
bigMeat.y = strongZombie.y;
rottenMeats.push(bigMeat);
game.addChild(bigMeat);
// Make player health full when eating big meat
player.health = player.maxHealth;
strongZombie.destroy();
strongZombies.splice(sz, 1);
continue;
}
// Remove strong zombies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(strongZombie.x - player.x, 2) + Math.pow(strongZombie.y - player.y, 2));
if (distanceFromPlayer > 3000) {
strongZombie.destroy();
strongZombies.splice(sz, 1);
}
}
// Update big zombies
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
var bigZombie = bigZombies[bz];
// Update target
bigZombie.targetX = player.x;
bigZombie.targetY = player.y;
// Check collision with player
if (bigZombie.intersects(player)) {
if (player.useKnife()) {
// Knife damages big zombie
if (bigZombie.takeDamage()) {
// Big zombie dies
LK.setScore(LK.getScore() + 100);
bigZombie.destroy();
bigZombies.splice(bz, 1);
}
} else {
// No knife, big zombie never gets destroyed from player collision
if (!isPlayerInSafeZone()) {
player.takeDamage(50); // High damage
}
}
continue;
}
// Big zombies never get removed for being too far away - they persist
}
// Update chicken jockies
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
var chickenJockey = chickenJockies[cj];
// Update target
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
// Check collision with player
if (chickenJockey.intersects(player)) {
// Chicken jockey deals 25 damage and reduces hunger by 2
if (!isPlayerInSafeZone()) {
player.takeDamage(25);
hungerLevel = Math.max(0, hungerLevel - 2);
}
chickenJockey.destroy();
chickenJockies.splice(cj, 1);
continue;
}
// Remove chicken jockies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(chickenJockey.x - player.x, 2) + Math.pow(chickenJockey.y - player.y, 2));
if (distanceFromPlayer > 3000) {
chickenJockey.destroy();
chickenJockies.splice(cj, 1);
}
}
// Handle bullets vs green zombies (bullets don't work)
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
for (var gz = 0; gz < greenZombies.length; gz++) {
var greenZombie = greenZombies[gz];
if (bullet.intersects(greenZombie)) {
// Bullets don't damage green zombies, just destroy bullet
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Handle bullets vs strong zombies (bullets don't work)
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
for (var sz = 0; sz < strongZombies.length; sz++) {
var strongZombie = strongZombies[sz];
if (bullet.intersects(strongZombie)) {
// Bullets don't damage strong zombies, just destroy bullet
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Handle bullets vs big zombies (bullets don't work)
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
for (var bz = 0; bz < bigZombies.length; bz++) {
var bigZombie = bigZombies[bz];
if (bullet.intersects(bigZombie)) {
// Bullets don't damage big zombies, just destroy bullet
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Handle soldier bullets vs green zombies (bullets don't work)
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
for (var gz = 0; gz < greenZombies.length; gz++) {
var greenZombie = greenZombies[gz];
if (bullet.intersects(greenZombie)) {
// Bullets don't damage green zombies, just destroy bullet
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Handle soldier bullets vs strong zombies (bullets don't work)
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
for (var sz = 0; sz < strongZombies.length; sz++) {
var strongZombie = strongZombies[sz];
if (bullet.intersects(strongZombie)) {
// Bullets don't damage strong zombies, just destroy bullet
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Handle soldier bullets vs big zombies (bullets don't work)
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
for (var bz = 0; bz < bigZombies.length; bz++) {
var bigZombie = bigZombies[bz];
if (bullet.intersects(bigZombie)) {
// Bullets don't damage big zombies, just destroy bullet
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Check rotten meat collisions
for (var m = rottenMeats.length - 1; m >= 0; m--) {
var meat = rottenMeats[m];
if (meat.intersects(player)) {
if (meat instanceof BigRottenMeat) {
// Big meat restores health but reduces hunger
player.health = player.maxHealth;
hungerLevel = Math.max(0, hungerLevel - 5);
} else {
// Regular meat increases hunger and stays green for 5 seconds
hungerLevel = Math.min(maxHunger, hungerLevel + 1);
hungerTimer = 300; // 5 seconds of green hunger bar
}
meatCollected++;
safeZoneRadius += 5; // Expand safe zone with each meat collected
LK.getSound('powerup').play();
meat.destroy();
rottenMeats.splice(m, 1);
// Spawn new house every 10 meat collected
if (meatCollected % 10 === 0 && houses.length < 5) {
spawnHouse();
}
continue;
}
if (meat.lifetime <= 0) {
rottenMeats.splice(m, 1);
}
}
// Weather system (more frequent in higher levels, blocked if rain deleted or rain toggle enabled)
var rainChance = 0.001 * currentLevel; // More rain in higher levels
if (!isRaining && Math.random() < rainChance && !rainDeleted && !rainToggleEnabled) {
// Start rain
isRaining = true;
rainTimer = 600 + Math.random() * 600; // Rain for 10-20 seconds
}
if (isRaining && !rainToggleEnabled) {
rainTimer--;
if (rainTimer <= 0) {
isRaining = false;
} else {
// Create raindrops (reduced frequency)
if (survivalTime % 16 == 0) {
// Further reduced from 8 to 16 for better performance
createRain();
}
}
}
// Lightning strikes during rain
if (isRaining && Math.random() < 0.005) {
// Lightning on zombies (100/50 chance)
if (zombies.length > 0 && Math.random() < 0.5) {
var randomZombie = zombies[Math.floor(Math.random() * zombies.length)];
createLightning(randomZombie.x, randomZombie.y - 100);
// Kill the zombie
LK.setScore(LK.getScore() + 20);
dropRottenMeat(randomZombie.x, randomZombie.y);
randomZombie.destroy();
zombies.splice(zombies.indexOf(randomZombie), 1);
}
// Lightning on trees (100/70 chance)
if (trees.length > 0 && Math.random() < 0.7) {
var randomTree = trees[Math.floor(Math.random() * trees.length)];
createLightning(randomTree.x, randomTree.y - 60);
randomTree.strikeWithLightning();
}
}
// Clean up raindrops
for (var r = raindrops.length - 1; r >= 0; r--) {
if (raindrops[r].y > 2800) {
raindrops.splice(r, 1);
}
}
// Clean up lightning
for (var l = lightnings.length - 1; l >= 0; l--) {
if (lightnings[l].lifetime <= 0) {
lightnings.splice(l, 1);
}
}
// Tank spawning logic
tankSpawnTimer--;
if (tankSpawnTimer <= 0) {
spawnTank();
tankSpawnTimer = 3600; // Reset to 1 minute
}
// Remove tank after some time and increase zombie spawn
if (tank) {
var tankDistance = Math.sqrt(Math.pow(tank.x - tank.targetX, 2) + Math.pow(tank.y - tank.targetY, 2));
if (tankDistance < 50) {
// Tank reached center, remove it and spawn more zombies
tank.destroy();
tank = null;
// Spawn extra zombies after tank leaves
for (var tz = 0; tz < 5; tz++) {
spawnZombie();
}
}
}
// Update soldiers
for (var s = soldiers.length - 1; s >= 0; s--) {
var soldier = soldiers[s];
if (soldier.health <= 0) {
soldiers.splice(s, 1);
continue;
}
// Soldier takes damage from nearby zombies
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
var distance = Math.sqrt(Math.pow(zombie.x - soldier.x, 2) + Math.pow(zombie.y - soldier.y, 2));
if (distance < 30) {
soldier.takeDamage(5);
break;
}
}
}
// Update soldier bullets
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
if (bullet.lifetime <= 0) {
soldierBullets.splice(sb, 1);
continue;
}
// Check collision with zombies
for (var z = zombies.length - 1; z >= 0; z--) {
var zombie = zombies[z];
if (bullet.intersects(zombie)) {
LK.setScore(LK.getScore() + 10);
dropRottenMeat(zombie.x, zombie.y);
zombie.destroy();
zombies.splice(z, 1);
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Update player bullets
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
if (bullet.lifetime <= 0) {
playerBullets.splice(pb, 1);
continue;
}
// Check collision with zombies
for (var z = zombies.length - 1; z >= 0; z--) {
var zombie = zombies[z];
if (bullet.intersects(zombie)) {
LK.setScore(LK.getScore() + 15);
dropRottenMeat(zombie.x, zombie.y);
zombie.destroy();
zombies.splice(z, 1);
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Check pistol collisions with player
for (var p = pistols.length - 1; p >= 0; p--) {
var pistol = pistols[p];
if (pistol.intersects(player)) {
playerHasPistol = true;
playerAmmo = pistol.ammo;
LK.getSound('powerup').play();
pistol.destroy();
pistols.splice(p, 1);
continue;
}
if (pistol.lifetime <= 0) {
pistols.splice(p, 1);
}
}
// Spawn pistols after tank visits (blocked in horror mode)
if (survivalTime > 3600 && Math.random() < 0.003 && !(horrorMode && currentLevel >= 1000)) {
spawnPistol();
}
// Spawn new soldiers when houses are built
if (meatCollected % 10 === 0 && survivalTime % 60 === 0 && houses.length > soldiers.length / 2) {
spawnSoldiers();
}
// Check level completion based on score milestones
var currentScore = Math.floor(survivalTime / 10) + LK.getScore();
// Level progression every 1000 points
var targetLevel = Math.floor(currentScore / 1000) + 1;
if (targetLevel > currentLevel && !levelCompleted && !bossMode) {
currentLevel = targetLevel;
levelCompleted = true;
if (currentLevel === 10) {
// Level 10 - BOSS FIGHT
bossMode = true;
levelCompleted = false;
// Clear EVERYTHING including soldiers and houses
clearAllGameObjects();
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
// Show BOSS FIGHT message
bossMessage = new Text2('BOSS FIGHT!!', {
size: 150,
fill: 0xFF0000
});
bossMessage.anchor.set(0.5, 0);
LK.gui.top.addChild(bossMessage);
// Spawn boss zombie
bossZombie = new BossZombie();
bossZombie.x = 1024;
bossZombie.y = 200;
bossZombie.targetX = player.x;
bossZombie.targetY = player.y;
game.addChild(bossZombie);
// Only spawn knives and pistols in boss mode
if (Math.random() < 0.05) {
var knife = new PowerUp('knife');
knife.x = Math.random() * 1800 + 100;
knife.y = Math.random() * 2400 + 100;
powerUps.push(knife);
game.addChild(knife);
}
if (Math.random() < 0.03) {
spawnPistol();
}
} else {
// Regular level progression (levels 2-9)
// Clear everything except soldiers, houses and trees
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
greenZombies[gz].destroy();
}
greenZombies = [];
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
strongZombies[sz].destroy();
}
strongZombies = [];
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
for (var p = powerUps.length - 1; p >= 0; p--) {
powerUps[p].destroy();
}
powerUps = [];
for (var m = rottenMeats.length - 1; m >= 0; m--) {
rottenMeats[m].destroy();
}
rottenMeats = [];
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
for (var l = lightnings.length - 1; l >= 0; l--) {
lightnings[l].destroy();
}
lightnings = [];
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
playerBullets[pb].destroy();
}
playerBullets = [];
for (var pi = pistols.length - 1; pi >= 0; pi--) {
pistols[pi].destroy();
}
pistols = [];
if (tank) {
tank.destroy();
tank = null;
}
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
}
chickenJockies = [];
for (var kz = kingZombies.length - 1; kz >= 0; kz--) {
kingZombies[kz].destroy();
}
kingZombies = [];
// Reset player position
player.x = 1024;
player.y = 1366;
// Show level complete for 2 seconds
levelCompleteMessage = new Text2('Level ' + currentLevel, {
size: 120,
fill: 0x00FF00
});
levelCompleteMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(levelCompleteMessage);
LK.setTimeout(function () {
if (levelCompleteMessage) {
levelCompleteMessage.destroy();
levelCompleteMessage = null;
}
levelCompleted = false;
}, 2000);
}
}
// Pause game mechanics when showing level complete
if (showingLevelComplete && currentLevel === 1) {
return; // Don't update game mechanics
}
// Admin mode effects (basic level and health manipulation)
if (adminMode && Math.random() < 0.01) {
// Randomly adjust level (simulate admin controls)
if (Math.random() < 0.5) {
currentLevel = Math.min(currentLevel + 1, 150);
}
// Randomly restore health
if (player.health < 100 && Math.random() < 0.3) {
player.health = 100;
}
}
// Hunger system
if (hungerTimer > 0) {
hungerTimer--;
}
// Hunger damage when hunger reaches 0
if (hungerLevel <= 0) {
hungerDamageTimer++;
if (hungerDamageTimer >= 300) {
// 5 seconds
hungerDamageTimer = 0;
if (!immortalMode) {
player.health -= 10;
LK.effects.flashObject(player, 0xff0000, 200);
if (player.health <= 0) {
player.health = 0;
LK.showGameOver();
}
}
}
}
// Update UI
meatTxt.setText('Meat: ' + meatCollected);
if (playerHasPistol && playerAmmo > 0) {
ammoTxt.setText('Ammo: ' + playerAmmo);
} else {
ammoTxt.setText('');
}
// Boss fight logic
if (bossMode && bossZombie) {
// Update boss target
bossZombie.targetX = player.x;
bossZombie.targetY = player.y;
// Boss collision with player
if (bossZombie.intersects(player)) {
if (player.useKnife()) {
if (bossZombie.takeDamage('knife')) {
// Boss defeated!
bossZombie.destroy();
bossZombie = null;
bossMode = false;
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
LK.showYouWin();
return;
}
} else {
// Boss attacks player
if (!isPlayerInSafeZone()) {
player.takeDamage(50);
}
}
}
// Check player bullets vs boss
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
if (bullet.intersects(bossZombie)) {
if (bossZombie.takeDamage('bullet')) {
// Boss defeated!
bossZombie.destroy();
bossZombie = null;
bossMode = false;
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
// Show REAL FINISH message
var realFinishMessage = new Text2('REAL FINISH!!', {
size: 120,
fill: 0x00FF00
});
realFinishMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(realFinishMessage);
LK.setTimeout(function () {
if (realFinishMessage && realFinishMessage.parent) {
realFinishMessage.destroy();
}
LK.showYouWin();
}, 3000);
return;
}
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
// Continue spawning chicken jockies and zombies in boss fight
if (survivalTime % 180 == 0) {
var chickenJockey = new ChickenJockey();
chickenJockey.x = Math.random() * 2048;
chickenJockey.y = -50;
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
chickenJockies.push(chickenJockey);
game.addChild(chickenJockey);
}
if (survivalTime % zombieSpawnRate == 0) {
spawnZombie();
}
return; // Skip normal game mechanics in boss mode
}
// Horror mode logic
if (horrorMode) {
// Check ground knife pickup
if (groundKnife && groundKnife.intersects(player)) {
player.activateKnife();
groundKnife.destroy();
groundKnife = null;
// Enable movement after knife pickup by allowing normal dragging
}
// Check blood zombie interactions
for (var bz = bloodZombies.length - 1; bz >= 0; bz--) {
var bloodZombie = bloodZombies[bz];
if (bloodZombie.intersects(player)) {
if (player.useKnife()) {
// Blood zombie killed with blood knife - activate all remaining blood zombies
if (bloodZombies.length > 1) {
var dieMessage = new Text2('I WANT YOU TO DIE', {
size: 200,
fill: 0xFF0000
});
dieMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(dieMessage);
// Activate all remaining blood zombies to attack player
for (var i = 0; i < bloodZombies.length; i++) {
if (i !== bz) {
bloodZombies[i].activate();
}
}
// Remove message after 3 seconds
LK.setTimeout(function () {
if (dieMessage && dieMessage.parent) {
dieMessage.destroy();
}
}, 3000);
}
bloodZombie.destroy();
bloodZombies.splice(bz, 1);
} else {
// Blood zombie attacks player
if (!isPlayerInSafeZone()) {
player.takeDamage(20);
}
}
}
}
return; // Skip normal game mechanics in horror mode
}
// Update hunger display
var hungerColor = 0xFF0000; // Red by default
if (hungerLevel > 5) {
hungerColor = 0x00FF00; // Green for high hunger
} else if (hungerLevel > 2) {
hungerColor = 0xFFFF00; // Yellow for medium hunger
}
if (hungerTimer > 0) {
hungerColor = 0x00FF00; // Green when eating
}
hungerTxt.setText('Hunger: ' + hungerLevel + '/' + maxHunger);
hungerTxt.fill = hungerColor;
};
LK.playMusic('bgmusic'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigRottenMeat = Container.expand(function () {
var self = Container.call(this);
var meatGraphics = self.attachAsset('rottenMeat', {
anchorX: 0.5,
anchorY: 0.5
});
meatGraphics.scaleX = 2; // Bigger meat
meatGraphics.scaleY = 2;
meatGraphics.tint = 0x00AA00; // Different color
self.lifetime = 300; // 5 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Big bounce effect
var bounce = Math.sin(LK.ticks * 0.1) * 4;
meatGraphics.y = bounce;
};
return self;
});
var BigZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('Big-zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.scaleX = 2.5; // Much bigger than other zombies
zombieGraphics.scaleY = 2.5;
zombieGraphics.tint = 0x4B0082; // Dark purple color for big zombie
self.speed = 0.2; // Very slow movement
self.targetX = 0;
self.targetY = 0;
self.knifeHits = 0; // Track knife hits
self.maxKnifeHits = 5; // Dies after 5 knife hits
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function () {
self.knifeHits++;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.knifeHits >= self.maxKnifeHits) {
return true; // Dies
}
return false; // Still alive
};
return self;
});
var BigZombieNoAI = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('Big-zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.scaleX = 2.5;
zombieGraphics.scaleY = 2.5;
zombieGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function - stationary
return self;
});
var BloodZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x8B0000; // Blood red color
zombieGraphics.scaleX = 1.2;
zombieGraphics.scaleY = 1.2;
self.speed = 2; // Fast when activated
self.targetX = 0;
self.targetY = 0;
self.isActive = false; // Start inactive
self.activate = function () {
self.isActive = true;
self.targetX = player.x;
self.targetY = player.y;
};
self.update = function () {
if (self.isActive) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
};
return self;
});
var BossZombie = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('King-Zombie', {
anchorX: 0.5,
anchorY: 0.5
});
bossGraphics.scaleX = 8; // Massive boss zombie
bossGraphics.scaleY = 8;
bossGraphics.tint = 0x8B0000; // Dark red for boss
self.speed = 0.5; // Slow but deadly
self.targetX = 0;
self.targetY = 0;
self.bulletHits = 0; // Track bullet hits only
self.maxBulletHits = 120; // Dies after 120 bullet hits only
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function (type) {
if (type === 'bullet') {
self.bulletHits++;
}
LK.effects.flashObject(self, 0xff0000, 300);
if (self.bulletHits >= self.maxBulletHits) {
return true; // Boss dies
}
return false; // Boss still alive
};
return self;
});
var ChickenJockey = Container.expand(function () {
var self = Container.call(this);
var chickenGraphics = self.attachAsset('Chicken-Jockey', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3; // Faster than zombies
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var ChickenJockeyNoAI = Container.expand(function () {
var self = Container.call(this);
var chickenGraphics = self.attachAsset('Chicken-Jockey', {
anchorX: 0.5,
anchorY: 0.5
});
chickenGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function - stationary
return self;
});
var GreenZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x00FF00; // Green color
zombieGraphics.scaleX = 1.5; // Bigger and stronger
zombieGraphics.scaleY = 1.5;
self.speed = 0.5; // Slow movement
self.targetX = 0;
self.targetY = 0;
self.knifeHits = 0; // Track knife hits
self.maxKnifeHits = 5; // Dies after 5 knife hits
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.takeDamage = function () {
self.knifeHits++;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.knifeHits >= self.maxKnifeHits) {
return true; // Dies
}
return false; // Still alive
};
return self;
});
var GroundKnife = Container.expand(function () {
var self = Container.call(this);
var knifeGraphics = self.attachAsset('knife', {
anchorX: 0.5,
anchorY: 0.5
});
knifeGraphics.tint = 0xFF0000; // Blood red knife
// Pulse effect
self.update = function () {
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
knifeGraphics.scaleX = scale;
knifeGraphics.scaleY = scale;
};
return self;
});
var House = Container.expand(function () {
var self = Container.call(this);
var houseGraphics = self.attachAsset('house', {
anchorX: 0.5,
anchorY: 1.0
});
self.safeRadius = 200; // Safe zone around house
return self;
});
var KingZombie = Container.expand(function () {
var self = Container.call(this);
var kingGraphics = self.attachAsset('King-Zombie', {
anchorX: 0.5,
anchorY: 0.5
});
kingGraphics.scaleX = 3; // Larger than other zombies
kingGraphics.scaleY = 3;
kingGraphics.tint = 0x8B008B; // Dark magenta for royalty
self.commandTimer = 0; // Timer for commanding zombies
self.commandCooldown = 300; // 5 seconds between commands
self.health = 50; // King zombies now have health
self.maxHealth = 50;
self.update = function () {
self.commandTimer++;
if (self.commandTimer >= self.commandCooldown) {
self.commandTimer = 0;
// Gather zombies around the king
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < 300) {
// Within command range
// Make zombie come to king and wait
zombie.targetX = self.x + (Math.random() - 0.5) * 100;
zombie.targetY = self.y + (Math.random() - 0.5) * 100;
// After 3 seconds, send them back to attack player
LK.setTimeout(function (zombie) {
if (zombie && zombie.parent) {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
}.bind(null, zombie), 3000);
}
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
return true; // King zombie dies
}
return false; // Still alive
};
return self;
});
var KingZombieNoAI = Container.expand(function () {
var self = Container.call(this);
var kingGraphics = self.attachAsset('King-Zombie', {
anchorX: 0.5,
anchorY: 0.5
});
kingGraphics.scaleX = 3;
kingGraphics.scaleY = 3;
kingGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function and no commands
return self;
});
var Lightning = Container.expand(function () {
var self = Container.call(this);
var lightningGraphics = self.attachAsset('lightning', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 10; // Very short flash
lightningGraphics.alpha = 0.8;
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
};
return self;
});
var Pistol = Container.expand(function () {
var self = Container.call(this);
var pistolGraphics = self.attachAsset('pistol', {
anchorX: 0.5,
anchorY: 0.5
});
self.ammo = 30;
self.lifetime = 300; // 5 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Small rotation animation
pistolGraphics.rotation += 0.02;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 1.0;
self.shielded = false;
self.shieldTime = 0;
self.hasKnife = false;
self.knifeUses = 0;
self.update = function () {
if (self.shielded) {
self.shieldTime--;
if (self.shieldTime <= 0) {
self.shielded = false;
playerGraphics.tint = 0xFFFFFF;
}
}
};
self.takeDamage = function (amount) {
if (immortalMode) return; // Immortal mode blocks all damage
if (!self.shielded) {
self.health -= amount;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0xff0000, 500);
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
}
};
self.activateShield = function () {
self.shielded = true;
self.shieldTime = 300; // 5 seconds at 60fps
playerGraphics.tint = 0x00FFFF;
};
self.activateKnife = function () {
self.hasKnife = true;
self.knifeUses = 5;
playerGraphics.tint = 0xFFFF00;
};
self.useKnife = function () {
if (self.hasKnife && self.knifeUses > 0) {
if (!infiniteKnife) {
self.knifeUses--;
}
LK.getSound('knife').play();
if (self.knifeUses <= 0 && !infiniteKnife) {
self.hasKnife = false;
playerGraphics.tint = 0xFFFFFF;
}
return true;
}
return false;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.tint = 0x00FF00; // Green bullets for player
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 120; // 2 seconds at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = type;
self.lifetime = 600; // 10 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Pulse effect
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
powerUpGraphics.scaleX = scale;
powerUpGraphics.scaleY = scale;
};
return self;
});
var Raindrop = Container.expand(function () {
var self = Container.call(this);
var dropGraphics = self.attachAsset('raindrop', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8 + Math.random() * 4;
self.update = function () {
self.y += self.speed;
// Remove when off screen
if (self.y > 2800) {
self.destroy();
}
};
return self;
});
var RottenMeat = Container.expand(function () {
var self = Container.call(this);
var meatGraphics = self.attachAsset('rottenMeat', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 300; // 5 seconds at 60fps
self.update = function () {
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Small bounce effect
var bounce = Math.sin(LK.ticks * 0.1) * 2;
meatGraphics.y = bounce;
};
return self;
});
var Soldier = Container.expand(function () {
var self = Container.call(this);
var soldierGraphics = self.attachAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.shootTimer = 0;
self.shootCooldown = 60; // 1 second at 60fps
self.range = 300;
self.update = function () {
self.shootTimer--;
if (self.shootTimer <= 0) {
// Find closest zombie within range
var closestZombie = null;
var closestDistance = Infinity;
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance < self.range && distance < closestDistance) {
closestDistance = distance;
closestZombie = zombie;
}
}
if (closestZombie) {
// Shoot at zombie
var bullet = new SoldierBullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = closestZombie.x - self.x;
var dy = closestZombie.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 8;
bullet.velocityY = dy / distance * 8;
}
soldierBullets.push(bullet);
game.addChild(bullet);
LK.getSound('gunshot').play();
self.shootTimer = self.shootCooldown;
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.destroy();
}
};
return self;
});
var SoldierBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifetime = 180; // 3 seconds at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
if (self.lifetime <= 0 || self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
}
};
return self;
});
var StrongZombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x8B0000; // Dark red color for strong zombie
zombieGraphics.scaleX = 1.8; // Bigger and more muscular
zombieGraphics.scaleY = 1.8;
self.speed = 0.3; // Very slow movement
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var Tank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('tank', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.targetX = 1024;
self.targetY = 1366;
self.crushRadius = 80;
self.update = function () {
// Move towards center of map
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Crush zombies
for (var z = zombies.length - 1; z >= 0; z--) {
var zombie = zombies[z];
var zombieDistance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (zombieDistance < self.crushRadius) {
LK.setScore(LK.getScore() + 15);
dropRottenMeat(zombie.x, zombie.y);
zombie.destroy();
zombies.splice(z, 1);
}
}
// Check collision with big zombies - tank gets destroyed
for (var bz = 0; bz < bigZombies.length; bz++) {
var bigZombie = bigZombies[bz];
var bigZombieDistance = Math.sqrt(Math.pow(bigZombie.x - self.x, 2) + Math.pow(bigZombie.y - self.y, 2));
if (bigZombieDistance < self.crushRadius) {
// Tank gets destroyed when hitting big zombie
self.destroy();
break;
}
}
};
return self;
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
});
self.isOnFire = false;
self.fireTime = 0;
self.strikeWithLightning = function () {
self.isOnFire = true;
self.fireTime = 300; // 5 seconds at 60fps
treeGraphics.tint = 0xFF4500; // Orange fire color
LK.getSound('lightning').play();
LK.effects.flashObject(self, 0xFFFF00, 200);
};
self.update = function () {
if (self.isOnFire) {
self.fireTime--;
if (self.fireTime <= 0) {
self.isOnFire = false;
treeGraphics.tint = 0xFFFFFF;
}
}
};
return self;
});
var TreeNoAI = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
});
treeGraphics.tint = 0x808080; // Gray color to indicate no AI
// No lightning strike functionality
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var ZombieNoAI = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
zombieGraphics.tint = 0x808080; // Gray color to indicate no AI
// No update function - stationary
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E7D32
});
/****
* Game Code
****/
game.setBackgroundColor(0x1B5E20);
var player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
var zombies = [];
var powerUps = [];
var rottenMeats = [];
var houses = [];
var trees = [];
var raindrops = [];
var lightnings = [];
var soldiers = [];
var soldierBullets = [];
var playerBullets = [];
var pistols = [];
var tank = null;
var tankSpawnTimer = 3600; // 1 minute at 60fps
var dragNode = null;
var playerHasPistol = false;
var playerAmmo = 0;
var survivalTime = 0;
var meatCollected = 0;
var hungerLevel = 10; // Start with full hunger
var maxHunger = 10;
var hungerTimer = 0;
var hungerDamageTimer = 0;
var greenZombies = [];
var strongZombies = [];
var bigZombies = [];
var bloodZombies = [];
var groundKnife = null;
var horrorMode = false;
var levelHackCount = 0;
var safeZoneRadius = 200;
var zombieSpawnRate = 120; // Start spawning every 2 seconds
var minZombieSpawnRate = 30; // Fastest spawn rate
var zombieSpeed = 1;
var maxZombieSpeed = 4;
var isRaining = false;
var rainTimer = 0;
var lightningTimer = 0;
var currentLevel = 1;
var levelCompleted = false;
var showingLevelComplete = false;
var levelCompleteMessage = null;
var levelContinueButton = null;
// Cheat system variables
var immortalMode = false;
var levelHackButton = null;
var adminMode = false;
var gameBlocked = false;
var hackMenuVisible = false;
var hackButton = null;
var hackMenuButtons = [];
var zombiesKilled = false;
var rainDeleted = false;
var adminHackCount = 0;
var adminHackButtons = [];
var adminHackVisible = false;
var infiniteKnife = false;
var chickenJockies = [];
var kingZombies = [];
var bossMode = false;
var bossZombie = null;
var bossMessage = null;
var rainToggleEnabled = false;
var zombieSlowEnabled = false;
// UI Elements
var healthTxt = new Text2('Health: 100', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthTxt);
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var timeTxt = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(timeTxt);
var knifeTxt = new Text2('', {
size: 60,
fill: 0xFFFF00
});
knifeTxt.anchor.set(0, 0);
knifeTxt.y = 260; // Position below meat counter
LK.gui.topLeft.addChild(knifeTxt);
var hungerTxt = new Text2('Hunger: 10/10', {
size: 60,
fill: 0x00FF00
});
hungerTxt.anchor.set(0, 0);
hungerTxt.y = 140; // Position below health
LK.gui.topLeft.addChild(hungerTxt);
var meatTxt = new Text2('Meat: 0', {
size: 60,
fill: 0x8B4513
});
meatTxt.anchor.set(0, 0);
meatTxt.y = 200; // Position below hunger bar
LK.gui.topLeft.addChild(meatTxt);
var ammoTxt = new Text2('', {
size: 60,
fill: 0x00FF00
});
ammoTxt.anchor.set(0, 0);
ammoTxt.y = 320; // Position below knife counter
LK.gui.topLeft.addChild(ammoTxt);
// Create hack button
hackButton = new Text2('HACK', {
size: 50,
fill: 0xFF00FF
});
hackButton.anchor.set(1, 0);
hackButton.y = 200;
LK.gui.topRight.addChild(hackButton);
// Create rewind button
var rewindButton = new Text2('REWIND', {
size: 50,
fill: 0x00FFFF
});
rewindButton.anchor.set(1, 0);
rewindButton.y = 260;
LK.gui.topRight.addChild(rewindButton);
// Create rain toggle button
var rainToggleButton = new Text2('Rain: OFF', {
size: 50,
fill: 0x00AAFF
});
rainToggleButton.anchor.set(1, 0);
rainToggleButton.y = 320;
LK.gui.topRight.addChild(rainToggleButton);
// Create zombie slow button
var zombieSlowButton = new Text2('Zombie Speed: Normal', {
size: 50,
fill: 0xFFAA00
});
zombieSlowButton.anchor.set(1, 0);
zombieSlowButton.y = 380;
LK.gui.topRight.addChild(zombieSlowButton);
// Rewind button functionality
rewindButton.down = function () {
if (gameBlocked) return;
// Reset the entire game
resetGame();
};
// Rain toggle button functionality
rainToggleButton.down = function () {
if (gameBlocked) return;
rainToggleEnabled = !rainToggleEnabled;
if (rainToggleEnabled) {
rainToggleButton.setText('Rain: OFF');
rainToggleButton.fill = 0xFF0000;
// Stop current rain
isRaining = false;
rainTimer = 0;
// Remove all existing raindrops
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
} else {
rainToggleButton.setText('Rain: ON');
rainToggleButton.fill = 0x00AAFF;
}
};
// Zombie slow button functionality
zombieSlowButton.down = function () {
if (gameBlocked) return;
zombieSlowEnabled = !zombieSlowEnabled;
if (zombieSlowEnabled) {
zombieSlowButton.setText('Zombie Speed: Slow');
zombieSlowButton.fill = 0x00FF00;
// Slow down all existing zombies
for (var z = 0; z < zombies.length; z++) {
zombies[z].speed = 0.3; // Level 1 speed
}
for (var gz = 0; gz < greenZombies.length; gz++) {
greenZombies[gz].speed = 0.3;
}
for (var sz = 0; sz < strongZombies.length; sz++) {
strongZombies[sz].speed = 0.3;
}
for (var bz = 0; bz < bigZombies.length; bz++) {
bigZombies[bz].speed = 0.3;
}
for (var cj = 0; cj < chickenJockies.length; cj++) {
chickenJockies[cj].speed = 0.3;
}
} else {
zombieSlowButton.setText('Zombie Speed: Normal');
zombieSlowButton.fill = 0xFFAA00;
}
};
function clearAllGameObjects() {
// Destroy all game objects
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
greenZombies[gz].destroy();
}
greenZombies = [];
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
strongZombies[sz].destroy();
}
strongZombies = [];
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
for (var p = powerUps.length - 1; p >= 0; p--) {
powerUps[p].destroy();
}
powerUps = [];
for (var m = rottenMeats.length - 1; m >= 0; m--) {
rottenMeats[m].destroy();
}
rottenMeats = [];
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var t = trees.length - 1; t >= 0; t--) {
trees[t].destroy();
}
trees = [];
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
for (var l = lightnings.length - 1; l >= 0; l--) {
lightnings[l].destroy();
}
lightnings = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
playerBullets[pb].destroy();
}
playerBullets = [];
for (var pi = pistols.length - 1; pi >= 0; pi--) {
pistols[pi].destroy();
}
pistols = [];
if (tank) {
tank.destroy();
tank = null;
}
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
}
chickenJockies = [];
for (var kz = kingZombies.length - 1; kz >= 0; kz--) {
kingZombies[kz].destroy();
}
kingZombies = [];
if (bossZombie) {
bossZombie.destroy();
bossZombie = null;
}
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
bossMode = false;
}
function resetGame() {
// Destroy all game objects except keeping meat count
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
greenZombies[gz].destroy();
}
greenZombies = [];
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
strongZombies[sz].destroy();
}
strongZombies = [];
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
for (var p = powerUps.length - 1; p >= 0; p--) {
powerUps[p].destroy();
}
powerUps = [];
for (var m = rottenMeats.length - 1; m >= 0; m--) {
rottenMeats[m].destroy();
}
rottenMeats = [];
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var t = trees.length - 1; t >= 0; t--) {
trees[t].destroy();
}
trees = [];
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
for (var l = lightnings.length - 1; l >= 0; l--) {
lightnings[l].destroy();
}
lightnings = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
playerBullets[pb].destroy();
}
playerBullets = [];
for (var pi = pistols.length - 1; pi >= 0; pi--) {
pistols[pi].destroy();
}
pistols = [];
if (tank) {
tank.destroy();
tank = null;
}
// Reset player
player.x = 1024;
player.y = 1366;
player.health = 100;
player.hasKnife = false;
player.knifeUses = 0;
player.shielded = false;
player.speed = 1.0;
// Reset all game variables except meatCollected
currentLevel = 1;
levelCompleted = false;
showingLevelComplete = false;
survivalTime = 0;
safeZoneRadius = 200;
zombieSpawnRate = 120;
zombieSpeed = 1;
tankSpawnTimer = 3600;
playerHasPistol = false;
playerAmmo = 0;
isRaining = false;
rainTimer = 0;
lightningTimer = 0;
hungerLevel = 10;
hungerTimer = 0;
hungerDamageTimer = 0;
horrorMode = false;
levelHackCount = 0;
zombiesKilled = false;
rainDeleted = false;
adminHackCount = 0;
adminHackVisible = false;
infiniteKnife = false;
rainToggleEnabled = false;
zombieSlowEnabled = false;
// Reset button states
rainToggleButton.setText('Rain: OFF');
rainToggleButton.fill = 0x00AAFF;
zombieSlowButton.setText('Zombie Speed: Normal');
zombieSlowButton.fill = 0xFFAA00;
// Clean up admin hack buttons
for (var ahb = adminHackButtons.length - 1; ahb >= 0; ahb--) {
adminHackButtons[ahb].destroy();
}
adminHackButtons = [];
for (var bz = bloodZombies.length - 1; bz >= 0; bz--) {
bloodZombies[bz].destroy();
}
bloodZombies = [];
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
}
chickenJockies = [];
for (var kz = kingZombies.length - 1; kz >= 0; kz--) {
kingZombies[kz].destroy();
}
kingZombies = [];
if (groundKnife) {
groundKnife.destroy();
groundKnife = null;
}
if (bossZombie) {
bossZombie.destroy();
bossZombie = null;
}
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
bossMode = false;
// Reset score
LK.setScore(0);
// Spawn initial house and soldiers
spawnHouse();
spawnSoldiers();
// Spawn initial trees
for (var t = 0; t < 8; t++) {
spawnTree();
}
}
// Hack button functionality
hackButton.down = function () {
if (gameBlocked) return;
hackMenuVisible = !hackMenuVisible;
if (hackMenuVisible) {
showHackMenu();
} else {
hideHackMenu();
}
};
// Show hack menu function
function showHackMenu() {
var cheatNames = ['/Immortality', '/Finish the Game', '/Admin', '/Level Hack', '/Kill Zombies and Big Zombies', '/Delete Rain', 'BOSS FIGHT!'];
var colors = [0x00FF00, 0xFF0000, 0xFF8800, 0x8800FF, 0xFF00FF, 0x00FFFF, 0xFF0000];
for (var i = 0; i < cheatNames.length; i++) {
var button = new Text2(cheatNames[i], {
size: 60,
fill: colors[i]
});
button.anchor.set(0.5, 0.5);
button.x = 0;
button.y = -250 + i * 80;
button.cheatType = cheatNames[i].toLowerCase();
button.down = function () {
if (gameBlocked) return;
executeCheat(this.cheatType);
hideHackMenu();
};
hackMenuButtons.push(button);
LK.gui.center.addChild(button);
}
}
// Hide hack menu function
function hideHackMenu() {
for (var i = hackMenuButtons.length - 1; i >= 0; i--) {
hackMenuButtons[i].destroy();
}
hackMenuButtons = [];
hackMenuVisible = false;
}
// Show admin hack menu function
function showAdminHacks() {
var adminCheatNames = ['/level 999', '/give knife', '/summon zombie', '/summon zombie no AI', '/summon big zombie', '/summon big zombie no AI', '/summon tree no AI', '/summon chicken jockey', '/summon King Zombie', '/summon King Zombie no AI', '/Horror Mode!!'];
var adminColors = [0xFF00FF, 0x00FF00, 0xFF0000, 0x808080, 0x8B0000, 0x404040, 0x228B22, 0xFFFF00, 0x8B008B, 0x404040, 0x8B0000];
for (var i = 0; i < adminCheatNames.length; i++) {
var button = new Text2('Admin Hack ' + (i + 1) + ' : ' + adminCheatNames[i], {
size: 50,
fill: adminColors[i]
});
button.anchor.set(0, 1);
button.x = 120;
button.y = -100 - i * 60; // Stack above Level Hack button
button.adminCheatType = adminCheatNames[i].toLowerCase();
button.down = function () {
if (gameBlocked) return;
executeAdminCheat(this.adminCheatType);
};
adminHackButtons.push(button);
LK.gui.bottomLeft.addChild(button);
}
}
// Execute admin cheat function
function executeAdminCheat(cheatType) {
switch (cheatType) {
case '/level 999':
currentLevel = 999;
break;
case '/give knife':
infiniteKnife = true;
player.hasKnife = true;
player.knifeUses = 999;
break;
case '/summon zombie':
var zombie = new Zombie();
zombie.x = player.x + (Math.random() - 0.5) * 200;
zombie.y = player.y + (Math.random() - 0.5) * 200;
zombie.targetX = player.x;
zombie.targetY = player.y;
zombies.push(zombie);
game.addChild(zombie);
break;
case '/summon zombie no ai':
var zombieNoAI = new ZombieNoAI();
zombieNoAI.x = player.x + (Math.random() - 0.5) * 200;
zombieNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(zombieNoAI);
break;
case '/summon big zombie':
var bigZombie = new BigZombie();
bigZombie.x = player.x + (Math.random() - 0.5) * 200;
bigZombie.y = player.y + (Math.random() - 0.5) * 200;
bigZombie.targetX = player.x;
bigZombie.targetY = player.y;
bigZombies.push(bigZombie);
game.addChild(bigZombie);
break;
case '/summon big zombie no ai':
var bigZombieNoAI = new BigZombieNoAI();
bigZombieNoAI.x = player.x + (Math.random() - 0.5) * 200;
bigZombieNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(bigZombieNoAI);
break;
case '/summon tree no ai':
var treeNoAI = new TreeNoAI();
treeNoAI.x = player.x + (Math.random() - 0.5) * 200;
treeNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(treeNoAI);
break;
case '/summon chicken jockey':
var chickenJockey = new ChickenJockey();
chickenJockey.x = player.x + (Math.random() - 0.5) * 200;
chickenJockey.y = player.y + (Math.random() - 0.5) * 200;
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
chickenJockies.push(chickenJockey);
game.addChild(chickenJockey);
break;
case '/summon king zombie':
var kingZombie = new KingZombie();
kingZombie.x = player.x + (Math.random() - 0.5) * 200;
kingZombie.y = player.y + (Math.random() - 0.5) * 200;
kingZombies.push(kingZombie);
game.addChild(kingZombie);
break;
case '/summon king zombie no ai':
var kingZombieNoAI = new KingZombieNoAI();
kingZombieNoAI.x = player.x + (Math.random() - 0.5) * 200;
kingZombieNoAI.y = player.y + (Math.random() - 0.5) * 200;
game.addChild(kingZombieNoAI);
break;
case '/horror mode!!':
// Activate horror mode immediately
currentLevel = 1000;
horrorMode = true;
gameBlocked = false;
// Clear everything
clearAllGameObjects();
// Replace hack and rewind buttons with horror message
hackButton.destroy();
rewindButton.destroy();
var horrorMessage = new Text2('I WANT YOU TO DIE', {
size: 80,
fill: 0xFF0000
});
horrorMessage.anchor.set(1, 0);
horrorMessage.y = 200;
LK.gui.topRight.addChild(horrorMessage);
// Spawn blood knife in front of player
groundKnife = new GroundKnife();
groundKnife.x = player.x;
groundKnife.y = player.y - 100;
game.addChild(groundKnife);
// Spawn 30 blood zombies at center position
for (var bz = 0; bz < 30; bz++) {
var bloodZombie = new BloodZombie();
bloodZombie.x = 1024 + (Math.random() - 0.5) * 100;
bloodZombie.y = 1366 + (Math.random() - 0.5) * 100;
bloodZombies.push(bloodZombie);
game.addChild(bloodZombie);
}
// Play scary music
LK.stopMusic();
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.3,
duration: 2000
}
});
break;
}
}
// Execute cheat function
function executeCheat(cheatType) {
switch (cheatType) {
case '/immortality':
immortalMode = true;
break;
case '/level hack':
if (!levelHackButton) {
levelHackButton = new Text2('Level Hack', {
size: 60,
fill: 0xFF0000
});
levelHackButton.anchor.set(0, 1);
levelHackButton.x = 120;
levelHackButton.y = -50;
LK.gui.bottomLeft.addChild(levelHackButton);
levelHackButton.down = function () {
if (gameBlocked) return;
currentLevel++;
levelHackCount++;
// Check for level 1000 horror mode
if (currentLevel >= 1000 && !horrorMode) {
horrorMode = true;
gameBlocked = false; // Unblock game
// Remove STOP message if it exists
var stopElements = LK.gui.center.children;
for (var i = stopElements.length - 1; i >= 0; i--) {
if (stopElements[i].text && stopElements[i].text === 'STOP!') {
stopElements[i].destroy();
}
}
// Clear everything
clearAllGameObjects();
// Replace hack and rewind buttons with horror message
hackButton.destroy();
rewindButton.destroy();
var horrorMessage = new Text2('I WANT YOU TO DIE', {
size: 80,
fill: 0xFF0000
});
horrorMessage.anchor.set(1, 0);
horrorMessage.y = 200;
LK.gui.topRight.addChild(horrorMessage);
// Spawn ground knife
groundKnife = new GroundKnife();
groundKnife.x = 1024;
groundKnife.y = 1366;
game.addChild(groundKnife);
// Spawn 30 blood zombies
for (var bz = 0; bz < 30; bz++) {
var bloodZombie = new BloodZombie();
bloodZombie.x = Math.random() * 1800 + 100;
bloodZombie.y = Math.random() * 2400 + 100;
bloodZombies.push(bloodZombie);
game.addChild(bloodZombie);
}
// Play scary music
LK.stopMusic();
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 0.3,
duration: 2000
}
});
}
if (currentLevel >= 100 && levelHackCount >= 5) {
gameBlocked = false;
// Remove STOP message
var stopElements = LK.gui.center.children;
for (var i = stopElements.length - 1; i >= 0; i--) {
if (stopElements[i].text && stopElements[i].text === 'STOP!') {
stopElements[i].destroy();
}
}
} else if (currentLevel >= 100) {
gameBlocked = true;
var stopMessage = new Text2('STOP!', {
size: 150,
fill: 0xFF0000
});
stopMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(stopMessage);
}
};
}
break;
case '/admin':
adminMode = true;
adminHackCount++;
if (adminHackCount >= 10 && !adminHackVisible) {
adminHackVisible = true;
showAdminHacks();
}
break;
case '/finish the game':
var finishMessage = new Text2('FINISH!', {
size: 120,
fill: 0x00FF00
});
finishMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(finishMessage);
currentLevel = 3;
LK.setTimeout(function () {
finishMessage.destroy();
}, 3000);
break;
case '/kill zombies and big zombies':
zombiesKilled = true;
// Kill all existing zombies
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
// Kill all existing big zombies
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
break;
case '/delete rain':
rainDeleted = true;
isRaining = false;
rainTimer = 0;
// Remove all existing raindrops
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
break;
case 'boss fight!':
// Activate boss mode immediately
bossMode = true;
currentLevel = 10;
levelCompleted = false;
// Clear EVERYTHING including soldiers and houses
clearAllGameObjects();
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
// Show BOSS FIGHT message
bossMessage = new Text2('BOSS FIGHT!!', {
size: 150,
fill: 0xFF0000
});
bossMessage.anchor.set(0.5, 0);
LK.gui.top.addChild(bossMessage);
// Spawn boss zombie
bossZombie = new BossZombie();
bossZombie.x = 1024;
bossZombie.y = 200;
bossZombie.targetX = player.x;
bossZombie.targetY = player.y;
game.addChild(bossZombie);
break;
}
}
// Spawn initial house
spawnHouse();
function spawnSoldiers() {
for (var h = 0; h < houses.length; h++) {
var house = houses[h];
// Spawn 2-3 soldiers behind each house
var soldierCount = 2 + Math.floor(Math.random() * 2);
for (var s = 0; s < soldierCount; s++) {
var soldier = new Soldier();
soldier.x = house.x + (Math.random() - 0.5) * 150;
soldier.y = house.y + 50 + Math.random() * 50;
soldiers.push(soldier);
game.addChild(soldier);
}
}
}
function spawnTank() {
if (tank) return; // Only one tank at a time
tank = new Tank();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top
tank.x = Math.random() * 2048;
tank.y = -100;
break;
case 1:
// Right
tank.x = 2148;
tank.y = Math.random() * 2732;
break;
case 2:
// Bottom
tank.x = Math.random() * 2048;
tank.y = 2832;
break;
case 3:
// Left
tank.x = -100;
tank.y = Math.random() * 2732;
break;
}
game.addChild(tank);
LK.getSound('tankEngine').play();
}
function spawnPistol() {
var pistol = new Pistol();
pistol.x = Math.random() * (2048 - 100) + 50;
pistol.y = Math.random() * (2732 - 200) + 100;
pistols.push(pistol);
game.addChild(pistol);
}
// Spawn initial soldiers
spawnSoldiers();
function spawnTree() {
var tree = new Tree();
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 20) {
tree.x = Math.random() * (2048 - 120) + 60;
tree.y = Math.random() * (2732 - 200) + 150;
validPosition = true;
// Check distance from houses and other trees
for (var h = 0; h < houses.length; h++) {
var distance = Math.sqrt(Math.pow(tree.x - houses[h].x, 2) + Math.pow(tree.y - houses[h].y, 2));
if (distance < 200) {
validPosition = false;
break;
}
}
for (var t = 0; t < trees.length; t++) {
var distance = Math.sqrt(Math.pow(tree.x - trees[t].x, 2) + Math.pow(tree.y - trees[t].y, 2));
if (distance < 100) {
validPosition = false;
break;
}
}
attempts++;
}
trees.push(tree);
game.addChild(tree);
}
function createRain() {
for (var r = 0; r < 1; r++) {
// Reduced from 2 to 1 raindrop per call
var raindrop = new Raindrop();
raindrop.x = Math.random() * 2048;
raindrop.y = -20;
raindrops.push(raindrop);
game.addChild(raindrop);
}
}
function createLightning(x, y) {
var lightning = new Lightning();
lightning.x = x;
lightning.y = y;
lightnings.push(lightning);
game.addChild(lightning);
LK.getSound('thunder').play();
LK.effects.flashScreen(0xFFFFFF, 200);
}
// Spawn initial trees
for (var t = 0; t < 8; t++) {
spawnTree();
}
function spawnZombie() {
var zombie = new Zombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top
zombie.x = Math.random() * 2048;
zombie.y = -50;
break;
case 1:
// Right
zombie.x = 2098;
zombie.y = Math.random() * 2732;
break;
case 2:
// Bottom
zombie.x = Math.random() * 2048;
zombie.y = 2782;
break;
case 3:
// Left
zombie.x = -50;
zombie.y = Math.random() * 2732;
break;
}
zombie.speed = zombieSlowEnabled ? 0.3 : zombieSpeed + Math.random() * 0.5;
zombie.targetX = player.x;
zombie.targetY = player.y;
zombies.push(zombie);
game.addChild(zombie);
}
function spawnPowerUp() {
var types = ['speedBoost', 'shield', 'extraPoints', 'knife'];
var type = types[Math.floor(Math.random() * types.length)];
var powerUp = new PowerUp(type);
powerUp.x = Math.random() * (2048 - 100) + 50;
powerUp.y = Math.random() * (2732 - 200) + 100;
powerUps.push(powerUp);
game.addChild(powerUp);
}
function spawnHouse() {
var house = new House();
// Place houses away from edges and other houses
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 20) {
house.x = Math.random() * (2048 - 300) + 150;
house.y = Math.random() * (2732 - 300) + 200;
validPosition = true;
// Check distance from other houses
for (var h = 0; h < houses.length; h++) {
var distance = Math.sqrt(Math.pow(house.x - houses[h].x, 2) + Math.pow(house.y - houses[h].y, 2));
if (distance < 400) {
validPosition = false;
break;
}
}
attempts++;
}
houses.push(house);
game.addChild(house);
}
function dropRottenMeat(x, y) {
var meat = new RottenMeat();
meat.x = x + (Math.random() - 0.5) * 50;
meat.y = y + (Math.random() - 0.5) * 50;
rottenMeats.push(meat);
game.addChild(meat);
}
function isPlayerInSafeZone() {
for (var h = 0; h < houses.length; h++) {
var distance = Math.sqrt(Math.pow(player.x - houses[h].x, 2) + Math.pow(player.y - houses[h].y, 2));
if (distance < safeZoneRadius) {
return true;
}
}
return false;
}
function handleMove(x, y, obj) {
if (gameBlocked) return; // Block movement when game is blocked
if (horrorMode && groundKnife) return; // Block movement until knife is picked up
if (dragNode) {
// Apply speed multiplier
var targetX = x;
var targetY = y;
// Smooth movement with speed
var dx = targetX - dragNode.x;
var dy = targetY - dragNode.y;
dragNode.x += dx * 0.1 * dragNode.speed;
dragNode.y += dy * 0.1 * dragNode.speed;
// Keep player within bounds
dragNode.x = Math.max(40, Math.min(2008, dragNode.x));
dragNode.y = Math.max(40, Math.min(2692, dragNode.y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Block all input if game is blocked
if (gameBlocked) return;
// Check if player has pistol and ammo
if (playerHasPistol && playerAmmo > 0) {
// Shoot towards touch/click position
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y;
var dx = x - player.x;
var dy = y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 10;
bullet.velocityY = dy / distance * 10;
}
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('gunshot').play();
playerAmmo--;
if (playerAmmo <= 0) {
playerHasPistol = false;
}
} else {
// Normal movement
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
survivalTime++;
// Update score and UI
var timeInSeconds = Math.floor(survivalTime / 60);
var score = Math.floor(survivalTime / 10) + LK.getScore();
var healthText = immortalMode ? 'Health: FOREVER' : 'Health: ' + player.health;
healthTxt.setText(healthText);
// Update knife display separately
if (player.hasKnife && player.knifeUses > 0) {
knifeTxt.setText('Knife: ' + player.knifeUses);
} else {
knifeTxt.setText('');
}
scoreTxt.setText('Level ' + currentLevel + ' - Score: ' + score);
timeTxt.setText('Time: ' + timeInSeconds + 's');
// Increase difficulty over time (more aggressive in higher levels)
if (survivalTime % 600 == 0) {
// Every 10 seconds
var spawnRateDecrease = currentLevel * 3; // More aggressive in higher levels
var speedIncrease = currentLevel * 0.15; // More aggressive in higher levels
if (zombieSpawnRate > minZombieSpawnRate) {
zombieSpawnRate -= spawnRateDecrease;
}
if (zombieSpeed < maxZombieSpeed) {
zombieSpeed += speedIncrease;
}
}
// Spawn zombies (but not in horror mode at level 1000 or after level 200)
if (survivalTime % zombieSpawnRate == 0 && !(horrorMode && currentLevel >= 1000) && currentLevel < 200 && !zombiesKilled) {
spawnZombie();
}
// Block spawning of dev zombies, normal zombies and items in horror mode
if (!horrorMode) {
// Spawn green zombie every 300 score (blocked if zombies killed cheat is active)
var currentScore = Math.floor(survivalTime / 10) + LK.getScore();
if (currentScore > 0 && currentScore % 300 === 0 && survivalTime % 60 === 0 && !zombiesKilled) {
var greenZombie = new GreenZombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
greenZombie.x = Math.random() * 2048;
greenZombie.y = -50;
break;
case 1:
greenZombie.x = 2098;
greenZombie.y = Math.random() * 2732;
break;
case 2:
greenZombie.x = Math.random() * 2048;
greenZombie.y = 2782;
break;
case 3:
greenZombie.x = -50;
greenZombie.y = Math.random() * 2732;
break;
}
greenZombie.targetX = player.x;
greenZombie.targetY = player.y;
greenZombies.push(greenZombie);
game.addChild(greenZombie);
}
// Spawn strong zombie every 200 score
if (currentScore > 0 && currentScore % 200 === 0 && survivalTime % 90 === 0) {
var strongZombie = new StrongZombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
strongZombie.x = Math.random() * 2048;
strongZombie.y = -50;
break;
case 1:
strongZombie.x = 2098;
strongZombie.y = Math.random() * 2732;
break;
case 2:
strongZombie.x = Math.random() * 2048;
strongZombie.y = 2782;
break;
case 3:
strongZombie.x = -50;
strongZombie.y = Math.random() * 2732;
break;
}
strongZombie.targetX = player.x;
strongZombie.targetY = player.y;
strongZombies.push(strongZombie);
game.addChild(strongZombie);
}
// Spawn big zombie at specific score intervals (blocked if zombies killed cheat is active)
var bigZombieScores = [300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600, 3900, 4200, 4500, 4800, 5100, 5400, 5700, 6000, 6300, 6600, 6900, 7200];
for (var i = 0; i < bigZombieScores.length; i++) {
if (currentScore === bigZombieScores[i] && survivalTime % 60 === 0 && !zombiesKilled) {
var bigZombie = new BigZombie();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
bigZombie.x = Math.random() * 2048;
bigZombie.y = -50;
break;
case 1:
bigZombie.x = 2098;
bigZombie.y = Math.random() * 2732;
break;
case 2:
bigZombie.x = Math.random() * 2048;
bigZombie.y = 2782;
break;
case 3:
bigZombie.x = -50;
bigZombie.y = Math.random() * 2732;
break;
}
bigZombie.targetX = player.x;
bigZombie.targetY = player.y;
bigZombies.push(bigZombie);
game.addChild(bigZombie);
break;
}
}
}
// Spawn chicken jockey at score 2200
if (currentScore === 2200 && survivalTime % 60 === 0 && chickenJockies.length === 0) {
var chickenJockey = new ChickenJockey();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
chickenJockey.x = Math.random() * 2048;
chickenJockey.y = -50;
break;
case 1:
chickenJockey.x = 2098;
chickenJockey.y = Math.random() * 2732;
break;
case 2:
chickenJockey.x = Math.random() * 2048;
chickenJockey.y = 2782;
break;
case 3:
chickenJockey.x = -50;
chickenJockey.y = Math.random() * 2732;
break;
}
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
chickenJockies.push(chickenJockey);
game.addChild(chickenJockey);
}
// Despawn chicken jockey at score 2900
if (currentScore >= 2900 && chickenJockies.length > 0) {
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
chickenJockies.splice(cj, 1);
}
}
// Spawn power-ups occasionally (less frequent in higher levels, blocked in horror mode)
if (!horrorMode) {
var powerUpChance = 0.002 / currentLevel; // Harder in higher levels
if (survivalTime > 300 && Math.random() < powerUpChance && !(horrorMode && currentLevel >= 1000)) {
spawnPowerUp();
}
}
// Update zombie targets
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
// Check if player is in safe zone
var playerInSafeZone = isPlayerInSafeZone();
if (playerInSafeZone) {
// Find closest house edge to target instead of player directly
var closestHouse = null;
var closestDistance = Infinity;
for (var h = 0; h < houses.length; h++) {
var houseDistance = Math.sqrt(Math.pow(player.x - houses[h].x, 2) + Math.pow(player.y - houses[h].y, 2));
if (houseDistance < safeZoneRadius && houseDistance < closestDistance) {
closestDistance = houseDistance;
closestHouse = houses[h];
}
}
if (closestHouse) {
// Target edge of safe zone instead of player
var dx = player.x - closestHouse.x;
var dy = player.y - closestHouse.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
zombie.targetX = closestHouse.x + dx / distance * (safeZoneRadius + 20);
zombie.targetY = closestHouse.y + dy / distance * (safeZoneRadius + 20);
} else {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
} else {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
} else {
zombie.targetX = player.x;
zombie.targetY = player.y;
}
// Check collision with player
if (zombie.intersects(player)) {
if (player.useKnife()) {
// Knife kills zombie and gives points
LK.setScore(LK.getScore() + 10);
dropRottenMeat(zombie.x, zombie.y); // Drop meat when killed
zombie.destroy();
zombies.splice(i, 1);
} else {
// No knife, take damage only if not in safe zone
if (!isPlayerInSafeZone()) {
player.takeDamage(10);
}
zombie.destroy();
zombies.splice(i, 1);
}
continue;
}
// Remove zombies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(zombie.x - player.x, 2) + Math.pow(zombie.y - player.y, 2));
if (distanceFromPlayer > 3000) {
zombie.destroy();
zombies.splice(i, 1);
}
}
// Check power-up collisions
for (var j = powerUps.length - 1; j >= 0; j--) {
var powerUp = powerUps[j];
if (powerUp.intersects(player)) {
LK.getSound('powerup').play();
switch (powerUp.type) {
case 'speedBoost':
player.speed = 1.5;
tween(player, {
speed: 1.0
}, {
duration: 3000
});
break;
case 'shield':
player.activateShield();
break;
case 'extraPoints':
LK.setScore(LK.getScore() + 50);
break;
case 'knife':
player.activateKnife();
break;
}
powerUp.destroy();
powerUps.splice(j, 1);
}
if (powerUp.lifetime <= 0) {
powerUps.splice(j, 1);
}
}
// Update green zombies
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
var greenZombie = greenZombies[gz];
// Update target
greenZombie.targetX = player.x;
greenZombie.targetY = player.y;
// Check collision with player
if (greenZombie.intersects(player)) {
if (player.useKnife()) {
// Knife damages green zombie
if (greenZombie.takeDamage()) {
// Green zombie dies, drop big meat
var bigMeat = new BigRottenMeat();
bigMeat.x = greenZombie.x;
bigMeat.y = greenZombie.y;
rottenMeats.push(bigMeat);
game.addChild(bigMeat);
LK.setScore(LK.getScore() + 50);
greenZombie.destroy();
greenZombies.splice(gz, 1);
}
} else {
// No knife, take big damage only if not in safe zone
if (!isPlayerInSafeZone()) {
player.takeDamage(30);
}
greenZombie.destroy();
greenZombies.splice(gz, 1);
}
continue;
}
// Remove green zombies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(greenZombie.x - player.x, 2) + Math.pow(greenZombie.y - player.y, 2));
if (distanceFromPlayer > 3000) {
greenZombie.destroy();
greenZombies.splice(gz, 1);
}
}
// Update strong zombies
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
var strongZombie = strongZombies[sz];
// Update target
strongZombie.targetX = player.x;
strongZombie.targetY = player.y;
// Check collision with player
if (strongZombie.intersects(player)) {
// Strong zombie always deals 30 damage, no knife defense
if (!isPlayerInSafeZone()) {
player.takeDamage(30);
}
// Drop big rotten meat when hitting player
var bigMeat = new BigRottenMeat();
bigMeat.x = strongZombie.x;
bigMeat.y = strongZombie.y;
rottenMeats.push(bigMeat);
game.addChild(bigMeat);
// Make player health full when eating big meat
player.health = player.maxHealth;
strongZombie.destroy();
strongZombies.splice(sz, 1);
continue;
}
// Remove strong zombies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(strongZombie.x - player.x, 2) + Math.pow(strongZombie.y - player.y, 2));
if (distanceFromPlayer > 3000) {
strongZombie.destroy();
strongZombies.splice(sz, 1);
}
}
// Update big zombies
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
var bigZombie = bigZombies[bz];
// Update target
bigZombie.targetX = player.x;
bigZombie.targetY = player.y;
// Check collision with player
if (bigZombie.intersects(player)) {
if (player.useKnife()) {
// Knife damages big zombie
if (bigZombie.takeDamage()) {
// Big zombie dies
LK.setScore(LK.getScore() + 100);
bigZombie.destroy();
bigZombies.splice(bz, 1);
}
} else {
// No knife, big zombie never gets destroyed from player collision
if (!isPlayerInSafeZone()) {
player.takeDamage(50); // High damage
}
}
continue;
}
// Big zombies never get removed for being too far away - they persist
}
// Update chicken jockies
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
var chickenJockey = chickenJockies[cj];
// Update target
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
// Check collision with player
if (chickenJockey.intersects(player)) {
// Chicken jockey deals 25 damage and reduces hunger by 2
if (!isPlayerInSafeZone()) {
player.takeDamage(25);
hungerLevel = Math.max(0, hungerLevel - 2);
}
chickenJockey.destroy();
chickenJockies.splice(cj, 1);
continue;
}
// Remove chicken jockies that are too far away
var distanceFromPlayer = Math.sqrt(Math.pow(chickenJockey.x - player.x, 2) + Math.pow(chickenJockey.y - player.y, 2));
if (distanceFromPlayer > 3000) {
chickenJockey.destroy();
chickenJockies.splice(cj, 1);
}
}
// Handle bullets vs green zombies (bullets don't work)
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
for (var gz = 0; gz < greenZombies.length; gz++) {
var greenZombie = greenZombies[gz];
if (bullet.intersects(greenZombie)) {
// Bullets don't damage green zombies, just destroy bullet
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Handle bullets vs strong zombies (bullets don't work)
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
for (var sz = 0; sz < strongZombies.length; sz++) {
var strongZombie = strongZombies[sz];
if (bullet.intersects(strongZombie)) {
// Bullets don't damage strong zombies, just destroy bullet
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Handle bullets vs big zombies (bullets don't work)
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
for (var bz = 0; bz < bigZombies.length; bz++) {
var bigZombie = bigZombies[bz];
if (bullet.intersects(bigZombie)) {
// Bullets don't damage big zombies, just destroy bullet
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Handle soldier bullets vs green zombies (bullets don't work)
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
for (var gz = 0; gz < greenZombies.length; gz++) {
var greenZombie = greenZombies[gz];
if (bullet.intersects(greenZombie)) {
// Bullets don't damage green zombies, just destroy bullet
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Handle soldier bullets vs strong zombies (bullets don't work)
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
for (var sz = 0; sz < strongZombies.length; sz++) {
var strongZombie = strongZombies[sz];
if (bullet.intersects(strongZombie)) {
// Bullets don't damage strong zombies, just destroy bullet
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Handle soldier bullets vs big zombies (bullets don't work)
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
for (var bz = 0; bz < bigZombies.length; bz++) {
var bigZombie = bigZombies[bz];
if (bullet.intersects(bigZombie)) {
// Bullets don't damage big zombies, just destroy bullet
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Check rotten meat collisions
for (var m = rottenMeats.length - 1; m >= 0; m--) {
var meat = rottenMeats[m];
if (meat.intersects(player)) {
if (meat instanceof BigRottenMeat) {
// Big meat restores health but reduces hunger
player.health = player.maxHealth;
hungerLevel = Math.max(0, hungerLevel - 5);
} else {
// Regular meat increases hunger and stays green for 5 seconds
hungerLevel = Math.min(maxHunger, hungerLevel + 1);
hungerTimer = 300; // 5 seconds of green hunger bar
}
meatCollected++;
safeZoneRadius += 5; // Expand safe zone with each meat collected
LK.getSound('powerup').play();
meat.destroy();
rottenMeats.splice(m, 1);
// Spawn new house every 10 meat collected
if (meatCollected % 10 === 0 && houses.length < 5) {
spawnHouse();
}
continue;
}
if (meat.lifetime <= 0) {
rottenMeats.splice(m, 1);
}
}
// Weather system (more frequent in higher levels, blocked if rain deleted or rain toggle enabled)
var rainChance = 0.001 * currentLevel; // More rain in higher levels
if (!isRaining && Math.random() < rainChance && !rainDeleted && !rainToggleEnabled) {
// Start rain
isRaining = true;
rainTimer = 600 + Math.random() * 600; // Rain for 10-20 seconds
}
if (isRaining && !rainToggleEnabled) {
rainTimer--;
if (rainTimer <= 0) {
isRaining = false;
} else {
// Create raindrops (reduced frequency)
if (survivalTime % 16 == 0) {
// Further reduced from 8 to 16 for better performance
createRain();
}
}
}
// Lightning strikes during rain
if (isRaining && Math.random() < 0.005) {
// Lightning on zombies (100/50 chance)
if (zombies.length > 0 && Math.random() < 0.5) {
var randomZombie = zombies[Math.floor(Math.random() * zombies.length)];
createLightning(randomZombie.x, randomZombie.y - 100);
// Kill the zombie
LK.setScore(LK.getScore() + 20);
dropRottenMeat(randomZombie.x, randomZombie.y);
randomZombie.destroy();
zombies.splice(zombies.indexOf(randomZombie), 1);
}
// Lightning on trees (100/70 chance)
if (trees.length > 0 && Math.random() < 0.7) {
var randomTree = trees[Math.floor(Math.random() * trees.length)];
createLightning(randomTree.x, randomTree.y - 60);
randomTree.strikeWithLightning();
}
}
// Clean up raindrops
for (var r = raindrops.length - 1; r >= 0; r--) {
if (raindrops[r].y > 2800) {
raindrops.splice(r, 1);
}
}
// Clean up lightning
for (var l = lightnings.length - 1; l >= 0; l--) {
if (lightnings[l].lifetime <= 0) {
lightnings.splice(l, 1);
}
}
// Tank spawning logic
tankSpawnTimer--;
if (tankSpawnTimer <= 0) {
spawnTank();
tankSpawnTimer = 3600; // Reset to 1 minute
}
// Remove tank after some time and increase zombie spawn
if (tank) {
var tankDistance = Math.sqrt(Math.pow(tank.x - tank.targetX, 2) + Math.pow(tank.y - tank.targetY, 2));
if (tankDistance < 50) {
// Tank reached center, remove it and spawn more zombies
tank.destroy();
tank = null;
// Spawn extra zombies after tank leaves
for (var tz = 0; tz < 5; tz++) {
spawnZombie();
}
}
}
// Update soldiers
for (var s = soldiers.length - 1; s >= 0; s--) {
var soldier = soldiers[s];
if (soldier.health <= 0) {
soldiers.splice(s, 1);
continue;
}
// Soldier takes damage from nearby zombies
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
var distance = Math.sqrt(Math.pow(zombie.x - soldier.x, 2) + Math.pow(zombie.y - soldier.y, 2));
if (distance < 30) {
soldier.takeDamage(5);
break;
}
}
}
// Update soldier bullets
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
var bullet = soldierBullets[sb];
if (bullet.lifetime <= 0) {
soldierBullets.splice(sb, 1);
continue;
}
// Check collision with zombies
for (var z = zombies.length - 1; z >= 0; z--) {
var zombie = zombies[z];
if (bullet.intersects(zombie)) {
LK.setScore(LK.getScore() + 10);
dropRottenMeat(zombie.x, zombie.y);
zombie.destroy();
zombies.splice(z, 1);
bullet.destroy();
soldierBullets.splice(sb, 1);
break;
}
}
}
// Update player bullets
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
if (bullet.lifetime <= 0) {
playerBullets.splice(pb, 1);
continue;
}
// Check collision with zombies
for (var z = zombies.length - 1; z >= 0; z--) {
var zombie = zombies[z];
if (bullet.intersects(zombie)) {
LK.setScore(LK.getScore() + 15);
dropRottenMeat(zombie.x, zombie.y);
zombie.destroy();
zombies.splice(z, 1);
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
}
// Check pistol collisions with player
for (var p = pistols.length - 1; p >= 0; p--) {
var pistol = pistols[p];
if (pistol.intersects(player)) {
playerHasPistol = true;
playerAmmo = pistol.ammo;
LK.getSound('powerup').play();
pistol.destroy();
pistols.splice(p, 1);
continue;
}
if (pistol.lifetime <= 0) {
pistols.splice(p, 1);
}
}
// Spawn pistols after tank visits (blocked in horror mode)
if (survivalTime > 3600 && Math.random() < 0.003 && !(horrorMode && currentLevel >= 1000)) {
spawnPistol();
}
// Spawn new soldiers when houses are built
if (meatCollected % 10 === 0 && survivalTime % 60 === 0 && houses.length > soldiers.length / 2) {
spawnSoldiers();
}
// Check level completion based on score milestones
var currentScore = Math.floor(survivalTime / 10) + LK.getScore();
// Level progression every 1000 points
var targetLevel = Math.floor(currentScore / 1000) + 1;
if (targetLevel > currentLevel && !levelCompleted && !bossMode) {
currentLevel = targetLevel;
levelCompleted = true;
if (currentLevel === 10) {
// Level 10 - BOSS FIGHT
bossMode = true;
levelCompleted = false;
// Clear EVERYTHING including soldiers and houses
clearAllGameObjects();
for (var h = houses.length - 1; h >= 0; h--) {
houses[h].destroy();
}
houses = [];
for (var s = soldiers.length - 1; s >= 0; s--) {
soldiers[s].destroy();
}
soldiers = [];
for (var sb = soldierBullets.length - 1; sb >= 0; sb--) {
soldierBullets[sb].destroy();
}
soldierBullets = [];
// Show BOSS FIGHT message
bossMessage = new Text2('BOSS FIGHT!!', {
size: 150,
fill: 0xFF0000
});
bossMessage.anchor.set(0.5, 0);
LK.gui.top.addChild(bossMessage);
// Spawn boss zombie
bossZombie = new BossZombie();
bossZombie.x = 1024;
bossZombie.y = 200;
bossZombie.targetX = player.x;
bossZombie.targetY = player.y;
game.addChild(bossZombie);
// Only spawn knives and pistols in boss mode
if (Math.random() < 0.05) {
var knife = new PowerUp('knife');
knife.x = Math.random() * 1800 + 100;
knife.y = Math.random() * 2400 + 100;
powerUps.push(knife);
game.addChild(knife);
}
if (Math.random() < 0.03) {
spawnPistol();
}
} else {
// Regular level progression (levels 2-9)
// Clear everything except soldiers, houses and trees
for (var z = zombies.length - 1; z >= 0; z--) {
zombies[z].destroy();
}
zombies = [];
for (var gz = greenZombies.length - 1; gz >= 0; gz--) {
greenZombies[gz].destroy();
}
greenZombies = [];
for (var sz = strongZombies.length - 1; sz >= 0; sz--) {
strongZombies[sz].destroy();
}
strongZombies = [];
for (var bz = bigZombies.length - 1; bz >= 0; bz--) {
bigZombies[bz].destroy();
}
bigZombies = [];
for (var p = powerUps.length - 1; p >= 0; p--) {
powerUps[p].destroy();
}
powerUps = [];
for (var m = rottenMeats.length - 1; m >= 0; m--) {
rottenMeats[m].destroy();
}
rottenMeats = [];
for (var r = raindrops.length - 1; r >= 0; r--) {
raindrops[r].destroy();
}
raindrops = [];
for (var l = lightnings.length - 1; l >= 0; l--) {
lightnings[l].destroy();
}
lightnings = [];
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
playerBullets[pb].destroy();
}
playerBullets = [];
for (var pi = pistols.length - 1; pi >= 0; pi--) {
pistols[pi].destroy();
}
pistols = [];
if (tank) {
tank.destroy();
tank = null;
}
for (var cj = chickenJockies.length - 1; cj >= 0; cj--) {
chickenJockies[cj].destroy();
}
chickenJockies = [];
for (var kz = kingZombies.length - 1; kz >= 0; kz--) {
kingZombies[kz].destroy();
}
kingZombies = [];
// Reset player position
player.x = 1024;
player.y = 1366;
// Show level complete for 2 seconds
levelCompleteMessage = new Text2('Level ' + currentLevel, {
size: 120,
fill: 0x00FF00
});
levelCompleteMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(levelCompleteMessage);
LK.setTimeout(function () {
if (levelCompleteMessage) {
levelCompleteMessage.destroy();
levelCompleteMessage = null;
}
levelCompleted = false;
}, 2000);
}
}
// Pause game mechanics when showing level complete
if (showingLevelComplete && currentLevel === 1) {
return; // Don't update game mechanics
}
// Admin mode effects (basic level and health manipulation)
if (adminMode && Math.random() < 0.01) {
// Randomly adjust level (simulate admin controls)
if (Math.random() < 0.5) {
currentLevel = Math.min(currentLevel + 1, 150);
}
// Randomly restore health
if (player.health < 100 && Math.random() < 0.3) {
player.health = 100;
}
}
// Hunger system
if (hungerTimer > 0) {
hungerTimer--;
}
// Hunger damage when hunger reaches 0
if (hungerLevel <= 0) {
hungerDamageTimer++;
if (hungerDamageTimer >= 300) {
// 5 seconds
hungerDamageTimer = 0;
if (!immortalMode) {
player.health -= 10;
LK.effects.flashObject(player, 0xff0000, 200);
if (player.health <= 0) {
player.health = 0;
LK.showGameOver();
}
}
}
}
// Update UI
meatTxt.setText('Meat: ' + meatCollected);
if (playerHasPistol && playerAmmo > 0) {
ammoTxt.setText('Ammo: ' + playerAmmo);
} else {
ammoTxt.setText('');
}
// Boss fight logic
if (bossMode && bossZombie) {
// Update boss target
bossZombie.targetX = player.x;
bossZombie.targetY = player.y;
// Boss collision with player
if (bossZombie.intersects(player)) {
if (player.useKnife()) {
if (bossZombie.takeDamage('knife')) {
// Boss defeated!
bossZombie.destroy();
bossZombie = null;
bossMode = false;
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
LK.showYouWin();
return;
}
} else {
// Boss attacks player
if (!isPlayerInSafeZone()) {
player.takeDamage(50);
}
}
}
// Check player bullets vs boss
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var bullet = playerBullets[pb];
if (bullet.intersects(bossZombie)) {
if (bossZombie.takeDamage('bullet')) {
// Boss defeated!
bossZombie.destroy();
bossZombie = null;
bossMode = false;
if (bossMessage) {
bossMessage.destroy();
bossMessage = null;
}
// Show REAL FINISH message
var realFinishMessage = new Text2('REAL FINISH!!', {
size: 120,
fill: 0x00FF00
});
realFinishMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(realFinishMessage);
LK.setTimeout(function () {
if (realFinishMessage && realFinishMessage.parent) {
realFinishMessage.destroy();
}
LK.showYouWin();
}, 3000);
return;
}
bullet.destroy();
playerBullets.splice(pb, 1);
break;
}
}
// Continue spawning chicken jockies and zombies in boss fight
if (survivalTime % 180 == 0) {
var chickenJockey = new ChickenJockey();
chickenJockey.x = Math.random() * 2048;
chickenJockey.y = -50;
chickenJockey.targetX = player.x;
chickenJockey.targetY = player.y;
chickenJockies.push(chickenJockey);
game.addChild(chickenJockey);
}
if (survivalTime % zombieSpawnRate == 0) {
spawnZombie();
}
return; // Skip normal game mechanics in boss mode
}
// Horror mode logic
if (horrorMode) {
// Check ground knife pickup
if (groundKnife && groundKnife.intersects(player)) {
player.activateKnife();
groundKnife.destroy();
groundKnife = null;
// Enable movement after knife pickup by allowing normal dragging
}
// Check blood zombie interactions
for (var bz = bloodZombies.length - 1; bz >= 0; bz--) {
var bloodZombie = bloodZombies[bz];
if (bloodZombie.intersects(player)) {
if (player.useKnife()) {
// Blood zombie killed with blood knife - activate all remaining blood zombies
if (bloodZombies.length > 1) {
var dieMessage = new Text2('I WANT YOU TO DIE', {
size: 200,
fill: 0xFF0000
});
dieMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(dieMessage);
// Activate all remaining blood zombies to attack player
for (var i = 0; i < bloodZombies.length; i++) {
if (i !== bz) {
bloodZombies[i].activate();
}
}
// Remove message after 3 seconds
LK.setTimeout(function () {
if (dieMessage && dieMessage.parent) {
dieMessage.destroy();
}
}, 3000);
}
bloodZombie.destroy();
bloodZombies.splice(bz, 1);
} else {
// Blood zombie attacks player
if (!isPlayerInSafeZone()) {
player.takeDamage(20);
}
}
}
}
return; // Skip normal game mechanics in horror mode
}
// Update hunger display
var hungerColor = 0xFF0000; // Red by default
if (hungerLevel > 5) {
hungerColor = 0x00FF00; // Green for high hunger
} else if (hungerLevel > 2) {
hungerColor = 0xFFFF00; // Yellow for medium hunger
}
if (hungerTimer > 0) {
hungerColor = 0x00FF00; // Green when eating
}
hungerTxt.setText('Hunger: ' + hungerLevel + '/' + maxHunger);
hungerTxt.fill = hungerColor;
};
LK.playMusic('bgmusic');
korkmuş turuncu tişörtlü mavi pantolonlu genç bir insan. In-Game asset. 2d. High contrast. No shadows
Bir zombi çiz ama 2 boyutlu. In-Game asset. 2d. High contrast. No shadows
house. In-Game asset. 2d. High contrast. No shadows
tree cartoons. In-Game asset. 2d. High contrast. No shadows
elinde silah olan 2 boyutlu asker. In-Game asset. 2d. High contrast. No shadows
askeri tank png. In-Game asset. 2d. High contrast. No shadows
büyük kaslı ve Güçlü zombie 2 boyutlu png. In-Game asset. 2d. High contrast. No shadows
Kral Zombi 2 boyutlu. In-Game asset. 2d. High contrast. No shadows