/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.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 = 15;
self.xSpeed = 0; // Horizontal speed component for spread shots
self.damage = 1;
self.update = function () {
self.y -= self.speed;
self.x += self.xSpeed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.fireRate = 20; // Frames between shots
self.nextFireTime = 0;
self.weaponPower = 1;
self.update = function () {
// Player update logic will be handled in the game's update function
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.getSound('playerHit').play();
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
return true; // Return true if player died
}
return false;
};
self.shoot = function () {
if (LK.ticks < self.nextFireTime) {
return;
}
self.nextFireTime = LK.ticks + self.fireRate;
LK.getSound('shoot').play();
if (self.weaponPower === 1) {
// Single bullet
return [createBullet(self.x, self.y - 40)];
} else if (self.weaponPower === 2) {
// Double bullet
return [createBullet(self.x - 20, self.y - 40), createBullet(self.x + 20, self.y - 40)];
} else {
// Triple bullet (spread)
return [createBullet(self.x, self.y - 40), createBullet(self.x - 25, self.y - 35, -0.3), createBullet(self.x + 25, self.y - 35, 0.3)];
}
function createBullet(x, y) {
var xSpeed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var bullet = new Bullet();
bullet.x = x;
bullet.y = y;
bullet.xSpeed = xSpeed;
return bullet;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.floor(Math.random() * 3); // 0: weapon, 1: fire rate, 2: health
// Set color based on type
if (self.type === 0) {
powerupGraphics.tint = 0xff5733; // Weapon upgrade (orange)
} else if (self.type === 1) {
powerupGraphics.tint = 0x33ff57; // Fire rate (green)
} else {
powerupGraphics.tint = 0x3357ff; // Health (blue)
}
self.speed = 3;
self.update = function () {
self.y += self.speed;
};
self.applyEffect = function (player) {
LK.getSound('powerupCollect').play();
if (self.type === 0) {
// Weapon upgrade
player.weaponPower = Math.min(player.weaponPower + 1, 3);
} else if (self.type === 1) {
// Fire rate increase
player.fireRate = Math.max(player.fireRate - 5, 5);
} else {
// Health
player.health = Math.min(player.health + 25, 100);
}
};
return self;
});
var RedLine = Container.expand(function () {
var self = Container.call(this);
// Create a red line that spans the width of the game
var graphics = self.attachAsset('redLine', {
anchorX: 0,
anchorY: 0
});
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 = 2;
self.health = 2;
self.value = 10; // Score value
self.update = function () {
self.y += self.speed;
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.getSound('zombieHit').play();
LK.effects.flashObject(self, 0xffff00, 100);
if (self.health <= 0) {
return true; // Return true if zombie died
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var player;
var bullets = [];
var zombies = [];
var powerups = [];
var wave = 1;
var waveZombiesRemaining = 0;
var nextWaveTimeout = null;
var spawnCooldown = 0;
var score = 0;
var gameActive = true;
// UI elements
var scoreTxt;
var healthTxt;
var waveTxt;
function initGame() {
// Reset game state
bullets = [];
zombies = [];
powerups = [];
wave = 1;
waveZombiesRemaining = 5;
spawnCooldown = 0;
score = 0;
gameActive = true;
// Set score
LK.setScore(0);
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 200;
game.addChild(player);
// Setup UI
setupUI();
// Start background music
LK.playMusic('bgMusic');
// Create red line at the bottom of the screen
var redLine = new RedLine();
redLine.x = 0;
redLine.y = 2732 - 100; // Position slightly above the bottom
game.addChild(redLine);
}
function setupUI() {
// Score Text
scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
// Health Text
healthTxt = new Text2('Health: 100', {
size: 80,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.top.addChild(healthTxt);
// Wave Text
waveTxt = new Text2('Wave: 1', {
size: 80,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveTxt);
// Reposition for better visibility
scoreTxt.x = -20;
scoreTxt.y = 20;
healthTxt.y = 20;
waveTxt.x = 120; // Avoid the top-left menu icon area
waveTxt.y = 20;
}
function updateUI() {
scoreTxt.setText('Score: ' + score);
healthTxt.setText('Health: ' + player.health);
waveTxt.setText('Wave: ' + wave);
}
function spawnZombie() {
var zombie = new Zombie();
// Randomize zombie properties based on wave
zombie.x = Math.random() * (2048 - 200) + 100;
zombie.y = -100;
zombie.speed = 2 + Math.random() * (wave * 0.5);
zombie.health = 1 + Math.floor(wave / 3);
zombie.value = 10 + wave * 2;
// Scale difficulty
if (wave > 5) {
zombie.speed *= 1.2;
}
zombies.push(zombie);
game.addChild(zombie);
waveZombiesRemaining--;
}
function spawnPowerUp() {
if (Math.random() < 0.3) {
var powerup = new PowerUp();
powerup.x = Math.random() * (2048 - 200) + 100;
powerup.y = -100;
powerups.push(powerup);
game.addChild(powerup);
}
}
function startNextWave() {
wave++;
waveZombiesRemaining = 5 + wave * 2;
LK.effects.flashScreen(0x0000ff, 500);
}
function handlePlayerMovement(x, y) {
if (!gameActive) {
return;
}
player.x = Math.max(50, Math.min(x, 2048 - 50));
player.y = Math.max(50, Math.min(y, 2732 - 50));
}
function handleCollisions() {
// 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)) {
if (zombie.takeDamage(bullet.damage)) {
// Zombie killed
score += zombie.value;
LK.setScore(score);
// Chance to spawn powerup
if (Math.random() < 0.1) {
spawnPowerUp();
}
zombies.splice(j, 1);
zombie.destroy();
}
bullets.splice(i, 1);
bullet.destroy();
break;
}
}
}
// Player-Zombie collisions
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (player.intersects(zombie)) {
if (player.takeDamage(10)) {
// Player died
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
zombies.splice(j, 1);
zombie.destroy();
}
}
// Player-PowerUp collisions
for (var k = powerups.length - 1; k >= 0; k--) {
var powerup = powerups[k];
if (player.intersects(powerup)) {
powerup.applyEffect(player);
powerups.splice(k, 1);
powerup.destroy();
}
}
}
function cleanupOffscreenObjects() {
// Remove bullets that are off-screen
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i].y < -50) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
// Remove zombies that are off-screen at the bottom or touching the red line
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (zombie.y > 2732 + 50) {
zombie.destroy();
zombies.splice(j, 1);
// Penalty for letting zombies through
score = Math.max(0, score - 5);
LK.setScore(score);
} else if (zombie.y >= 2732 - 110 && zombie.y <= 2732 - 90) {
// Zombie has touched the red line at the bottom
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Remove powerups that are off-screen
for (var k = powerups.length - 1; k >= 0; k--) {
if (powerups[k].y > 2732 + 50) {
powerups[k].destroy();
powerups.splice(k, 1);
}
}
}
// Event handlers
game.down = function (x, y, obj) {
handlePlayerMovement(x, y);
// Shoot when touching
if (gameActive) {
var newBullets = player.shoot();
if (newBullets) {
bullets = bullets.concat(newBullets);
newBullets.forEach(function (bullet) {
game.addChild(bullet);
});
}
}
};
game.move = function (x, y, obj) {
handlePlayerMovement(x, y);
};
game.up = function (x, y, obj) {
// Nothing specific needed for up event
};
// Game update loop
game.update = function () {
if (!gameActive) {
return;
}
// Spawn zombies
if (waveZombiesRemaining > 0) {
spawnCooldown--;
if (spawnCooldown <= 0) {
spawnZombie();
spawnCooldown = Math.max(10, 60 - wave * 5); // Spawn faster as waves progress
}
} else if (zombies.length === 0 && waveZombiesRemaining <= 0 && !nextWaveTimeout) {
// Start next wave if all zombies are cleared and none remaining to spawn
// Use timeout to prevent multiple wave starts
nextWaveTimeout = LK.setTimeout(function () {
startNextWave();
nextWaveTimeout = null;
}, 1000); // 1 second delay between waves
}
// Auto-fire
if (LK.ticks % 5 === 0) {
var newBullets = player.shoot();
if (newBullets) {
bullets = bullets.concat(newBullets);
newBullets.forEach(function (bullet) {
game.addChild(bullet);
});
}
}
// Update game objects
for (var i = 0; i < bullets.length; i++) {
bullets[i].update();
}
for (var j = 0; j < zombies.length; j++) {
zombies[j].update();
}
for (var k = 0; k < powerups.length; k++) {
powerups[k].update();
}
// Handle collisions
handleCollisions();
// Cleanup off-screen objects
cleanupOffscreenObjects();
// Update UI
updateUI();
};
// Initialize the game
initGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.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 = 15;
self.xSpeed = 0; // Horizontal speed component for spread shots
self.damage = 1;
self.update = function () {
self.y -= self.speed;
self.x += self.xSpeed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.fireRate = 20; // Frames between shots
self.nextFireTime = 0;
self.weaponPower = 1;
self.update = function () {
// Player update logic will be handled in the game's update function
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.getSound('playerHit').play();
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
return true; // Return true if player died
}
return false;
};
self.shoot = function () {
if (LK.ticks < self.nextFireTime) {
return;
}
self.nextFireTime = LK.ticks + self.fireRate;
LK.getSound('shoot').play();
if (self.weaponPower === 1) {
// Single bullet
return [createBullet(self.x, self.y - 40)];
} else if (self.weaponPower === 2) {
// Double bullet
return [createBullet(self.x - 20, self.y - 40), createBullet(self.x + 20, self.y - 40)];
} else {
// Triple bullet (spread)
return [createBullet(self.x, self.y - 40), createBullet(self.x - 25, self.y - 35, -0.3), createBullet(self.x + 25, self.y - 35, 0.3)];
}
function createBullet(x, y) {
var xSpeed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var bullet = new Bullet();
bullet.x = x;
bullet.y = y;
bullet.xSpeed = xSpeed;
return bullet;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.floor(Math.random() * 3); // 0: weapon, 1: fire rate, 2: health
// Set color based on type
if (self.type === 0) {
powerupGraphics.tint = 0xff5733; // Weapon upgrade (orange)
} else if (self.type === 1) {
powerupGraphics.tint = 0x33ff57; // Fire rate (green)
} else {
powerupGraphics.tint = 0x3357ff; // Health (blue)
}
self.speed = 3;
self.update = function () {
self.y += self.speed;
};
self.applyEffect = function (player) {
LK.getSound('powerupCollect').play();
if (self.type === 0) {
// Weapon upgrade
player.weaponPower = Math.min(player.weaponPower + 1, 3);
} else if (self.type === 1) {
// Fire rate increase
player.fireRate = Math.max(player.fireRate - 5, 5);
} else {
// Health
player.health = Math.min(player.health + 25, 100);
}
};
return self;
});
var RedLine = Container.expand(function () {
var self = Container.call(this);
// Create a red line that spans the width of the game
var graphics = self.attachAsset('redLine', {
anchorX: 0,
anchorY: 0
});
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 = 2;
self.health = 2;
self.value = 10; // Score value
self.update = function () {
self.y += self.speed;
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.getSound('zombieHit').play();
LK.effects.flashObject(self, 0xffff00, 100);
if (self.health <= 0) {
return true; // Return true if zombie died
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var player;
var bullets = [];
var zombies = [];
var powerups = [];
var wave = 1;
var waveZombiesRemaining = 0;
var nextWaveTimeout = null;
var spawnCooldown = 0;
var score = 0;
var gameActive = true;
// UI elements
var scoreTxt;
var healthTxt;
var waveTxt;
function initGame() {
// Reset game state
bullets = [];
zombies = [];
powerups = [];
wave = 1;
waveZombiesRemaining = 5;
spawnCooldown = 0;
score = 0;
gameActive = true;
// Set score
LK.setScore(0);
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 200;
game.addChild(player);
// Setup UI
setupUI();
// Start background music
LK.playMusic('bgMusic');
// Create red line at the bottom of the screen
var redLine = new RedLine();
redLine.x = 0;
redLine.y = 2732 - 100; // Position slightly above the bottom
game.addChild(redLine);
}
function setupUI() {
// Score Text
scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
// Health Text
healthTxt = new Text2('Health: 100', {
size: 80,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.top.addChild(healthTxt);
// Wave Text
waveTxt = new Text2('Wave: 1', {
size: 80,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveTxt);
// Reposition for better visibility
scoreTxt.x = -20;
scoreTxt.y = 20;
healthTxt.y = 20;
waveTxt.x = 120; // Avoid the top-left menu icon area
waveTxt.y = 20;
}
function updateUI() {
scoreTxt.setText('Score: ' + score);
healthTxt.setText('Health: ' + player.health);
waveTxt.setText('Wave: ' + wave);
}
function spawnZombie() {
var zombie = new Zombie();
// Randomize zombie properties based on wave
zombie.x = Math.random() * (2048 - 200) + 100;
zombie.y = -100;
zombie.speed = 2 + Math.random() * (wave * 0.5);
zombie.health = 1 + Math.floor(wave / 3);
zombie.value = 10 + wave * 2;
// Scale difficulty
if (wave > 5) {
zombie.speed *= 1.2;
}
zombies.push(zombie);
game.addChild(zombie);
waveZombiesRemaining--;
}
function spawnPowerUp() {
if (Math.random() < 0.3) {
var powerup = new PowerUp();
powerup.x = Math.random() * (2048 - 200) + 100;
powerup.y = -100;
powerups.push(powerup);
game.addChild(powerup);
}
}
function startNextWave() {
wave++;
waveZombiesRemaining = 5 + wave * 2;
LK.effects.flashScreen(0x0000ff, 500);
}
function handlePlayerMovement(x, y) {
if (!gameActive) {
return;
}
player.x = Math.max(50, Math.min(x, 2048 - 50));
player.y = Math.max(50, Math.min(y, 2732 - 50));
}
function handleCollisions() {
// 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)) {
if (zombie.takeDamage(bullet.damage)) {
// Zombie killed
score += zombie.value;
LK.setScore(score);
// Chance to spawn powerup
if (Math.random() < 0.1) {
spawnPowerUp();
}
zombies.splice(j, 1);
zombie.destroy();
}
bullets.splice(i, 1);
bullet.destroy();
break;
}
}
}
// Player-Zombie collisions
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (player.intersects(zombie)) {
if (player.takeDamage(10)) {
// Player died
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
zombies.splice(j, 1);
zombie.destroy();
}
}
// Player-PowerUp collisions
for (var k = powerups.length - 1; k >= 0; k--) {
var powerup = powerups[k];
if (player.intersects(powerup)) {
powerup.applyEffect(player);
powerups.splice(k, 1);
powerup.destroy();
}
}
}
function cleanupOffscreenObjects() {
// Remove bullets that are off-screen
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i].y < -50) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
// Remove zombies that are off-screen at the bottom or touching the red line
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (zombie.y > 2732 + 50) {
zombie.destroy();
zombies.splice(j, 1);
// Penalty for letting zombies through
score = Math.max(0, score - 5);
LK.setScore(score);
} else if (zombie.y >= 2732 - 110 && zombie.y <= 2732 - 90) {
// Zombie has touched the red line at the bottom
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Remove powerups that are off-screen
for (var k = powerups.length - 1; k >= 0; k--) {
if (powerups[k].y > 2732 + 50) {
powerups[k].destroy();
powerups.splice(k, 1);
}
}
}
// Event handlers
game.down = function (x, y, obj) {
handlePlayerMovement(x, y);
// Shoot when touching
if (gameActive) {
var newBullets = player.shoot();
if (newBullets) {
bullets = bullets.concat(newBullets);
newBullets.forEach(function (bullet) {
game.addChild(bullet);
});
}
}
};
game.move = function (x, y, obj) {
handlePlayerMovement(x, y);
};
game.up = function (x, y, obj) {
// Nothing specific needed for up event
};
// Game update loop
game.update = function () {
if (!gameActive) {
return;
}
// Spawn zombies
if (waveZombiesRemaining > 0) {
spawnCooldown--;
if (spawnCooldown <= 0) {
spawnZombie();
spawnCooldown = Math.max(10, 60 - wave * 5); // Spawn faster as waves progress
}
} else if (zombies.length === 0 && waveZombiesRemaining <= 0 && !nextWaveTimeout) {
// Start next wave if all zombies are cleared and none remaining to spawn
// Use timeout to prevent multiple wave starts
nextWaveTimeout = LK.setTimeout(function () {
startNextWave();
nextWaveTimeout = null;
}, 1000); // 1 second delay between waves
}
// Auto-fire
if (LK.ticks % 5 === 0) {
var newBullets = player.shoot();
if (newBullets) {
bullets = bullets.concat(newBullets);
newBullets.forEach(function (bullet) {
game.addChild(bullet);
});
}
}
// Update game objects
for (var i = 0; i < bullets.length; i++) {
bullets[i].update();
}
for (var j = 0; j < zombies.length; j++) {
zombies[j].update();
}
for (var k = 0; k < powerups.length; k++) {
powerups[k].update();
}
// Handle collisions
handleCollisions();
// Cleanup off-screen objects
cleanupOffscreenObjects();
// Update UI
updateUI();
};
// Initialize the game
initGame();