/**** * 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 () { if (typeof Entity.prototype.die === 'function') { Entity.prototype.die.call(this); } else { console.error("Entity.prototype.die is not defined"); } // 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(); } };
/****
* 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 () {
if (typeof Entity.prototype.die === 'function') {
Entity.prototype.die.call(this);
} else {
console.error("Entity.prototype.die is not defined");
}
// 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();
}
};
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