User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'call')' in or related to this line: 'Entity.prototype.die.call(this);' Line Number: 197
Code edit (1 edits merged)
Please save this source code
User prompt
Sandbox Survivors: Yellow vs. Zombies
User prompt
Please continue polishing my design document.
Initial prompt
we are making a top down sandbox game where yellow guys and zombies fight.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ 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.velocityX = 0; self.velocityY = 0; self.damage = 20; self.lifespan = 60; // Frames until bullet is destroyed self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.lifespan--; if (self.lifespan <= 0) { self.destroy(); var index = game.bullets.indexOf(self); if (index !== -1) { game.bullets.splice(index, 1); } return; } // Check collision with zombies for (var i = 0; i < game.zombies.length; i++) { var zombie = game.zombies[i]; if (zombie.isAlive && self.intersects(zombie)) { zombie.takeDamage(self.damage); LK.getSound('zombieHit').play(); // Remove bullet self.destroy(); var bulletIndex = game.bullets.indexOf(self); if (bulletIndex !== -1) { game.bullets.splice(bulletIndex, 1); } return; } } // Check collision with walls for (var j = 0; j < game.walls.length; j++) { var wall = game.walls[j]; if (self.intersects(wall)) { // Remove bullet self.destroy(); var bulletWallIndex = game.bullets.indexOf(self); if (bulletWallIndex !== -1) { game.bullets.splice(bulletWallIndex, 1); } return; } } }; return self; }); var Entity = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.health = 100; self.maxHealth = 100; self.angle = 0; self.isAlive = true; // Create health bar background var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0, y: -40 }); // Create health bar var healthBar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0, y: -40 }); self.updateHealthBar = function () { var healthPercentage = self.health / self.maxHealth; healthBar.scale.x = healthPercentage; if (healthPercentage > 0.6) { healthBar.tint = 0x00ff00; // Green } else if (healthPercentage > 0.3) { healthBar.tint = 0xffff00; // Yellow } else { healthBar.tint = 0xff0000; // Red } }; self.takeDamage = function (amount) { if (!self.isAlive) { return; } self.health -= amount; if (self.health <= 0) { self.health = 0; self.die(); } self.updateHealthBar(); LK.effects.flashObject(self, 0xff0000, 200); }; self.die = function () { self.isAlive = false; self.visible = false; self.healthBar = null; self.healthBarBg = null; }; self.updateHealthBar(); return self; }); var Zombie = Entity.expand(function () { var self = Entity.call(this); var zombieGraphics = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.damage = 10; self.attackCooldown = 0; self.attackDelay = 30; self.scoreValue = 10; self.update = function () { if (!self.isAlive) { return; } // Get the player position var player = game.player; if (!player.isAlive) { return; } // Calculate direction to player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Check for walls and try to navigate around them var canMoveDirectly = true; for (var i = 0; i < game.walls.length; i++) { var wall = game.walls[i]; // Simple collision avoidance by checking if the wall is between zombie and player var wallToPLayerDist = Math.sqrt(Math.pow(player.x - wall.x, 2) + Math.pow(player.y - wall.y, 2)); var zombieToWallDist = Math.sqrt(Math.pow(self.x - wall.x, 2) + Math.pow(self.y - wall.y, 2)); if (zombieToWallDist < 80 && zombieToWallDist < wallToPLayerDist) { // Wall is between zombie and player, try to move around it canMoveDirectly = false; // Simple avoidance by moving perpendicular to the wall var perpX = -(player.y - self.y); var perpY = player.x - self.x; var perpMag = Math.sqrt(perpX * perpX + perpY * perpY); if (perpMag > 0) { var moveX = perpX / perpMag * self.speed; var moveY = perpY / perpMag * self.speed; self.x += moveX; self.y += moveY; } break; } } if (canMoveDirectly && distance > 0) { // Move towards player self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Attack cooldown if (self.attackCooldown > 0) { self.attackCooldown--; } // Check if close enough to attack player if (distance < 70 && self.attackCooldown === 0) { self.attack(player); } }; self.attack = function (target) { target.takeDamage(self.damage); self.attackCooldown = self.attackDelay; LK.getSound('playerHit').play(); }; self.die = function () { Entity.prototype.die.call(this); // Drop resource with 30% chance if (Math.random() < 0.3) { var resource = new Resource(); resource.x = self.x; resource.y = self.y; resource.value = Math.floor(Math.random() * 3) + 1; game.resources.push(resource); game.addChild(resource); } // Increase score game.increaseScore(self.scoreValue); // Remove from zombies array var index = game.zombies.indexOf(self); if (index !== -1) { game.zombies.splice(index, 1); } }; return self; }); var Wall = Entity.expand(function () { var self = Entity.call(this); var wallGraphics = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); self.health = 150; self.maxHealth = 150; self.updateHealthBar(); return self; }); var Player = Entity.expand(function () { var self = Entity.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.shootCooldown = 0; self.shootDelay = 10; self.resources = 0; self.damage = 20; self.targetX = 0; self.targetY = 0; self.isMoving = false; self.update = function () { if (!self.isAlive) { return; } // Movement if (self.isMoving) { var dx = self.targetX - self.x; var dy = self.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 = self.targetX; self.y = self.targetY; self.isMoving = false; } } // Shooting cooldown if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.shoot = function (targetX, targetY) { if (!self.isAlive || self.shootCooldown > 0) { return; } var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; // Calculate direction var dx = targetX - self.x; var dy = targetY - self.y; var magnitude = Math.sqrt(dx * dx + dy * dy); bullet.velocityX = dx / magnitude * bullet.speed; bullet.velocityY = dy / magnitude * bullet.speed; bullet.rotation = Math.atan2(dy, dx); bullet.damage = self.damage; game.bullets.push(bullet); game.addChild(bullet); self.shootCooldown = self.shootDelay; LK.getSound('shoot').play(); }; self.collectResource = function (resource) { self.resources += resource.value; game.updateResourceText(); LK.getSound('collect').play(); }; self.buildWall = function () { if (self.resources >= 10) { var wall = new Wall(); wall.x = self.x; wall.y = self.y; // Check if wall overlaps with player or other walls var canBuild = true; if (wall.intersects(self)) { canBuild = false; } for (var i = 0; i < game.walls.length; i++) { if (wall.intersects(game.walls[i])) { canBuild = false; break; } } if (canBuild) { game.walls.push(wall); game.addChild(wall); self.resources -= 10; game.updateResourceText(); LK.getSound('build').play(); } else { wall.destroy(); } } }; return self; }); var Resource = Container.expand(function () { var self = Container.call(this); var resourceGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5 }); self.value = 1; self.pulse = function () { tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: self.pulse }); } }); }; self.pulse(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2e2e2e }); /**** * Game Code ****/ // Game state variables game.player = null; game.zombies = []; game.bullets = []; game.resources = []; game.walls = []; game.wave = 1; game.zombiesInWave = 5; game.zombiesSpawned = 0; game.waveActive = false; game.spawnTimer = 0; game.spawnDelay = 60; game.score = 0; game.gameStarted = false; // Initialize game ground var ground = LK.getAsset('ground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.5 }); game.addChild(ground); // Initialize UI elements var scoreText = new Text2('Score: 0', { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topRight.addChild(scoreText); scoreText.x = -200; scoreText.y = 50; var waveText = new Text2('Wave: 1', { size: 50, fill: 0xFFFFFF }); waveText.anchor.set(0, 0); LK.gui.topRight.addChild(waveText); waveText.x = -200; waveText.y = 110; var resourceText = new Text2('Resources: 0', { size: 50, fill: 0xFFFFFF }); resourceText.anchor.set(0, 0); LK.gui.topRight.addChild(resourceText); resourceText.x = -300; resourceText.y = 170; var healthText = new Text2('Health: 100', { size: 50, fill: 0xFFFFFF }); healthText.anchor.set(0, 0); LK.gui.topRight.addChild(healthText); healthText.x = -250; healthText.y = 230; var startText = new Text2('Tap to Start', { size: 80, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); LK.gui.center.addChild(startText); var buildWallText = new Text2('Build Wall (10 Resources)', { size: 40, fill: 0xFFFFFF }); buildWallText.anchor.set(0.5, 0); LK.gui.bottom.addChild(buildWallText); buildWallText.y = -100; buildWallText.visible = false; // Helper functions for UI updates game.updateScoreText = function () { scoreText.setText('Score: ' + game.score); }; game.updateWaveText = function () { waveText.setText('Wave: ' + game.wave); }; game.updateResourceText = function () { resourceText.setText('Resources: ' + game.player.resources); }; game.updateHealthText = function () { healthText.setText('Health: ' + game.player.health); }; game.increaseScore = function (amount) { game.score += amount; game.updateScoreText(); // Update high score if needed if (game.score > storage.highScore) { storage.highScore = game.score; } }; // Game initialization function game.startGame = function () { if (game.gameStarted) { return; } game.gameStarted = true; startText.visible = false; buildWallText.visible = true; // Create player game.player = new Player(); game.player.x = 2048 / 2; game.player.y = 2732 / 2; game.addChild(game.player); // Start first wave game.startWave(); // Play background music LK.playMusic('bgmusic'); }; // Wave management game.startWave = function () { game.waveActive = true; game.zombiesSpawned = 0; game.spawnTimer = 0; game.zombiesInWave = 5 + (game.wave - 1) * 3; game.updateWaveText(); // Show wave number var waveAnnouncement = new Text2('Wave ' + game.wave, { size: 120, fill: 0xFF0000 }); waveAnnouncement.anchor.set(0.5, 0.5); LK.gui.center.addChild(waveAnnouncement); // Animate and remove after 2 seconds tween(waveAnnouncement, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { waveAnnouncement.destroy(); } }); }; game.waveCompleted = function () { game.waveActive = false; game.wave++; // Spawn resources as reward for (var i = 0; i < 3; i++) { var resource = new Resource(); resource.x = Math.random() * 1800 + 124; resource.y = Math.random() * 2500 + 116; resource.value = Math.floor(Math.random() * 3) + 2; game.resources.push(resource); game.addChild(resource); } // Start next wave after delay LK.setTimeout(function () { game.startWave(); }, 5000); // Show wave completed var completedText = new Text2('Wave Completed!', { size: 80, fill: 0x00FF00 }); completedText.anchor.set(0.5, 0.5); LK.gui.center.addChild(completedText); // Animate and remove after 2 seconds tween(completedText, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { completedText.destroy(); } }); }; // Spawn a zombie at a random edge position game.spawnZombie = function () { var zombie = new Zombie(); // Determine spawn position at the edge of the screen 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 = 2048 + 50; zombie.y = Math.random() * 2732; break; case 2: // Bottom zombie.x = Math.random() * 2048; zombie.y = 2732 + 50; break; case 3: // Left zombie.x = -50; zombie.y = Math.random() * 2732; break; } // Add to game game.zombies.push(zombie); game.addChild(zombie); game.zombiesSpawned++; }; // Input handling game.down = function (x, y, obj) { if (!game.gameStarted) { game.startGame(); return; } if (!game.player || !game.player.isAlive) { return; } // Check if the bottom button was clicked var localPos = buildWallText.toGlobal({ x: 0, y: 0 }); var textBounds = { x: localPos.x - buildWallText.width / 2, y: localPos.y, width: buildWallText.width, height: buildWallText.height }; if (x >= textBounds.x && x <= textBounds.x + textBounds.width && y >= textBounds.y && y <= textBounds.y + textBounds.height) { // Build wall button clicked game.player.buildWall(); return; } // Move player to clicked position game.player.targetX = x; game.player.targetY = y; game.player.isMoving = true; // Also shoot towards that direction game.player.shoot(x, y); }; // Auto shooting at nearest zombie when not moving game.autoShoot = function () { if (!game.player || !game.player.isAlive || game.player.isMoving) { return; } // Find closest zombie var closestZombie = null; var closestDistance = Infinity; for (var i = 0; i < game.zombies.length; i++) { var zombie = game.zombies[i]; if (!zombie.isAlive) { continue; } var distance = Math.sqrt(Math.pow(zombie.x - game.player.x, 2) + Math.pow(zombie.y - game.player.y, 2)); if (distance < closestDistance) { closestDistance = distance; closestZombie = zombie; } } // Shoot at closest zombie if in range if (closestZombie && closestDistance < 800) { game.player.shoot(closestZombie.x, closestZombie.y); } }; // Collision detection for resources game.checkResourceCollection = function () { if (!game.player || !game.player.isAlive) { return; } for (var i = game.resources.length - 1; i >= 0; i--) { var resource = game.resources[i]; if (game.player.intersects(resource)) { game.player.collectResource(resource); resource.destroy(); game.resources.splice(i, 1); } } }; // Game update function game.update = function () { // Don't update if game hasn't started if (!game.gameStarted) { return; } // If player is dead, show game over if (game.player && !game.player.isAlive) { LK.showGameOver(); return; } // Update health text if (game.player) { game.updateHealthText(); } // Update all game entities if (game.player) { game.player.update(); } // Update zombies for (var i = 0; i < game.zombies.length; i++) { if (game.zombies[i].isAlive) { game.zombies[i].update(); } } // Update bullets for (var j = 0; j < game.bullets.length; j++) { game.bullets[j].update(); } // Check for resource collection game.checkResourceCollection(); // Auto shoot if not moving if (LK.ticks % 15 === 0) { game.autoShoot(); } // Spawn zombies during active wave if (game.waveActive && game.zombiesSpawned < game.zombiesInWave) { game.spawnTimer++; if (game.spawnTimer >= game.spawnDelay) { game.spawnZombie(); game.spawnTimer = 0; } } // Check if wave is complete if (game.waveActive && game.zombiesSpawned >= game.zombiesInWave && game.zombies.length === 0) { game.waveCompleted(); } };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,661 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0
+});
+
+/****
+* Classes
+****/
+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.velocityX = 0;
+ self.velocityY = 0;
+ self.damage = 20;
+ self.lifespan = 60; // Frames until bullet is destroyed
+ self.update = function () {
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ self.lifespan--;
+ if (self.lifespan <= 0) {
+ self.destroy();
+ var index = game.bullets.indexOf(self);
+ if (index !== -1) {
+ game.bullets.splice(index, 1);
+ }
+ return;
+ }
+ // Check collision with zombies
+ for (var i = 0; i < game.zombies.length; i++) {
+ var zombie = game.zombies[i];
+ if (zombie.isAlive && self.intersects(zombie)) {
+ zombie.takeDamage(self.damage);
+ LK.getSound('zombieHit').play();
+ // Remove bullet
+ self.destroy();
+ var bulletIndex = game.bullets.indexOf(self);
+ if (bulletIndex !== -1) {
+ game.bullets.splice(bulletIndex, 1);
+ }
+ return;
+ }
+ }
+ // Check collision with walls
+ for (var j = 0; j < game.walls.length; j++) {
+ var wall = game.walls[j];
+ if (self.intersects(wall)) {
+ // Remove bullet
+ self.destroy();
+ var bulletWallIndex = game.bullets.indexOf(self);
+ if (bulletWallIndex !== -1) {
+ game.bullets.splice(bulletWallIndex, 1);
+ }
+ return;
+ }
+ }
+ };
+ return self;
+});
+var Entity = Container.expand(function () {
+ var self = Container.call(this);
+ self.speed = 0;
+ self.health = 100;
+ self.maxHealth = 100;
+ self.angle = 0;
+ self.isAlive = true;
+ // Create health bar background
+ var healthBarBg = self.attachAsset('healthBarBg', {
+ anchorX: 0.5,
+ anchorY: 0,
+ y: -40
+ });
+ // Create health bar
+ var healthBar = self.attachAsset('healthBar', {
+ anchorX: 0.5,
+ anchorY: 0,
+ y: -40
+ });
+ self.updateHealthBar = function () {
+ var healthPercentage = self.health / self.maxHealth;
+ healthBar.scale.x = healthPercentage;
+ if (healthPercentage > 0.6) {
+ healthBar.tint = 0x00ff00; // Green
+ } else if (healthPercentage > 0.3) {
+ healthBar.tint = 0xffff00; // Yellow
+ } else {
+ healthBar.tint = 0xff0000; // Red
+ }
+ };
+ self.takeDamage = function (amount) {
+ if (!self.isAlive) {
+ return;
+ }
+ self.health -= amount;
+ if (self.health <= 0) {
+ self.health = 0;
+ self.die();
+ }
+ self.updateHealthBar();
+ LK.effects.flashObject(self, 0xff0000, 200);
+ };
+ self.die = function () {
+ self.isAlive = false;
+ self.visible = false;
+ self.healthBar = null;
+ self.healthBarBg = null;
+ };
+ self.updateHealthBar();
+ return self;
+});
+var Zombie = Entity.expand(function () {
+ var self = Entity.call(this);
+ var zombieGraphics = self.attachAsset('zombie', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 2;
+ self.damage = 10;
+ self.attackCooldown = 0;
+ self.attackDelay = 30;
+ self.scoreValue = 10;
+ self.update = function () {
+ if (!self.isAlive) {
+ return;
+ }
+ // Get the player position
+ var player = game.player;
+ if (!player.isAlive) {
+ return;
+ }
+ // Calculate direction to player
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ // Check for walls and try to navigate around them
+ var canMoveDirectly = true;
+ for (var i = 0; i < game.walls.length; i++) {
+ var wall = game.walls[i];
+ // Simple collision avoidance by checking if the wall is between zombie and player
+ var wallToPLayerDist = Math.sqrt(Math.pow(player.x - wall.x, 2) + Math.pow(player.y - wall.y, 2));
+ var zombieToWallDist = Math.sqrt(Math.pow(self.x - wall.x, 2) + Math.pow(self.y - wall.y, 2));
+ if (zombieToWallDist < 80 && zombieToWallDist < wallToPLayerDist) {
+ // Wall is between zombie and player, try to move around it
+ canMoveDirectly = false;
+ // Simple avoidance by moving perpendicular to the wall
+ var perpX = -(player.y - self.y);
+ var perpY = player.x - self.x;
+ var perpMag = Math.sqrt(perpX * perpX + perpY * perpY);
+ if (perpMag > 0) {
+ var moveX = perpX / perpMag * self.speed;
+ var moveY = perpY / perpMag * self.speed;
+ self.x += moveX;
+ self.y += moveY;
+ }
+ break;
+ }
+ }
+ if (canMoveDirectly && distance > 0) {
+ // Move towards player
+ self.x += dx / distance * self.speed;
+ self.y += dy / distance * self.speed;
+ }
+ // Attack cooldown
+ if (self.attackCooldown > 0) {
+ self.attackCooldown--;
+ }
+ // Check if close enough to attack player
+ if (distance < 70 && self.attackCooldown === 0) {
+ self.attack(player);
+ }
+ };
+ self.attack = function (target) {
+ target.takeDamage(self.damage);
+ self.attackCooldown = self.attackDelay;
+ LK.getSound('playerHit').play();
+ };
+ self.die = function () {
+ Entity.prototype.die.call(this);
+ // Drop resource with 30% chance
+ if (Math.random() < 0.3) {
+ var resource = new Resource();
+ resource.x = self.x;
+ resource.y = self.y;
+ resource.value = Math.floor(Math.random() * 3) + 1;
+ game.resources.push(resource);
+ game.addChild(resource);
+ }
+ // Increase score
+ game.increaseScore(self.scoreValue);
+ // Remove from zombies array
+ var index = game.zombies.indexOf(self);
+ if (index !== -1) {
+ game.zombies.splice(index, 1);
+ }
+ };
+ return self;
+});
+var Wall = Entity.expand(function () {
+ var self = Entity.call(this);
+ var wallGraphics = self.attachAsset('wall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 150;
+ self.maxHealth = 150;
+ self.updateHealthBar();
+ return self;
+});
+var Player = Entity.expand(function () {
+ var self = Entity.call(this);
+ var playerGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 5;
+ self.shootCooldown = 0;
+ self.shootDelay = 10;
+ self.resources = 0;
+ self.damage = 20;
+ self.targetX = 0;
+ self.targetY = 0;
+ self.isMoving = false;
+ self.update = function () {
+ if (!self.isAlive) {
+ return;
+ }
+ // Movement
+ if (self.isMoving) {
+ var dx = self.targetX - self.x;
+ var dy = self.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 = self.targetX;
+ self.y = self.targetY;
+ self.isMoving = false;
+ }
+ }
+ // Shooting cooldown
+ if (self.shootCooldown > 0) {
+ self.shootCooldown--;
+ }
+ };
+ self.shoot = function (targetX, targetY) {
+ if (!self.isAlive || self.shootCooldown > 0) {
+ return;
+ }
+ var bullet = new Bullet();
+ bullet.x = self.x;
+ bullet.y = self.y;
+ // Calculate direction
+ var dx = targetX - self.x;
+ var dy = targetY - self.y;
+ var magnitude = Math.sqrt(dx * dx + dy * dy);
+ bullet.velocityX = dx / magnitude * bullet.speed;
+ bullet.velocityY = dy / magnitude * bullet.speed;
+ bullet.rotation = Math.atan2(dy, dx);
+ bullet.damage = self.damage;
+ game.bullets.push(bullet);
+ game.addChild(bullet);
+ self.shootCooldown = self.shootDelay;
+ LK.getSound('shoot').play();
+ };
+ self.collectResource = function (resource) {
+ self.resources += resource.value;
+ game.updateResourceText();
+ LK.getSound('collect').play();
+ };
+ self.buildWall = function () {
+ if (self.resources >= 10) {
+ var wall = new Wall();
+ wall.x = self.x;
+ wall.y = self.y;
+ // Check if wall overlaps with player or other walls
+ var canBuild = true;
+ if (wall.intersects(self)) {
+ canBuild = false;
+ }
+ for (var i = 0; i < game.walls.length; i++) {
+ if (wall.intersects(game.walls[i])) {
+ canBuild = false;
+ break;
+ }
+ }
+ if (canBuild) {
+ game.walls.push(wall);
+ game.addChild(wall);
+ self.resources -= 10;
+ game.updateResourceText();
+ LK.getSound('build').play();
+ } else {
+ wall.destroy();
+ }
+ }
+ };
+ return self;
+});
+var Resource = Container.expand(function () {
+ var self = Container.call(this);
+ var resourceGraphics = self.attachAsset('resource', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.value = 1;
+ self.pulse = function () {
+ tween(self, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: self.pulse
+ });
+ }
+ });
+ };
+ self.pulse();
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2e2e2e
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+game.player = null;
+game.zombies = [];
+game.bullets = [];
+game.resources = [];
+game.walls = [];
+game.wave = 1;
+game.zombiesInWave = 5;
+game.zombiesSpawned = 0;
+game.waveActive = false;
+game.spawnTimer = 0;
+game.spawnDelay = 60;
+game.score = 0;
+game.gameStarted = false;
+// Initialize game ground
+var ground = LK.getAsset('ground', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 2732 / 2,
+ alpha: 0.5
+});
+game.addChild(ground);
+// Initialize UI elements
+var scoreText = new Text2('Score: 0', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0, 0);
+LK.gui.topRight.addChild(scoreText);
+scoreText.x = -200;
+scoreText.y = 50;
+var waveText = new Text2('Wave: 1', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+waveText.anchor.set(0, 0);
+LK.gui.topRight.addChild(waveText);
+waveText.x = -200;
+waveText.y = 110;
+var resourceText = new Text2('Resources: 0', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+resourceText.anchor.set(0, 0);
+LK.gui.topRight.addChild(resourceText);
+resourceText.x = -300;
+resourceText.y = 170;
+var healthText = new Text2('Health: 100', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+healthText.anchor.set(0, 0);
+LK.gui.topRight.addChild(healthText);
+healthText.x = -250;
+healthText.y = 230;
+var startText = new Text2('Tap to Start', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+startText.anchor.set(0.5, 0.5);
+LK.gui.center.addChild(startText);
+var buildWallText = new Text2('Build Wall (10 Resources)', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+buildWallText.anchor.set(0.5, 0);
+LK.gui.bottom.addChild(buildWallText);
+buildWallText.y = -100;
+buildWallText.visible = false;
+// Helper functions for UI updates
+game.updateScoreText = function () {
+ scoreText.setText('Score: ' + game.score);
+};
+game.updateWaveText = function () {
+ waveText.setText('Wave: ' + game.wave);
+};
+game.updateResourceText = function () {
+ resourceText.setText('Resources: ' + game.player.resources);
+};
+game.updateHealthText = function () {
+ healthText.setText('Health: ' + game.player.health);
+};
+game.increaseScore = function (amount) {
+ game.score += amount;
+ game.updateScoreText();
+ // Update high score if needed
+ if (game.score > storage.highScore) {
+ storage.highScore = game.score;
+ }
+};
+// Game initialization function
+game.startGame = function () {
+ if (game.gameStarted) {
+ return;
+ }
+ game.gameStarted = true;
+ startText.visible = false;
+ buildWallText.visible = true;
+ // Create player
+ game.player = new Player();
+ game.player.x = 2048 / 2;
+ game.player.y = 2732 / 2;
+ game.addChild(game.player);
+ // Start first wave
+ game.startWave();
+ // Play background music
+ LK.playMusic('bgmusic');
+};
+// Wave management
+game.startWave = function () {
+ game.waveActive = true;
+ game.zombiesSpawned = 0;
+ game.spawnTimer = 0;
+ game.zombiesInWave = 5 + (game.wave - 1) * 3;
+ game.updateWaveText();
+ // Show wave number
+ var waveAnnouncement = new Text2('Wave ' + game.wave, {
+ size: 120,
+ fill: 0xFF0000
+ });
+ waveAnnouncement.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(waveAnnouncement);
+ // Animate and remove after 2 seconds
+ tween(waveAnnouncement, {
+ alpha: 0
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ waveAnnouncement.destroy();
+ }
+ });
+};
+game.waveCompleted = function () {
+ game.waveActive = false;
+ game.wave++;
+ // Spawn resources as reward
+ for (var i = 0; i < 3; i++) {
+ var resource = new Resource();
+ resource.x = Math.random() * 1800 + 124;
+ resource.y = Math.random() * 2500 + 116;
+ resource.value = Math.floor(Math.random() * 3) + 2;
+ game.resources.push(resource);
+ game.addChild(resource);
+ }
+ // Start next wave after delay
+ LK.setTimeout(function () {
+ game.startWave();
+ }, 5000);
+ // Show wave completed
+ var completedText = new Text2('Wave Completed!', {
+ size: 80,
+ fill: 0x00FF00
+ });
+ completedText.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(completedText);
+ // Animate and remove after 2 seconds
+ tween(completedText, {
+ alpha: 0
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ completedText.destroy();
+ }
+ });
+};
+// Spawn a zombie at a random edge position
+game.spawnZombie = function () {
+ var zombie = new Zombie();
+ // Determine spawn position at the edge of the screen
+ 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 = 2048 + 50;
+ zombie.y = Math.random() * 2732;
+ break;
+ case 2:
+ // Bottom
+ zombie.x = Math.random() * 2048;
+ zombie.y = 2732 + 50;
+ break;
+ case 3:
+ // Left
+ zombie.x = -50;
+ zombie.y = Math.random() * 2732;
+ break;
+ }
+ // Add to game
+ game.zombies.push(zombie);
+ game.addChild(zombie);
+ game.zombiesSpawned++;
+};
+// Input handling
+game.down = function (x, y, obj) {
+ if (!game.gameStarted) {
+ game.startGame();
+ return;
+ }
+ if (!game.player || !game.player.isAlive) {
+ return;
+ }
+ // Check if the bottom button was clicked
+ var localPos = buildWallText.toGlobal({
+ x: 0,
+ y: 0
+ });
+ var textBounds = {
+ x: localPos.x - buildWallText.width / 2,
+ y: localPos.y,
+ width: buildWallText.width,
+ height: buildWallText.height
+ };
+ if (x >= textBounds.x && x <= textBounds.x + textBounds.width && y >= textBounds.y && y <= textBounds.y + textBounds.height) {
+ // Build wall button clicked
+ game.player.buildWall();
+ return;
+ }
+ // Move player to clicked position
+ game.player.targetX = x;
+ game.player.targetY = y;
+ game.player.isMoving = true;
+ // Also shoot towards that direction
+ game.player.shoot(x, y);
+};
+// Auto shooting at nearest zombie when not moving
+game.autoShoot = function () {
+ if (!game.player || !game.player.isAlive || game.player.isMoving) {
+ return;
+ }
+ // Find closest zombie
+ var closestZombie = null;
+ var closestDistance = Infinity;
+ for (var i = 0; i < game.zombies.length; i++) {
+ var zombie = game.zombies[i];
+ if (!zombie.isAlive) {
+ continue;
+ }
+ var distance = Math.sqrt(Math.pow(zombie.x - game.player.x, 2) + Math.pow(zombie.y - game.player.y, 2));
+ if (distance < closestDistance) {
+ closestDistance = distance;
+ closestZombie = zombie;
+ }
+ }
+ // Shoot at closest zombie if in range
+ if (closestZombie && closestDistance < 800) {
+ game.player.shoot(closestZombie.x, closestZombie.y);
+ }
+};
+// Collision detection for resources
+game.checkResourceCollection = function () {
+ if (!game.player || !game.player.isAlive) {
+ return;
+ }
+ for (var i = game.resources.length - 1; i >= 0; i--) {
+ var resource = game.resources[i];
+ if (game.player.intersects(resource)) {
+ game.player.collectResource(resource);
+ resource.destroy();
+ game.resources.splice(i, 1);
+ }
+ }
+};
+// Game update function
+game.update = function () {
+ // Don't update if game hasn't started
+ if (!game.gameStarted) {
+ return;
+ }
+ // If player is dead, show game over
+ if (game.player && !game.player.isAlive) {
+ LK.showGameOver();
+ return;
+ }
+ // Update health text
+ if (game.player) {
+ game.updateHealthText();
+ }
+ // Update all game entities
+ if (game.player) {
+ game.player.update();
+ }
+ // Update zombies
+ for (var i = 0; i < game.zombies.length; i++) {
+ if (game.zombies[i].isAlive) {
+ game.zombies[i].update();
+ }
+ }
+ // Update bullets
+ for (var j = 0; j < game.bullets.length; j++) {
+ game.bullets[j].update();
+ }
+ // Check for resource collection
+ game.checkResourceCollection();
+ // Auto shoot if not moving
+ if (LK.ticks % 15 === 0) {
+ game.autoShoot();
+ }
+ // Spawn zombies during active wave
+ if (game.waveActive && game.zombiesSpawned < game.zombiesInWave) {
+ game.spawnTimer++;
+ if (game.spawnTimer >= game.spawnDelay) {
+ game.spawnZombie();
+ game.spawnTimer = 0;
+ }
+ }
+ // Check if wave is complete
+ if (game.waveActive && game.zombiesSpawned >= game.zombiesInWave && game.zombies.length === 0) {
+ game.waveCompleted();
+ }
+};
\ No newline at end of file
Make A Topdown Yellow Ball With Eyes. Single Game Texture. In-Game asset. Blank background. High contrast. No shadows
Make A Topdown Green Ball With Eyes. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A Yellow Blurry Ball. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A Topdown Stone Ground. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Wood Plank. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows