/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
self.speed = 15;
self.damage = 20;
self.maxRange = 1200;
self.distanceTraveled = 0;
self.angle = 0;
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
// Move bullet based on angle
var vx = Math.cos(self.angle) * self.speed;
var vy = Math.sin(self.angle) * self.speed;
self.x += vx;
self.y += vy;
self.distanceTraveled += self.speed;
// Check if bullet has reached max range
if (self.distanceTraveled >= self.maxRange) {
self.active = false;
}
// Check collision with walls
for (var i = 0; i < walls.length; i++) {
if (self.intersects(walls[i])) {
self.active = false;
break;
}
}
// Check collision with enemies
if (self.active) {
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].active && self.intersects(enemies[i])) {
enemies[i].takeDamage(self.damage);
self.active = false;
LK.getSound('hit').play();
break;
}
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
self.enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.speed = 2;
self.active = true;
self.fireRate = 1500; // milliseconds between shots
self.lastFired = 0;
self.detectionRange = 600;
self.angle = 0;
self.points = 100;
self.takeDamage = function (amount) {
self.health -= amount;
// Flash enemy red when hit
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.active = false;
score += self.points;
updateScore();
// Check if all enemies are defeated
var allDefeated = true;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].active) {
allDefeated = false;
break;
}
}
if (allDefeated && objectives.length === 0) {
LK.showYouWin();
}
}
};
self.update = function () {
if (!self.active || !player.active) {
return;
}
// Calculate distance to player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distToPlayer = Math.sqrt(dx * dx + dy * dy);
// Calculate angle to player
self.angle = Math.atan2(dy, dx);
self.enemyGraphics.rotation = self.angle;
// If player is within detection range, move towards player and shoot
if (distToPlayer < self.detectionRange) {
// Check if path to player is clear
var canSeePlayer = true;
var steps = 10;
for (var i = 1; i < steps; i++) {
var checkX = self.x + dx * i / steps;
var checkY = self.y + dy * i / steps;
for (var j = 0; j < walls.length; j++) {
var wall = walls[j];
if (checkX > wall.x - wall.width / 2 && checkX < wall.x + wall.width / 2 && checkY > wall.y - wall.height / 2 && checkY < wall.y + wall.height / 2) {
canSeePlayer = false;
break;
}
}
if (!canSeePlayer) {
break;
}
}
if (canSeePlayer) {
// Move towards player if not too close
if (distToPlayer > 200) {
var moveX = Math.cos(self.angle) * self.speed;
var moveY = Math.sin(self.angle) * self.speed;
var newX = self.x + moveX;
var newY = self.y + moveY;
// Check for wall collisions
var canMove = true;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (Math.abs(newX - wall.x) < self.enemyGraphics.width / 2 + wall.width / 2 && Math.abs(newY - wall.y) < self.enemyGraphics.height / 2 + wall.height / 2) {
canMove = false;
break;
}
}
if (canMove) {
self.x = newX;
self.y = newY;
}
}
// Try to shoot
var currentTime = Date.now();
if (currentTime - self.lastFired > self.fireRate) {
self.lastFired = currentTime;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.angle = self.angle;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('enemyShoot').play();
}
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
self.bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
self.speed = 10;
self.damage = 10;
self.maxRange = 1000;
self.distanceTraveled = 0;
self.angle = 0;
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
// Move bullet based on angle
var vx = Math.cos(self.angle) * self.speed;
var vy = Math.sin(self.angle) * self.speed;
self.x += vx;
self.y += vy;
self.distanceTraveled += self.speed;
// Check if bullet has reached max range
if (self.distanceTraveled >= self.maxRange) {
self.active = false;
}
// Check collision with walls
for (var i = 0; i < walls.length; i++) {
if (self.intersects(walls[i])) {
self.active = false;
break;
}
}
// Check collision with player
if (self.active && self.intersects(player) && player.active) {
player.takeDamage(self.damage);
self.active = false;
LK.getSound('hit').play();
}
};
return self;
});
var Objective = Container.expand(function () {
var self = Container.call(this);
self.objectiveGraphics = self.attachAsset('objective', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.captureProgress = 0;
self.captureTime = 3000; // 3 seconds to capture
self.isPlayerInRange = false;
self.lastCaptureTime = 0;
self.points = 500;
self.update = function () {
if (!self.active) {
return;
}
// Check if player is within capture range
var dx = player.x - self.x;
var dy = player.y - self.y;
var distToPlayer = Math.sqrt(dx * dx + dy * dy);
self.isPlayerInRange = distToPlayer < 100;
if (self.isPlayerInRange && player.active) {
var currentTime = Date.now();
var timeDelta = currentTime - self.lastCaptureTime;
self.lastCaptureTime = currentTime;
if (timeDelta > 0) {
self.captureProgress += timeDelta;
// Pulse effect during capture
var pulseScale = 1 + 0.1 * Math.sin(currentTime / 200);
self.objectiveGraphics.scale.set(pulseScale, pulseScale);
}
if (self.captureProgress >= self.captureTime) {
self.complete();
}
} else {
// Reset if player leaves
self.lastCaptureTime = Date.now();
self.objectiveGraphics.scale.set(1, 1);
}
};
self.complete = function () {
if (!self.active) {
return;
}
self.active = false;
score += self.points;
updateScore();
LK.getSound('objectiveComplete').play();
LK.effects.flashObject(self, 0x00ff00, 1000);
// Remove from objectives array
var index = objectives.indexOf(self);
if (index !== -1) {
objectives.splice(index, 1);
}
// Check win condition
if (objectives.length === 0) {
var allEnemiesDefeated = true;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].active) {
allEnemiesDefeated = false;
break;
}
}
if (allEnemiesDefeated) {
LK.showYouWin();
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
self.playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.aimLine = self.attachAsset('aimLine', {
anchorX: 0,
anchorY: 0.5,
alpha: 0.3
});
self.health = 100;
self.maxHealth = 100;
self.speed = 5;
self.angle = 0;
self.fireRate = 300; // milliseconds between shots
self.lastFired = 0;
self.active = true;
self.ammo = 30;
self.maxAmmo = 30;
self.reloading = false;
self.reloadTime = 2000; // 2 seconds to reload
self.weaponType = "standard"; // standard, shotgun, rifle
self.takeDamage = function (amount) {
self.health -= amount;
updateHealthBar();
if (self.health <= 0) {
self.active = false;
LK.showGameOver();
}
};
self.shoot = function () {
if (!self.active || self.reloading) {
return;
}
var currentTime = Date.now();
if (currentTime - self.lastFired < self.fireRate) {
return;
}
if (self.ammo <= 0) {
self.reload();
return;
}
self.lastFired = currentTime;
self.ammo--;
updateAmmoBar();
LK.getSound('shoot').play();
if (self.weaponType === "shotgun") {
// Create 5 bullets in a spread pattern
for (var i = -2; i <= 2; i++) {
var spreadAngle = self.angle + i * 0.1;
createBullet(self.x, self.y, spreadAngle);
}
} else if (self.weaponType === "rifle") {
// Rifle has higher fire rate and damage
self.fireRate = 150;
var bullet = createBullet(self.x, self.y, self.angle);
bullet.damage = 30;
} else {
// Standard pistol
createBullet(self.x, self.y, self.angle);
}
};
self.reload = function () {
if (self.reloading || self.ammo === self.maxAmmo) {
return;
}
self.reloading = true;
LK.getSound('reload').play();
LK.setTimeout(function () {
self.ammo = self.maxAmmo;
self.reloading = false;
updateAmmoBar();
}, self.reloadTime);
};
self.updateAim = function (targetX, targetY) {
// Calculate angle to target
var dx = targetX - self.x;
var dy = targetY - self.y;
self.angle = Math.atan2(dy, dx);
// Rotate player to face aim direction
self.playerGraphics.rotation = self.angle;
// Update aim line rotation and visibility
self.aimLine.rotation = self.angle;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
self.wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var WeaponPickup = Container.expand(function () {
var self = Container.call(this);
self.pickupGraphics = self.attachAsset('weaponPickup', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.type = "standard"; // standard, shotgun, rifle
self.update = function () {
if (!self.active) {
return;
}
if (self.intersects(player) && player.active) {
self.pickup();
}
// Rotate pickup for visual effect
self.pickupGraphics.rotation += 0.02;
};
self.pickup = function () {
if (!self.active) {
return;
}
self.active = false;
player.weaponType = self.type;
player.ammo = player.maxAmmo;
updateAmmoBar();
LK.getSound('pickup').play();
// Adjust player's weapon properties based on type
if (self.type === "shotgun") {
player.fireRate = 800;
player.maxAmmo = 8;
} else if (self.type === "rifle") {
player.fireRate = 150;
player.maxAmmo = 25;
} else {
player.fireRate = 300;
player.maxAmmo = 15;
}
// Remove from pickups array
var index = weaponPickups.indexOf(self);
if (index !== -1) {
weaponPickups.splice(index, 1);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
var player;
var bullets = [];
var enemyBullets = [];
var enemies = [];
var walls = [];
var objectives = [];
var weaponPickups = [];
var score = 0;
var level = storage.level || 1;
var dragActive = false;
var dragStartX = 0;
var dragStartY = 0;
var moveTargetX = 0;
var moveTargetY = 0;
var isMoving = false;
var lastShootTime = 0;
// UI elements
var scoreTxt;
var healthBar;
var healthBarBg;
var ammoBar;
var ammoBarBg;
var levelTxt;
// Initialize game
function initGame() {
// Reset game state
bullets = [];
enemyBullets = [];
enemies = [];
walls = [];
objectives = [];
weaponPickups = [];
score = 0;
// Create player
player = new Player();
player.x = 300;
player.y = 300;
game.addChild(player);
// Create UI
createUI();
// Create level based on current level
createLevel(level);
// Start background music
LK.playMusic('bgMusic');
}
function createUI() {
// Score text
scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.x = 120;
scoreTxt.y = 20;
// Level text
levelTxt = new Text2('Level: ' + level, {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
levelTxt.x = -20;
levelTxt.y = 20;
// Health bar background
healthBarBg = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x333333
});
LK.gui.bottom.addChild(healthBarBg);
healthBarBg.x = -200;
healthBarBg.y = -60;
// Health bar
healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x00cc00
});
LK.gui.bottom.addChild(healthBar);
healthBar.x = -200;
healthBar.y = -60;
// Ammo bar background
ammoBarBg = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x333333
});
LK.gui.bottom.addChild(ammoBarBg);
ammoBarBg.x = -200;
ammoBarBg.y = -30;
// Ammo bar
ammoBar = LK.getAsset('ammoBar', {
anchorX: 0,
anchorY: 0,
tint: 0x3366ff
});
LK.gui.bottom.addChild(ammoBar);
ammoBar.x = -200;
ammoBar.y = -30;
}
function updateScore() {
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
// Update high score
if (score > storage.highScore) {
storage.highScore = score;
}
}
function updateHealthBar() {
var healthPercent = player.health / player.maxHealth;
healthBar.scale.x = healthPercent;
// Change color based on health
if (healthPercent < 0.3) {
healthBar.tint = 0xff0000; // Red when low health
} else if (healthPercent < 0.6) {
healthBar.tint = 0xffcc00; // Yellow when medium health
} else {
healthBar.tint = 0x00cc00; // Green when high health
}
}
function updateAmmoBar() {
var ammoPercent = player.ammo / player.maxAmmo;
ammoBar.scale.x = ammoPercent;
}
function createLevel(levelNum) {
// Clear any existing level elements
for (var i = walls.length - 1; i >= 0; i--) {
game.removeChild(walls[i]);
walls.splice(i, 1);
}
for (var i = enemies.length - 1; i >= 0; i--) {
game.removeChild(enemies[i]);
enemies.splice(i, 1);
}
for (var i = objectives.length - 1; i >= 0; i--) {
game.removeChild(objectives[i]);
objectives.splice(i, 1);
}
for (var i = weaponPickups.length - 1; i >= 0; i--) {
game.removeChild(weaponPickups[i]);
weaponPickups.splice(i, 1);
}
// Create level based on level number
if (levelNum === 1) {
createLevel1();
} else if (levelNum === 2) {
createLevel2();
} else if (levelNum === 3) {
createLevel3();
} else {
// If no specific level, create a random one
createRandomLevel();
}
}
function createLevel1() {
// Create walls for level 1
createWall(400, 400, 300, 50);
createWall(800, 400, 300, 50);
createWall(600, 600, 50, 400);
createWall(600, 1200, 800, 50);
createWall(200, 800, 50, 800);
createWall(1000, 800, 50, 800);
// Create enemies
createEnemy(800, 200);
createEnemy(1000, 600);
createEnemy(400, 1000);
// Create objectives
createObjective(600, 1000);
// Create weapon pickups
createWeaponPickup(600, 400, "shotgun");
}
function createLevel2() {
// Create a more complex level with more enemies and obstacles
// Create walls for level 2
createWall(600, 400, 1000, 50);
createWall(200, 800, 50, 800);
createWall(1000, 800, 50, 800);
createWall(400, 800, 200, 200);
createWall(800, 800, 200, 200);
createWall(600, 1200, 800, 50);
// Create enemies
createEnemy(300, 200);
createEnemy(900, 200);
createEnemy(300, 600);
createEnemy(900, 600);
createEnemy(600, 1000);
// Create objectives
createObjective(400, 600);
createObjective(800, 600);
// Create weapon pickups
createWeaponPickup(600, 200, "rifle");
createWeaponPickup(600, 800, "shotgun");
}
function createLevel3() {
// Create an even more complex level with more enemies and obstacles
// Create walls for level 3
createWall(600, 400, 1000, 50);
createWall(200, 1000, 50, 1200);
createWall(1000, 1000, 50, 1200);
createWall(400, 800, 100, 100);
createWall(800, 800, 100, 100);
createWall(400, 1200, 100, 100);
createWall(800, 1200, 100, 100);
createWall(600, 1500, 800, 50);
// Create enemies
createEnemy(300, 200);
createEnemy(900, 200);
createEnemy(300, 600);
createEnemy(900, 600);
createEnemy(300, 1000);
createEnemy(900, 1000);
createEnemy(600, 1300);
// Create objectives
createObjective(400, 600);
createObjective(800, 600);
createObjective(600, 1000);
// Create weapon pickups
createWeaponPickup(200, 500, "rifle");
createWeaponPickup(1000, 500, "shotgun");
createWeaponPickup(600, 1300, "rifle");
}
function createRandomLevel() {
// Create a random level with walls, enemies, and objectives
var numWalls = 10 + level * 2;
var numEnemies = 5 + level;
var numObjectives = 2 + Math.floor(level / 2);
var numPickups = 1 + Math.floor(level / 2);
// Create boundary walls
createWall(600, 100, 1000, 50);
createWall(600, 2000, 1000, 50);
createWall(100, 1050, 50, 1900);
createWall(1100, 1050, 50, 1900);
// Create random walls
for (var i = 0; i < numWalls; i++) {
var x = 200 + Math.random() * 800;
var y = 200 + Math.random() * 1600;
var width = 50 + Math.random() * 200;
var height = 50 + Math.random() * 200;
if (Math.random() < 0.5) {
// Horizontal wall
createWall(x, y, width, 50);
} else {
// Vertical wall
createWall(x, y, 50, height);
}
}
// Create random enemies
for (var i = 0; i < numEnemies; i++) {
var x = 200 + Math.random() * 800;
var y = 300 + Math.random() * 1400;
// Make sure enemy is not too close to player
if (Math.sqrt(Math.pow(x - player.x, 2) + Math.pow(y - player.y, 2)) > 400) {
createEnemy(x, y);
}
}
// Create random objectives
for (var i = 0; i < numObjectives; i++) {
var x = 200 + Math.random() * 800;
var y = 300 + Math.random() * 1400;
createObjective(x, y);
}
// Create random weapon pickups
for (var i = 0; i < numPickups; i++) {
var x = 200 + Math.random() * 800;
var y = 300 + Math.random() * 1400;
var type = Math.random() < 0.5 ? "shotgun" : "rifle";
createWeaponPickup(x, y, type);
}
}
function createWall(x, y, width, height) {
var wall = new Wall();
wall.x = x;
wall.y = y;
wall.wallGraphics.width = width;
wall.wallGraphics.height = height;
walls.push(wall);
game.addChild(wall);
return wall;
}
function createEnemy(x, y) {
var enemy = new Enemy();
enemy.x = x;
enemy.y = y;
enemies.push(enemy);
game.addChild(enemy);
return enemy;
}
function createObjective(x, y) {
var objective = new Objective();
objective.x = x;
objective.y = y;
objectives.push(objective);
game.addChild(objective);
return objective;
}
function createWeaponPickup(x, y, type) {
var pickup = new WeaponPickup();
pickup.x = x;
pickup.y = y;
pickup.type = type;
// Change color based on weapon type
if (type === "shotgun") {
pickup.pickupGraphics.tint = 0xff9900;
} else if (type === "rifle") {
pickup.pickupGraphics.tint = 0x6699ff;
}
weaponPickups.push(pickup);
game.addChild(pickup);
return pickup;
}
function createBullet(x, y, angle) {
var bullet = new Bullet();
bullet.x = x;
bullet.y = y;
bullet.angle = angle;
bullets.push(bullet);
game.addChild(bullet);
return bullet;
}
function handlePlayerMovement() {
if (!isMoving || !player.active) {
return;
}
var dx = moveTargetX - player.x;
var dy = moveTargetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < player.speed) {
// Arrived at destination
isMoving = false;
return;
}
// Normalize direction vector
var dirX = dx / distance;
var dirY = dy / distance;
// Calculate new position
var newX = player.x + dirX * player.speed;
var newY = player.y + dirY * player.speed;
// Check for wall collisions
var canMove = true;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var playerRadius = player.playerGraphics.width / 2;
// Simple collision check between circle (player) and rectangle (wall)
var testX = newX;
var testY = newY;
if (newX < wall.x - wall.wallGraphics.width / 2) {
testX = wall.x - wall.wallGraphics.width / 2;
} else if (newX > wall.x + wall.wallGraphics.width / 2) {
testX = wall.x + wall.wallGraphics.width / 2;
}
if (newY < wall.y - wall.wallGraphics.height / 2) {
testY = wall.y - wall.wallGraphics.height / 2;
} else if (newY > wall.y + wall.wallGraphics.height / 2) {
testY = wall.y + wall.wallGraphics.height / 2;
}
var distX = newX - testX;
var distY = newY - testY;
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance < playerRadius) {
canMove = false;
break;
}
}
if (canMove) {
player.x = newX;
player.y = newY;
} else {
// Try to slide along walls
var canMoveX = true;
var canMoveY = true;
// Check X movement only
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var playerRadius = player.playerGraphics.width / 2;
var testX = player.x + dirX * player.speed;
var testY = player.y;
var closestX = testX;
var closestY = testY;
if (testX < wall.x - wall.wallGraphics.width / 2) {
closestX = wall.x - wall.wallGraphics.width / 2;
} else if (testX > wall.x + wall.wallGraphics.width / 2) {
closestX = wall.x + wall.wallGraphics.width / 2;
}
if (testY < wall.y - wall.wallGraphics.height / 2) {
closestY = wall.y - wall.wallGraphics.height / 2;
} else if (testY > wall.y + wall.wallGraphics.height / 2) {
closestY = wall.y + wall.wallGraphics.height / 2;
}
var distX = testX - closestX;
var distY = testY - closestY;
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance < playerRadius) {
canMoveX = false;
break;
}
}
// Check Y movement only
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var playerRadius = player.playerGraphics.width / 2;
var testX = player.x;
var testY = player.y + dirY * player.speed;
var closestX = testX;
var closestY = testY;
if (testX < wall.x - wall.wallGraphics.width / 2) {
closestX = wall.x - wall.wallGraphics.width / 2;
} else if (testX > wall.x + wall.wallGraphics.width / 2) {
closestX = wall.x + wall.wallGraphics.width / 2;
}
if (testY < wall.y - wall.wallGraphics.height / 2) {
closestY = wall.y - wall.wallGraphics.height / 2;
} else if (testY > wall.y + wall.wallGraphics.height / 2) {
closestY = wall.y + wall.wallGraphics.height / 2;
}
var distX = testX - closestX;
var distY = testY - closestY;
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance < playerRadius) {
canMoveY = false;
break;
}
}
// Apply sliding movement
if (canMoveX) {
player.x += dirX * player.speed;
}
if (canMoveY) {
player.y += dirY * player.speed;
}
}
}
// Game input handlers
game.down = function (x, y, obj) {
if (!player.active) {
return;
}
dragActive = true;
dragStartX = x;
dragStartY = y;
// Calculate time since last shoot
var currentTime = Date.now();
if (currentTime - lastShootTime < 300) {
// Double tap detected - shoot
player.shoot();
}
lastShootTime = currentTime;
};
game.up = function (x, y, obj) {
dragActive = false;
// Set movement target if drag distance is small
var dragDistX = x - dragStartX;
var dragDistY = y - dragStartY;
var dragDist = Math.sqrt(dragDistX * dragDistX + dragDistY * dragDistY);
if (dragDist < 20) {
// Tap (not drag) - set movement target
moveTargetX = x;
moveTargetY = y;
isMoving = true;
}
};
game.move = function (x, y, obj) {
if (!dragActive || !player.active) {
return;
}
// Update player aim direction
player.updateAim(x, y);
// Check if drag distance is large enough to be considered a drag rather than a tap
var dragDistX = x - dragStartX;
var dragDistY = y - dragStartY;
var dragDist = Math.sqrt(dragDistX * dragDistX + dragDistY * dragDistY);
if (dragDist > 20) {
// Long enough drag - shoot
player.shoot();
}
};
// Game update loop
game.update = function () {
// Handle player movement
handlePlayerMovement();
// Update all bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (!bullet.active) {
game.removeChild(bullet);
bullets.splice(i, 1);
continue;
}
}
// Update all enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (!bullet.active) {
game.removeChild(bullet);
enemyBullets.splice(i, 1);
continue;
}
}
// Update all enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (!enemy.active) {
game.removeChild(enemy);
enemies.splice(i, 1);
continue;
}
}
// Update all objectives
for (var i = objectives.length - 1; i >= 0; i--) {
var objective = objectives[i];
if (!objective.active) {
game.removeChild(objective);
objectives.splice(i, 1);
continue;
}
}
// Update all weapon pickups
for (var i = weaponPickups.length - 1; i >= 0; i--) {
var pickup = weaponPickups[i];
if (!pickup.active) {
game.removeChild(pickup);
weaponPickups.splice(i, 1);
continue;
}
}
// Check for win condition
if (objectives.length === 0 && enemies.length === 0) {
// Level completed
level++;
storage.level = level;
// Check if we have more levels
if (level <= 3) {
// Advance to next level
LK.showYouWin();
} else {
// Game completed
LK.showYouWin();
level = 1; // Reset level for next game
storage.level = level;
}
}
};
// Initialize the game
initGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
self.speed = 15;
self.damage = 20;
self.maxRange = 1200;
self.distanceTraveled = 0;
self.angle = 0;
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
// Move bullet based on angle
var vx = Math.cos(self.angle) * self.speed;
var vy = Math.sin(self.angle) * self.speed;
self.x += vx;
self.y += vy;
self.distanceTraveled += self.speed;
// Check if bullet has reached max range
if (self.distanceTraveled >= self.maxRange) {
self.active = false;
}
// Check collision with walls
for (var i = 0; i < walls.length; i++) {
if (self.intersects(walls[i])) {
self.active = false;
break;
}
}
// Check collision with enemies
if (self.active) {
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].active && self.intersects(enemies[i])) {
enemies[i].takeDamage(self.damage);
self.active = false;
LK.getSound('hit').play();
break;
}
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
self.enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.speed = 2;
self.active = true;
self.fireRate = 1500; // milliseconds between shots
self.lastFired = 0;
self.detectionRange = 600;
self.angle = 0;
self.points = 100;
self.takeDamage = function (amount) {
self.health -= amount;
// Flash enemy red when hit
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.active = false;
score += self.points;
updateScore();
// Check if all enemies are defeated
var allDefeated = true;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].active) {
allDefeated = false;
break;
}
}
if (allDefeated && objectives.length === 0) {
LK.showYouWin();
}
}
};
self.update = function () {
if (!self.active || !player.active) {
return;
}
// Calculate distance to player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distToPlayer = Math.sqrt(dx * dx + dy * dy);
// Calculate angle to player
self.angle = Math.atan2(dy, dx);
self.enemyGraphics.rotation = self.angle;
// If player is within detection range, move towards player and shoot
if (distToPlayer < self.detectionRange) {
// Check if path to player is clear
var canSeePlayer = true;
var steps = 10;
for (var i = 1; i < steps; i++) {
var checkX = self.x + dx * i / steps;
var checkY = self.y + dy * i / steps;
for (var j = 0; j < walls.length; j++) {
var wall = walls[j];
if (checkX > wall.x - wall.width / 2 && checkX < wall.x + wall.width / 2 && checkY > wall.y - wall.height / 2 && checkY < wall.y + wall.height / 2) {
canSeePlayer = false;
break;
}
}
if (!canSeePlayer) {
break;
}
}
if (canSeePlayer) {
// Move towards player if not too close
if (distToPlayer > 200) {
var moveX = Math.cos(self.angle) * self.speed;
var moveY = Math.sin(self.angle) * self.speed;
var newX = self.x + moveX;
var newY = self.y + moveY;
// Check for wall collisions
var canMove = true;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (Math.abs(newX - wall.x) < self.enemyGraphics.width / 2 + wall.width / 2 && Math.abs(newY - wall.y) < self.enemyGraphics.height / 2 + wall.height / 2) {
canMove = false;
break;
}
}
if (canMove) {
self.x = newX;
self.y = newY;
}
}
// Try to shoot
var currentTime = Date.now();
if (currentTime - self.lastFired > self.fireRate) {
self.lastFired = currentTime;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.angle = self.angle;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('enemyShoot').play();
}
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
self.bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
self.speed = 10;
self.damage = 10;
self.maxRange = 1000;
self.distanceTraveled = 0;
self.angle = 0;
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
// Move bullet based on angle
var vx = Math.cos(self.angle) * self.speed;
var vy = Math.sin(self.angle) * self.speed;
self.x += vx;
self.y += vy;
self.distanceTraveled += self.speed;
// Check if bullet has reached max range
if (self.distanceTraveled >= self.maxRange) {
self.active = false;
}
// Check collision with walls
for (var i = 0; i < walls.length; i++) {
if (self.intersects(walls[i])) {
self.active = false;
break;
}
}
// Check collision with player
if (self.active && self.intersects(player) && player.active) {
player.takeDamage(self.damage);
self.active = false;
LK.getSound('hit').play();
}
};
return self;
});
var Objective = Container.expand(function () {
var self = Container.call(this);
self.objectiveGraphics = self.attachAsset('objective', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.captureProgress = 0;
self.captureTime = 3000; // 3 seconds to capture
self.isPlayerInRange = false;
self.lastCaptureTime = 0;
self.points = 500;
self.update = function () {
if (!self.active) {
return;
}
// Check if player is within capture range
var dx = player.x - self.x;
var dy = player.y - self.y;
var distToPlayer = Math.sqrt(dx * dx + dy * dy);
self.isPlayerInRange = distToPlayer < 100;
if (self.isPlayerInRange && player.active) {
var currentTime = Date.now();
var timeDelta = currentTime - self.lastCaptureTime;
self.lastCaptureTime = currentTime;
if (timeDelta > 0) {
self.captureProgress += timeDelta;
// Pulse effect during capture
var pulseScale = 1 + 0.1 * Math.sin(currentTime / 200);
self.objectiveGraphics.scale.set(pulseScale, pulseScale);
}
if (self.captureProgress >= self.captureTime) {
self.complete();
}
} else {
// Reset if player leaves
self.lastCaptureTime = Date.now();
self.objectiveGraphics.scale.set(1, 1);
}
};
self.complete = function () {
if (!self.active) {
return;
}
self.active = false;
score += self.points;
updateScore();
LK.getSound('objectiveComplete').play();
LK.effects.flashObject(self, 0x00ff00, 1000);
// Remove from objectives array
var index = objectives.indexOf(self);
if (index !== -1) {
objectives.splice(index, 1);
}
// Check win condition
if (objectives.length === 0) {
var allEnemiesDefeated = true;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].active) {
allEnemiesDefeated = false;
break;
}
}
if (allEnemiesDefeated) {
LK.showYouWin();
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
self.playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.aimLine = self.attachAsset('aimLine', {
anchorX: 0,
anchorY: 0.5,
alpha: 0.3
});
self.health = 100;
self.maxHealth = 100;
self.speed = 5;
self.angle = 0;
self.fireRate = 300; // milliseconds between shots
self.lastFired = 0;
self.active = true;
self.ammo = 30;
self.maxAmmo = 30;
self.reloading = false;
self.reloadTime = 2000; // 2 seconds to reload
self.weaponType = "standard"; // standard, shotgun, rifle
self.takeDamage = function (amount) {
self.health -= amount;
updateHealthBar();
if (self.health <= 0) {
self.active = false;
LK.showGameOver();
}
};
self.shoot = function () {
if (!self.active || self.reloading) {
return;
}
var currentTime = Date.now();
if (currentTime - self.lastFired < self.fireRate) {
return;
}
if (self.ammo <= 0) {
self.reload();
return;
}
self.lastFired = currentTime;
self.ammo--;
updateAmmoBar();
LK.getSound('shoot').play();
if (self.weaponType === "shotgun") {
// Create 5 bullets in a spread pattern
for (var i = -2; i <= 2; i++) {
var spreadAngle = self.angle + i * 0.1;
createBullet(self.x, self.y, spreadAngle);
}
} else if (self.weaponType === "rifle") {
// Rifle has higher fire rate and damage
self.fireRate = 150;
var bullet = createBullet(self.x, self.y, self.angle);
bullet.damage = 30;
} else {
// Standard pistol
createBullet(self.x, self.y, self.angle);
}
};
self.reload = function () {
if (self.reloading || self.ammo === self.maxAmmo) {
return;
}
self.reloading = true;
LK.getSound('reload').play();
LK.setTimeout(function () {
self.ammo = self.maxAmmo;
self.reloading = false;
updateAmmoBar();
}, self.reloadTime);
};
self.updateAim = function (targetX, targetY) {
// Calculate angle to target
var dx = targetX - self.x;
var dy = targetY - self.y;
self.angle = Math.atan2(dy, dx);
// Rotate player to face aim direction
self.playerGraphics.rotation = self.angle;
// Update aim line rotation and visibility
self.aimLine.rotation = self.angle;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
self.wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var WeaponPickup = Container.expand(function () {
var self = Container.call(this);
self.pickupGraphics = self.attachAsset('weaponPickup', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.type = "standard"; // standard, shotgun, rifle
self.update = function () {
if (!self.active) {
return;
}
if (self.intersects(player) && player.active) {
self.pickup();
}
// Rotate pickup for visual effect
self.pickupGraphics.rotation += 0.02;
};
self.pickup = function () {
if (!self.active) {
return;
}
self.active = false;
player.weaponType = self.type;
player.ammo = player.maxAmmo;
updateAmmoBar();
LK.getSound('pickup').play();
// Adjust player's weapon properties based on type
if (self.type === "shotgun") {
player.fireRate = 800;
player.maxAmmo = 8;
} else if (self.type === "rifle") {
player.fireRate = 150;
player.maxAmmo = 25;
} else {
player.fireRate = 300;
player.maxAmmo = 15;
}
// Remove from pickups array
var index = weaponPickups.indexOf(self);
if (index !== -1) {
weaponPickups.splice(index, 1);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
var player;
var bullets = [];
var enemyBullets = [];
var enemies = [];
var walls = [];
var objectives = [];
var weaponPickups = [];
var score = 0;
var level = storage.level || 1;
var dragActive = false;
var dragStartX = 0;
var dragStartY = 0;
var moveTargetX = 0;
var moveTargetY = 0;
var isMoving = false;
var lastShootTime = 0;
// UI elements
var scoreTxt;
var healthBar;
var healthBarBg;
var ammoBar;
var ammoBarBg;
var levelTxt;
// Initialize game
function initGame() {
// Reset game state
bullets = [];
enemyBullets = [];
enemies = [];
walls = [];
objectives = [];
weaponPickups = [];
score = 0;
// Create player
player = new Player();
player.x = 300;
player.y = 300;
game.addChild(player);
// Create UI
createUI();
// Create level based on current level
createLevel(level);
// Start background music
LK.playMusic('bgMusic');
}
function createUI() {
// Score text
scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.x = 120;
scoreTxt.y = 20;
// Level text
levelTxt = new Text2('Level: ' + level, {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
levelTxt.x = -20;
levelTxt.y = 20;
// Health bar background
healthBarBg = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x333333
});
LK.gui.bottom.addChild(healthBarBg);
healthBarBg.x = -200;
healthBarBg.y = -60;
// Health bar
healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x00cc00
});
LK.gui.bottom.addChild(healthBar);
healthBar.x = -200;
healthBar.y = -60;
// Ammo bar background
ammoBarBg = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x333333
});
LK.gui.bottom.addChild(ammoBarBg);
ammoBarBg.x = -200;
ammoBarBg.y = -30;
// Ammo bar
ammoBar = LK.getAsset('ammoBar', {
anchorX: 0,
anchorY: 0,
tint: 0x3366ff
});
LK.gui.bottom.addChild(ammoBar);
ammoBar.x = -200;
ammoBar.y = -30;
}
function updateScore() {
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
// Update high score
if (score > storage.highScore) {
storage.highScore = score;
}
}
function updateHealthBar() {
var healthPercent = player.health / player.maxHealth;
healthBar.scale.x = healthPercent;
// Change color based on health
if (healthPercent < 0.3) {
healthBar.tint = 0xff0000; // Red when low health
} else if (healthPercent < 0.6) {
healthBar.tint = 0xffcc00; // Yellow when medium health
} else {
healthBar.tint = 0x00cc00; // Green when high health
}
}
function updateAmmoBar() {
var ammoPercent = player.ammo / player.maxAmmo;
ammoBar.scale.x = ammoPercent;
}
function createLevel(levelNum) {
// Clear any existing level elements
for (var i = walls.length - 1; i >= 0; i--) {
game.removeChild(walls[i]);
walls.splice(i, 1);
}
for (var i = enemies.length - 1; i >= 0; i--) {
game.removeChild(enemies[i]);
enemies.splice(i, 1);
}
for (var i = objectives.length - 1; i >= 0; i--) {
game.removeChild(objectives[i]);
objectives.splice(i, 1);
}
for (var i = weaponPickups.length - 1; i >= 0; i--) {
game.removeChild(weaponPickups[i]);
weaponPickups.splice(i, 1);
}
// Create level based on level number
if (levelNum === 1) {
createLevel1();
} else if (levelNum === 2) {
createLevel2();
} else if (levelNum === 3) {
createLevel3();
} else {
// If no specific level, create a random one
createRandomLevel();
}
}
function createLevel1() {
// Create walls for level 1
createWall(400, 400, 300, 50);
createWall(800, 400, 300, 50);
createWall(600, 600, 50, 400);
createWall(600, 1200, 800, 50);
createWall(200, 800, 50, 800);
createWall(1000, 800, 50, 800);
// Create enemies
createEnemy(800, 200);
createEnemy(1000, 600);
createEnemy(400, 1000);
// Create objectives
createObjective(600, 1000);
// Create weapon pickups
createWeaponPickup(600, 400, "shotgun");
}
function createLevel2() {
// Create a more complex level with more enemies and obstacles
// Create walls for level 2
createWall(600, 400, 1000, 50);
createWall(200, 800, 50, 800);
createWall(1000, 800, 50, 800);
createWall(400, 800, 200, 200);
createWall(800, 800, 200, 200);
createWall(600, 1200, 800, 50);
// Create enemies
createEnemy(300, 200);
createEnemy(900, 200);
createEnemy(300, 600);
createEnemy(900, 600);
createEnemy(600, 1000);
// Create objectives
createObjective(400, 600);
createObjective(800, 600);
// Create weapon pickups
createWeaponPickup(600, 200, "rifle");
createWeaponPickup(600, 800, "shotgun");
}
function createLevel3() {
// Create an even more complex level with more enemies and obstacles
// Create walls for level 3
createWall(600, 400, 1000, 50);
createWall(200, 1000, 50, 1200);
createWall(1000, 1000, 50, 1200);
createWall(400, 800, 100, 100);
createWall(800, 800, 100, 100);
createWall(400, 1200, 100, 100);
createWall(800, 1200, 100, 100);
createWall(600, 1500, 800, 50);
// Create enemies
createEnemy(300, 200);
createEnemy(900, 200);
createEnemy(300, 600);
createEnemy(900, 600);
createEnemy(300, 1000);
createEnemy(900, 1000);
createEnemy(600, 1300);
// Create objectives
createObjective(400, 600);
createObjective(800, 600);
createObjective(600, 1000);
// Create weapon pickups
createWeaponPickup(200, 500, "rifle");
createWeaponPickup(1000, 500, "shotgun");
createWeaponPickup(600, 1300, "rifle");
}
function createRandomLevel() {
// Create a random level with walls, enemies, and objectives
var numWalls = 10 + level * 2;
var numEnemies = 5 + level;
var numObjectives = 2 + Math.floor(level / 2);
var numPickups = 1 + Math.floor(level / 2);
// Create boundary walls
createWall(600, 100, 1000, 50);
createWall(600, 2000, 1000, 50);
createWall(100, 1050, 50, 1900);
createWall(1100, 1050, 50, 1900);
// Create random walls
for (var i = 0; i < numWalls; i++) {
var x = 200 + Math.random() * 800;
var y = 200 + Math.random() * 1600;
var width = 50 + Math.random() * 200;
var height = 50 + Math.random() * 200;
if (Math.random() < 0.5) {
// Horizontal wall
createWall(x, y, width, 50);
} else {
// Vertical wall
createWall(x, y, 50, height);
}
}
// Create random enemies
for (var i = 0; i < numEnemies; i++) {
var x = 200 + Math.random() * 800;
var y = 300 + Math.random() * 1400;
// Make sure enemy is not too close to player
if (Math.sqrt(Math.pow(x - player.x, 2) + Math.pow(y - player.y, 2)) > 400) {
createEnemy(x, y);
}
}
// Create random objectives
for (var i = 0; i < numObjectives; i++) {
var x = 200 + Math.random() * 800;
var y = 300 + Math.random() * 1400;
createObjective(x, y);
}
// Create random weapon pickups
for (var i = 0; i < numPickups; i++) {
var x = 200 + Math.random() * 800;
var y = 300 + Math.random() * 1400;
var type = Math.random() < 0.5 ? "shotgun" : "rifle";
createWeaponPickup(x, y, type);
}
}
function createWall(x, y, width, height) {
var wall = new Wall();
wall.x = x;
wall.y = y;
wall.wallGraphics.width = width;
wall.wallGraphics.height = height;
walls.push(wall);
game.addChild(wall);
return wall;
}
function createEnemy(x, y) {
var enemy = new Enemy();
enemy.x = x;
enemy.y = y;
enemies.push(enemy);
game.addChild(enemy);
return enemy;
}
function createObjective(x, y) {
var objective = new Objective();
objective.x = x;
objective.y = y;
objectives.push(objective);
game.addChild(objective);
return objective;
}
function createWeaponPickup(x, y, type) {
var pickup = new WeaponPickup();
pickup.x = x;
pickup.y = y;
pickup.type = type;
// Change color based on weapon type
if (type === "shotgun") {
pickup.pickupGraphics.tint = 0xff9900;
} else if (type === "rifle") {
pickup.pickupGraphics.tint = 0x6699ff;
}
weaponPickups.push(pickup);
game.addChild(pickup);
return pickup;
}
function createBullet(x, y, angle) {
var bullet = new Bullet();
bullet.x = x;
bullet.y = y;
bullet.angle = angle;
bullets.push(bullet);
game.addChild(bullet);
return bullet;
}
function handlePlayerMovement() {
if (!isMoving || !player.active) {
return;
}
var dx = moveTargetX - player.x;
var dy = moveTargetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < player.speed) {
// Arrived at destination
isMoving = false;
return;
}
// Normalize direction vector
var dirX = dx / distance;
var dirY = dy / distance;
// Calculate new position
var newX = player.x + dirX * player.speed;
var newY = player.y + dirY * player.speed;
// Check for wall collisions
var canMove = true;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var playerRadius = player.playerGraphics.width / 2;
// Simple collision check between circle (player) and rectangle (wall)
var testX = newX;
var testY = newY;
if (newX < wall.x - wall.wallGraphics.width / 2) {
testX = wall.x - wall.wallGraphics.width / 2;
} else if (newX > wall.x + wall.wallGraphics.width / 2) {
testX = wall.x + wall.wallGraphics.width / 2;
}
if (newY < wall.y - wall.wallGraphics.height / 2) {
testY = wall.y - wall.wallGraphics.height / 2;
} else if (newY > wall.y + wall.wallGraphics.height / 2) {
testY = wall.y + wall.wallGraphics.height / 2;
}
var distX = newX - testX;
var distY = newY - testY;
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance < playerRadius) {
canMove = false;
break;
}
}
if (canMove) {
player.x = newX;
player.y = newY;
} else {
// Try to slide along walls
var canMoveX = true;
var canMoveY = true;
// Check X movement only
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var playerRadius = player.playerGraphics.width / 2;
var testX = player.x + dirX * player.speed;
var testY = player.y;
var closestX = testX;
var closestY = testY;
if (testX < wall.x - wall.wallGraphics.width / 2) {
closestX = wall.x - wall.wallGraphics.width / 2;
} else if (testX > wall.x + wall.wallGraphics.width / 2) {
closestX = wall.x + wall.wallGraphics.width / 2;
}
if (testY < wall.y - wall.wallGraphics.height / 2) {
closestY = wall.y - wall.wallGraphics.height / 2;
} else if (testY > wall.y + wall.wallGraphics.height / 2) {
closestY = wall.y + wall.wallGraphics.height / 2;
}
var distX = testX - closestX;
var distY = testY - closestY;
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance < playerRadius) {
canMoveX = false;
break;
}
}
// Check Y movement only
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var playerRadius = player.playerGraphics.width / 2;
var testX = player.x;
var testY = player.y + dirY * player.speed;
var closestX = testX;
var closestY = testY;
if (testX < wall.x - wall.wallGraphics.width / 2) {
closestX = wall.x - wall.wallGraphics.width / 2;
} else if (testX > wall.x + wall.wallGraphics.width / 2) {
closestX = wall.x + wall.wallGraphics.width / 2;
}
if (testY < wall.y - wall.wallGraphics.height / 2) {
closestY = wall.y - wall.wallGraphics.height / 2;
} else if (testY > wall.y + wall.wallGraphics.height / 2) {
closestY = wall.y + wall.wallGraphics.height / 2;
}
var distX = testX - closestX;
var distY = testY - closestY;
var distance = Math.sqrt(distX * distX + distY * distY);
if (distance < playerRadius) {
canMoveY = false;
break;
}
}
// Apply sliding movement
if (canMoveX) {
player.x += dirX * player.speed;
}
if (canMoveY) {
player.y += dirY * player.speed;
}
}
}
// Game input handlers
game.down = function (x, y, obj) {
if (!player.active) {
return;
}
dragActive = true;
dragStartX = x;
dragStartY = y;
// Calculate time since last shoot
var currentTime = Date.now();
if (currentTime - lastShootTime < 300) {
// Double tap detected - shoot
player.shoot();
}
lastShootTime = currentTime;
};
game.up = function (x, y, obj) {
dragActive = false;
// Set movement target if drag distance is small
var dragDistX = x - dragStartX;
var dragDistY = y - dragStartY;
var dragDist = Math.sqrt(dragDistX * dragDistX + dragDistY * dragDistY);
if (dragDist < 20) {
// Tap (not drag) - set movement target
moveTargetX = x;
moveTargetY = y;
isMoving = true;
}
};
game.move = function (x, y, obj) {
if (!dragActive || !player.active) {
return;
}
// Update player aim direction
player.updateAim(x, y);
// Check if drag distance is large enough to be considered a drag rather than a tap
var dragDistX = x - dragStartX;
var dragDistY = y - dragStartY;
var dragDist = Math.sqrt(dragDistX * dragDistX + dragDistY * dragDistY);
if (dragDist > 20) {
// Long enough drag - shoot
player.shoot();
}
};
// Game update loop
game.update = function () {
// Handle player movement
handlePlayerMovement();
// Update all bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (!bullet.active) {
game.removeChild(bullet);
bullets.splice(i, 1);
continue;
}
}
// Update all enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (!bullet.active) {
game.removeChild(bullet);
enemyBullets.splice(i, 1);
continue;
}
}
// Update all enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (!enemy.active) {
game.removeChild(enemy);
enemies.splice(i, 1);
continue;
}
}
// Update all objectives
for (var i = objectives.length - 1; i >= 0; i--) {
var objective = objectives[i];
if (!objective.active) {
game.removeChild(objective);
objectives.splice(i, 1);
continue;
}
}
// Update all weapon pickups
for (var i = weaponPickups.length - 1; i >= 0; i--) {
var pickup = weaponPickups[i];
if (!pickup.active) {
game.removeChild(pickup);
weaponPickups.splice(i, 1);
continue;
}
}
// Check for win condition
if (objectives.length === 0 && enemies.length === 0) {
// Level completed
level++;
storage.level = level;
// Check if we have more levels
if (level <= 3) {
// Advance to next level
LK.showYouWin();
} else {
// Game completed
LK.showYouWin();
level = 1; // Reset level for next game
storage.level = level;
}
}
};
// Initialize the game
initGame();