User prompt
Please fix the bug: 'TypeError: zombie.die is not a function' in or related to this line: 'zombie.die();' Line Number: 623
User prompt
Please fix the bug: 'ReferenceError: updateUI is not defined' in or related to this line: 'updateUI();' Line Number: 631
User prompt
Please fix the bug: 'ReferenceError: SHOOT_THRESHOLD is not defined' in or related to this line: 'if (rightJoystick.distance > SHOOT_THRESHOLD) {' Line Number: 605
User prompt
Please fix the bug: 'ReferenceError: PLAYER_SPEED is not defined' in or related to this line: 'player.x += moveInput.x * PLAYER_SPEED;' Line Number: 595
User prompt
Please fix the bug: 'ZOMBIE_BASE_SPEED is not defined' in or related to this line: 'var ZOMBIE_TYPES = [{' Line Number: 543
Code edit (1 edits merged)
Please save this source code
User prompt
No matter where you shoot, the swarm of bullets goes in the Y direction.
User prompt
Zombies become invisible and reduce player health. Fix this bug.
User prompt
Apply disintegration effect when zombies are hit ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zombies disintegrate in red when shot ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Zombies should double their speed and try to dodge bullets.
User prompt
Wherever we drag the right joystick, the gun will point there and fire, and put a sprite on the gun.
Code edit (1 edits merged)
Please save this source code
User prompt
Zombie Siege: Survivor's Last Stand
Initial prompt
Game Idea: Create a 2D top-down zombie shooter mobile game. Player: A single human survivor with a gun. Controls: There are two on-screen joysticks: Left joystick: Controls player movement (X,Y axis). Right joystick: Controls aiming direction. When pushed, the character’s gun aims toward the joystick direction and fires automatically if pushed far enough. Perspective: Top-down (bird’s-eye view). Enemies: Zombies continuously spawn at random positions outside the screen and move towards the player. Gameplay: Zombies deal damage on contact. Player can shoot and kill zombies. Killed zombies can drop items like ammo or health packs (optional). Player’s score increases for each zombie killed. Visuals: Simple sprites for player, zombies, bullets, blood splatter effect when zombies get shot. Background: Urban or post-apocalyptic style. Audio: Background music with a horror or action vibe. Gunshot and zombie sounds. Upgrades: (Optional) Unlock stronger weapons as the player survives longer. Platform: Mobile devices (Android/iOS).
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.velocityX = 0; self.velocityY = 0; self.lifeTime = 0; self.maxLifeTime = 180; // 3 seconds at 60fps self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.lifeTime++; // Remove if off screen or too old if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782 || self.lifeTime > self.maxLifeTime) { self.destroy(); for (var i = bullets.length - 1; i >= 0; i--) { if (bullets[i] === self) { bullets.splice(i, 1); break; } } } }; return self; }); var Joystick = Container.expand(function () { var self = Container.call(this); var base = self.attachAsset('joystickBase', { anchorX: 0.5, anchorY: 0.5 }); var knob = self.attachAsset('joystickKnob', { anchorX: 0.5, anchorY: 0.5 }); self.isActive = false; self.startX = 0; self.startY = 0; self.deltaX = 0; self.deltaY = 0; self.distance = 0; self.angle = 0; self.maxDistance = 50; self.activate = function (x, y) { self.isActive = true; self.startX = x; self.startY = y; self.x = x; self.y = y; self.visible = true; }; self.updatePosition = function (x, y) { if (self.isActive) { self.deltaX = x - self.startX; self.deltaY = y - self.startY; self.distance = Math.sqrt(self.deltaX * self.deltaX + self.deltaY * self.deltaY); self.angle = Math.atan2(self.deltaY, self.deltaX); if (self.distance > self.maxDistance) { self.deltaX = Math.cos(self.angle) * self.maxDistance; self.deltaY = Math.sin(self.angle) * self.maxDistance; self.distance = self.maxDistance; } knob.x = self.deltaX; knob.y = self.deltaY; } }; self.deactivate = function () { self.isActive = false; self.visible = false; self.deltaX = 0; self.deltaY = 0; self.distance = 0; knob.x = 0; knob.y = 0; }; self.getNormalizedInput = function () { if (self.distance === 0) { return { x: 0, y: 0 }; } return { x: self.deltaX / self.maxDistance, y: self.deltaY / self.maxDistance }; }; self.visible = false; base.alpha = 0.5; knob.alpha = 0.7; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); var gunGraphics = self.attachAsset('gun', { anchorX: 0, anchorY: 0.5, x: 0, y: 0 }); self.health = 100; self.maxHealth = 100; self.ammo = 30; self.maxAmmo = 100; self.shootCooldown = 0; self.invulnerabilityTime = 0; self.gunRotation = 0; self.updateGunRotation = function (angle) { self.gunRotation = angle; gunGraphics.rotation = angle; }; self.takeDamage = function (damage) { if (self.invulnerabilityTime <= 0) { self.health -= damage; self.invulnerabilityTime = 60; // 1 second at 60fps LK.getSound('playerHit').play(); LK.effects.flashObject(self, 0xFF0000, 500); if (self.health <= 0) { LK.showGameOver(); } } }; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } if (self.invulnerabilityTime > 0) { self.invulnerabilityTime--; } }; return self; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); self.type = type; var powerUpGraphics = self.attachAsset(type === 'health' ? 'healthPack' : 'ammoPack', { anchorX: 0.5, anchorY: 0.5 }); self.lifeTime = 0; self.maxLifeTime = 600; // 10 seconds at 60fps self.update = function () { self.lifeTime++; // Pulse effect var pulse = 1 + Math.sin(self.lifeTime * 0.1) * 0.1; powerUpGraphics.scaleX = pulse; powerUpGraphics.scaleY = pulse; // Check collision with player if (self.intersects(player)) { if (self.type === 'health') { player.health = Math.min(player.maxHealth, player.health + 25); } else { player.ammo = Math.min(player.maxAmmo, player.ammo + 15); } LK.getSound('pickup').play(); self.destroy(); for (var i = powerUps.length - 1; i >= 0; i--) { if (powerUps[i] === self) { powerUps.splice(i, 1); break; } } } // Remove if too old if (self.lifeTime > self.maxLifeTime) { self.destroy(); for (var i = powerUps.length - 1; i >= 0; i--) { if (powerUps[i] === self) { powerUps.splice(i, 1); break; } } } }; 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 + Math.random() * 0.5) * 2; // Double the speed self.health = 1; self.dodgeCooldown = 0; self.dodgeVelocityX = 0; self.dodgeVelocityY = 0; self.die = function () { // Store zombie position for power-up drop var zombieX = self.x; var zombieY = self.y; // Red disintegration effect tween(self, { tint: 0xFF0000, alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); // Chance to drop power-up if (Math.random() < 0.15) { // 15% chance var powerUpType = Math.random() < 0.6 ? 'health' : 'ammo'; var powerUp = new PowerUp(powerUpType); powerUp.x = zombieX; powerUp.y = zombieY; powerUps.push(powerUp); game.addChild(powerUp); } }; self.update = function () { // Reduce dodge cooldown if (self.dodgeCooldown > 0) { self.dodgeCooldown--; } // Check for nearby bullets to dodge var shouldDodge = false; var dodgeX = 0; var dodgeY = 0; if (self.dodgeCooldown <= 0) { for (var i = 0; i < bullets.length; i++) { var bullet = bullets[i]; var bulletDx = bullet.x - self.x; var bulletDy = bullet.y - self.y; var bulletDistance = Math.sqrt(bulletDx * bulletDx + bulletDy * bulletDy); // Check if bullet is close and heading towards zombie if (bulletDistance < 120) { var bulletDirection = Math.atan2(bullet.velocityY, bullet.velocityX); var zombieDirection = Math.atan2(bulletDy, bulletDx); var angleDiff = Math.abs(bulletDirection - zombieDirection); // If bullet is roughly heading towards zombie if (angleDiff < 1.5 || angleDiff > Math.PI * 2 - 1.5) { shouldDodge = true; // Dodge perpendicular to bullet direction dodgeX = -bullet.velocityY; dodgeY = bullet.velocityX; var dodgeLength = Math.sqrt(dodgeX * dodgeX + dodgeY * dodgeY); if (dodgeLength > 0) { dodgeX = dodgeX / dodgeLength * self.speed * 1.5; dodgeY = dodgeY / dodgeLength * self.speed * 1.5; } break; } } } } if (shouldDodge) { self.dodgeVelocityX = dodgeX; self.dodgeVelocityY = dodgeY; self.dodgeCooldown = 30; // 0.5 second dodge cooldown } // Apply dodge movement if active if (self.dodgeCooldown > 20) { self.x += self.dodgeVelocityX; self.y += self.dodgeVelocityY; } else { // Normal movement towards player var dx = player.x - self.x; var dy = player.y - 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; } } // Check collision with player if (self.intersects(player)) { player.takeDamage(10); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2F4F2F }); /**** * Game Code ****/ // Utility function to remove items from arrays function removeFromArray(array, item) { for (var i = array.length - 1; i >= 0; i--) { if (array[i] === item) { array.splice(i, 1); break; } } } // Game variables var player; var zombies = []; var bullets = []; var powerUps = []; var leftJoystick; var rightJoystick; var activeTouch = null; var secondTouch = null; var zombieSpawnTimer = 0; var zombieSpawnRate = 120; // Start spawning every 2 seconds var minSpawnRate = 30; // Minimum spawn rate (0.5 seconds) var difficultyTimer = 0; var score = 0; // UI elements var healthBar = LK.getAsset('healthPack', { anchorX: 0, anchorY: 0, scaleX: 10, scaleY: 1, x: 100, y: 50 }); var ammoText = new Text2('Ammo: 30', { size: 40, fill: 0xFFFFFF }); ammoText.anchor.set(0, 0); var scoreText = new Text2('Score: 0', { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); // Add UI to GUI LK.gui.topLeft.addChild(healthBar); LK.gui.topLeft.addChild(ammoText); ammoText.x = 100; ammoText.y = 100; LK.gui.top.addChild(scoreText); // Initialize player player = game.addChild(new Player()); player.x = 1024; player.y = 1366; // Initialize joysticks leftJoystick = game.addChild(new Joystick()); rightJoystick = game.addChild(new Joystick()); // Input handling game.down = function (x, y, obj) { if (x < 1024) { // Left side - movement joystick if (!leftJoystick.isActive) { leftJoystick.activate(x, y); activeTouch = { x: x, y: y, side: 'left' }; } } else { // Right side - shooting joystick if (!rightJoystick.isActive) { rightJoystick.activate(x, y); if (!activeTouch) { activeTouch = { x: x, y: y, side: 'right' }; } else { secondTouch = { x: x, y: y, side: 'right' }; } } } }; game.move = function (x, y, obj) { if (activeTouch && activeTouch.side === 'left') { leftJoystick.updatePosition(x, y); } else if (activeTouch && activeTouch.side === 'right') { rightJoystick.updatePosition(x, y); } if (secondTouch && secondTouch.side === 'right') { rightJoystick.updatePosition(x, y); } else if (secondTouch && secondTouch.side === 'left') { leftJoystick.updatePosition(x, y); } }; game.up = function (x, y, obj) { if (activeTouch && (activeTouch.side === 'left' && x < 1024 || activeTouch.side === 'right' && x >= 1024)) { if (activeTouch.side === 'left') { leftJoystick.deactivate(); } else { rightJoystick.deactivate(); } activeTouch = secondTouch; secondTouch = null; } else if (secondTouch && (secondTouch.side === 'left' && x < 1024 || secondTouch.side === 'right' && x >= 1024)) { if (secondTouch.side === 'left') { leftJoystick.deactivate(); } else { rightJoystick.deactivate(); } secondTouch = null; } }; function spawnZombie() { var zombie = new Zombie(); var side = Math.floor(Math.random() * 4); switch (side) { 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; } zombies.push(zombie); game.addChild(zombie); } function fireBullet() { if (player.ammo > 0 && player.shootCooldown <= 0) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y; var input = rightJoystick.getNormalizedInput(); // Only fire if there's actual joystick input if (input.x !== 0 || input.y !== 0) { bullet.velocityX = input.x * bullet.speed; bullet.velocityY = input.y * bullet.speed; bullets.push(bullet); game.addChild(bullet); player.ammo--; player.shootCooldown = 15; // Quarter second cooldown LK.getSound('shoot').play(); } } } ; game.update = function () { // Handle movement var moveInput = leftJoystick.getNormalizedInput(); player.x += moveInput.x * 4; player.y += moveInput.y * 4; // Keep player in bounds player.x = Math.max(40, Math.min(2008, player.x)); player.y = Math.max(40, Math.min(2692, player.y)); // Handle shooting var shootInput = rightJoystick.getNormalizedInput(); if (rightJoystick.distance > 0) { // Update gun rotation to point towards joystick direction var gunAngle = Math.atan2(shootInput.y, shootInput.x); player.updateGunRotation(gunAngle); } if (rightJoystick.distance > 30) { // Only shoot if joystick is pushed far enough fireBullet(); } // Spawn zombies zombieSpawnTimer++; if (zombieSpawnTimer >= zombieSpawnRate) { spawnZombie(); zombieSpawnTimer = 0; } // Increase difficulty over time difficultyTimer++; if (difficultyTimer >= 600) { // Every 10 seconds if (zombieSpawnRate > minSpawnRate) { zombieSpawnRate -= 5; } difficultyTimer = 0; } // Check bullet-zombie collisions for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; for (var j = zombies.length - 1; j >= 0; j--) { var zombie = zombies[j]; if (bullet.intersects(zombie)) { // Zombie hit LK.getSound('zombieHit').play(); score += 10; LK.setScore(score); scoreText.setText('Score: ' + score); // Store zombie position for power-up drop var zombieX = zombie.x; var zombieY = zombie.y; // Remove zombie from array and game immediately zombies.splice(j, 1); // Red disintegration effect tween(zombie, { tint: 0xFF0000, alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { zombie.destroy(); } }); // Chance to drop power-up if (Math.random() < 0.15) { // 15% chance var powerUpType = Math.random() < 0.6 ? 'health' : 'ammo'; var powerUp = new PowerUp(powerUpType); powerUp.x = zombieX; powerUp.y = zombieY; powerUps.push(powerUp); game.addChild(powerUp); } // Remove bullet bullet.destroy(); bullets.splice(i, 1); break; } } } // Update UI healthBar.scaleX = player.health / player.maxHealth * 10; ammoText.setText('Ammo: ' + player.ammo); // Change health bar color based on health if (player.health < 25) { healthBar.tint = 0xFF0000; // Red } else if (player.health < 50) { healthBar.tint = 0xFFFF00; // Yellow } else { healthBar.tint = 0x00FF00; // Green } }; /*********************** * EK ÖZELLİKLER ***********************/ // Player movement speed var PLAYER_SPEED = 4; // Shooting threshold for joystick sensitivity var SHOOT_THRESHOLD = 30; // Zombi temel hızı var ZOMBIE_BASE_SPEED = 2; // Zombi türleri var ZOMBIE_TYPES = [{ type: 'normal', speed: ZOMBIE_BASE_SPEED, health: 1 }, { type: 'runner', speed: ZOMBIE_BASE_SPEED * 1.8, health: 0.5 }, { type: 'tank', speed: ZOMBIE_BASE_SPEED * 0.6, health: 3 }]; // Level up skorları var LEVEL_THRESHOLDS = [0, 200, 500, 1000]; var currentLevel = 1; /*********************** * LEVEL SYSTEM ***********************/ function checkLevelUp() { if (score >= LEVEL_THRESHOLDS[currentLevel]) { currentLevel++; zombieSpawnRate = Math.max(ZOMBIE_SPAWN_MIN, zombieSpawnRate - 10); showLevelUp(currentLevel); } } function showLevelUp(level) { var levelText = new Text2("LEVEL ".concat(level), { size: 100, fill: 0xFFD700 }); levelText.anchor.set(0.5); levelText.x = 1024; levelText.y = 1366; LK.gui.center.addChild(levelText); tween(levelText, { alpha: 0 }, { duration: 2000, easing: tween.easeIn, onFinish: function onFinish() { return levelText.destroy(); } }); } /*********************** * GAME LOOP PATCH ***********************/ game.update = function () { var moveInput = leftJoystick.getNormalizedInput(); player.x += moveInput.x * PLAYER_SPEED; player.y += moveInput.y * PLAYER_SPEED; player.x = Math.max(40, Math.min(2008, player.x)); player.y = Math.max(40, Math.min(2692, player.y)); var shootInput = rightJoystick.getNormalizedInput(); if (rightJoystick.distance > 0) { player.updateGunRotation(Math.atan2(shootInput.y, shootInput.x)); } if (rightJoystick.distance > SHOOT_THRESHOLD) fireBullet(); zombieSpawnTimer++; if (zombieSpawnTimer >= zombieSpawnRate) { spawnZombie(); zombieSpawnTimer = 0; } for (var _i = 0, _arr = [].concat(bullets); _i < _arr.length; _i++) { var bullet = _arr[_i]; for (var _i2 = 0, _arr2 = [].concat(zombies); _i2 < _arr2.length; _i2++) { var zombie = _arr2[_i2]; if (bullet.intersects(zombie)) { LK.getSound('zombieHit').play(); score += 10; checkLevelUp(); // HER ZOMBİDE LEVEL KONTROL zombie.die(); bullet.destroy(); removeFromArray(bullets, bullet); removeFromArray(zombies, zombie); break; } } } updateUI(); }; function updateUI() { // Update health bar healthBar.scaleX = player.health / player.maxHealth * 10; ammoText.setText('Ammo: ' + player.ammo); scoreText.setText('Score: ' + score); // Change health bar color based on health if (player.health < 25) { healthBar.tint = 0xFF0000; // Red } else if (player.health < 50) { healthBar.tint = 0xFFFF00; // Yellow } else { healthBar.tint = 0x00FF00; // Green } }
===================================================================
--- original.js
+++ change.js
@@ -199,8 +199,36 @@
self.health = 1;
self.dodgeCooldown = 0;
self.dodgeVelocityX = 0;
self.dodgeVelocityY = 0;
+ self.die = function () {
+ // Store zombie position for power-up drop
+ var zombieX = self.x;
+ var zombieY = self.y;
+ // Red disintegration effect
+ tween(self, {
+ tint: 0xFF0000,
+ alpha: 0,
+ scaleX: 0.3,
+ scaleY: 0.3
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ // Chance to drop power-up
+ if (Math.random() < 0.15) {
+ // 15% chance
+ var powerUpType = Math.random() < 0.6 ? 'health' : 'ammo';
+ var powerUp = new PowerUp(powerUpType);
+ powerUp.x = zombieX;
+ powerUp.y = zombieY;
+ powerUps.push(powerUp);
+ game.addChild(powerUp);
+ }
+ };
self.update = function () {
// Reduce dodge cooldown
if (self.dodgeCooldown > 0) {
self.dodgeCooldown--;
@@ -272,8 +300,17 @@
/****
* Game Code
****/
+// Utility function to remove items from arrays
+function removeFromArray(array, item) {
+ for (var i = array.length - 1; i >= 0; i--) {
+ if (array[i] === item) {
+ array.splice(i, 1);
+ break;
+ }
+ }
+}
// Game variables
var player;
var zombies = [];
var bullets = [];