User prompt
variller spawn olur ve spawn olmuş variller mermiyle patlayabilir
User prompt
variller objedir
User prompt
variller kırılabilir ve kırılınca kendi boyutunda patlama efekti çıkarır
User prompt
oyuna varil ekle rastgele yerlerde spawn olsun ve assests e ekle
User prompt
bombaya bir patlama efekti ekle ve assets e koy bombadan büyük olmalı
User prompt
arabayı sağ alt köşeye taşı
User prompt
bomba kutuları kırabilir
User prompt
oyuna terk edilmiş bir araba ekle sağ köşeye koy büyük olsun görünür olsun
User prompt
sağ köşede bir obje oluştur
User prompt
bomba mapin rastgele bir yerlerinde spawnlanır
User prompt
wave başlamadan bomba spawnlanmaz
User prompt
bomba eğer zombiye hasar verirse zombi ölür
User prompt
kırmızı alanı sil
User prompt
daha çok
User prompt
bombanın kırmızı alana göre konumunu sağa al
User prompt
bomba yalnız başına spawn oluyor böyle olmaz
User prompt
kırmızı alan bombanın altında spawn olur birleşiktirler
User prompt
bomba gözükmüyor ?
User prompt
bomba kırmızı alanda spawn olur
User prompt
çok daha sağa
User prompt
bomba biraz daha sağa
User prompt
biraz sağa
User prompt
bomba daha ortada olmalı
User prompt
güzel gözükmüyor tam ortalamamız lazım işte çaprazına denk gelicek bomba
User prompt
bombanın biraz yukarsında spawn olması daha iyi
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highscore: 0, weaponLevel: 1 }); /**** * Classes ****/ var Bomb = Container.expand(function (x, y) { var self = Container.call(this); var bombGraphic = self.attachAsset('smallBomb', { anchorX: 0.5, anchorY: 0.5 }); self.x = x; self.y = y; self.explode = function () { // Check for player in red area if (player.intersects(self)) { player.takeDamage(100); // Inflict damage to player } // Check for zombies in red area zombies.forEach(function (zombie) { if (zombie.intersects(self)) { var zombieDied = zombie.takeDamage(100); // Inflict damage to zombie if (zombieDied) { // Increase score and zombie kill counter var scoreToAdd = zombie instanceof BossZombie ? 100 : 10; score += scoreToAdd; zombiesKilled++; // Chance to drop pickup if (Math.random() < 0.3) { spawnPickup(zombie.x, zombie.y); } // Remove zombie zombie.destroy(); zombies.splice(zombies.indexOf(zombie), 1); } } }); self.destroy(); // Remove bomb after explosion }; return self; }); var Bullet = Container.expand(function (startX, startY, targetX, targetY, damage) { var self = Container.call(this); var bulletGraphic = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.damage = damage || 10; // Calculate direction vector var dx = targetX - startX; var dy = targetY - startY; var distance = Math.sqrt(dx * dx + dy * dy); self.vx = dx / distance * self.speed; self.vy = dy / distance * self.speed; self.x = startX; self.y = startY; self.update = function () { self.x += self.vx; self.y += self.vy; // Check if bullet is out of bounds if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) { return true; // Remove bullet } return false; }; return self; }); var Obstacle = Container.expand(function (x, y, type) { var self = Container.call(this); var obstacleGraphic = self.attachAsset(type === 'stone' ? 'stone' : type === 'crate' ? 'crate' : 'bush', { anchorX: 0.5, anchorY: 0.5 }); self.x = x; self.y = y; self.type = type; // Store the type of obstacle self.update = function () { // Check for bullet collision with crate if (self.type === 'crate') { for (var i = bullets.length - 1; i >= 0; i--) { if (bullets[i].intersects(self)) { bullets[i].destroy(); bullets.splice(i, 1); // 50% chance to drop a pickup when crate is destroyed if (Math.random() < 0.5) { spawnPickup(self.x, self.y); } self.destroy(); return true; // Remove crate } } } return false; }; self.spawnPickup = spawnPickup; // Make spawnPickup accessible return self; }); var Pickup = Container.expand(function (x, y, type) { var self = Container.call(this); var pickupGraphic = self.attachAsset(type === 'health' ? 'healthPack' : 'ammoBox', { anchorX: 0.5, anchorY: 0.5 }); self.type = type; // 'health' or 'ammo' self.x = x; self.y = y; self.lifespan = 10000; // milliseconds until pickup disappears self.creationTime = Date.now(); self.update = function () { // Make pickup pulse var age = Date.now() - self.creationTime; var pulse = Math.sin(age / 200) * 0.2 + 1; self.scale.set(pulse, pulse); // Check if pickup should expire if (age > self.lifespan) { return true; // Remove pickup } return false; }; self.collect = function (player) { LK.getSound('pickup').play(); if (self.type === 'health') { player.heal(25); } else if (self.type === 'ammo') { player.ammo = player.maxAmmo; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphic = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.ammo = 30; self.maxAmmo = 30; self.reloadTime = 1000; // milliseconds self.isReloading = false; self.speed = 7; self.weaponLevel = storage.weaponLevel || 0.5; // Reduced initial weapon level self.bulletDamage = 10 * self.weaponLevel; // Adjusted bullet damage to prevent one-hit kills in wave 1 self.lastShotTime = 0; self.shootDelay = 300; // milliseconds between shots self.moveTowards = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.x = targetX; self.y = targetY; } // Keep player within bounds self.x = Math.max(50, Math.min(2048 - 50, self.x)); self.y = Math.max(50, Math.min(2732 - 50, self.y)); }; self.shoot = function (targetX, targetY) { var currentTime = Date.now(); if (!self.infiniteAmmo && self.ammo <= 0) { self.reload(); return null; } if (self.isReloading) { return null; } if (currentTime - self.lastShotTime < self.shootDelay) { return null; } self.lastShotTime = currentTime; self.ammo--; LK.getSound('shoot').play(); // 25% chance for a critical hit var criticalHit = Math.random() < 0.25; var damage = criticalHit ? self.bulletDamage * 2 : self.bulletDamage; var bullet = new Bullet(self.x, self.y, targetX, targetY, damage); // Removed critical effect display return bullet; }; self.reload = function () { if (!self.isReloading && self.ammo < self.maxAmmo) { self.isReloading = true; LK.setTimeout(function () { self.ammo = self.maxAmmo; self.isReloading = false; }, self.reloadTime); } }; self.takeDamage = function (damage) { LK.getSound('playerHit').play(); LK.effects.flashObject(self, 0xff0000, 300); self.health -= damage; if (self.health <= 0) { self.health = 0; return true; // player died } return false; // player still alive }; self.heal = function (amount) { self.health = Math.min(self.maxHealth, self.health + amount); }; self.upgradeWeapon = function () { self.weaponLevel++; self.bulletDamage = 10 * self.weaponLevel; storage.weaponLevel = self.weaponLevel; }; return self; }); var Zombie = Container.expand(function (x, y, health, speed, damage) { var self = Container.call(this); var zombieGraphic = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); // Add health bar background var healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0.5, anchorY: 1.0, x: 0, y: -zombieGraphic.height / 2 - 10, scaleX: 0.5, // Reduce the width of the health bar background scaleY: 0.5 // Reduce the height of the health bar background }); self.addChild(healthBarBg); // Add health bar var healthBar = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 1.0, x: 0, y: -zombieGraphic.height / 2 - 10, scaleX: 0.5, // Reduce the width of the health bar scaleY: 0.5 // Reduce the height of the health bar }); self.addChild(healthBar); self.health = health || 30; self.maxHealth = self.health; self.speed = speed || 3; // Increased speed for regular zombies self.damage = damage || 10; self.attackCooldown = 1000; // milliseconds self.lastAttackTime = 0; self.x = x; self.y = y; self.moveTowards = function (targetX, targetY) { var dx = targetX - self.x; var dy = 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.attack = function (player) { var currentTime = Date.now(); if (currentTime - self.lastAttackTime >= self.attackCooldown) { self.lastAttackTime = currentTime; return player.takeDamage(self.damage); } return false; }; self.takeDamage = function (damage) { self.health -= damage; // Update health bar scale var healthPercentage = self.health / self.maxHealth; healthBar.scale.x = healthPercentage; // Flash zombie when hit LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('zombieHit').play(); // Change color based on health percentage var healthPercentage = self.health / self.maxHealth; var green = Math.floor(204 * healthPercentage); zombieGraphic.tint = 0 << 16 | green << 8 | 0; if (self.health <= 0) { if (damage > player.bulletDamage) { // Check if it was a critical hit var criticalEffect = LK.getAsset('criticalEffect', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y }); game.addChild(criticalEffect); tween(criticalEffect, {}, { // Use tween to extend the duration duration: 500, // Extend duration to 500ms onFinish: function onFinish() { criticalEffect.destroy(); } }); } // 20% chance to trigger infinite ammo power-up if (Math.random() < 0.2) { player.infiniteAmmo = true; LK.setTimeout(function () { player.infiniteAmmo = false; }, 10000); // 10 seconds duration } // Remove health bar healthBar.destroy(); healthBarBg.destroy(); return true; // zombie died } return false; // zombie still alive }; return self; }); var FastZombie = Zombie.expand(function (x, y, health, speed, damage) { var self = Zombie.call(this, x, y, health, speed, damage); self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic var fastZombieGraphic = self.attachAsset('fastZombie', { anchorX: 0.5, anchorY: 0.5 }); self.speed = speed || 600; // Further increased speed for fast zombies return self; }); var BossZombie = Zombie.expand(function (x, y, waveNumber) { var self = Zombie.call(this, x, y, bossHealth, bossSpeed, bossDamage); // Calculate boss stats based on wave number var bossHealth = Math.max(5000, 5000 + waveNumber * 500); // Ensure minimum health of 5000 var bossSpeed = 12.0 + waveNumber * 1.5; // Significantly increase base speed and scaling factor for boss var bossDamage = 50 + waveNumber * 10; // Replace the zombie graphic with a boss graphic self.removeChild(self.getChildAt(0)); // Remove the zombie graphic var bossGraphic = self.attachAsset('bossZombie', { anchorX: 0.5, anchorY: 0.5 }); self.scoreValue = 100; // More points for killing a boss return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // New bomb asset with smaller effect area function spawnFastZombie(health, speed, damage) { var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left var x, y; switch (edge) { case 0: x = Math.random() * 2048; y = -100; break; case 1: x = 2048 + 100; y = Math.random() * 2732; break; case 2: x = Math.random() * 2048; y = 2732 + 100; break; case 3: x = -100; y = Math.random() * 2732; break; } var fastZombie = new FastZombie(x, y, health, speed, damage); zombies.push(fastZombie); game.addChild(fastZombie); } // Game state variables var player; var obstacles = []; var bullets = []; var bulletHitZombies = {}; // Use a plain object to track which zombies have been hit by which bullets var zombies = []; var missiles = []; var pickups = []; var wave = 1; var zombiesKilled = 0; var score = 0; var gameStartTime; var waveStartTime; var isWaveActive = false; var targetPosition = { x: 0, y: 0 }; var isGameOver = false; // UI elements var scoreText; var waveText; var healthBar; var healthBarBg; var ammoBar; var ammoBarBg; var gameStatusText; function initGame() { // Reset game state wave = 1; zombiesKilled = 0; score = 0; bullets = []; zombies = []; pickups = []; isWaveActive = false; isGameOver = false; gameStartTime = Date.now(); // Set background var background = LK.getAsset('backgroundImage', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(background); background.zIndex = -1; // Ensure the background is rendered behind other elements // Play background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); // Create player at center of screen player = new Player(); player.infiniteAmmo = false; // Initialize infinite ammo property player.x = 2048 / 2; player.y = 2732 / 2; if (player) { player.lastX = player.x; // Initialize lastX for tracking player.lastY = player.y; // Initialize lastY for tracking } game.addChild(player); // Add obstacles var obstacles = []; // Add decorative elements to the corners obstacles.push(new Obstacle(150, 150, 'bush')); // Near top-left corner obstacles.push(new Obstacle(1898, 150, 'bush')); // Near top-right corner obstacles.push(new Obstacle(150, 2582, 'bush')); // Near bottom-left corner obstacles.push(new Obstacle(1898, 2582, 'bush')); // Near bottom-right corner obstacles.push(new Obstacle(150, 150, 'crate')); // Near top-left corner obstacles.push(new Obstacle(1898, 150, 'crate')); // Near top-right corner obstacles.push(new Obstacle(150, 2582, 'crate')); // Near bottom-left corner obstacles.push(new Obstacle(1898, 2582, 'crate')); // Near bottom-right corner // Add more bushes for (var i = 0; i < 50; i++) { // Increased from 20 to 50 for more bushes var randomX = Math.random() * 2048; var randomY = Math.random() * 2732; obstacles.push(new Obstacle(randomX, randomY, 'bush')); } // Add small stone patterns for (var i = 0; i < 100; i++) { // Increased from 50 to 100 for more stones var randomX = Math.random() * 2048; var randomY = Math.random() * 2732; obstacles.push(new Obstacle(randomX, randomY, 'stone')); } // Add more crate obstacles at random positions for (var i = 0; i < 10; i++) { var randomX = Math.random() * 2048; var randomY = Math.random() * 2732; obstacles.push(new Obstacle(randomX, randomY, 'crate')); } obstacles.forEach(function (obstacle) { game.addChild(obstacle); }); // Initialize UI createUI(); // Start first wave startWave(); } function createUI() { // Score text scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.x = 0; scoreText.y = 20; // Wave text waveText = new Text2('Wave: 1', { size: 60, fill: 0xFFFFFF }); waveText.anchor.set(0, 0); LK.gui.topLeft.addChild(waveText); waveText.x = 20; waveText.y = 20; // Game status text (wave start, game over, etc.) gameStatusText = new Text2('', { size: 100, fill: 0xFFFFFF }); gameStatusText.anchor.set(0.5, 0.5); LK.gui.center.addChild(gameStatusText); gameStatusText.alpha = 0; // Adjust gameStatusText position to be slightly below the wave text gameStatusText.y = waveText.y + 70; // Health bar background healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0, anchorY: 0.5 }); LK.gui.bottomLeft.addChild(healthBarBg); healthBarBg.x = 20; healthBarBg.y = -50; // Health bar healthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5 }); LK.gui.bottomLeft.addChild(healthBar); healthBar.x = 20; healthBar.y = -50; // Ammo bar background ammoBarBg = LK.getAsset('ammoBarBg', { anchorX: 0, anchorY: 0.5 }); LK.gui.bottomLeft.addChild(ammoBarBg); ammoBarBg.x = 20; ammoBarBg.y = -100; // Ammo bar ammoBar = LK.getAsset('ammoBar', { anchorX: 0, anchorY: 0.5 }); LK.gui.bottomLeft.addChild(ammoBar); ammoBar.x = 20; ammoBar.y = -100; // Game status text (wave start, game over, etc.) gameStatusText = new Text2('', { size: 100, fill: 0xFFFFFF }); gameStatusText.anchor.set(0.5, 0.5); LK.gui.center.addChild(gameStatusText); gameStatusText.alpha = 0; } function updateUI() { // Update score scoreText.setText('Score: ' + score); // Update wave waveText.setText('Wave: ' + wave); // Update health bar var healthPercent = player.health / player.maxHealth; healthBar.scale.x = healthPercent; // Update ammo bar var ammoPercent = player.ammo / player.maxAmmo; ammoBar.scale.x = ammoPercent; // Change ammo bar color when reloading if (player.isReloading) { ammoBar.tint = 0xff6600; } else { ammoBar.tint = 0xcc9900; } } function startWave() { waveStartTime = Date.now(); isWaveActive = false; // Display countdown before wave starts var countdown = 3; gameStatusText.setText('Wave ' + wave + ' in ' + countdown); gameStatusText.alpha = 1; var countdownInterval = LK.setInterval(function () { countdown--; if (countdown > 0) { gameStatusText.setText('Wave ' + wave + ' in ' + countdown); } else { LK.clearInterval(countdownInterval); isWaveActive = true; gameStatusText.setText('WAVE ' + wave); tween(gameStatusText, { alpha: 0 }, { duration: 1500, easing: tween.easeIn }); LK.getSound('newWave').play(); } }, 1000); // Spawn zombies based on wave number var zombieCount = wave === 1 ? 10 : wave === 2 ? 4 : wave === 3 ? 5 : 5 + wave * 2; // Increased zombie count for wave 1 var zombieHealth = wave === 1 ? 30 : wave === 3 ? 20 : 30 + wave * 5; // Adjusted health for wave 1 var zombieSpeed = wave === 1 ? 1.2 : wave === 3 ? 1.5 : 2 + wave * 0.1; // Adjusted speed for wave 3 var zombieDamage = wave === 1 ? 5 : wave === 3 ? 5 : 10 + wave * 2; // Adjusted damage for wave 1 // Schedule zombie spawns over time // Delay zombie spawning until countdown is complete var spawnInterval = LK.setInterval(function () { if (isWaveActive && zombies.length < zombieCount) { if (Math.random() < 0.2) { // 20% chance to spawn a fast zombie spawnFastZombie(zombieHealth, zombieSpeed * 2, zombieDamage); // Double the speed for fast zombies } else { spawnZombie(zombieHealth, zombieSpeed, zombieDamage); } } else if (zombies.length >= zombieCount) { LK.clearInterval(spawnInterval); } }, 500); // Spawn a boss every 5 waves if (wave % 5 === 0) { LK.setTimeout(function () { spawnBossZombie(); }, 5000); } } function spawnZombie(health, speed, damage) { var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left var x, y; switch (edge) { case 0: // top x = Math.random() * 2048; y = -100; break; case 1: // right x = 2048 + 100; y = Math.random() * 2732; break; case 2: // bottom x = Math.random() * 2048; y = 2732 + 100; break; case 3: // left x = -100; y = Math.random() * 2732; break; } var zombie = new Zombie(x, y, health, speed, damage); zombies.push(zombie); game.addChild(zombie); } function spawnBossZombie() { // Spawn boss at a random edge var edge = Math.floor(Math.random() * 4); var x, y; switch (edge) { case 0: // top x = Math.random() * 2048; y = -150; break; case 1: // right x = 2048 + 150; y = Math.random() * 2732; break; case 2: // bottom x = Math.random() * 2048; y = 2732 + 150; break; case 3: // left x = -150; y = Math.random() * 2732; break; } var boss = new BossZombie(x, y, wave); zombies.push(boss); game.addChild(boss); // Play boss appear sound LK.getSound('bossAppear').play(); // Show boss alert gameStatusText.setText('BOSS ZOMBIE APPEARED!'); gameStatusText.alpha = 1; tween(gameStatusText, { alpha: 0 }, { duration: 2000, easing: tween.easeIn }); } function spawnPickup(x, y) { // 30% chance for health, 70% for ammo var type = Math.random() < 0.3 ? 'health' : 'ammo'; var pickup = new Pickup(x, y, type); pickups.push(pickup); game.addChild(pickup); } function checkWaveCompletion() { if (isWaveActive && zombies.length === 0 && !isGameOver && zombiesKilled >= 5 + wave * 2) { isWaveActive = false; // Display wave complete message gameStatusText.setText('WAVE ' + wave + ' COMPLETE!'); gameStatusText.alpha = 1; // Give player a weapon upgrade every 3 waves if (wave % 3 === 0) { player.upgradeWeapon(); // Show upgrade message LK.setTimeout(function () { gameStatusText.setText('WEAPON UPGRADED!'); }, 2000); } // Spawn crates as objects after wave completion for (var i = 0; i < 5; i++) { var randomX = Math.random() * 2048; var randomY = Math.random() * 2732; var crate = new Obstacle(randomX, randomY, 'crate'); obstacles.push(crate); game.addChild(crate); } // Start next wave after a delay LK.setTimeout(function () { wave++; gameStatusText.alpha = 0; startWave(); }, 4000); } } // Event handling game.down = function (x, y) { if (isGameOver) { return; } targetPosition.x = x; targetPosition.y = y; // Player shoots at clicked position var bullet = player.shoot(x, y); if (bullet) { bullets.push(bullet); game.addChild(bullet); } }; game.move = function (x, y) { targetPosition.x = x; targetPosition.y = y; }; game.up = function () { // Not needed for this game }; // Main game update loop game.update = function () { if (isGameOver) { return; } // Check for player collision with obstacles obstacles.forEach(function (obstacle) { if (player.intersects(obstacle)) { // Prevent player from moving through the obstacle player.x = player.lastX; player.y = player.lastY; } }); // Update player movement if (player) { player.lastX = player.x; // Track lastX before moving player.lastY = player.y; // Track lastY before moving player.moveTowards(targetPosition.x, targetPosition.y); // Regenerate health slowly if not at max health if (player.health < player.maxHealth) { player.health = Math.min(player.maxHealth, player.health + 0.05); // Regenerate 0.05 health per update } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var shouldRemove = bullets[i].update(); if (shouldRemove) { bullets[i].destroy(); bullets.splice(i, 1); continue; } // Check bullet collision with zombies for (var j = zombies.length - 1; j >= 0; j--) { if (bullets[i] && bullets[i].intersects(zombies[j])) { // Check if this bullet has already hit this zombie if (!bulletHitZombies[bullets[i]]) { bulletHitZombies[bullets[i]] = []; } if (!bulletHitZombies[bullets[i]].includes(zombies[j])) { bulletHitZombies[bullets[i]].push(zombies[j]); var zombieDied = zombies[j].takeDamage(bullets[i].damage); // Remove bullet after hit bullets[i].destroy(); bullets.splice(i, 1); if (zombieDied) { // Increase score and zombie kill counter var scoreToAdd = zombies[j] instanceof BossZombie ? 100 : 10; score += scoreToAdd; zombiesKilled++; // Chance to drop pickup if (Math.random() < 0.3) { spawnPickup(zombies[j].x, zombies[j].y); } // Remove zombie zombies[j].destroy(); zombies.splice(j, 1); } break; } } } } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var shouldRemove = obstacles[i].update(); if (shouldRemove) { obstacles[i].destroy(); obstacles.splice(i, 1); } } // Update zombies for (var i = zombies.length - 1; i >= 0; i--) { // Move zombie towards player zombies[i].moveTowards(player.x, player.y); // Check if zombie reached player if (zombies[i].intersects(player)) { var playerDied = zombies[i].attack(player); if (playerDied) { handleGameOver(); } } } for (var i = pickups.length - 1; i >= 0; i--) { var shouldRemove = pickups[i].update(); if (shouldRemove) { pickups[i].destroy(); pickups.splice(i, 1); continue; } // Check if player collects pickup if (player.intersects(pickups[i])) { pickups[i].collect(player); pickups[i].destroy(); pickups.splice(i, 1); } } // Update UI updateUI(); // Spawn bomb in red area every 10 seconds if (LK.ticks % 600 === 0) { var bombX = 1024 + (Math.random() * 500 - 250); // Centered around the middle of the red area var bombY = 1366 + (Math.random() * 500 - 250) - 50; // Slightly above the center of the red area var bomb = new Bomb(bombX, bombY); game.addChild(bomb); // Add red area under bomb var redArea = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: bombX, y: bombY, scaleX: 0.25, scaleY: 0.25 }); game.addChild(redArea); redArea.zIndex = -1; // Ensure the red area is rendered below the bomb // Trigger explosion after 3 seconds LK.setTimeout(function () { bomb.explode(); redArea.destroy(); // Remove red area after explosion }, 3000); } // Check if wave is complete checkWaveCompletion(); // Auto-reload when empty and not already reloading if (player.ammo === 0 && !player.isReloading) { player.reload(); } }; function handleGameOver() { isGameOver = true; // Fade out background music LK.playMusic('gameMusic', { fade: { start: 0.3, end: 0, duration: 1000 } }); // Update high score if needed if (score > storage.highscore) { storage.highscore = score; } // Show score in game over dialog LK.setScore(score); // Show game over screen after a short delay LK.setTimeout(function () { LK.showGameOver(); }, 1000); } initGame(); // Start the game immediately
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highscore: 0,
weaponLevel: 1
});
/****
* Classes
****/
var Bomb = Container.expand(function (x, y) {
var self = Container.call(this);
var bombGraphic = self.attachAsset('smallBomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.explode = function () {
// Check for player in red area
if (player.intersects(self)) {
player.takeDamage(100); // Inflict damage to player
}
// Check for zombies in red area
zombies.forEach(function (zombie) {
if (zombie.intersects(self)) {
var zombieDied = zombie.takeDamage(100); // Inflict damage to zombie
if (zombieDied) {
// Increase score and zombie kill counter
var scoreToAdd = zombie instanceof BossZombie ? 100 : 10;
score += scoreToAdd;
zombiesKilled++;
// Chance to drop pickup
if (Math.random() < 0.3) {
spawnPickup(zombie.x, zombie.y);
}
// Remove zombie
zombie.destroy();
zombies.splice(zombies.indexOf(zombie), 1);
}
}
});
self.destroy(); // Remove bomb after explosion
};
return self;
});
var Bullet = Container.expand(function (startX, startY, targetX, targetY, damage) {
var self = Container.call(this);
var bulletGraphic = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.damage = damage || 10;
// Calculate direction vector
var dx = targetX - startX;
var dy = targetY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
self.vx = dx / distance * self.speed;
self.vy = dy / distance * self.speed;
self.x = startX;
self.y = startY;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
// Check if bullet is out of bounds
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
return true; // Remove bullet
}
return false;
};
return self;
});
var Obstacle = Container.expand(function (x, y, type) {
var self = Container.call(this);
var obstacleGraphic = self.attachAsset(type === 'stone' ? 'stone' : type === 'crate' ? 'crate' : 'bush', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.type = type; // Store the type of obstacle
self.update = function () {
// Check for bullet collision with crate
if (self.type === 'crate') {
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i].intersects(self)) {
bullets[i].destroy();
bullets.splice(i, 1);
// 50% chance to drop a pickup when crate is destroyed
if (Math.random() < 0.5) {
spawnPickup(self.x, self.y);
}
self.destroy();
return true; // Remove crate
}
}
}
return false;
};
self.spawnPickup = spawnPickup; // Make spawnPickup accessible
return self;
});
var Pickup = Container.expand(function (x, y, type) {
var self = Container.call(this);
var pickupGraphic = self.attachAsset(type === 'health' ? 'healthPack' : 'ammoBox', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = type; // 'health' or 'ammo'
self.x = x;
self.y = y;
self.lifespan = 10000; // milliseconds until pickup disappears
self.creationTime = Date.now();
self.update = function () {
// Make pickup pulse
var age = Date.now() - self.creationTime;
var pulse = Math.sin(age / 200) * 0.2 + 1;
self.scale.set(pulse, pulse);
// Check if pickup should expire
if (age > self.lifespan) {
return true; // Remove pickup
}
return false;
};
self.collect = function (player) {
LK.getSound('pickup').play();
if (self.type === 'health') {
player.heal(25);
} else if (self.type === 'ammo') {
player.ammo = player.maxAmmo;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphic = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.ammo = 30;
self.maxAmmo = 30;
self.reloadTime = 1000; // milliseconds
self.isReloading = false;
self.speed = 7;
self.weaponLevel = storage.weaponLevel || 0.5; // Reduced initial weapon level
self.bulletDamage = 10 * self.weaponLevel; // Adjusted bullet damage to prevent one-hit kills in wave 1
self.lastShotTime = 0;
self.shootDelay = 300; // milliseconds between shots
self.moveTowards = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.x = targetX;
self.y = targetY;
}
// Keep player within bounds
self.x = Math.max(50, Math.min(2048 - 50, self.x));
self.y = Math.max(50, Math.min(2732 - 50, self.y));
};
self.shoot = function (targetX, targetY) {
var currentTime = Date.now();
if (!self.infiniteAmmo && self.ammo <= 0) {
self.reload();
return null;
}
if (self.isReloading) {
return null;
}
if (currentTime - self.lastShotTime < self.shootDelay) {
return null;
}
self.lastShotTime = currentTime;
self.ammo--;
LK.getSound('shoot').play();
// 25% chance for a critical hit
var criticalHit = Math.random() < 0.25;
var damage = criticalHit ? self.bulletDamage * 2 : self.bulletDamage;
var bullet = new Bullet(self.x, self.y, targetX, targetY, damage);
// Removed critical effect display
return bullet;
};
self.reload = function () {
if (!self.isReloading && self.ammo < self.maxAmmo) {
self.isReloading = true;
LK.setTimeout(function () {
self.ammo = self.maxAmmo;
self.isReloading = false;
}, self.reloadTime);
}
};
self.takeDamage = function (damage) {
LK.getSound('playerHit').play();
LK.effects.flashObject(self, 0xff0000, 300);
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
return true; // player died
}
return false; // player still alive
};
self.heal = function (amount) {
self.health = Math.min(self.maxHealth, self.health + amount);
};
self.upgradeWeapon = function () {
self.weaponLevel++;
self.bulletDamage = 10 * self.weaponLevel;
storage.weaponLevel = self.weaponLevel;
};
return self;
});
var Zombie = Container.expand(function (x, y, health, speed, damage) {
var self = Container.call(this);
var zombieGraphic = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
// Add health bar background
var healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -zombieGraphic.height / 2 - 10,
scaleX: 0.5,
// Reduce the width of the health bar background
scaleY: 0.5 // Reduce the height of the health bar background
});
self.addChild(healthBarBg);
// Add health bar
var healthBar = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -zombieGraphic.height / 2 - 10,
scaleX: 0.5,
// Reduce the width of the health bar
scaleY: 0.5 // Reduce the height of the health bar
});
self.addChild(healthBar);
self.health = health || 30;
self.maxHealth = self.health;
self.speed = speed || 3; // Increased speed for regular zombies
self.damage = damage || 10;
self.attackCooldown = 1000; // milliseconds
self.lastAttackTime = 0;
self.x = x;
self.y = y;
self.moveTowards = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = 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.attack = function (player) {
var currentTime = Date.now();
if (currentTime - self.lastAttackTime >= self.attackCooldown) {
self.lastAttackTime = currentTime;
return player.takeDamage(self.damage);
}
return false;
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar scale
var healthPercentage = self.health / self.maxHealth;
healthBar.scale.x = healthPercentage;
// Flash zombie when hit
LK.effects.flashObject(self, 0xff0000, 200);
LK.getSound('zombieHit').play();
// Change color based on health percentage
var healthPercentage = self.health / self.maxHealth;
var green = Math.floor(204 * healthPercentage);
zombieGraphic.tint = 0 << 16 | green << 8 | 0;
if (self.health <= 0) {
if (damage > player.bulletDamage) {
// Check if it was a critical hit
var criticalEffect = LK.getAsset('criticalEffect', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
});
game.addChild(criticalEffect);
tween(criticalEffect, {}, {
// Use tween to extend the duration
duration: 500,
// Extend duration to 500ms
onFinish: function onFinish() {
criticalEffect.destroy();
}
});
}
// 20% chance to trigger infinite ammo power-up
if (Math.random() < 0.2) {
player.infiniteAmmo = true;
LK.setTimeout(function () {
player.infiniteAmmo = false;
}, 10000); // 10 seconds duration
}
// Remove health bar
healthBar.destroy();
healthBarBg.destroy();
return true; // zombie died
}
return false; // zombie still alive
};
return self;
});
var FastZombie = Zombie.expand(function (x, y, health, speed, damage) {
var self = Zombie.call(this, x, y, health, speed, damage);
self.removeChild(self.getChildAt(0)); // Remove the default zombie graphic
var fastZombieGraphic = self.attachAsset('fastZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = speed || 600; // Further increased speed for fast zombies
return self;
});
var BossZombie = Zombie.expand(function (x, y, waveNumber) {
var self = Zombie.call(this, x, y, bossHealth, bossSpeed, bossDamage);
// Calculate boss stats based on wave number
var bossHealth = Math.max(5000, 5000 + waveNumber * 500); // Ensure minimum health of 5000
var bossSpeed = 12.0 + waveNumber * 1.5; // Significantly increase base speed and scaling factor for boss
var bossDamage = 50 + waveNumber * 10;
// Replace the zombie graphic with a boss graphic
self.removeChild(self.getChildAt(0)); // Remove the zombie graphic
var bossGraphic = self.attachAsset('bossZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.scoreValue = 100; // More points for killing a boss
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// New bomb asset with smaller effect area
function spawnFastZombie(health, speed, damage) {
var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
var x, y;
switch (edge) {
case 0:
x = Math.random() * 2048;
y = -100;
break;
case 1:
x = 2048 + 100;
y = Math.random() * 2732;
break;
case 2:
x = Math.random() * 2048;
y = 2732 + 100;
break;
case 3:
x = -100;
y = Math.random() * 2732;
break;
}
var fastZombie = new FastZombie(x, y, health, speed, damage);
zombies.push(fastZombie);
game.addChild(fastZombie);
}
// Game state variables
var player;
var obstacles = [];
var bullets = [];
var bulletHitZombies = {}; // Use a plain object to track which zombies have been hit by which bullets
var zombies = [];
var missiles = [];
var pickups = [];
var wave = 1;
var zombiesKilled = 0;
var score = 0;
var gameStartTime;
var waveStartTime;
var isWaveActive = false;
var targetPosition = {
x: 0,
y: 0
};
var isGameOver = false;
// UI elements
var scoreText;
var waveText;
var healthBar;
var healthBarBg;
var ammoBar;
var ammoBarBg;
var gameStatusText;
function initGame() {
// Reset game state
wave = 1;
zombiesKilled = 0;
score = 0;
bullets = [];
zombies = [];
pickups = [];
isWaveActive = false;
isGameOver = false;
gameStartTime = Date.now();
// Set background
var background = LK.getAsset('backgroundImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
background.zIndex = -1; // Ensure the background is rendered behind other elements
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
// Create player at center of screen
player = new Player();
player.infiniteAmmo = false; // Initialize infinite ammo property
player.x = 2048 / 2;
player.y = 2732 / 2;
if (player) {
player.lastX = player.x; // Initialize lastX for tracking
player.lastY = player.y; // Initialize lastY for tracking
}
game.addChild(player);
// Add obstacles
var obstacles = [];
// Add decorative elements to the corners
obstacles.push(new Obstacle(150, 150, 'bush')); // Near top-left corner
obstacles.push(new Obstacle(1898, 150, 'bush')); // Near top-right corner
obstacles.push(new Obstacle(150, 2582, 'bush')); // Near bottom-left corner
obstacles.push(new Obstacle(1898, 2582, 'bush')); // Near bottom-right corner
obstacles.push(new Obstacle(150, 150, 'crate')); // Near top-left corner
obstacles.push(new Obstacle(1898, 150, 'crate')); // Near top-right corner
obstacles.push(new Obstacle(150, 2582, 'crate')); // Near bottom-left corner
obstacles.push(new Obstacle(1898, 2582, 'crate')); // Near bottom-right corner
// Add more bushes
for (var i = 0; i < 50; i++) {
// Increased from 20 to 50 for more bushes
var randomX = Math.random() * 2048;
var randomY = Math.random() * 2732;
obstacles.push(new Obstacle(randomX, randomY, 'bush'));
}
// Add small stone patterns
for (var i = 0; i < 100; i++) {
// Increased from 50 to 100 for more stones
var randomX = Math.random() * 2048;
var randomY = Math.random() * 2732;
obstacles.push(new Obstacle(randomX, randomY, 'stone'));
}
// Add more crate obstacles at random positions
for (var i = 0; i < 10; i++) {
var randomX = Math.random() * 2048;
var randomY = Math.random() * 2732;
obstacles.push(new Obstacle(randomX, randomY, 'crate'));
}
obstacles.forEach(function (obstacle) {
game.addChild(obstacle);
});
// Initialize UI
createUI();
// Start first wave
startWave();
}
function createUI() {
// Score text
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.x = 0;
scoreText.y = 20;
// Wave text
waveText = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
waveText.x = 20;
waveText.y = 20;
// Game status text (wave start, game over, etc.)
gameStatusText = new Text2('', {
size: 100,
fill: 0xFFFFFF
});
gameStatusText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(gameStatusText);
gameStatusText.alpha = 0;
// Adjust gameStatusText position to be slightly below the wave text
gameStatusText.y = waveText.y + 70;
// Health bar background
healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(healthBarBg);
healthBarBg.x = 20;
healthBarBg.y = -50;
// Health bar
healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(healthBar);
healthBar.x = 20;
healthBar.y = -50;
// Ammo bar background
ammoBarBg = LK.getAsset('ammoBarBg', {
anchorX: 0,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(ammoBarBg);
ammoBarBg.x = 20;
ammoBarBg.y = -100;
// Ammo bar
ammoBar = LK.getAsset('ammoBar', {
anchorX: 0,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(ammoBar);
ammoBar.x = 20;
ammoBar.y = -100;
// Game status text (wave start, game over, etc.)
gameStatusText = new Text2('', {
size: 100,
fill: 0xFFFFFF
});
gameStatusText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(gameStatusText);
gameStatusText.alpha = 0;
}
function updateUI() {
// Update score
scoreText.setText('Score: ' + score);
// Update wave
waveText.setText('Wave: ' + wave);
// Update health bar
var healthPercent = player.health / player.maxHealth;
healthBar.scale.x = healthPercent;
// Update ammo bar
var ammoPercent = player.ammo / player.maxAmmo;
ammoBar.scale.x = ammoPercent;
// Change ammo bar color when reloading
if (player.isReloading) {
ammoBar.tint = 0xff6600;
} else {
ammoBar.tint = 0xcc9900;
}
}
function startWave() {
waveStartTime = Date.now();
isWaveActive = false;
// Display countdown before wave starts
var countdown = 3;
gameStatusText.setText('Wave ' + wave + ' in ' + countdown);
gameStatusText.alpha = 1;
var countdownInterval = LK.setInterval(function () {
countdown--;
if (countdown > 0) {
gameStatusText.setText('Wave ' + wave + ' in ' + countdown);
} else {
LK.clearInterval(countdownInterval);
isWaveActive = true;
gameStatusText.setText('WAVE ' + wave);
tween(gameStatusText, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeIn
});
LK.getSound('newWave').play();
}
}, 1000);
// Spawn zombies based on wave number
var zombieCount = wave === 1 ? 10 : wave === 2 ? 4 : wave === 3 ? 5 : 5 + wave * 2; // Increased zombie count for wave 1
var zombieHealth = wave === 1 ? 30 : wave === 3 ? 20 : 30 + wave * 5; // Adjusted health for wave 1
var zombieSpeed = wave === 1 ? 1.2 : wave === 3 ? 1.5 : 2 + wave * 0.1; // Adjusted speed for wave 3
var zombieDamage = wave === 1 ? 5 : wave === 3 ? 5 : 10 + wave * 2; // Adjusted damage for wave 1
// Schedule zombie spawns over time
// Delay zombie spawning until countdown is complete
var spawnInterval = LK.setInterval(function () {
if (isWaveActive && zombies.length < zombieCount) {
if (Math.random() < 0.2) {
// 20% chance to spawn a fast zombie
spawnFastZombie(zombieHealth, zombieSpeed * 2, zombieDamage); // Double the speed for fast zombies
} else {
spawnZombie(zombieHealth, zombieSpeed, zombieDamage);
}
} else if (zombies.length >= zombieCount) {
LK.clearInterval(spawnInterval);
}
}, 500);
// Spawn a boss every 5 waves
if (wave % 5 === 0) {
LK.setTimeout(function () {
spawnBossZombie();
}, 5000);
}
}
function spawnZombie(health, speed, damage) {
var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
var x, y;
switch (edge) {
case 0:
// top
x = Math.random() * 2048;
y = -100;
break;
case 1:
// right
x = 2048 + 100;
y = Math.random() * 2732;
break;
case 2:
// bottom
x = Math.random() * 2048;
y = 2732 + 100;
break;
case 3:
// left
x = -100;
y = Math.random() * 2732;
break;
}
var zombie = new Zombie(x, y, health, speed, damage);
zombies.push(zombie);
game.addChild(zombie);
}
function spawnBossZombie() {
// Spawn boss at a random edge
var edge = Math.floor(Math.random() * 4);
var x, y;
switch (edge) {
case 0:
// top
x = Math.random() * 2048;
y = -150;
break;
case 1:
// right
x = 2048 + 150;
y = Math.random() * 2732;
break;
case 2:
// bottom
x = Math.random() * 2048;
y = 2732 + 150;
break;
case 3:
// left
x = -150;
y = Math.random() * 2732;
break;
}
var boss = new BossZombie(x, y, wave);
zombies.push(boss);
game.addChild(boss);
// Play boss appear sound
LK.getSound('bossAppear').play();
// Show boss alert
gameStatusText.setText('BOSS ZOMBIE APPEARED!');
gameStatusText.alpha = 1;
tween(gameStatusText, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeIn
});
}
function spawnPickup(x, y) {
// 30% chance for health, 70% for ammo
var type = Math.random() < 0.3 ? 'health' : 'ammo';
var pickup = new Pickup(x, y, type);
pickups.push(pickup);
game.addChild(pickup);
}
function checkWaveCompletion() {
if (isWaveActive && zombies.length === 0 && !isGameOver && zombiesKilled >= 5 + wave * 2) {
isWaveActive = false;
// Display wave complete message
gameStatusText.setText('WAVE ' + wave + ' COMPLETE!');
gameStatusText.alpha = 1;
// Give player a weapon upgrade every 3 waves
if (wave % 3 === 0) {
player.upgradeWeapon();
// Show upgrade message
LK.setTimeout(function () {
gameStatusText.setText('WEAPON UPGRADED!');
}, 2000);
}
// Spawn crates as objects after wave completion
for (var i = 0; i < 5; i++) {
var randomX = Math.random() * 2048;
var randomY = Math.random() * 2732;
var crate = new Obstacle(randomX, randomY, 'crate');
obstacles.push(crate);
game.addChild(crate);
}
// Start next wave after a delay
LK.setTimeout(function () {
wave++;
gameStatusText.alpha = 0;
startWave();
}, 4000);
}
}
// Event handling
game.down = function (x, y) {
if (isGameOver) {
return;
}
targetPosition.x = x;
targetPosition.y = y;
// Player shoots at clicked position
var bullet = player.shoot(x, y);
if (bullet) {
bullets.push(bullet);
game.addChild(bullet);
}
};
game.move = function (x, y) {
targetPosition.x = x;
targetPosition.y = y;
};
game.up = function () {
// Not needed for this game
};
// Main game update loop
game.update = function () {
if (isGameOver) {
return;
}
// Check for player collision with obstacles
obstacles.forEach(function (obstacle) {
if (player.intersects(obstacle)) {
// Prevent player from moving through the obstacle
player.x = player.lastX;
player.y = player.lastY;
}
});
// Update player movement
if (player) {
player.lastX = player.x; // Track lastX before moving
player.lastY = player.y; // Track lastY before moving
player.moveTowards(targetPosition.x, targetPosition.y);
// Regenerate health slowly if not at max health
if (player.health < player.maxHealth) {
player.health = Math.min(player.maxHealth, player.health + 0.05); // Regenerate 0.05 health per update
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var shouldRemove = bullets[i].update();
if (shouldRemove) {
bullets[i].destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet collision with zombies
for (var j = zombies.length - 1; j >= 0; j--) {
if (bullets[i] && bullets[i].intersects(zombies[j])) {
// Check if this bullet has already hit this zombie
if (!bulletHitZombies[bullets[i]]) {
bulletHitZombies[bullets[i]] = [];
}
if (!bulletHitZombies[bullets[i]].includes(zombies[j])) {
bulletHitZombies[bullets[i]].push(zombies[j]);
var zombieDied = zombies[j].takeDamage(bullets[i].damage);
// Remove bullet after hit
bullets[i].destroy();
bullets.splice(i, 1);
if (zombieDied) {
// Increase score and zombie kill counter
var scoreToAdd = zombies[j] instanceof BossZombie ? 100 : 10;
score += scoreToAdd;
zombiesKilled++;
// Chance to drop pickup
if (Math.random() < 0.3) {
spawnPickup(zombies[j].x, zombies[j].y);
}
// Remove zombie
zombies[j].destroy();
zombies.splice(j, 1);
}
break;
}
}
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var shouldRemove = obstacles[i].update();
if (shouldRemove) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
}
// Update zombies
for (var i = zombies.length - 1; i >= 0; i--) {
// Move zombie towards player
zombies[i].moveTowards(player.x, player.y);
// Check if zombie reached player
if (zombies[i].intersects(player)) {
var playerDied = zombies[i].attack(player);
if (playerDied) {
handleGameOver();
}
}
}
for (var i = pickups.length - 1; i >= 0; i--) {
var shouldRemove = pickups[i].update();
if (shouldRemove) {
pickups[i].destroy();
pickups.splice(i, 1);
continue;
}
// Check if player collects pickup
if (player.intersects(pickups[i])) {
pickups[i].collect(player);
pickups[i].destroy();
pickups.splice(i, 1);
}
}
// Update UI
updateUI();
// Spawn bomb in red area every 10 seconds
if (LK.ticks % 600 === 0) {
var bombX = 1024 + (Math.random() * 500 - 250); // Centered around the middle of the red area
var bombY = 1366 + (Math.random() * 500 - 250) - 50; // Slightly above the center of the red area
var bomb = new Bomb(bombX, bombY);
game.addChild(bomb);
// Add red area under bomb
var redArea = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
x: bombX,
y: bombY,
scaleX: 0.25,
scaleY: 0.25
});
game.addChild(redArea);
redArea.zIndex = -1; // Ensure the red area is rendered below the bomb
// Trigger explosion after 3 seconds
LK.setTimeout(function () {
bomb.explode();
redArea.destroy(); // Remove red area after explosion
}, 3000);
}
// Check if wave is complete
checkWaveCompletion();
// Auto-reload when empty and not already reloading
if (player.ammo === 0 && !player.isReloading) {
player.reload();
}
};
function handleGameOver() {
isGameOver = true;
// Fade out background music
LK.playMusic('gameMusic', {
fade: {
start: 0.3,
end: 0,
duration: 1000
}
});
// Update high score if needed
if (score > storage.highscore) {
storage.highscore = score;
}
// Show score in game over dialog
LK.setScore(score);
// Show game over screen after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
initGame(); // Start the game immediately