/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AmmoPowerup = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('ammoPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.rotationSpeed = 0.05;
self.update = function () {
self.rotation += self.rotationSpeed;
};
return self;
});
var Cover = Container.expand(function () {
var self = Container.call(this);
var coverGraphics = self.attachAsset('cover', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
return true; // Cover is destroyed
}
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.speed = 1;
self.shootCooldown = 0;
self.targetX = 0;
self.targetY = 0;
self.lastShotTime = 0;
self.update = function () {
// Move towards player
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Shoot at player occasionally
if (LK.ticks - self.lastShotTime > 120 && Math.random() < 0.02) {
self.shoot();
}
};
self.shoot = function () {
self.lastShotTime = LK.ticks;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 3;
bullet.velocityY = dy / distance * 3;
}
enemyBullets.push(bullet);
game.addChild(bullet);
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
return true; // Enemy is dead
}
return false;
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 8;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var Soldier = Container.expand(function () {
var self = Container.call(this);
var soldierGraphics = self.attachAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.lastHit = 0;
self.takeDamage = function (damage) {
if (LK.ticks - self.lastHit > 30) {
// Invincibility frames
self.health -= damage;
self.lastHit = LK.ticks;
LK.effects.flashObject(self, 0xff0000, 500);
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
var player = game.addChild(new Soldier());
player.x = 1024;
player.y = 1800;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var covers = [];
var powerups = [];
var ammo = 30;
var maxAmmo = 30;
var reloadTime = 0;
var wave = 1;
var enemiesInWave = 5;
var enemiesSpawned = 0;
var waveComplete = false;
// Create cover objects
for (var i = 0; i < 4; i++) {
var cover = new Cover();
cover.x = 400 + i * 400;
cover.y = 1200 + i % 2 * 300;
covers.push(cover);
game.addChild(cover);
}
// UI Elements
var ammoText = new Text2('Ammo: ' + ammo, {
size: 60,
fill: 0xFFFFFF
});
ammoText.anchor.set(1, 0);
LK.gui.topRight.addChild(ammoText);
var waveText = new Text2('Wave: ' + wave, {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
var healthText = new Text2('Health: ' + player.health, {
size: 60,
fill: 0xFFFFFF
});
healthText.anchor.set(0.5, 0);
LK.gui.top.addChild(healthText);
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(scoreText);
var dragNode = null;
var lastTapTime = 0;
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(40, Math.min(2008, x));
dragNode.y = Math.max(40, Math.min(2692, y));
}
}
function spawnEnemy() {
if (enemiesSpawned >= enemiesInWave) return;
var enemy = new Enemy();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 2098;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2782;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 2732;
break;
}
enemy.targetX = player.x;
enemy.targetY = player.y;
enemy.speed = 0.5 + wave * 0.2;
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
}
function shoot(targetX, targetY) {
if (ammo <= 0 || reloadTime > 0) return;
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y;
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * bullet.speed;
bullet.velocityY = dy / distance * bullet.speed;
}
playerBullets.push(bullet);
game.addChild(bullet);
ammo--;
ammoText.setText('Ammo: ' + ammo);
LK.getSound('shoot').play();
if (ammo <= 0) {
reloadTime = 120; // 2 seconds at 60fps
}
}
function spawnPowerup() {
if (Math.random() < 0.1 && powerups.length < 2) {
var powerup = new AmmoPowerup();
powerup.x = 200 + Math.random() * 1648;
powerup.y = 200 + Math.random() * 1400;
powerups.push(powerup);
game.addChild(powerup);
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
var currentTime = LK.ticks;
if (currentTime - lastTapTime < 10) {
// Drag mode
dragNode = player;
handleMove(x, y, obj);
} else {
// Shoot mode
shoot(x, y);
}
lastTapTime = currentTime;
};
game.up = function (x, y, obj) {
dragNode = null;
};
var enemySpawnTimer = 0;
game.update = function () {
// Reload handling
if (reloadTime > 0) {
reloadTime--;
if (reloadTime === 0) {
ammo = maxAmmo;
ammoText.setText('Ammo: ' + ammo);
LK.getSound('reload').play();
}
}
// Update enemy targets
for (var i = 0; i < enemies.length; i++) {
enemies[i].targetX = player.x;
enemies[i].targetY = player.y;
}
// Spawn enemies
enemySpawnTimer++;
if (enemySpawnTimer > 180 && enemiesSpawned < enemiesInWave) {
// 3 seconds
spawnEnemy();
enemySpawnTimer = 0;
}
// Spawn powerups occasionally
if (LK.ticks % 600 === 0) {
spawnPowerup();
}
// Check player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Remove bullets that are off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
if (enemy.takeDamage(25)) {
LK.setScore(LK.getScore() + 100);
scoreText.setText('Score: ' + LK.getScore());
enemy.destroy();
enemies.splice(j, 1);
LK.getSound('enemyHit').play();
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
// Check collision with covers
for (var k = covers.length - 1; k >= 0; k--) {
var cover = covers[k];
if (bullet.intersects(cover)) {
if (cover.takeDamage(10)) {
cover.destroy();
covers.splice(k, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
}
// Check enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Remove bullets that are off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
if (player.takeDamage(15)) {
healthText.setText('Health: ' + player.health);
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with covers
for (var k = covers.length - 1; k >= 0; k--) {
var cover = covers[k];
if (bullet.intersects(cover)) {
if (cover.takeDamage(5)) {
cover.destroy();
covers.splice(k, 1);
}
bullet.destroy();
enemyBullets.splice(i, 1);
break;
}
}
}
// Check powerup collection
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.intersects(player)) {
ammo = Math.min(maxAmmo, ammo + 15);
ammoText.setText('Ammo: ' + ammo);
powerup.destroy();
powerups.splice(i, 1);
}
}
// Check wave completion
if (enemiesSpawned >= enemiesInWave && enemies.length === 0) {
wave++;
waveText.setText('Wave: ' + wave);
enemiesInWave = 5 + wave * 2;
enemiesSpawned = 0;
// Restore some health between waves
player.health = Math.min(player.maxHealth, player.health + 20);
healthText.setText('Health: ' + player.health);
// Win condition after wave 10
if (wave > 10) {
LK.showYouWin();
return;
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AmmoPowerup = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('ammoPowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.rotationSpeed = 0.05;
self.update = function () {
self.rotation += self.rotationSpeed;
};
return self;
});
var Cover = Container.expand(function () {
var self = Container.call(this);
var coverGraphics = self.attachAsset('cover', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
return true; // Cover is destroyed
}
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.speed = 1;
self.shootCooldown = 0;
self.targetX = 0;
self.targetY = 0;
self.lastShotTime = 0;
self.update = function () {
// Move towards player
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Shoot at player occasionally
if (LK.ticks - self.lastShotTime > 120 && Math.random() < 0.02) {
self.shoot();
}
};
self.shoot = function () {
self.lastShotTime = LK.ticks;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * 3;
bullet.velocityY = dy / distance * 3;
}
enemyBullets.push(bullet);
game.addChild(bullet);
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
return true; // Enemy is dead
}
return false;
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 8;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
};
return self;
});
var Soldier = Container.expand(function () {
var self = Container.call(this);
var soldierGraphics = self.attachAsset('soldier', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.lastHit = 0;
self.takeDamage = function (damage) {
if (LK.ticks - self.lastHit > 30) {
// Invincibility frames
self.health -= damage;
self.lastHit = LK.ticks;
LK.effects.flashObject(self, 0xff0000, 500);
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
var player = game.addChild(new Soldier());
player.x = 1024;
player.y = 1800;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var covers = [];
var powerups = [];
var ammo = 30;
var maxAmmo = 30;
var reloadTime = 0;
var wave = 1;
var enemiesInWave = 5;
var enemiesSpawned = 0;
var waveComplete = false;
// Create cover objects
for (var i = 0; i < 4; i++) {
var cover = new Cover();
cover.x = 400 + i * 400;
cover.y = 1200 + i % 2 * 300;
covers.push(cover);
game.addChild(cover);
}
// UI Elements
var ammoText = new Text2('Ammo: ' + ammo, {
size: 60,
fill: 0xFFFFFF
});
ammoText.anchor.set(1, 0);
LK.gui.topRight.addChild(ammoText);
var waveText = new Text2('Wave: ' + wave, {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
var healthText = new Text2('Health: ' + player.health, {
size: 60,
fill: 0xFFFFFF
});
healthText.anchor.set(0.5, 0);
LK.gui.top.addChild(healthText);
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(scoreText);
var dragNode = null;
var lastTapTime = 0;
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(40, Math.min(2008, x));
dragNode.y = Math.max(40, Math.min(2692, y));
}
}
function spawnEnemy() {
if (enemiesSpawned >= enemiesInWave) return;
var enemy = new Enemy();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 2098;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2782;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 2732;
break;
}
enemy.targetX = player.x;
enemy.targetY = player.y;
enemy.speed = 0.5 + wave * 0.2;
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
}
function shoot(targetX, targetY) {
if (ammo <= 0 || reloadTime > 0) return;
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y;
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * bullet.speed;
bullet.velocityY = dy / distance * bullet.speed;
}
playerBullets.push(bullet);
game.addChild(bullet);
ammo--;
ammoText.setText('Ammo: ' + ammo);
LK.getSound('shoot').play();
if (ammo <= 0) {
reloadTime = 120; // 2 seconds at 60fps
}
}
function spawnPowerup() {
if (Math.random() < 0.1 && powerups.length < 2) {
var powerup = new AmmoPowerup();
powerup.x = 200 + Math.random() * 1648;
powerup.y = 200 + Math.random() * 1400;
powerups.push(powerup);
game.addChild(powerup);
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
var currentTime = LK.ticks;
if (currentTime - lastTapTime < 10) {
// Drag mode
dragNode = player;
handleMove(x, y, obj);
} else {
// Shoot mode
shoot(x, y);
}
lastTapTime = currentTime;
};
game.up = function (x, y, obj) {
dragNode = null;
};
var enemySpawnTimer = 0;
game.update = function () {
// Reload handling
if (reloadTime > 0) {
reloadTime--;
if (reloadTime === 0) {
ammo = maxAmmo;
ammoText.setText('Ammo: ' + ammo);
LK.getSound('reload').play();
}
}
// Update enemy targets
for (var i = 0; i < enemies.length; i++) {
enemies[i].targetX = player.x;
enemies[i].targetY = player.y;
}
// Spawn enemies
enemySpawnTimer++;
if (enemySpawnTimer > 180 && enemiesSpawned < enemiesInWave) {
// 3 seconds
spawnEnemy();
enemySpawnTimer = 0;
}
// Spawn powerups occasionally
if (LK.ticks % 600 === 0) {
spawnPowerup();
}
// Check player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Remove bullets that are off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
if (enemy.takeDamage(25)) {
LK.setScore(LK.getScore() + 100);
scoreText.setText('Score: ' + LK.getScore());
enemy.destroy();
enemies.splice(j, 1);
LK.getSound('enemyHit').play();
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
// Check collision with covers
for (var k = covers.length - 1; k >= 0; k--) {
var cover = covers[k];
if (bullet.intersects(cover)) {
if (cover.takeDamage(10)) {
cover.destroy();
covers.splice(k, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
}
// Check enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Remove bullets that are off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
if (player.takeDamage(15)) {
healthText.setText('Health: ' + player.health);
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with covers
for (var k = covers.length - 1; k >= 0; k--) {
var cover = covers[k];
if (bullet.intersects(cover)) {
if (cover.takeDamage(5)) {
cover.destroy();
covers.splice(k, 1);
}
bullet.destroy();
enemyBullets.splice(i, 1);
break;
}
}
}
// Check powerup collection
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.intersects(player)) {
ammo = Math.min(maxAmmo, ammo + 15);
ammoText.setText('Ammo: ' + ammo);
powerup.destroy();
powerups.splice(i, 1);
}
}
// Check wave completion
if (enemiesSpawned >= enemiesInWave && enemies.length === 0) {
wave++;
waveText.setText('Wave: ' + wave);
enemiesInWave = 5 + wave * 2;
enemiesSpawned = 0;
// Restore some health between waves
player.health = Math.min(player.maxHealth, player.health + 20);
healthText.setText('Health: ' + player.health);
// Win condition after wave 10
if (wave > 10) {
LK.showYouWin();
return;
}
}
};