User prompt
Undo the last thing
User prompt
Whenever they shoot make them walk a bit faster
User prompt
Make code so that wherever the player shoots that's where they go
User prompt
Make code so zombies don't do as much damage
User prompt
I didn't say make them instantly die make it like it was
User prompt
Can you code it so you can't get stuck Inside zombies so you die instantly please
User prompt
Can you make code for the player to be able to choose where to move
User prompt
Can you write code for it
Code edit (1 edits merged)
Please save this source code
User prompt
Zombie Bros: Apocalypse Duo
Initial prompt
Can you make a game about two brothers battling zombies in the apocalypse and you only control one brother. Make it feel like it is multiplayer with the other brother and also make it in an 8-bit type style please.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var AmmoDisplay = Container.expand(function () { var self = Container.call(this); self.indicators = []; self.player = null; self.init = function (playerRef) { self.player = playerRef; // Clear existing indicators for (var i = 0; i < self.indicators.length; i++) { self.removeChild(self.indicators[i]); } self.indicators = []; // Create new indicators for (var i = 0; i < self.player.maxAmmo; i++) { var indicator = LK.getAsset('ammoIndicator', { anchorX: 0.5, anchorY: 0.5, x: i * 20, y: 0 }); self.addChild(indicator); self.indicators.push(indicator); } }; self.update = function () { if (!self.player) { return; } // Update visibility based on current ammo for (var i = 0; i < self.indicators.length; i++) { self.indicators[i].visible = i < self.player.ammo; // Fade effect when reloading if (self.player.isReloading) { var reloadProgress = 1 - self.player.reloadCounter / self.player.reloadTime; if (i < Math.floor(reloadProgress * self.player.maxAmmo)) { self.indicators[i].visible = true; self.indicators[i].alpha = 0.5; } else { self.indicators[i].visible = false; } } else { self.indicators[i].alpha = 1; } } }; return self; }); var Blood = Container.expand(function () { var self = Container.call(this); var bloodGraphics = self.attachAsset('blood', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); self.lifespan = 60; // Frames self.init = function (x, y) { self.x = x; self.y = y; self.scale.x = 0.5 + Math.random() * 0.5; self.scale.y = 0.5 + Math.random() * 0.5; self.rotation = Math.random() * Math.PI * 2; self.alpha = 0.8; }; self.update = function () { self.lifespan--; if (self.lifespan <= 20) { self.alpha = self.lifespan / 20 * 0.8; } if (self.lifespan <= 0) { self.shouldDestroy = true; } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.damage = 25; self.direction = { x: 0, y: 0 }; self.shooter = null; self.update = function () { self.x += self.direction.x * self.speed; self.y += self.direction.y * self.speed; // Destroy bullet if it goes off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.shouldDestroy = true; } }; self.fire = function (startX, startY, targetX, targetY, shooterRef) { self.x = startX; self.y = startY; self.shooter = shooterRef; // Calculate direction var dx = targetX - startX; var dy = targetY - startY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.direction.x = dx / distance; self.direction.y = dy / distance; } }; return self; }); var HealthBar = Container.expand(function () { var self = Container.call(this); var background = self.attachAsset('healthBarBackground', { anchorX: 0, anchorY: 0 }); var bar = self.attachAsset('healthBar', { anchorX: 0, anchorY: 0, x: 2, y: 2 }); var playerText = new Text2("P1", { size: 20, fill: 0xFFFFFF }); playerText.anchor.set(0.5); playerText.x = background.width / 2; playerText.y = background.height / 2; self.addChild(playerText); self.player = null; self.init = function (playerRef, isPlayer1) { self.player = playerRef; playerText.setText(isPlayer1 ? "P1" : "P2"); }; self.update = function () { if (!self.player) { return; } var healthPercent = self.player.health / self.player.maxHealth; bar.scale.x = healthPercent; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); self.isPlayer1 = true; // Will be set when initializing var graphicsId = 'player1'; // Default self.health = 100; self.maxHealth = 100; self.moveSpeed = 5; self.fireRate = 15; // Frames between shots self.fireCounter = 0; self.ammo = 12; self.maxAmmo = 12; self.reloadTime = 120; // 2 seconds at 60fps self.reloadCounter = 0; self.isReloading = false; self.isDead = false; self.lastMoveDirection = { x: 0, y: -1 }; // Default facing up self.init = function (isFirstPlayer) { self.isPlayer1 = isFirstPlayer; graphicsId = isFirstPlayer ? 'player1' : 'player2'; if (self.graphics) { self.removeChild(self.graphics); } self.graphics = self.attachAsset(graphicsId, { anchorX: 0.5, anchorY: 0.5 }); self.health = self.maxHealth; self.ammo = self.maxAmmo; self.fireCounter = 0; self.reloadCounter = 0; self.isReloading = false; self.isDead = false; }; self.takeDamage = function (amount) { if (self.isDead) { return; } self.health -= amount; if (self.health <= 0) { self.health = 0; self.die(); } else { // Flash red when hit LK.effects.flashObject(self, 0xff0000, 300); LK.getSound('playerHit').play(); } }; self.die = function () { self.isDead = true; self.alpha = 0.5; // Flash red when dead LK.effects.flashObject(self, 0xff0000, 1000); }; self.shoot = function (targetX, targetY) { if (self.isDead || self.isReloading) { return null; } if (self.ammo <= 0) { self.reload(); return null; } if (self.fireCounter <= 0) { // Create bullet var bullet = new Bullet(); bullet.fire(self.x, self.y, targetX, targetY, self); // Update state self.ammo--; self.fireCounter = self.fireRate; // Keep track of facing direction based on shot var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.lastMoveDirection.x = dx / distance; self.lastMoveDirection.y = dy / distance; } // Play sound LK.getSound('shoot').play(); return bullet; } return null; }; self.reload = function () { if (self.isDead || self.isReloading || self.ammo === self.maxAmmo) { return; } self.isReloading = true; self.reloadCounter = self.reloadTime; LK.getSound('reload').play(); }; self.move = function (dx, dy) { if (self.isDead) { return; } // If moving, update last move direction if (dx !== 0 || dy !== 0) { var length = Math.sqrt(dx * dx + dy * dy); if (length > 0) { self.lastMoveDirection.x = dx / length; self.lastMoveDirection.y = dy / length; } } // Apply movement var newX = self.x + dx * self.moveSpeed; var newY = self.y + dy * self.moveSpeed; // Constrain to game bounds with a margin var margin = 50; newX = Math.max(margin, Math.min(2048 - margin, newX)); newY = Math.max(margin, Math.min(2732 - margin, newY)); self.x = newX; self.y = newY; }; self.update = function () { // Update reload state if (self.isReloading) { self.reloadCounter--; if (self.reloadCounter <= 0) { self.isReloading = false; self.ammo = self.maxAmmo; } } // Update fire rate counter if (self.fireCounter > 0) { self.fireCounter--; } // AI behavior for Player 2 if (!self.isPlayer1 && !self.isDead) { self.updateAI(); } }; self.updateAI = function () { // Find the nearest zombie var nearestZombie = null; var nearestDistance = Number.MAX_VALUE; for (var i = 0; i < zombies.length; i++) { var zombie = zombies[i]; var distance = getDistance(self, zombie); if (distance < nearestDistance) { nearestDistance = distance; nearestZombie = zombie; } } // Move and shoot logic if (nearestZombie) { // If zombie is close, move away from it if (nearestDistance < 300) { var dx = self.x - nearestZombie.x; var dy = self.y - nearestZombie.y; var length = Math.sqrt(dx * dx + dy * dy); if (length > 0) { dx /= length; dy /= length; self.move(dx, dy); } } // Otherwise, stay close to player 1 else { var distToPlayer1 = getDistance(self, player1); if (distToPlayer1 > 300) { var dx = player1.x - self.x; var dy = player1.y - self.y; var length = Math.sqrt(dx * dx + dy * dy); if (length > 0) { dx /= length; dy /= length; self.move(dx, dy); } } } // Shoot at nearest zombie if not reloading and it's in range if (!self.isReloading && nearestDistance < 600) { var bullet = self.shoot(nearestZombie.x, nearestZombie.y); if (bullet) { bullets.push(bullet); game.addChild(bullet); } } // Reload if low on ammo and no zombies nearby if (self.ammo <= self.maxAmmo / 4 && nearestDistance > 400) { self.reload(); } } }; return self; }); var Zombie = Container.expand(function () { var self = Container.call(this); var zombieGraphics = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.moveSpeed = 2; self.damage = 10; self.attackRate = 60; // 1 second between attacks self.attackCounter = 0; self.isDead = false; self.init = function (x, y, moveSpeed, health) { self.x = x; self.y = y; self.moveSpeed = moveSpeed || 2; self.health = health || 100; }; self.takeDamage = function (amount) { if (self.isDead) { return; } self.health -= amount; // Flash red when hit LK.effects.flashObject(self, 0xff0000, 150); LK.getSound('zombieHit').play(); if (self.health <= 0) { self.die(); } }; self.die = function () { self.isDead = true; self.shouldDestroy = true; // Create blood splatter createBlood(self.x, self.y); // Increase score currentScore += 10; updateScoreText(); }; self.attack = function (player) { if (self.isDead || self.attackCounter > 0) { return; } player.takeDamage(self.damage); self.attackCounter = self.attackRate; }; self.update = function () { if (self.isDead) { return; } // Update attack counter if (self.attackCounter > 0) { self.attackCounter--; } // Target the nearest player that's alive var target = null; if (!player1.isDead && !player2.isDead) { // Target closest player var dist1 = getDistance(self, player1); var dist2 = getDistance(self, player2); target = dist1 < dist2 ? player1 : player2; } else if (!player1.isDead) { target = player1; } else if (!player2.isDead) { target = player2; } if (target) { // Move towards target var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { var moveX = dx / distance * self.moveSpeed; var moveY = dy / distance * self.moveSpeed; self.x += moveX; self.y += moveY; } // Attack if close enough if (distance < 80) { self.attack(target); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x111111 }); /**** * Game Code ****/ // Game state variables var player1; var player2; var player1HealthBar; var player2HealthBar; var player1AmmoDisplay; var player2AmmoDisplay; var bullets = []; var zombies = []; var bloodSplatters = []; var currentWave = 0; var zombiesInWave = 0; var zombiesLeft = 0; var currentScore = 0; var gameActive = false; var waveText; var scoreText; var highScoreText; var gameStartText; var groundTiles = []; // Helper functions function getDistance(obj1, obj2) { var dx = obj1.x - obj2.x; var dy = obj1.y - obj2.y; return Math.sqrt(dx * dx + dy * dy); } function createGround() { var tileSize = 128; var tilesX = Math.ceil(2048 / tileSize); var tilesY = Math.ceil(2732 / tileSize); for (var y = 0; y < tilesY; y++) { for (var x = 0; x < tilesX; x++) { var tile = LK.getAsset('groundTile', { anchorX: 0, anchorY: 0, x: x * tileSize, y: y * tileSize, alpha: 0.3 }); // Add slight randomness to tiles tile.tint = 0x666666 + Math.floor(Math.random() * 0x111111); groundTiles.push(tile); game.addChild(tile); } } } function updateScoreText() { scoreText.setText("Score: " + currentScore); // Update high score if needed if (currentScore > storage.highScore) { storage.highScore = currentScore; highScoreText.setText("High Score: " + storage.highScore); } } function createBlood(x, y) { for (var i = 0; i < 3; i++) { var blood = new Blood(); blood.init(x + (Math.random() * 60 - 30), y + (Math.random() * 60 - 30)); bloodSplatters.push(blood); game.addChild(blood); } } function startGame() { // Reset game state gameActive = true; currentWave = 0; currentScore = 0; // Clear any existing entities clearEntities(); // Create players player1 = new Player(); player1.init(true); player1.x = 2048 / 2 - 150; player1.y = 2732 / 2; game.addChild(player1); player2 = new Player(); player2.init(false); player2.x = 2048 / 2 + 150; player2.y = 2732 / 2; game.addChild(player2); // Create health bars player1HealthBar = new HealthBar(); player1HealthBar.init(player1, true); player1HealthBar.x = 20; player1HealthBar.y = 100; LK.gui.left.addChild(player1HealthBar); player2HealthBar = new HealthBar(); player2HealthBar.init(player2, false); player2HealthBar.x = 20; player2HealthBar.y = 160; LK.gui.left.addChild(player2HealthBar); // Create ammo displays player1AmmoDisplay = new AmmoDisplay(); player1AmmoDisplay.init(player1); player1AmmoDisplay.x = 250; player1AmmoDisplay.y = 115; LK.gui.left.addChild(player1AmmoDisplay); player2AmmoDisplay = new AmmoDisplay(); player2AmmoDisplay.init(player2); player2AmmoDisplay.x = 250; player2AmmoDisplay.y = 175; LK.gui.left.addChild(player2AmmoDisplay); // Update score display updateScoreText(); // Start first wave startNextWave(); // Hide start game text gameStartText.visible = false; // Play music LK.playMusic('bgMusic', { fade: { start: 0, end: 0.3, duration: 2000 } }); } function clearEntities() { // Remove all bullets for (var i = 0; i < bullets.length; i++) { if (bullets[i].parent) { bullets[i].parent.removeChild(bullets[i]); } } bullets = []; // Remove all zombies for (var i = 0; i < zombies.length; i++) { if (zombies[i].parent) { zombies[i].parent.removeChild(zombies[i]); } } zombies = []; // Remove all blood splatters for (var i = 0; i < bloodSplatters.length; i++) { if (bloodSplatters[i].parent) { bloodSplatters[i].parent.removeChild(bloodSplatters[i]); } } bloodSplatters = []; // Remove players and their UI if they exist if (player1 && player1.parent) { player1.parent.removeChild(player1); } if (player2 && player2.parent) { player2.parent.removeChild(player2); } // Remove UI elements if they exist if (player1HealthBar && player1HealthBar.parent) { player1HealthBar.parent.removeChild(player1HealthBar); } if (player2HealthBar && player2HealthBar.parent) { player2HealthBar.parent.removeChild(player2HealthBar); } if (player1AmmoDisplay && player1AmmoDisplay.parent) { player1AmmoDisplay.parent.removeChild(player1AmmoDisplay); } if (player2AmmoDisplay && player2AmmoDisplay.parent) { player2AmmoDisplay.parent.removeChild(player2AmmoDisplay); } } function spawnZombie() { if (zombiesLeft <= 0) { return; } var zombie = new Zombie(); // Determine zombie spawn position (outside the screen) var spawnSide = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left var x, y; switch (spawnSide) { case 0: // top x = Math.random() * 2048; y = -100; break; case 1: // right x = 2148; y = Math.random() * 2732; break; case 2: // bottom x = Math.random() * 2048; y = 2832; break; case 3: // left x = -100; y = Math.random() * 2732; break; } // Scale zombie difficulty based on wave var healthMultiplier = 1 + currentWave * 0.1; var speedMultiplier = 1 + currentWave * 0.05; zombie.init(x, y, 2 * speedMultiplier, 100 * healthMultiplier); zombies.push(zombie); game.addChild(zombie); zombiesLeft--; } function startNextWave() { currentWave++; zombiesInWave = 5 + currentWave * 3; zombiesLeft = zombiesInWave; waveText.setText("Wave " + currentWave); tween(waveText, { alpha: 1 }, { duration: 500 }); // Play wave start sound LK.getSound('waveStart').play(); // After 2 seconds, fade out the wave text LK.setTimeout(function () { tween(waveText, { alpha: 0 }, { duration: 500 }); }, 2000); // Initial zombie spawn for (var i = 0; i < Math.min(5, zombiesInWave); i++) { spawnZombie(); } } function checkGameOver() { if (!gameActive) { return; } // Game over if both players are dead if (player1.isDead && player2.isDead) { gameActive = false; // Show game over screen after a short delay LK.setTimeout(function () { LK.showGameOver(); }, 1500); // Stop music with fade out LK.playMusic('bgMusic', { fade: { start: 0.3, end: 0, duration: 1500 } }); } } function handlePlayerMovement() { if (!gameActive || player1.isDead) { return; } var dx = 0; var dy = 0; if (moveUp) { dy -= 1; } if (moveDown) { dy += 1; } if (moveLeft) { dx -= 1; } if (moveRight) { dx += 1; } // Normalize diagonal movement if (dx !== 0 && dy !== 0) { var length = Math.sqrt(dx * dx + dy * dy); dx /= length; dy /= length; } player1.move(dx, dy); } // Initialize UI elements function createUI() { // Wave text waveText = new Text2("Wave 1", { size: 100, fill: 0xFFFFFF }); waveText.anchor.set(0.5); waveText.alpha = 0; LK.gui.center.addChild(waveText); // Score text scoreText = new Text2("Score: 0", { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.y = 20; LK.gui.top.addChild(scoreText); // High score text highScoreText = new Text2("High Score: " + storage.highScore, { size: 30, fill: 0xAAAAAA }); highScoreText.anchor.set(0.5, 0); highScoreText.y = 70; LK.gui.top.addChild(highScoreText); // Game start text gameStartText = new Text2("TAP TO START", { size: 80, fill: 0xFFFFFF }); gameStartText.anchor.set(0.5); LK.gui.center.addChild(gameStartText); // Pulse animation for game start text function pulseText() { tween(gameStartText.scale, { x: 1.1, y: 1.1 }, { duration: 800, easing: tween.sinceOut, onFinish: function onFinish() { tween(gameStartText.scale, { x: 1, y: 1 }, { duration: 800, easing: tween.sinceIn, onFinish: pulseText }); } }); } pulseText(); } // Input tracking variables var moveUp = false; var moveDown = false; var moveLeft = false; var moveRight = false; var isShooting = false; var shootTarget = { x: 0, y: 0 }; // Input handlers game.down = function (x, y, obj) { if (!gameActive) { startGame(); return; } // Determine which side of the screen was pressed if (x < 2048 / 2) { // Left side controls movement if (y < 2732 / 3) { moveUp = true; moveDown = moveLeft = moveRight = false; } else if (y > 2732 * 2 / 3) { moveDown = true; moveUp = moveLeft = moveRight = false; } else if (x < 2048 / 4) { moveLeft = true; moveUp = moveDown = moveRight = false; } else { moveRight = true; moveUp = moveDown = moveLeft = false; } } else { // Right side controls shooting isShooting = true; shootTarget.x = x; shootTarget.y = y; } }; game.up = function (x, y, obj) { // Stop movement or shooting based on which side was released if (x < 2048 / 2) { moveUp = moveDown = moveLeft = moveRight = false; } else { isShooting = false; } }; game.move = function (x, y, obj) { // Update shoot target if shooting if (isShooting && x > 2048 / 2) { shootTarget.x = x; shootTarget.y = y; } // Update movement direction if on left side if (x < 2048 / 2) { if (y < 2732 / 3) { moveUp = true; moveDown = moveLeft = moveRight = false; } else if (y > 2732 * 2 / 3) { moveDown = true; moveUp = moveLeft = moveRight = false; } else if (x < 2048 / 4) { moveLeft = true; moveUp = moveDown = moveRight = false; } else { moveRight = true; moveUp = moveDown = moveLeft = false; } } }; // Create the ground and UI createGround(); createUI(); // Main game update loop game.update = function () { if (gameActive) { // Handle player movement handlePlayerMovement(); // Handle player shooting if (isShooting && !player1.isDead) { var bullet = player1.shoot(shootTarget.x, shootTarget.y); if (bullet) { bullets.push(bullet); game.addChild(bullet); } } // Update players player1.update(); player2.update(); // Update health bars player1HealthBar.update(); player2HealthBar.update(); // Update ammo displays player1AmmoDisplay.update(); player2AmmoDisplay.update(); // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; bullet.update(); // Check for bullet collisions with zombies for (var j = zombies.length - 1; j >= 0; j--) { var zombie = zombies[j]; if (!zombie.isDead && bullet.intersects(zombie)) { zombie.takeDamage(bullet.damage); bullet.shouldDestroy = true; break; } } // Remove bullets marked for destruction if (bullet.shouldDestroy) { game.removeChild(bullet); bullets.splice(i, 1); } } // Update zombies for (var i = zombies.length - 1; i >= 0; i--) { var zombie = zombies[i]; zombie.update(); // Remove zombies marked for destruction if (zombie.shouldDestroy) { game.removeChild(zombie); zombies.splice(i, 1); } } // Update blood splatters for (var i = bloodSplatters.length - 1; i >= 0; i--) { var blood = bloodSplatters[i]; blood.update(); // Remove blood marked for destruction if (blood.shouldDestroy) { game.removeChild(blood); bloodSplatters.splice(i, 1); } } // Spawn more zombies if needed if (zombies.length === 0 && zombiesLeft === 0) { // All zombies in wave defeated, start next wave startNextWave(); } else if (zombies.length < 10 && zombiesLeft > 0 && LK.ticks % 60 === 0) { // Spawn a new zombie every second if there are less than 10 on screen spawnZombie(); } // Check for game over checkGameOver(); } }; // Play music with low volume LK.playMusic('bgMusic', { volume: 0.3 });
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,913 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0
+});
+
+/****
+* Classes
+****/
+var AmmoDisplay = Container.expand(function () {
+ var self = Container.call(this);
+ self.indicators = [];
+ self.player = null;
+ self.init = function (playerRef) {
+ self.player = playerRef;
+ // Clear existing indicators
+ for (var i = 0; i < self.indicators.length; i++) {
+ self.removeChild(self.indicators[i]);
+ }
+ self.indicators = [];
+ // Create new indicators
+ for (var i = 0; i < self.player.maxAmmo; i++) {
+ var indicator = LK.getAsset('ammoIndicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: i * 20,
+ y: 0
+ });
+ self.addChild(indicator);
+ self.indicators.push(indicator);
+ }
+ };
+ self.update = function () {
+ if (!self.player) {
+ return;
+ }
+ // Update visibility based on current ammo
+ for (var i = 0; i < self.indicators.length; i++) {
+ self.indicators[i].visible = i < self.player.ammo;
+ // Fade effect when reloading
+ if (self.player.isReloading) {
+ var reloadProgress = 1 - self.player.reloadCounter / self.player.reloadTime;
+ if (i < Math.floor(reloadProgress * self.player.maxAmmo)) {
+ self.indicators[i].visible = true;
+ self.indicators[i].alpha = 0.5;
+ } else {
+ self.indicators[i].visible = false;
+ }
+ } else {
+ self.indicators[i].alpha = 1;
+ }
+ }
+ };
+ return self;
+});
+var Blood = Container.expand(function () {
+ var self = Container.call(this);
+ var bloodGraphics = self.attachAsset('blood', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.8
+ });
+ self.lifespan = 60; // Frames
+ self.init = function (x, y) {
+ self.x = x;
+ self.y = y;
+ self.scale.x = 0.5 + Math.random() * 0.5;
+ self.scale.y = 0.5 + Math.random() * 0.5;
+ self.rotation = Math.random() * Math.PI * 2;
+ self.alpha = 0.8;
+ };
+ self.update = function () {
+ self.lifespan--;
+ if (self.lifespan <= 20) {
+ self.alpha = self.lifespan / 20 * 0.8;
+ }
+ if (self.lifespan <= 0) {
+ self.shouldDestroy = true;
+ }
+ };
+ return self;
+});
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 15;
+ self.damage = 25;
+ self.direction = {
+ x: 0,
+ y: 0
+ };
+ self.shooter = null;
+ self.update = function () {
+ self.x += self.direction.x * self.speed;
+ self.y += self.direction.y * self.speed;
+ // Destroy bullet if it goes off screen
+ if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
+ self.shouldDestroy = true;
+ }
+ };
+ self.fire = function (startX, startY, targetX, targetY, shooterRef) {
+ self.x = startX;
+ self.y = startY;
+ self.shooter = shooterRef;
+ // Calculate direction
+ var dx = targetX - startX;
+ var dy = targetY - startY;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 0) {
+ self.direction.x = dx / distance;
+ self.direction.y = dy / distance;
+ }
+ };
+ return self;
+});
+var HealthBar = Container.expand(function () {
+ var self = Container.call(this);
+ var background = self.attachAsset('healthBarBackground', {
+ anchorX: 0,
+ anchorY: 0
+ });
+ var bar = self.attachAsset('healthBar', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 2,
+ y: 2
+ });
+ var playerText = new Text2("P1", {
+ size: 20,
+ fill: 0xFFFFFF
+ });
+ playerText.anchor.set(0.5);
+ playerText.x = background.width / 2;
+ playerText.y = background.height / 2;
+ self.addChild(playerText);
+ self.player = null;
+ self.init = function (playerRef, isPlayer1) {
+ self.player = playerRef;
+ playerText.setText(isPlayer1 ? "P1" : "P2");
+ };
+ self.update = function () {
+ if (!self.player) {
+ return;
+ }
+ var healthPercent = self.player.health / self.player.maxHealth;
+ bar.scale.x = healthPercent;
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ self.isPlayer1 = true; // Will be set when initializing
+ var graphicsId = 'player1'; // Default
+ self.health = 100;
+ self.maxHealth = 100;
+ self.moveSpeed = 5;
+ self.fireRate = 15; // Frames between shots
+ self.fireCounter = 0;
+ self.ammo = 12;
+ self.maxAmmo = 12;
+ self.reloadTime = 120; // 2 seconds at 60fps
+ self.reloadCounter = 0;
+ self.isReloading = false;
+ self.isDead = false;
+ self.lastMoveDirection = {
+ x: 0,
+ y: -1
+ }; // Default facing up
+ self.init = function (isFirstPlayer) {
+ self.isPlayer1 = isFirstPlayer;
+ graphicsId = isFirstPlayer ? 'player1' : 'player2';
+ if (self.graphics) {
+ self.removeChild(self.graphics);
+ }
+ self.graphics = self.attachAsset(graphicsId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = self.maxHealth;
+ self.ammo = self.maxAmmo;
+ self.fireCounter = 0;
+ self.reloadCounter = 0;
+ self.isReloading = false;
+ self.isDead = false;
+ };
+ self.takeDamage = function (amount) {
+ if (self.isDead) {
+ return;
+ }
+ self.health -= amount;
+ if (self.health <= 0) {
+ self.health = 0;
+ self.die();
+ } else {
+ // Flash red when hit
+ LK.effects.flashObject(self, 0xff0000, 300);
+ LK.getSound('playerHit').play();
+ }
+ };
+ self.die = function () {
+ self.isDead = true;
+ self.alpha = 0.5;
+ // Flash red when dead
+ LK.effects.flashObject(self, 0xff0000, 1000);
+ };
+ self.shoot = function (targetX, targetY) {
+ if (self.isDead || self.isReloading) {
+ return null;
+ }
+ if (self.ammo <= 0) {
+ self.reload();
+ return null;
+ }
+ if (self.fireCounter <= 0) {
+ // Create bullet
+ var bullet = new Bullet();
+ bullet.fire(self.x, self.y, targetX, targetY, self);
+ // Update state
+ self.ammo--;
+ self.fireCounter = self.fireRate;
+ // Keep track of facing direction based on shot
+ var dx = targetX - self.x;
+ var dy = targetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 0) {
+ self.lastMoveDirection.x = dx / distance;
+ self.lastMoveDirection.y = dy / distance;
+ }
+ // Play sound
+ LK.getSound('shoot').play();
+ return bullet;
+ }
+ return null;
+ };
+ self.reload = function () {
+ if (self.isDead || self.isReloading || self.ammo === self.maxAmmo) {
+ return;
+ }
+ self.isReloading = true;
+ self.reloadCounter = self.reloadTime;
+ LK.getSound('reload').play();
+ };
+ self.move = function (dx, dy) {
+ if (self.isDead) {
+ return;
+ }
+ // If moving, update last move direction
+ if (dx !== 0 || dy !== 0) {
+ var length = Math.sqrt(dx * dx + dy * dy);
+ if (length > 0) {
+ self.lastMoveDirection.x = dx / length;
+ self.lastMoveDirection.y = dy / length;
+ }
+ }
+ // Apply movement
+ var newX = self.x + dx * self.moveSpeed;
+ var newY = self.y + dy * self.moveSpeed;
+ // Constrain to game bounds with a margin
+ var margin = 50;
+ newX = Math.max(margin, Math.min(2048 - margin, newX));
+ newY = Math.max(margin, Math.min(2732 - margin, newY));
+ self.x = newX;
+ self.y = newY;
+ };
+ self.update = function () {
+ // Update reload state
+ if (self.isReloading) {
+ self.reloadCounter--;
+ if (self.reloadCounter <= 0) {
+ self.isReloading = false;
+ self.ammo = self.maxAmmo;
+ }
+ }
+ // Update fire rate counter
+ if (self.fireCounter > 0) {
+ self.fireCounter--;
+ }
+ // AI behavior for Player 2
+ if (!self.isPlayer1 && !self.isDead) {
+ self.updateAI();
+ }
+ };
+ self.updateAI = function () {
+ // Find the nearest zombie
+ var nearestZombie = null;
+ var nearestDistance = Number.MAX_VALUE;
+ for (var i = 0; i < zombies.length; i++) {
+ var zombie = zombies[i];
+ var distance = getDistance(self, zombie);
+ if (distance < nearestDistance) {
+ nearestDistance = distance;
+ nearestZombie = zombie;
+ }
+ }
+ // Move and shoot logic
+ if (nearestZombie) {
+ // If zombie is close, move away from it
+ if (nearestDistance < 300) {
+ var dx = self.x - nearestZombie.x;
+ var dy = self.y - nearestZombie.y;
+ var length = Math.sqrt(dx * dx + dy * dy);
+ if (length > 0) {
+ dx /= length;
+ dy /= length;
+ self.move(dx, dy);
+ }
+ }
+ // Otherwise, stay close to player 1
+ else {
+ var distToPlayer1 = getDistance(self, player1);
+ if (distToPlayer1 > 300) {
+ var dx = player1.x - self.x;
+ var dy = player1.y - self.y;
+ var length = Math.sqrt(dx * dx + dy * dy);
+ if (length > 0) {
+ dx /= length;
+ dy /= length;
+ self.move(dx, dy);
+ }
+ }
+ }
+ // Shoot at nearest zombie if not reloading and it's in range
+ if (!self.isReloading && nearestDistance < 600) {
+ var bullet = self.shoot(nearestZombie.x, nearestZombie.y);
+ if (bullet) {
+ bullets.push(bullet);
+ game.addChild(bullet);
+ }
+ }
+ // Reload if low on ammo and no zombies nearby
+ if (self.ammo <= self.maxAmmo / 4 && nearestDistance > 400) {
+ self.reload();
+ }
+ }
+ };
+ return self;
+});
+var Zombie = Container.expand(function () {
+ var self = Container.call(this);
+ var zombieGraphics = self.attachAsset('zombie', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 100;
+ self.moveSpeed = 2;
+ self.damage = 10;
+ self.attackRate = 60; // 1 second between attacks
+ self.attackCounter = 0;
+ self.isDead = false;
+ self.init = function (x, y, moveSpeed, health) {
+ self.x = x;
+ self.y = y;
+ self.moveSpeed = moveSpeed || 2;
+ self.health = health || 100;
+ };
+ self.takeDamage = function (amount) {
+ if (self.isDead) {
+ return;
+ }
+ self.health -= amount;
+ // Flash red when hit
+ LK.effects.flashObject(self, 0xff0000, 150);
+ LK.getSound('zombieHit').play();
+ if (self.health <= 0) {
+ self.die();
+ }
+ };
+ self.die = function () {
+ self.isDead = true;
+ self.shouldDestroy = true;
+ // Create blood splatter
+ createBlood(self.x, self.y);
+ // Increase score
+ currentScore += 10;
+ updateScoreText();
+ };
+ self.attack = function (player) {
+ if (self.isDead || self.attackCounter > 0) {
+ return;
+ }
+ player.takeDamage(self.damage);
+ self.attackCounter = self.attackRate;
+ };
+ self.update = function () {
+ if (self.isDead) {
+ return;
+ }
+ // Update attack counter
+ if (self.attackCounter > 0) {
+ self.attackCounter--;
+ }
+ // Target the nearest player that's alive
+ var target = null;
+ if (!player1.isDead && !player2.isDead) {
+ // Target closest player
+ var dist1 = getDistance(self, player1);
+ var dist2 = getDistance(self, player2);
+ target = dist1 < dist2 ? player1 : player2;
+ } else if (!player1.isDead) {
+ target = player1;
+ } else if (!player2.isDead) {
+ target = player2;
+ }
+ if (target) {
+ // Move towards target
+ var dx = target.x - self.x;
+ var dy = target.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 0) {
+ var moveX = dx / distance * self.moveSpeed;
+ var moveY = dy / distance * self.moveSpeed;
+ self.x += moveX;
+ self.y += moveY;
+ }
+ // Attack if close enough
+ if (distance < 80) {
+ self.attack(target);
+ }
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x111111
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+var player1;
+var player2;
+var player1HealthBar;
+var player2HealthBar;
+var player1AmmoDisplay;
+var player2AmmoDisplay;
+var bullets = [];
+var zombies = [];
+var bloodSplatters = [];
+var currentWave = 0;
+var zombiesInWave = 0;
+var zombiesLeft = 0;
+var currentScore = 0;
+var gameActive = false;
+var waveText;
+var scoreText;
+var highScoreText;
+var gameStartText;
+var groundTiles = [];
+// Helper functions
+function getDistance(obj1, obj2) {
+ var dx = obj1.x - obj2.x;
+ var dy = obj1.y - obj2.y;
+ return Math.sqrt(dx * dx + dy * dy);
+}
+function createGround() {
+ var tileSize = 128;
+ var tilesX = Math.ceil(2048 / tileSize);
+ var tilesY = Math.ceil(2732 / tileSize);
+ for (var y = 0; y < tilesY; y++) {
+ for (var x = 0; x < tilesX; x++) {
+ var tile = LK.getAsset('groundTile', {
+ anchorX: 0,
+ anchorY: 0,
+ x: x * tileSize,
+ y: y * tileSize,
+ alpha: 0.3
+ });
+ // Add slight randomness to tiles
+ tile.tint = 0x666666 + Math.floor(Math.random() * 0x111111);
+ groundTiles.push(tile);
+ game.addChild(tile);
+ }
+ }
+}
+function updateScoreText() {
+ scoreText.setText("Score: " + currentScore);
+ // Update high score if needed
+ if (currentScore > storage.highScore) {
+ storage.highScore = currentScore;
+ highScoreText.setText("High Score: " + storage.highScore);
+ }
+}
+function createBlood(x, y) {
+ for (var i = 0; i < 3; i++) {
+ var blood = new Blood();
+ blood.init(x + (Math.random() * 60 - 30), y + (Math.random() * 60 - 30));
+ bloodSplatters.push(blood);
+ game.addChild(blood);
+ }
+}
+function startGame() {
+ // Reset game state
+ gameActive = true;
+ currentWave = 0;
+ currentScore = 0;
+ // Clear any existing entities
+ clearEntities();
+ // Create players
+ player1 = new Player();
+ player1.init(true);
+ player1.x = 2048 / 2 - 150;
+ player1.y = 2732 / 2;
+ game.addChild(player1);
+ player2 = new Player();
+ player2.init(false);
+ player2.x = 2048 / 2 + 150;
+ player2.y = 2732 / 2;
+ game.addChild(player2);
+ // Create health bars
+ player1HealthBar = new HealthBar();
+ player1HealthBar.init(player1, true);
+ player1HealthBar.x = 20;
+ player1HealthBar.y = 100;
+ LK.gui.left.addChild(player1HealthBar);
+ player2HealthBar = new HealthBar();
+ player2HealthBar.init(player2, false);
+ player2HealthBar.x = 20;
+ player2HealthBar.y = 160;
+ LK.gui.left.addChild(player2HealthBar);
+ // Create ammo displays
+ player1AmmoDisplay = new AmmoDisplay();
+ player1AmmoDisplay.init(player1);
+ player1AmmoDisplay.x = 250;
+ player1AmmoDisplay.y = 115;
+ LK.gui.left.addChild(player1AmmoDisplay);
+ player2AmmoDisplay = new AmmoDisplay();
+ player2AmmoDisplay.init(player2);
+ player2AmmoDisplay.x = 250;
+ player2AmmoDisplay.y = 175;
+ LK.gui.left.addChild(player2AmmoDisplay);
+ // Update score display
+ updateScoreText();
+ // Start first wave
+ startNextWave();
+ // Hide start game text
+ gameStartText.visible = false;
+ // Play music
+ LK.playMusic('bgMusic', {
+ fade: {
+ start: 0,
+ end: 0.3,
+ duration: 2000
+ }
+ });
+}
+function clearEntities() {
+ // Remove all bullets
+ for (var i = 0; i < bullets.length; i++) {
+ if (bullets[i].parent) {
+ bullets[i].parent.removeChild(bullets[i]);
+ }
+ }
+ bullets = [];
+ // Remove all zombies
+ for (var i = 0; i < zombies.length; i++) {
+ if (zombies[i].parent) {
+ zombies[i].parent.removeChild(zombies[i]);
+ }
+ }
+ zombies = [];
+ // Remove all blood splatters
+ for (var i = 0; i < bloodSplatters.length; i++) {
+ if (bloodSplatters[i].parent) {
+ bloodSplatters[i].parent.removeChild(bloodSplatters[i]);
+ }
+ }
+ bloodSplatters = [];
+ // Remove players and their UI if they exist
+ if (player1 && player1.parent) {
+ player1.parent.removeChild(player1);
+ }
+ if (player2 && player2.parent) {
+ player2.parent.removeChild(player2);
+ }
+ // Remove UI elements if they exist
+ if (player1HealthBar && player1HealthBar.parent) {
+ player1HealthBar.parent.removeChild(player1HealthBar);
+ }
+ if (player2HealthBar && player2HealthBar.parent) {
+ player2HealthBar.parent.removeChild(player2HealthBar);
+ }
+ if (player1AmmoDisplay && player1AmmoDisplay.parent) {
+ player1AmmoDisplay.parent.removeChild(player1AmmoDisplay);
+ }
+ if (player2AmmoDisplay && player2AmmoDisplay.parent) {
+ player2AmmoDisplay.parent.removeChild(player2AmmoDisplay);
+ }
+}
+function spawnZombie() {
+ if (zombiesLeft <= 0) {
+ return;
+ }
+ var zombie = new Zombie();
+ // Determine zombie spawn position (outside the screen)
+ var spawnSide = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
+ var x, y;
+ switch (spawnSide) {
+ case 0:
+ // top
+ x = Math.random() * 2048;
+ y = -100;
+ break;
+ case 1:
+ // right
+ x = 2148;
+ y = Math.random() * 2732;
+ break;
+ case 2:
+ // bottom
+ x = Math.random() * 2048;
+ y = 2832;
+ break;
+ case 3:
+ // left
+ x = -100;
+ y = Math.random() * 2732;
+ break;
+ }
+ // Scale zombie difficulty based on wave
+ var healthMultiplier = 1 + currentWave * 0.1;
+ var speedMultiplier = 1 + currentWave * 0.05;
+ zombie.init(x, y, 2 * speedMultiplier, 100 * healthMultiplier);
+ zombies.push(zombie);
+ game.addChild(zombie);
+ zombiesLeft--;
+}
+function startNextWave() {
+ currentWave++;
+ zombiesInWave = 5 + currentWave * 3;
+ zombiesLeft = zombiesInWave;
+ waveText.setText("Wave " + currentWave);
+ tween(waveText, {
+ alpha: 1
+ }, {
+ duration: 500
+ });
+ // Play wave start sound
+ LK.getSound('waveStart').play();
+ // After 2 seconds, fade out the wave text
+ LK.setTimeout(function () {
+ tween(waveText, {
+ alpha: 0
+ }, {
+ duration: 500
+ });
+ }, 2000);
+ // Initial zombie spawn
+ for (var i = 0; i < Math.min(5, zombiesInWave); i++) {
+ spawnZombie();
+ }
+}
+function checkGameOver() {
+ if (!gameActive) {
+ return;
+ }
+ // Game over if both players are dead
+ if (player1.isDead && player2.isDead) {
+ gameActive = false;
+ // Show game over screen after a short delay
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 1500);
+ // Stop music with fade out
+ LK.playMusic('bgMusic', {
+ fade: {
+ start: 0.3,
+ end: 0,
+ duration: 1500
+ }
+ });
+ }
+}
+function handlePlayerMovement() {
+ if (!gameActive || player1.isDead) {
+ return;
+ }
+ var dx = 0;
+ var dy = 0;
+ if (moveUp) {
+ dy -= 1;
+ }
+ if (moveDown) {
+ dy += 1;
+ }
+ if (moveLeft) {
+ dx -= 1;
+ }
+ if (moveRight) {
+ dx += 1;
+ }
+ // Normalize diagonal movement
+ if (dx !== 0 && dy !== 0) {
+ var length = Math.sqrt(dx * dx + dy * dy);
+ dx /= length;
+ dy /= length;
+ }
+ player1.move(dx, dy);
+}
+// Initialize UI elements
+function createUI() {
+ // Wave text
+ waveText = new Text2("Wave 1", {
+ size: 100,
+ fill: 0xFFFFFF
+ });
+ waveText.anchor.set(0.5);
+ waveText.alpha = 0;
+ LK.gui.center.addChild(waveText);
+ // Score text
+ scoreText = new Text2("Score: 0", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ scoreText.anchor.set(0.5, 0);
+ scoreText.y = 20;
+ LK.gui.top.addChild(scoreText);
+ // High score text
+ highScoreText = new Text2("High Score: " + storage.highScore, {
+ size: 30,
+ fill: 0xAAAAAA
+ });
+ highScoreText.anchor.set(0.5, 0);
+ highScoreText.y = 70;
+ LK.gui.top.addChild(highScoreText);
+ // Game start text
+ gameStartText = new Text2("TAP TO START", {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ gameStartText.anchor.set(0.5);
+ LK.gui.center.addChild(gameStartText);
+ // Pulse animation for game start text
+ function pulseText() {
+ tween(gameStartText.scale, {
+ x: 1.1,
+ y: 1.1
+ }, {
+ duration: 800,
+ easing: tween.sinceOut,
+ onFinish: function onFinish() {
+ tween(gameStartText.scale, {
+ x: 1,
+ y: 1
+ }, {
+ duration: 800,
+ easing: tween.sinceIn,
+ onFinish: pulseText
+ });
+ }
+ });
+ }
+ pulseText();
+}
+// Input tracking variables
+var moveUp = false;
+var moveDown = false;
+var moveLeft = false;
+var moveRight = false;
+var isShooting = false;
+var shootTarget = {
+ x: 0,
+ y: 0
+};
+// Input handlers
+game.down = function (x, y, obj) {
+ if (!gameActive) {
+ startGame();
+ return;
+ }
+ // Determine which side of the screen was pressed
+ if (x < 2048 / 2) {
+ // Left side controls movement
+ if (y < 2732 / 3) {
+ moveUp = true;
+ moveDown = moveLeft = moveRight = false;
+ } else if (y > 2732 * 2 / 3) {
+ moveDown = true;
+ moveUp = moveLeft = moveRight = false;
+ } else if (x < 2048 / 4) {
+ moveLeft = true;
+ moveUp = moveDown = moveRight = false;
+ } else {
+ moveRight = true;
+ moveUp = moveDown = moveLeft = false;
+ }
+ } else {
+ // Right side controls shooting
+ isShooting = true;
+ shootTarget.x = x;
+ shootTarget.y = y;
+ }
+};
+game.up = function (x, y, obj) {
+ // Stop movement or shooting based on which side was released
+ if (x < 2048 / 2) {
+ moveUp = moveDown = moveLeft = moveRight = false;
+ } else {
+ isShooting = false;
+ }
+};
+game.move = function (x, y, obj) {
+ // Update shoot target if shooting
+ if (isShooting && x > 2048 / 2) {
+ shootTarget.x = x;
+ shootTarget.y = y;
+ }
+ // Update movement direction if on left side
+ if (x < 2048 / 2) {
+ if (y < 2732 / 3) {
+ moveUp = true;
+ moveDown = moveLeft = moveRight = false;
+ } else if (y > 2732 * 2 / 3) {
+ moveDown = true;
+ moveUp = moveLeft = moveRight = false;
+ } else if (x < 2048 / 4) {
+ moveLeft = true;
+ moveUp = moveDown = moveRight = false;
+ } else {
+ moveRight = true;
+ moveUp = moveDown = moveLeft = false;
+ }
+ }
+};
+// Create the ground and UI
+createGround();
+createUI();
+// Main game update loop
+game.update = function () {
+ if (gameActive) {
+ // Handle player movement
+ handlePlayerMovement();
+ // Handle player shooting
+ if (isShooting && !player1.isDead) {
+ var bullet = player1.shoot(shootTarget.x, shootTarget.y);
+ if (bullet) {
+ bullets.push(bullet);
+ game.addChild(bullet);
+ }
+ }
+ // Update players
+ player1.update();
+ player2.update();
+ // Update health bars
+ player1HealthBar.update();
+ player2HealthBar.update();
+ // Update ammo displays
+ player1AmmoDisplay.update();
+ player2AmmoDisplay.update();
+ // Update bullets
+ for (var i = bullets.length - 1; i >= 0; i--) {
+ var bullet = bullets[i];
+ bullet.update();
+ // Check for bullet collisions with zombies
+ for (var j = zombies.length - 1; j >= 0; j--) {
+ var zombie = zombies[j];
+ if (!zombie.isDead && bullet.intersects(zombie)) {
+ zombie.takeDamage(bullet.damage);
+ bullet.shouldDestroy = true;
+ break;
+ }
+ }
+ // Remove bullets marked for destruction
+ if (bullet.shouldDestroy) {
+ game.removeChild(bullet);
+ bullets.splice(i, 1);
+ }
+ }
+ // Update zombies
+ for (var i = zombies.length - 1; i >= 0; i--) {
+ var zombie = zombies[i];
+ zombie.update();
+ // Remove zombies marked for destruction
+ if (zombie.shouldDestroy) {
+ game.removeChild(zombie);
+ zombies.splice(i, 1);
+ }
+ }
+ // Update blood splatters
+ for (var i = bloodSplatters.length - 1; i >= 0; i--) {
+ var blood = bloodSplatters[i];
+ blood.update();
+ // Remove blood marked for destruction
+ if (blood.shouldDestroy) {
+ game.removeChild(blood);
+ bloodSplatters.splice(i, 1);
+ }
+ }
+ // Spawn more zombies if needed
+ if (zombies.length === 0 && zombiesLeft === 0) {
+ // All zombies in wave defeated, start next wave
+ startNextWave();
+ } else if (zombies.length < 10 && zombiesLeft > 0 && LK.ticks % 60 === 0) {
+ // Spawn a new zombie every second if there are less than 10 on screen
+ spawnZombie();
+ }
+ // Check for game over
+ checkGameOver();
+ }
+};
+// Play music with low volume
+LK.playMusic('bgMusic', {
+ volume: 0.3
});
\ No newline at end of file
Make it a 8 bit zombie that is menacing. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Make an 8 bit boy. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Make an 8 bit black and white grayscale boy. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Make an 8bit red blood splater. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Make an green grass 8bit texture 2d and flat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows