/****
* Plugins
****/
var tween = LK.import("@upit/tween.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 = 10;
self.damage = 25;
self.directionX = 0;
self.directionY = 0;
self.update = function () {
self.x += self.speed * self.directionX;
self.y += self.speed * self.directionY;
};
return self;
});
var HealthPack = Container.expand(function () {
var self = Container.call(this);
var healthGraphics = self.attachAsset('healthPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.healAmount = 30;
self.update = function () {
// Simple floating animation
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
// Check pickup
if (self.intersects(player)) {
player.heal(self.healAmount);
LK.getSound('pickup').play();
self.collected = true;
}
};
return self;
});
var HowToPlay = Container.expand(function () {
var self = Container.call(this);
// Create background overlay
var background = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
alpha: 0.9
});
self.addChild(background);
// Title
var titleText = new Text2('HOW TO PLAY', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.x = 1024;
titleText.y = 200;
self.addChild(titleText);
// Controls section
var controlsTitle = new Text2('CONTROLS', {
size: 80,
fill: 0xFFFF00
});
controlsTitle.anchor.set(0.5, 0);
controlsTitle.x = 1024;
controlsTitle.y = 400;
self.addChild(controlsTitle);
// PC controls
var pcText = new Text2('PC CONTROLS:', {
size: 60,
fill: 0x00FF00
});
pcText.anchor.set(0, 0);
pcText.x = 200;
pcText.y = 520;
self.addChild(pcText);
var pcControls = new Text2('• W/A/S/D - Move Up/Left/Down/Right\n• Mouse - Aim direction\n• Left Click - Shoot\n• Navigate the maze to find the exit', {
size: 45,
fill: 0xFFFFFF
});
pcControls.anchor.set(0, 0);
pcControls.x = 200;
pcControls.y = 600;
self.addChild(pcControls);
// Gameplay section
var gameplayTitle = new Text2('GAMEPLAY', {
size: 80,
fill: 0xFFFF00
});
gameplayTitle.anchor.set(0.5, 0);
gameplayTitle.x = 1024;
gameplayTitle.y = 950;
self.addChild(gameplayTitle);
var gameplayText = new Text2('• Navigate through a dark maze facility\n• Kill zombies to earn points (50 points each)\n• Collect health packs (red circles)\n• Collect weapon upgrades (blue boxes)\n• Score increases ONLY by killing zombies', {
size: 45,
fill: 0xFFFFFF
});
gameplayText.anchor.set(0, 0);
gameplayText.x = 200;
gameplayText.y = 1050;
self.addChild(gameplayText);
// Objectives
var objectiveTitle = new Text2('OBJECTIVES', {
size: 80,
fill: 0xFFFF00
});
objectiveTitle.anchor.set(0.5, 0);
objectiveTitle.x = 1024;
objectiveTitle.y = 1400;
self.addChild(objectiveTitle);
var objectiveText = new Text2('• Kill as many zombies as possible\n• Escape through the green exit to end game\n• Survive and maximize your kill count\n• Use maze walls for tactical advantage', {
size: 45,
fill: 0xFFFFFF
});
objectiveText.anchor.set(0, 0);
objectiveText.x = 200;
objectiveText.y = 1500;
self.addChild(objectiveText);
// Close button
var closeButton = LK.getAsset('player', {
width: 200,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
closeButton.x = 1024;
closeButton.y = 1900;
self.addChild(closeButton);
var closeText = new Text2('TAP TO START', {
size: 60,
fill: 0x000000
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1024;
closeText.y = 1900;
self.addChild(closeText);
closeButton.down = function () {
self.visible = false;
gameStarted = true;
};
background.down = function () {
self.visible = false;
gameStarted = true;
};
return self;
});
var MazeExit = Container.expand(function () {
var self = Container.call(this);
var exitGraphics = self.attachAsset('exit', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
// Pulsing effect for exit
exitGraphics.alpha = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3;
// Check if player reached exit
if (self.intersects(player)) {
LK.showYouWin();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Add bird head
var birdHead = self.attachAsset('playerHead', {
anchorX: 0.5,
anchorY: 0.5
});
birdHead.x = 0;
birdHead.y = -8; // Position head above body
// Add bird beak
var birdBeak = self.attachAsset('playerBeak', {
anchorX: 0,
anchorY: 0.5
});
birdBeak.x = 15; // Position to right of head
birdBeak.y = -8; // Same height as head
self.health = 100;
self.maxHealth = 100;
self.speed = 4;
self.weapon = 1;
self.maxWeapon = 3;
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
gameOver = true;
}
// Flash red when taking damage
LK.effects.flashObject(self, 0xFF0000, 500);
};
self.heal = function (amount) {
self.health = Math.min(self.maxHealth, self.health + amount);
};
self.upgradeWeapon = function () {
if (self.weapon < self.maxWeapon) {
self.weapon++;
}
};
self.checkWallCollision = function (newX, newY) {
// Check collision with maze walls
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (newX < wall.x + 80 && newX + 40 > wall.x && newY < wall.y + 80 && newY + 40 > wall.y) {
return true;
}
}
return false;
};
self.update = function () {
// No gravity or ground collision in top-down view
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0,
anchorY: 0
});
return self;
});
var WeaponPickup = Container.expand(function () {
var self = Container.call(this);
var weaponGraphics = self.attachAsset('weaponPickup', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Simple floating animation
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
// Check pickup
if (self.intersects(player)) {
player.upgradeWeapon();
LK.getSound('pickup').play();
self.collected = true;
}
};
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.speed = 1.5;
self.damage = 20;
self.lastAttackTime = 0;
self.moveTimer = 0;
self.targetX = 0;
self.targetY = 0;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
return true; // Zombie is dead
}
return false;
};
self.checkWallCollision = function (newX, newY) {
// Check collision with maze walls
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (newX < wall.x + 80 && newX + 35 > wall.x && newY < wall.y + 80 && newY + 35 > wall.y) {
return true;
}
}
return false;
};
self.update = function () {
// Simple AI: move towards player if path is clear
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
var moveX = deltaX / distance * self.speed;
var moveY = deltaY / distance * self.speed;
var newX = self.x + moveX;
var newY = self.y + moveY;
// Only move if not hitting walls
if (!self.checkWallCollision(newX, self.y)) {
self.x = newX;
}
if (!self.checkWallCollision(self.x, newY)) {
self.y = newY;
}
}
// Check collision with player
if (self.intersects(player)) {
var currentTime = LK.ticks;
if (currentTime - self.lastAttackTime > 60) {
// Attack every second
player.takeDamage(self.damage);
self.lastAttackTime = currentTime;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Game variables
var player;
var zombies = [];
var bullets = [];
var healthPacks = [];
var weaponPickups = [];
var walls = [];
var mazeExit;
var gameOver = false;
var gameStarted = false;
var score = 0;
var zombieSpawnTimer = 0;
var pickupSpawnTimer = 0;
var howToPlayScreen;
// Movement controls
var moveUp = false;
var moveDown = false;
var moveLeft = false;
var moveRight = false;
var shooting = false;
var shootTimer = 0;
var shootTargetX = 0;
var shootTargetY = 0;
// Create maze layout (simplified maze pattern)
var mazePattern = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1], [1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], [1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1], [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1], [1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
// Build maze walls
for (var row = 0; row < mazePattern.length; row++) {
for (var col = 0; col < mazePattern[row].length; col++) {
var cellX = col * 80;
var cellY = row * 80;
if (mazePattern[row][col] === 1) {
// Wall
var wall = game.addChild(new Wall());
wall.x = cellX;
wall.y = cellY;
walls.push(wall);
} else if (mazePattern[row][col] === 2) {
// Exit
mazeExit = game.addChild(new MazeExit());
mazeExit.x = cellX;
mazeExit.y = cellY;
}
}
}
// Create player
player = game.addChild(new Player());
player.x = 120; // Start position in maze
player.y = 120;
// UI Elements positioned for PC
var scoreText = new Text2('Kills: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 20;
scoreText.y = 120;
LK.gui.topLeft.addChild(scoreText);
var healthText = new Text2('Health: 100', {
size: 50,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
healthText.x = 20;
healthText.y = 180;
LK.gui.topLeft.addChild(healthText);
var weaponText = new Text2('Weapon: 1', {
size: 50,
fill: 0x00BFFF
});
weaponText.anchor.set(0, 0);
weaponText.x = 20;
weaponText.y = 240;
LK.gui.topLeft.addChild(weaponText);
var objectiveText = new Text2('Kill Zombies! Escape to End Game!', {
size: 60,
fill: 0xFF4444
});
objectiveText.anchor.set(0.5, 0);
objectiveText.x = 1024;
objectiveText.y = 30;
LK.gui.top.addChild(objectiveText);
var controlHint = new Text2('WASD to move, Mouse to aim & shoot', {
size: 40,
fill: 0xCCCCCC
});
controlHint.anchor.set(1, 0);
controlHint.x = 2028;
controlHint.y = 120;
LK.gui.topRight.addChild(controlHint);
// Keyboard event listeners for PC controls
LK.on('keydown', function (key) {
if (key === 'w' || key === 'W') moveUp = true;
if (key === 's' || key === 'S') moveDown = true;
if (key === 'a' || key === 'A') moveLeft = true;
if (key === 'd' || key === 'D') moveRight = true;
});
LK.on('keyup', function (key) {
if (key === 'w' || key === 'W') moveUp = false;
if (key === 's' || key === 'S') moveDown = false;
if (key === 'a' || key === 'A') moveLeft = false;
if (key === 'd' || key === 'D') moveRight = false;
});
// Create How to Play screen
howToPlayScreen = game.addChild(new HowToPlay());
howToPlayScreen.visible = true;
// Game event handlers for mouse shooting
game.down = function (x, y, obj) {
// Convert screen coordinates to game coordinates
var gamePos = game.toLocal({
x: x,
y: y
});
shootTargetX = gamePos.x;
shootTargetY = gamePos.y;
shooting = true;
};
game.up = function (x, y, obj) {
shooting = false;
};
// Track mouse position for aiming
game.move = function (x, y, obj) {
var gamePos = game.toLocal({
x: x,
y: y
});
shootTargetX = gamePos.x;
shootTargetY = gamePos.y;
};
// Spawn functions
function spawnZombie() {
var zombie = new Zombie();
// Find a random open space in the maze
var spawnAttempts = 0;
do {
zombie.x = Math.random() * 1920 + 80;
zombie.y = Math.random() * 1520 + 80;
spawnAttempts++;
} while (zombie.checkWallCollision(zombie.x, zombie.y) && spawnAttempts < 50);
zombies.push(zombie);
game.addChild(zombie);
}
function spawnHealthPack() {
var healthPack = new HealthPack();
// Find a random open space in the maze
var spawnAttempts = 0;
do {
healthPack.x = Math.random() * 1920 + 80;
healthPack.y = Math.random() * 1520 + 80;
spawnAttempts++;
} while (spawnAttempts < 50 && isPositionBlocked(healthPack.x, healthPack.y));
healthPacks.push(healthPack);
game.addChild(healthPack);
}
function spawnWeaponPickup() {
var weaponPickup = new WeaponPickup();
// Find a random open space in the maze
var spawnAttempts = 0;
do {
weaponPickup.x = Math.random() * 1920 + 80;
weaponPickup.y = Math.random() * 1520 + 80;
spawnAttempts++;
} while (spawnAttempts < 50 && isPositionBlocked(weaponPickup.x, weaponPickup.y));
weaponPickups.push(weaponPickup);
game.addChild(weaponPickup);
}
function isPositionBlocked(x, y) {
// Check if position overlaps with walls
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (x < wall.x + 80 && x + 25 > wall.x && y < wall.y + 80 && y + 25 > wall.y) {
return true;
}
}
return false;
}
function shootBullet() {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
bullet.damage = 25 * player.weapon; // More damage with better weapons
// Calculate direction toward shoot target
var deltaX = shootTargetX - player.x;
var deltaY = shootTargetY - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
bullet.directionX = deltaX / distance;
bullet.directionY = deltaY / distance;
} else {
bullet.directionX = 1; // Default right
bullet.directionY = 0;
}
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
// Main game update
game.update = function () {
if (!gameStarted) {
return; // Don't start game until player dismisses how to play screen
}
if (gameOver) {
LK.showGameOver();
return;
}
// Score is only increased by killing zombies
LK.setScore(score);
// Handle player movement with wall collision
var newX = player.x;
var newY = player.y;
if (moveLeft) {
newX = player.x - player.speed;
}
if (moveRight) {
newX = player.x + player.speed;
}
if (moveUp) {
newY = player.y - player.speed;
}
if (moveDown) {
newY = player.y + player.speed;
}
// Check wall collisions and move if valid
if (!player.checkWallCollision(newX, player.y)) {
player.x = newX;
}
if (!player.checkWallCollision(player.x, newY)) {
player.y = newY;
}
// Handle shooting
if (shooting && LK.ticks - shootTimer > 30 / player.weapon) {
// Faster shooting with better weapons
shootBullet();
shootTimer = LK.ticks;
}
// Spawn zombies
zombieSpawnTimer++;
var spawnRate = Math.max(180, 120); // Spawn every 3-2 seconds
if (zombieSpawnTimer >= spawnRate) {
spawnZombie();
zombieSpawnTimer = 0;
}
// Spawn pickups occasionally
pickupSpawnTimer++;
if (pickupSpawnTimer >= 900) {
// Every 15 seconds
if (Math.random() < 0.7) {
spawnHealthPack();
} else {
spawnWeaponPickup();
}
pickupSpawnTimer = 0;
}
// Update bullets and check collisions
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet is off screen or hits walls
if (bullet.x < 0 || bullet.x > 2000 || bullet.y < 0 || bullet.y > 1600) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check wall collision
var bulletHitWall = false;
for (var w = 0; w < walls.length; w++) {
var wall = walls[w];
if (bullet.x < wall.x + 80 && bullet.x + 12 > wall.x && bullet.y < wall.y + 80 && bullet.y + 12 > wall.y) {
bulletHitWall = true;
break;
}
}
if (bulletHitWall) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-zombie collisions
var hit = false;
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (bullet.intersects(zombie)) {
if (zombie.takeDamage(bullet.damage)) {
// Zombie died
score += 50;
LK.getSound('zombieHit').play();
zombie.destroy();
zombies.splice(j, 1);
}
bullet.destroy();
bullets.splice(i, 1);
hit = true;
break;
}
}
}
// Update health packs
for (var i = healthPacks.length - 1; i >= 0; i--) {
var healthPack = healthPacks[i];
if (healthPack.collected) {
healthPack.destroy();
healthPacks.splice(i, 1);
}
}
// Update weapon pickups
for (var i = weaponPickups.length - 1; i >= 0; i--) {
var weaponPickup = weaponPickups[i];
if (weaponPickup.collected) {
weaponPickup.destroy();
weaponPickups.splice(i, 1);
}
}
// Update UI
scoreText.setText('Kills: ' + score / 50);
healthText.setText('Health: ' + player.health);
weaponText.setText('Weapon: ' + player.weapon);
// Exit reached condition handled by MazeExit class
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.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 = 10;
self.damage = 25;
self.directionX = 0;
self.directionY = 0;
self.update = function () {
self.x += self.speed * self.directionX;
self.y += self.speed * self.directionY;
};
return self;
});
var HealthPack = Container.expand(function () {
var self = Container.call(this);
var healthGraphics = self.attachAsset('healthPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.healAmount = 30;
self.update = function () {
// Simple floating animation
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
// Check pickup
if (self.intersects(player)) {
player.heal(self.healAmount);
LK.getSound('pickup').play();
self.collected = true;
}
};
return self;
});
var HowToPlay = Container.expand(function () {
var self = Container.call(this);
// Create background overlay
var background = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
alpha: 0.9
});
self.addChild(background);
// Title
var titleText = new Text2('HOW TO PLAY', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.x = 1024;
titleText.y = 200;
self.addChild(titleText);
// Controls section
var controlsTitle = new Text2('CONTROLS', {
size: 80,
fill: 0xFFFF00
});
controlsTitle.anchor.set(0.5, 0);
controlsTitle.x = 1024;
controlsTitle.y = 400;
self.addChild(controlsTitle);
// PC controls
var pcText = new Text2('PC CONTROLS:', {
size: 60,
fill: 0x00FF00
});
pcText.anchor.set(0, 0);
pcText.x = 200;
pcText.y = 520;
self.addChild(pcText);
var pcControls = new Text2('• W/A/S/D - Move Up/Left/Down/Right\n• Mouse - Aim direction\n• Left Click - Shoot\n• Navigate the maze to find the exit', {
size: 45,
fill: 0xFFFFFF
});
pcControls.anchor.set(0, 0);
pcControls.x = 200;
pcControls.y = 600;
self.addChild(pcControls);
// Gameplay section
var gameplayTitle = new Text2('GAMEPLAY', {
size: 80,
fill: 0xFFFF00
});
gameplayTitle.anchor.set(0.5, 0);
gameplayTitle.x = 1024;
gameplayTitle.y = 950;
self.addChild(gameplayTitle);
var gameplayText = new Text2('• Navigate through a dark maze facility\n• Kill zombies to earn points (50 points each)\n• Collect health packs (red circles)\n• Collect weapon upgrades (blue boxes)\n• Score increases ONLY by killing zombies', {
size: 45,
fill: 0xFFFFFF
});
gameplayText.anchor.set(0, 0);
gameplayText.x = 200;
gameplayText.y = 1050;
self.addChild(gameplayText);
// Objectives
var objectiveTitle = new Text2('OBJECTIVES', {
size: 80,
fill: 0xFFFF00
});
objectiveTitle.anchor.set(0.5, 0);
objectiveTitle.x = 1024;
objectiveTitle.y = 1400;
self.addChild(objectiveTitle);
var objectiveText = new Text2('• Kill as many zombies as possible\n• Escape through the green exit to end game\n• Survive and maximize your kill count\n• Use maze walls for tactical advantage', {
size: 45,
fill: 0xFFFFFF
});
objectiveText.anchor.set(0, 0);
objectiveText.x = 200;
objectiveText.y = 1500;
self.addChild(objectiveText);
// Close button
var closeButton = LK.getAsset('player', {
width: 200,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
closeButton.x = 1024;
closeButton.y = 1900;
self.addChild(closeButton);
var closeText = new Text2('TAP TO START', {
size: 60,
fill: 0x000000
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1024;
closeText.y = 1900;
self.addChild(closeText);
closeButton.down = function () {
self.visible = false;
gameStarted = true;
};
background.down = function () {
self.visible = false;
gameStarted = true;
};
return self;
});
var MazeExit = Container.expand(function () {
var self = Container.call(this);
var exitGraphics = self.attachAsset('exit', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
// Pulsing effect for exit
exitGraphics.alpha = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3;
// Check if player reached exit
if (self.intersects(player)) {
LK.showYouWin();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Add bird head
var birdHead = self.attachAsset('playerHead', {
anchorX: 0.5,
anchorY: 0.5
});
birdHead.x = 0;
birdHead.y = -8; // Position head above body
// Add bird beak
var birdBeak = self.attachAsset('playerBeak', {
anchorX: 0,
anchorY: 0.5
});
birdBeak.x = 15; // Position to right of head
birdBeak.y = -8; // Same height as head
self.health = 100;
self.maxHealth = 100;
self.speed = 4;
self.weapon = 1;
self.maxWeapon = 3;
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
gameOver = true;
}
// Flash red when taking damage
LK.effects.flashObject(self, 0xFF0000, 500);
};
self.heal = function (amount) {
self.health = Math.min(self.maxHealth, self.health + amount);
};
self.upgradeWeapon = function () {
if (self.weapon < self.maxWeapon) {
self.weapon++;
}
};
self.checkWallCollision = function (newX, newY) {
// Check collision with maze walls
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (newX < wall.x + 80 && newX + 40 > wall.x && newY < wall.y + 80 && newY + 40 > wall.y) {
return true;
}
}
return false;
};
self.update = function () {
// No gravity or ground collision in top-down view
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0,
anchorY: 0
});
return self;
});
var WeaponPickup = Container.expand(function () {
var self = Container.call(this);
var weaponGraphics = self.attachAsset('weaponPickup', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Simple floating animation
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
// Check pickup
if (self.intersects(player)) {
player.upgradeWeapon();
LK.getSound('pickup').play();
self.collected = true;
}
};
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.speed = 1.5;
self.damage = 20;
self.lastAttackTime = 0;
self.moveTimer = 0;
self.targetX = 0;
self.targetY = 0;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
return true; // Zombie is dead
}
return false;
};
self.checkWallCollision = function (newX, newY) {
// Check collision with maze walls
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (newX < wall.x + 80 && newX + 35 > wall.x && newY < wall.y + 80 && newY + 35 > wall.y) {
return true;
}
}
return false;
};
self.update = function () {
// Simple AI: move towards player if path is clear
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
var moveX = deltaX / distance * self.speed;
var moveY = deltaY / distance * self.speed;
var newX = self.x + moveX;
var newY = self.y + moveY;
// Only move if not hitting walls
if (!self.checkWallCollision(newX, self.y)) {
self.x = newX;
}
if (!self.checkWallCollision(self.x, newY)) {
self.y = newY;
}
}
// Check collision with player
if (self.intersects(player)) {
var currentTime = LK.ticks;
if (currentTime - self.lastAttackTime > 60) {
// Attack every second
player.takeDamage(self.damage);
self.lastAttackTime = currentTime;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Game variables
var player;
var zombies = [];
var bullets = [];
var healthPacks = [];
var weaponPickups = [];
var walls = [];
var mazeExit;
var gameOver = false;
var gameStarted = false;
var score = 0;
var zombieSpawnTimer = 0;
var pickupSpawnTimer = 0;
var howToPlayScreen;
// Movement controls
var moveUp = false;
var moveDown = false;
var moveLeft = false;
var moveRight = false;
var shooting = false;
var shootTimer = 0;
var shootTargetX = 0;
var shootTargetY = 0;
// Create maze layout (simplified maze pattern)
var mazePattern = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1], [1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], [1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1], [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1], [1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
// Build maze walls
for (var row = 0; row < mazePattern.length; row++) {
for (var col = 0; col < mazePattern[row].length; col++) {
var cellX = col * 80;
var cellY = row * 80;
if (mazePattern[row][col] === 1) {
// Wall
var wall = game.addChild(new Wall());
wall.x = cellX;
wall.y = cellY;
walls.push(wall);
} else if (mazePattern[row][col] === 2) {
// Exit
mazeExit = game.addChild(new MazeExit());
mazeExit.x = cellX;
mazeExit.y = cellY;
}
}
}
// Create player
player = game.addChild(new Player());
player.x = 120; // Start position in maze
player.y = 120;
// UI Elements positioned for PC
var scoreText = new Text2('Kills: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 20;
scoreText.y = 120;
LK.gui.topLeft.addChild(scoreText);
var healthText = new Text2('Health: 100', {
size: 50,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
healthText.x = 20;
healthText.y = 180;
LK.gui.topLeft.addChild(healthText);
var weaponText = new Text2('Weapon: 1', {
size: 50,
fill: 0x00BFFF
});
weaponText.anchor.set(0, 0);
weaponText.x = 20;
weaponText.y = 240;
LK.gui.topLeft.addChild(weaponText);
var objectiveText = new Text2('Kill Zombies! Escape to End Game!', {
size: 60,
fill: 0xFF4444
});
objectiveText.anchor.set(0.5, 0);
objectiveText.x = 1024;
objectiveText.y = 30;
LK.gui.top.addChild(objectiveText);
var controlHint = new Text2('WASD to move, Mouse to aim & shoot', {
size: 40,
fill: 0xCCCCCC
});
controlHint.anchor.set(1, 0);
controlHint.x = 2028;
controlHint.y = 120;
LK.gui.topRight.addChild(controlHint);
// Keyboard event listeners for PC controls
LK.on('keydown', function (key) {
if (key === 'w' || key === 'W') moveUp = true;
if (key === 's' || key === 'S') moveDown = true;
if (key === 'a' || key === 'A') moveLeft = true;
if (key === 'd' || key === 'D') moveRight = true;
});
LK.on('keyup', function (key) {
if (key === 'w' || key === 'W') moveUp = false;
if (key === 's' || key === 'S') moveDown = false;
if (key === 'a' || key === 'A') moveLeft = false;
if (key === 'd' || key === 'D') moveRight = false;
});
// Create How to Play screen
howToPlayScreen = game.addChild(new HowToPlay());
howToPlayScreen.visible = true;
// Game event handlers for mouse shooting
game.down = function (x, y, obj) {
// Convert screen coordinates to game coordinates
var gamePos = game.toLocal({
x: x,
y: y
});
shootTargetX = gamePos.x;
shootTargetY = gamePos.y;
shooting = true;
};
game.up = function (x, y, obj) {
shooting = false;
};
// Track mouse position for aiming
game.move = function (x, y, obj) {
var gamePos = game.toLocal({
x: x,
y: y
});
shootTargetX = gamePos.x;
shootTargetY = gamePos.y;
};
// Spawn functions
function spawnZombie() {
var zombie = new Zombie();
// Find a random open space in the maze
var spawnAttempts = 0;
do {
zombie.x = Math.random() * 1920 + 80;
zombie.y = Math.random() * 1520 + 80;
spawnAttempts++;
} while (zombie.checkWallCollision(zombie.x, zombie.y) && spawnAttempts < 50);
zombies.push(zombie);
game.addChild(zombie);
}
function spawnHealthPack() {
var healthPack = new HealthPack();
// Find a random open space in the maze
var spawnAttempts = 0;
do {
healthPack.x = Math.random() * 1920 + 80;
healthPack.y = Math.random() * 1520 + 80;
spawnAttempts++;
} while (spawnAttempts < 50 && isPositionBlocked(healthPack.x, healthPack.y));
healthPacks.push(healthPack);
game.addChild(healthPack);
}
function spawnWeaponPickup() {
var weaponPickup = new WeaponPickup();
// Find a random open space in the maze
var spawnAttempts = 0;
do {
weaponPickup.x = Math.random() * 1920 + 80;
weaponPickup.y = Math.random() * 1520 + 80;
spawnAttempts++;
} while (spawnAttempts < 50 && isPositionBlocked(weaponPickup.x, weaponPickup.y));
weaponPickups.push(weaponPickup);
game.addChild(weaponPickup);
}
function isPositionBlocked(x, y) {
// Check if position overlaps with walls
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (x < wall.x + 80 && x + 25 > wall.x && y < wall.y + 80 && y + 25 > wall.y) {
return true;
}
}
return false;
}
function shootBullet() {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
bullet.damage = 25 * player.weapon; // More damage with better weapons
// Calculate direction toward shoot target
var deltaX = shootTargetX - player.x;
var deltaY = shootTargetY - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
bullet.directionX = deltaX / distance;
bullet.directionY = deltaY / distance;
} else {
bullet.directionX = 1; // Default right
bullet.directionY = 0;
}
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
// Main game update
game.update = function () {
if (!gameStarted) {
return; // Don't start game until player dismisses how to play screen
}
if (gameOver) {
LK.showGameOver();
return;
}
// Score is only increased by killing zombies
LK.setScore(score);
// Handle player movement with wall collision
var newX = player.x;
var newY = player.y;
if (moveLeft) {
newX = player.x - player.speed;
}
if (moveRight) {
newX = player.x + player.speed;
}
if (moveUp) {
newY = player.y - player.speed;
}
if (moveDown) {
newY = player.y + player.speed;
}
// Check wall collisions and move if valid
if (!player.checkWallCollision(newX, player.y)) {
player.x = newX;
}
if (!player.checkWallCollision(player.x, newY)) {
player.y = newY;
}
// Handle shooting
if (shooting && LK.ticks - shootTimer > 30 / player.weapon) {
// Faster shooting with better weapons
shootBullet();
shootTimer = LK.ticks;
}
// Spawn zombies
zombieSpawnTimer++;
var spawnRate = Math.max(180, 120); // Spawn every 3-2 seconds
if (zombieSpawnTimer >= spawnRate) {
spawnZombie();
zombieSpawnTimer = 0;
}
// Spawn pickups occasionally
pickupSpawnTimer++;
if (pickupSpawnTimer >= 900) {
// Every 15 seconds
if (Math.random() < 0.7) {
spawnHealthPack();
} else {
spawnWeaponPickup();
}
pickupSpawnTimer = 0;
}
// Update bullets and check collisions
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet is off screen or hits walls
if (bullet.x < 0 || bullet.x > 2000 || bullet.y < 0 || bullet.y > 1600) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check wall collision
var bulletHitWall = false;
for (var w = 0; w < walls.length; w++) {
var wall = walls[w];
if (bullet.x < wall.x + 80 && bullet.x + 12 > wall.x && bullet.y < wall.y + 80 && bullet.y + 12 > wall.y) {
bulletHitWall = true;
break;
}
}
if (bulletHitWall) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-zombie collisions
var hit = false;
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (bullet.intersects(zombie)) {
if (zombie.takeDamage(bullet.damage)) {
// Zombie died
score += 50;
LK.getSound('zombieHit').play();
zombie.destroy();
zombies.splice(j, 1);
}
bullet.destroy();
bullets.splice(i, 1);
hit = true;
break;
}
}
}
// Update health packs
for (var i = healthPacks.length - 1; i >= 0; i--) {
var healthPack = healthPacks[i];
if (healthPack.collected) {
healthPack.destroy();
healthPacks.splice(i, 1);
}
}
// Update weapon pickups
for (var i = weaponPickups.length - 1; i >= 0; i--) {
var weaponPickup = weaponPickups[i];
if (weaponPickup.collected) {
weaponPickup.destroy();
weaponPickups.splice(i, 1);
}
}
// Update UI
scoreText.setText('Kills: ' + score / 50);
healthText.setText('Health: ' + player.health);
weaponText.setText('Weapon: ' + player.weapon);
// Exit reached condition handled by MazeExit class
};
Human. In-Game asset. 2d. High contrast. No shadows
Zombie. In-Game asset. 2d. High contrast. No shadows
Health. In-Game asset. 2d. High contrast. No shadows
Weapon. In-Game asset. 2d. High contrast. No shadows
Exit. In-Game asset. 2d. High contrast. No shadows
Maze exit. In-Game asset. 2d. High contrast. No shadows
Bullet. In-Game asset. 2d. High contrast. No shadows
Player Health. In-Game asset. 2d. High contrast. No shadows