/**** * 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();