/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, totalKills: 0 }); /**** * Classes ****/ var BloodSplatter = Container.expand(function () { var self = Container.call(this); var splatterGraphics = self.attachAsset('bloodSplatter', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); // Rotate splatter randomly splatterGraphics.rotation = Math.random() * Math.PI * 2; // Random scale variation var scale = 0.5 + Math.random() * 0.5; splatterGraphics.scale.set(scale, scale); // Fade out over time self.lifespan = 60; // 1 second at 60fps self.update = function () { self.lifespan--; splatterGraphics.alpha = self.lifespan / 60; if (self.lifespan <= 0) { self.readyToRemove = true; } }; return self; }); var Bullet = Container.expand(function (x, y, speed, damage) { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.x = x; self.y = y; self.speed = speed; self.damage = damage; self.update = function () { self.y += self.speed; if (self.y < -bulletGraphics.height) { self.destroy(); } }; return self; }); var Powerup = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'fire'; var assetId; switch (self.type) { case 'fire': assetId = 'powerupFire'; break; case 'ice': assetId = 'powerupIce'; break; case 'size': assetId = 'powerupSize'; break; } var powerupGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Powerup properties self.speed = 2; self.oscillationSpeed = 0.05; self.oscillationAmount = 10; self.initialY = self.y; self.update = function () { self.y += self.speed; // Oscillate side to side self.x += Math.sin(LK.ticks * self.oscillationSpeed) * self.oscillationAmount; // Spin the powerup powerupGraphics.rotation += 0.03; // Check if powerup has moved past the bottom of the screen if (self.y > 2732 + powerupGraphics.height) { self.isOffscreen = true; } }; return self; }); var Sword = Container.expand(function () { var self = Container.call(this); var swordGraphics = self.attachAsset('sword', { anchorX: 0.5, anchorY: 0.5 }); // Sword properties self.slashing = false; self.damage = 1; self.isPoweredUp = false; self.powerupType = null; self.powerupTimer = 0; self.powerupDuration = 300; // 5 seconds at 60fps self.update = function () { // Handle powerups if (self.isPoweredUp) { self.powerupTimer--; if (self.powerupTimer <= 0) { self.deactivatePowerup(); } } }; self.slash = function () { self.slashing = true; LK.getSound('swordSlash').play(); LK.setTimeout(function () { self.slashing = false; }, 200); // Slash lasts for 200ms }; self.activatePowerup = function (type) { self.isPoweredUp = true; self.powerupType = type; self.powerupTimer = self.powerupDuration; switch (type) { case 'fire': swordGraphics.tint = 0xFF4500; self.damage = 3; break; case 'ice': swordGraphics.tint = 0x1E90FF; self.damage = 2; break; case 'size': swordGraphics.tint = 0xFFD700; swordGraphics.scale.set(1.5, 1.5); self.damage = 2; break; } LK.getSound('powerupCollect').play(); }; self.deactivatePowerup = function () { self.isPoweredUp = false; self.powerupType = null; swordGraphics.tint = 0xFFFFFF; swordGraphics.scale.set(1, 1); self.damage = 1; }; self.down = function (x, y, obj) { self.slash(); // Trigger slashing }; return self; }); var Zombie = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'basic'; var assetId = self.type === 'elite' ? 'zombieElite' : 'zombieBasic'; var zombieGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Zombie properties self.speed = self.type === 'elite' ? 2 : 3; self.health = self.type === 'elite' ? 3 : 1; self.points = self.type === 'elite' ? 10 : 5; self.dropsPowerup = self.type === 'elite'; self.update = function () { self.y += self.speed; // Slightly move side to side for shambling effect self.x += Math.sin(LK.ticks * 0.05) * 0.5; // Slightly move side to side for shambling effect self.x += Math.sin(LK.ticks * 0.05) * 0.5; // Check if zombie has moved past the bottom of the screen if (self.y > 2732 + zombieGraphics.height) { self.isOffscreen = true; } }; self.takeDamage = function (amount) { self.health -= amount; // Flash red when taking damage LK.effects.flashObject(self, 0xFF0000, 200); if (self.health <= 0) { return true; // Zombie is defeated } LK.getSound('zombieGrunt').play(); return false; // Zombie is still alive }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game state variables var bullets = []; // Array to store bullet instances var sword; var zombies = []; var bloodSplatters = []; var powerups = []; var score = 0; var level = 1; var zombiesKilled = 0; var waveSize = 5; var waveDelay = 180; // 3 seconds at 60fps var waveTimer = waveDelay; var eliteChance = 0.2; // 20% chance for an elite zombie var gameActive = false; var dragActive = false; // UI elements var scoreTxt; var levelTxt; var highScoreTxt; // Initialize the game function initializeGame() { // Reset game state zombies = []; bloodSplatters = []; powerups = []; score = 0; level = 1; zombiesKilled = 0; waveSize = 5; waveDelay = 180; waveTimer = waveDelay; eliteChance = 0.2; gameActive = true; // Create and position the sword sword = new Sword(); sword.x = 2048 / 2; sword.y = 2732 - 400; game.addChild(sword); // Create UI elements createUI(); // Add game banner var bannerTxt = new Text2('Zombie Slayer', { size: 100, fill: 0xFF0000 }); bannerTxt.anchor.set(0.5, 0); LK.gui.top.addChild(bannerTxt); bannerTxt.y = 10; // Play background music LK.playMusic('battleTheme', { loop: true, fade: { start: 0, end: 0.8, duration: 1000 } }); } function createUI() { // Score text scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -300; scoreTxt.y = 50; // Level text levelTxt = new Text2('Level: 1', { size: 80, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); levelTxt.y = 50; // High score text highScoreTxt = new Text2('Best: ' + storage.highScore, { size: 60, fill: 0xCCCCCC }); highScoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(highScoreTxt); highScoreTxt.x = -300; highScoreTxt.y = 130; } function spawnZombieWave() { for (var i = 0; i < waveSize; i++) { // Determine zombie type var type = Math.random() < eliteChance ? 'elite' : 'basic'; // Create zombie var zombie = new Zombie(type); // Position zombie randomly along the top of the screen zombie.x = 200 + Math.random() * (2048 - 400); zombie.y = -200 - i * 200; // Stagger the zombies zombies.push(zombie); game.addChild(zombie); } // Update wave parameters for next wave waveSize = Math.min(waveSize + 1, 15); waveDelay = Math.max(waveDelay - 5, 120); eliteChance = Math.min(eliteChance + 0.05, 0.5); } function spawnPowerup(x, y) { // Random powerup type var types = ['fire', 'ice', 'size']; var type = types[Math.floor(Math.random() * types.length)]; var powerup = new Powerup(type); powerup.x = x; powerup.y = y; powerups.push(powerup); game.addChild(powerup); } function createBloodSplatter(x, y) { var splatter = new BloodSplatter(); splatter.x = x; splatter.y = y; bloodSplatters.push(splatter); game.addChild(splatter); } function updateScore(points) { score += points; scoreTxt.setText('Score: ' + score); // Update high score if needed if (score > storage.highScore) { storage.highScore = score; highScoreTxt.setText('Best: ' + storage.highScore); } } function advanceLevel() { level++; levelTxt.setText('Level: ' + level); // Increase difficulty eliteChance = Math.min(eliteChance + 0.1, 0.6); } function checkSwordZombieCollisions() { for (var i = zombies.length - 1; i >= 0; i--) { var zombie = zombies[i]; if (sword.slashing && sword.intersects(zombie)) { // Sword hit zombie var defeated = zombie.takeDamage(sword.damage); if (defeated) { // Zombie defeated zombiesKilled++; updateScore(zombie.points); // Create blood splatter createBloodSplatter(zombie.x, zombie.y); // Spawn powerup if elite if (zombie.dropsPowerup) { spawnPowerup(zombie.x, zombie.y); } // Play death sound LK.getSound('zombieDeath').play(); // Remove zombie zombie.destroy(); zombies.splice(i, 1); // Check for level advancement if (zombiesKilled % 20 === 0) { advanceLevel(); } } } } } function checkSwordPowerupCollisions() { for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (sword.intersects(powerup)) { // Sword collected powerup sword.activatePowerup(powerup.type); // Remove powerup powerup.destroy(); powerups.splice(i, 1); } } } function handleMove(x, y, obj) { if (dragActive && gameActive) { sword.x = x; sword.y = y; } } // Input handlers game.down = function (x, y, obj) { if (gameActive) { dragActive = true; sword.x = x; sword.y = y; sword.slash(); } }; game.up = function (x, y, obj) { dragActive = false; }; game.move = handleMove; // Game update function game.update = function () { if (!gameActive) { initializeGame(); return; } // Spawn new zombie wave when timer expires waveTimer--; if (waveTimer <= 0) { spawnZombieWave(); waveTimer = waveDelay; } // Update blood splatters and remove expired ones for (var i = bloodSplatters.length - 1; i >= 0; i--) { var splatter = bloodSplatters[i]; if (splatter.readyToRemove) { splatter.destroy(); bloodSplatters.splice(i, 1); } } // Check for zombies that have gone offscreen for (var i = zombies.length - 1; i >= 0; i--) { var zombie = zombies[i]; if (zombie.isOffscreen) { zombie.destroy(); zombies.splice(i, 1); // Penalize for missed zombies LK.effects.flashScreen(0xFF0000, 300); // Game over if too many zombies get through if (zombies.length === 0 && level >= 3) { // Player survives if no zombies remain and they're at least level 3 updateScore(level * 50); // Bonus for surviving storage.totalKills += zombiesKilled; LK.showGameOver(); gameActive = false; } } } // Check for powerups that have gone offscreen for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (powerup.isOffscreen) { powerup.destroy(); powerups.splice(i, 1); } } // Check for collisions checkSwordZombieCollisions(); checkSwordPowerupCollisions(); // Check for win condition if (score >= 1000) { LK.showYouWin(); gameActive = false; storage.totalKills += zombiesKilled; } }; // Start the game initializeGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
totalKills: 0
});
/****
* Classes
****/
var BloodSplatter = Container.expand(function () {
var self = Container.call(this);
var splatterGraphics = self.attachAsset('bloodSplatter', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
// Rotate splatter randomly
splatterGraphics.rotation = Math.random() * Math.PI * 2;
// Random scale variation
var scale = 0.5 + Math.random() * 0.5;
splatterGraphics.scale.set(scale, scale);
// Fade out over time
self.lifespan = 60; // 1 second at 60fps
self.update = function () {
self.lifespan--;
splatterGraphics.alpha = self.lifespan / 60;
if (self.lifespan <= 0) {
self.readyToRemove = true;
}
};
return self;
});
var Bullet = Container.expand(function (x, y, speed, damage) {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.speed = speed;
self.damage = damage;
self.update = function () {
self.y += self.speed;
if (self.y < -bulletGraphics.height) {
self.destroy();
}
};
return self;
});
var Powerup = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'fire';
var assetId;
switch (self.type) {
case 'fire':
assetId = 'powerupFire';
break;
case 'ice':
assetId = 'powerupIce';
break;
case 'size':
assetId = 'powerupSize';
break;
}
var powerupGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Powerup properties
self.speed = 2;
self.oscillationSpeed = 0.05;
self.oscillationAmount = 10;
self.initialY = self.y;
self.update = function () {
self.y += self.speed;
// Oscillate side to side
self.x += Math.sin(LK.ticks * self.oscillationSpeed) * self.oscillationAmount;
// Spin the powerup
powerupGraphics.rotation += 0.03;
// Check if powerup has moved past the bottom of the screen
if (self.y > 2732 + powerupGraphics.height) {
self.isOffscreen = true;
}
};
return self;
});
var Sword = Container.expand(function () {
var self = Container.call(this);
var swordGraphics = self.attachAsset('sword', {
anchorX: 0.5,
anchorY: 0.5
});
// Sword properties
self.slashing = false;
self.damage = 1;
self.isPoweredUp = false;
self.powerupType = null;
self.powerupTimer = 0;
self.powerupDuration = 300; // 5 seconds at 60fps
self.update = function () {
// Handle powerups
if (self.isPoweredUp) {
self.powerupTimer--;
if (self.powerupTimer <= 0) {
self.deactivatePowerup();
}
}
};
self.slash = function () {
self.slashing = true;
LK.getSound('swordSlash').play();
LK.setTimeout(function () {
self.slashing = false;
}, 200); // Slash lasts for 200ms
};
self.activatePowerup = function (type) {
self.isPoweredUp = true;
self.powerupType = type;
self.powerupTimer = self.powerupDuration;
switch (type) {
case 'fire':
swordGraphics.tint = 0xFF4500;
self.damage = 3;
break;
case 'ice':
swordGraphics.tint = 0x1E90FF;
self.damage = 2;
break;
case 'size':
swordGraphics.tint = 0xFFD700;
swordGraphics.scale.set(1.5, 1.5);
self.damage = 2;
break;
}
LK.getSound('powerupCollect').play();
};
self.deactivatePowerup = function () {
self.isPoweredUp = false;
self.powerupType = null;
swordGraphics.tint = 0xFFFFFF;
swordGraphics.scale.set(1, 1);
self.damage = 1;
};
self.down = function (x, y, obj) {
self.slash(); // Trigger slashing
};
return self;
});
var Zombie = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'basic';
var assetId = self.type === 'elite' ? 'zombieElite' : 'zombieBasic';
var zombieGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Zombie properties
self.speed = self.type === 'elite' ? 2 : 3;
self.health = self.type === 'elite' ? 3 : 1;
self.points = self.type === 'elite' ? 10 : 5;
self.dropsPowerup = self.type === 'elite';
self.update = function () {
self.y += self.speed;
// Slightly move side to side for shambling effect
self.x += Math.sin(LK.ticks * 0.05) * 0.5;
// Slightly move side to side for shambling effect
self.x += Math.sin(LK.ticks * 0.05) * 0.5;
// Check if zombie has moved past the bottom of the screen
if (self.y > 2732 + zombieGraphics.height) {
self.isOffscreen = true;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
// Flash red when taking damage
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
return true; // Zombie is defeated
}
LK.getSound('zombieGrunt').play();
return false; // Zombie is still alive
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game state variables
var bullets = []; // Array to store bullet instances
var sword;
var zombies = [];
var bloodSplatters = [];
var powerups = [];
var score = 0;
var level = 1;
var zombiesKilled = 0;
var waveSize = 5;
var waveDelay = 180; // 3 seconds at 60fps
var waveTimer = waveDelay;
var eliteChance = 0.2; // 20% chance for an elite zombie
var gameActive = false;
var dragActive = false;
// UI elements
var scoreTxt;
var levelTxt;
var highScoreTxt;
// Initialize the game
function initializeGame() {
// Reset game state
zombies = [];
bloodSplatters = [];
powerups = [];
score = 0;
level = 1;
zombiesKilled = 0;
waveSize = 5;
waveDelay = 180;
waveTimer = waveDelay;
eliteChance = 0.2;
gameActive = true;
// Create and position the sword
sword = new Sword();
sword.x = 2048 / 2;
sword.y = 2732 - 400;
game.addChild(sword);
// Create UI elements
createUI();
// Add game banner
var bannerTxt = new Text2('Zombie Slayer', {
size: 100,
fill: 0xFF0000
});
bannerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(bannerTxt);
bannerTxt.y = 10;
// Play background music
LK.playMusic('battleTheme', {
loop: true,
fade: {
start: 0,
end: 0.8,
duration: 1000
}
});
}
function createUI() {
// Score text
scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -300;
scoreTxt.y = 50;
// Level text
levelTxt = new Text2('Level: 1', {
size: 80,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 50;
// High score text
highScoreTxt = new Text2('Best: ' + storage.highScore, {
size: 60,
fill: 0xCCCCCC
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -300;
highScoreTxt.y = 130;
}
function spawnZombieWave() {
for (var i = 0; i < waveSize; i++) {
// Determine zombie type
var type = Math.random() < eliteChance ? 'elite' : 'basic';
// Create zombie
var zombie = new Zombie(type);
// Position zombie randomly along the top of the screen
zombie.x = 200 + Math.random() * (2048 - 400);
zombie.y = -200 - i * 200; // Stagger the zombies
zombies.push(zombie);
game.addChild(zombie);
}
// Update wave parameters for next wave
waveSize = Math.min(waveSize + 1, 15);
waveDelay = Math.max(waveDelay - 5, 120);
eliteChance = Math.min(eliteChance + 0.05, 0.5);
}
function spawnPowerup(x, y) {
// Random powerup type
var types = ['fire', 'ice', 'size'];
var type = types[Math.floor(Math.random() * types.length)];
var powerup = new Powerup(type);
powerup.x = x;
powerup.y = y;
powerups.push(powerup);
game.addChild(powerup);
}
function createBloodSplatter(x, y) {
var splatter = new BloodSplatter();
splatter.x = x;
splatter.y = y;
bloodSplatters.push(splatter);
game.addChild(splatter);
}
function updateScore(points) {
score += points;
scoreTxt.setText('Score: ' + score);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('Best: ' + storage.highScore);
}
}
function advanceLevel() {
level++;
levelTxt.setText('Level: ' + level);
// Increase difficulty
eliteChance = Math.min(eliteChance + 0.1, 0.6);
}
function checkSwordZombieCollisions() {
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
if (sword.slashing && sword.intersects(zombie)) {
// Sword hit zombie
var defeated = zombie.takeDamage(sword.damage);
if (defeated) {
// Zombie defeated
zombiesKilled++;
updateScore(zombie.points);
// Create blood splatter
createBloodSplatter(zombie.x, zombie.y);
// Spawn powerup if elite
if (zombie.dropsPowerup) {
spawnPowerup(zombie.x, zombie.y);
}
// Play death sound
LK.getSound('zombieDeath').play();
// Remove zombie
zombie.destroy();
zombies.splice(i, 1);
// Check for level advancement
if (zombiesKilled % 20 === 0) {
advanceLevel();
}
}
}
}
}
function checkSwordPowerupCollisions() {
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (sword.intersects(powerup)) {
// Sword collected powerup
sword.activatePowerup(powerup.type);
// Remove powerup
powerup.destroy();
powerups.splice(i, 1);
}
}
}
function handleMove(x, y, obj) {
if (dragActive && gameActive) {
sword.x = x;
sword.y = y;
}
}
// Input handlers
game.down = function (x, y, obj) {
if (gameActive) {
dragActive = true;
sword.x = x;
sword.y = y;
sword.slash();
}
};
game.up = function (x, y, obj) {
dragActive = false;
};
game.move = handleMove;
// Game update function
game.update = function () {
if (!gameActive) {
initializeGame();
return;
}
// Spawn new zombie wave when timer expires
waveTimer--;
if (waveTimer <= 0) {
spawnZombieWave();
waveTimer = waveDelay;
}
// Update blood splatters and remove expired ones
for (var i = bloodSplatters.length - 1; i >= 0; i--) {
var splatter = bloodSplatters[i];
if (splatter.readyToRemove) {
splatter.destroy();
bloodSplatters.splice(i, 1);
}
}
// Check for zombies that have gone offscreen
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
if (zombie.isOffscreen) {
zombie.destroy();
zombies.splice(i, 1);
// Penalize for missed zombies
LK.effects.flashScreen(0xFF0000, 300);
// Game over if too many zombies get through
if (zombies.length === 0 && level >= 3) {
// Player survives if no zombies remain and they're at least level 3
updateScore(level * 50); // Bonus for surviving
storage.totalKills += zombiesKilled;
LK.showGameOver();
gameActive = false;
}
}
}
// Check for powerups that have gone offscreen
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.isOffscreen) {
powerup.destroy();
powerups.splice(i, 1);
}
}
// Check for collisions
checkSwordZombieCollisions();
checkSwordPowerupCollisions();
// Check for win condition
if (score >= 1000) {
LK.showYouWin();
gameActive = false;
storage.totalKills += zombiesKilled;
}
};
// Start the game
initializeGame();
Sword. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. 2d
Zombie 2d. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Big zombie. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. 3d
Powerup. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. 3d
Powerupice. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. 3d
Many blood drop. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. 3d
Maga zombie. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. 3d
Bullet. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows