/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.velocityX = 0;
self.velocityY = 0;
self.setVelocity = function (vx, vy) {
self.velocityX = vx;
self.velocityY = vy;
};
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.speed = 12;
self.update = function () {
self.y -= self.speed;
};
return self;
});
var PlayerTank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('playerTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.fireRate = 15;
self.fireTimer = 0;
self.update = function () {
if (self.fireTimer > 0) {
self.fireTimer--;
}
};
self.canFire = function () {
return self.fireTimer <= 0;
};
self.fire = function () {
if (self.canFire()) {
self.fireTimer = self.fireRate;
return true;
}
return false;
};
return self;
});
var SmallUFO = Container.expand(function () {
var self = Container.call(this);
var smallUfoGraphics = self.attachAsset('ufo', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
self.speed = 3;
self.direction = Math.random() < 0.5 ? -1 : 1;
self.fireTimer = 0;
self.fireRate = 120;
self.update = function () {
self.x += self.speed * self.direction;
if (self.x > 1900 || self.x < 148) {
self.direction *= -1;
}
self.fireTimer++;
if (self.fireTimer >= self.fireRate) {
self.fireTimer = 0;
return true;
}
return false;
};
return self;
});
var Spaceship = Container.expand(function () {
var self = Container.call(this);
var spaceshipGraphics = self.attachAsset('spaceship', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = 1;
self.deployTimer = 0;
self.deployRate = 180;
self.movePattern = Math.random() < 0.5 ? 'horizontal' : 'diagonal';
self.update = function () {
if (self.movePattern === 'horizontal') {
self.x += self.speed * self.direction;
if (self.x > 1900 || self.x < 148) {
self.direction *= -1;
}
} else {
self.x += self.speed * self.direction;
self.y += self.speed * 0.5;
if (self.x > 1900 || self.x < 148) {
self.direction *= -1;
}
}
self.deployTimer++;
if (self.deployTimer >= self.deployRate) {
self.deployTimer = 0;
return true;
}
return false;
};
return self;
});
var UFO = Container.expand(function () {
var self = Container.call(this);
var ufoGraphics = self.attachAsset('ufo', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = 1;
self.verticalSpeed = 0.5;
self.fireTimer = 0;
self.fireRate = 80;
self.isMoving = false;
self.hitCount = 0;
self.maxHits = 30;
self.level = 1;
self.startMovement = function () {
if (!self.isMoving) {
self.isMoving = true;
self.moveLeftRight();
}
};
self.moveLeftRight = function () {
var targetX = self.direction > 0 ? 1600 : 448;
tween(self, {
x: targetX
}, {
duration: 4000,
easing: tween.linear,
onFinish: function onFinish() {
self.direction *= -1;
self.moveLeftRight();
}
});
};
self.update = function () {
if (!self.isMoving) {
self.startMovement();
}
self.fireTimer++;
if (self.fireTimer >= self.fireRate) {
self.fireTimer = 0;
return 'fire';
}
// Deploy spaceship every 240 frames (4 seconds)
if (self.fireTimer % 240 === 0) {
return 'deploy';
}
return false;
};
self.hit = function () {
self.hitCount++;
if (self.hitCount >= self.maxHits) {
// UFO dies after 21 hits
return 'destroy';
}
return false; // UFO not dead yet
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(background);
var player = new PlayerTank();
player.x = 1024;
player.y = 2450;
game.addChild(player);
var playerBullets = [];
var spaceships = [];
var ufos = [];
var smallUfos = [];
var enemyBullets = [];
var spawnTimer = 0;
var spawnRate = 120;
var ufoSpawnTimer = 0;
var ufoSpawnRate = 600;
var hasActiveUFO = false;
var enemyFireTimer = 0;
var enemyFireRate = 90;
var currentLevel = 1;
var maxLevel = 10;
var enemiesKilledThisLevel = 0;
var enemiesToKillForNextLevel = 1;
var playerLives = 3;
var maxLives = 3;
var lastScoreMilestone = 0;
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFF00
});
levelTxt.anchor.set(0.5, 0);
levelTxt.x = 0;
levelTxt.y = 80;
LK.gui.top.addChild(levelTxt);
var lifeHearts = [];
for (var lifeIndex = 0; lifeIndex < maxLives; lifeIndex++) {
var lifeIcon = LK.getAsset('playerTank', {
anchorX: 0,
anchorY: 1,
scaleX: 0.2,
scaleY: 0.2
});
lifeIcon.x = 120 + lifeIndex * 80;
lifeIcon.y = -20;
lifeHearts.push(lifeIcon);
LK.gui.bottomLeft.addChild(lifeIcon);
}
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
}
function updateLevel() {
levelTxt.setText('Level: ' + currentLevel);
}
function updateLives() {
for (var i = 0; i < maxLives; i++) {
if (i < playerLives) {
lifeHearts[i].alpha = 1.0;
} else {
lifeHearts[i].alpha = 0.3;
}
}
}
function checkLevelProgression() {
var shouldLevelUp = false;
// Check if we should level up based on UFO kills only
if (enemiesKilledThisLevel >= enemiesToKillForNextLevel) {
if (currentLevel < maxLevel) {
shouldLevelUp = true;
currentLevel++;
enemiesKilledThisLevel = 0;
enemiesToKillForNextLevel = 1; // Only need 1 UFO kill to advance
}
}
if (shouldLevelUp) {
if (currentLevel >= maxLevel) {
// Player completed all levels
LK.showYouWin();
} else {
updateLevel();
// Increase difficulty based on level
spawnRate = Math.max(30, 120 - (currentLevel - 1) * 10);
enemyFireRate = Math.max(20, 90 - (currentLevel - 1) * 8);
// Flash screen to indicate level up
LK.effects.flashScreen(0x00ffff, 1000); // Cyan flash for level up
}
}
}
function spawnSpaceship() {
var spaceship = new Spaceship();
// If there's an active UFO, spawn from its position
if (hasActiveUFO && ufos.length > 0) {
spaceship.x = ufos[0].x;
spaceship.y = ufos[0].y + 100; // Spawn slightly below UFO
} else {
spaceship.x = Math.random() * 1800 + 124;
spaceship.y = -50;
}
spaceships.push(spaceship);
game.addChild(spaceship);
}
function spawnUFO() {
if (!hasActiveUFO && ufos.length === 0) {
var ufo = new UFO();
ufo.x = 1024;
ufo.y = 200;
// Make subsequent UFOs stronger
if (currentLevel > 1) {
ufo.level = Math.min(currentLevel, 5);
ufo.fireRate = Math.max(20, 80 - (ufo.level - 1) * 15);
var newScale = 1 + (ufo.level - 1) * 0.2;
ufo.scaleX = newScale;
ufo.scaleY = newScale;
}
ufos.push(ufo);
game.addChild(ufo);
hasActiveUFO = true;
}
}
function deploySmallUFO(fromX, fromY) {
var smallUfo = new SmallUFO();
smallUfo.x = fromX;
smallUfo.y = fromY;
smallUfos.push(smallUfo);
game.addChild(smallUfo);
LK.getSound('uavDeploy').play();
}
function clearAllEnemiesAndStartNewLevel() {
// Destroy all spaceships
for (var i = spaceships.length - 1; i >= 0; i--) {
spaceships[i].destroy();
}
spaceships = [];
// Destroy all small UFOs
for (var j = smallUfos.length - 1; j >= 0; j--) {
smallUfos[j].destroy();
}
smallUfos = [];
// Destroy all UFOs
for (var k = ufos.length - 1; k >= 0; k--) {
ufos[k].destroy();
}
ufos = [];
hasActiveUFO = false;
// Destroy all enemy bullets
for (var l = enemyBullets.length - 1; l >= 0; l--) {
enemyBullets[l].destroy();
}
enemyBullets = [];
// Don't automatically advance level - let normal progression handle it
// Just check if we should advance based on current kills
checkLevelProgression();
}
function fireEnemyBullet(fromX, fromY) {
var bullet = new EnemyBullet();
bullet.x = fromX;
bullet.y = fromY;
bullet.setVelocity(0, 6);
enemyBullets.push(bullet);
game.addChild(bullet);
}
game.down = function (x, y, obj) {
// Move player to touch position
player.x = x;
// Keep player within screen boundaries
if (player.x > 1988) {
player.x = 1988;
}
if (player.x < 60) {
player.x = 60;
}
// Shooting now handled by up event for better control
};
game.move = function (x, y, obj) {
// Move player horizontally based on touch/mouse position
player.x = x;
// Keep player within screen boundaries
if (player.x > 1988) {
player.x = 1988;
}
if (player.x < 60) {
player.x = 60;
}
};
game.up = function (x, y, obj) {
// Fire bullet when releasing touch/click
if (player.fire()) {
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y - 40;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('playerShoot').play();
}
};
game.update = function () {
// Check for score milestones to award extra lives
var currentScore = LK.getScore();
var currentMilestone2500 = Math.floor(currentScore / 2500);
var currentMilestone5000 = Math.floor(currentScore / 5000);
if (currentMilestone2500 > lastScoreMilestone) {
// Award extra life for reaching 2500 point milestone
if (playerLives < maxLives) {
playerLives++;
updateLives();
LK.effects.flashScreen(0x00ff00, 1000); // Green flash for life reward
}
lastScoreMilestone = currentMilestone2500;
}
// Check for 5000 point milestones
if (currentMilestone5000 > 0 && currentScore >= currentMilestone5000 * 5000 && currentScore - 5000 < (currentMilestone5000 - 1) * 5000) {
// Award extra life for reaching 5000 point milestone
if (playerLives < maxLives) {
playerLives++;
updateLives();
LK.effects.flashScreen(0x00ff00, 1000); // Green flash for life reward
}
}
// Player movement is now handled by touch/mouse controls
// Spawn spaceships
spawnTimer++;
if (spawnTimer >= spawnRate) {
spawnTimer = 0;
spawnSpaceship();
}
// Spawn UFOs
ufoSpawnTimer++;
if (ufoSpawnTimer >= ufoSpawnRate && !hasActiveUFO) {
ufoSpawnTimer = 0;
spawnUFO();
}
// Difficulty is now controlled by level progression
// Player auto-fire removed - now controlled by touch
// Enemy firing
enemyFireTimer++;
if (enemyFireTimer >= enemyFireRate) {
enemyFireTimer = 0;
if (spaceships.length > 0) {
var randomSpaceship = spaceships[Math.floor(Math.random() * spaceships.length)];
fireEnemyBullet(randomSpaceship.x, randomSpaceship.y);
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
if (bullet.lastY >= -20 && bullet.y < -20) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
bullet.lastY = bullet.y;
}
// Update spaceships
for (var j = spaceships.length - 1; j >= 0; j--) {
var spaceship = spaceships[j];
if (spaceship.lastY === undefined) spaceship.lastY = spaceship.y;
if (spaceship.deployCount === undefined) spaceship.deployCount = 0;
var shouldDeploy = spaceship.update();
if (shouldDeploy) {
deploySmallUFO(spaceship.x, spaceship.y);
}
if (spaceship.lastY < 2732 && spaceship.y >= 2732) {
playerLives--;
updateLives();
spaceship.destroy();
spaceships.splice(j, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
continue;
}
spaceship.lastY = spaceship.y;
}
// Update small UFOs
for (var su = smallUfos.length - 1; su >= 0; su--) {
var smallUfo = smallUfos[su];
if (smallUfo.lastY === undefined) smallUfo.lastY = smallUfo.y;
var shouldFire = smallUfo.update();
if (shouldFire) {
fireEnemyBullet(smallUfo.x, smallUfo.y);
}
if (smallUfo.lastY < 2732 && smallUfo.y >= 2732) {
playerLives--;
updateLives();
smallUfo.destroy();
smallUfos.splice(su, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
continue;
}
smallUfo.lastY = smallUfo.y;
}
// Update UFOs - only one UFO at a time
if (ufos.length > 0) {
var ufo = ufos[0];
if (ufo.lastY === undefined) ufo.lastY = ufo.y;
var action = ufo.update();
if (action === 'fire') {
fireEnemyBullet(ufo.x, ufo.y);
} else if (action === 'deploy') {
spawnSpaceship();
}
if (ufo.lastY < 2732 && ufo.y >= 2732) {
playerLives--;
updateLives();
ufo.destroy();
ufos.splice(0, 1);
hasActiveUFO = false;
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
}
ufo.lastY = ufo.y;
}
// Update enemy bullets
for (var l = enemyBullets.length - 1; l >= 0; l--) {
var enemyBullet = enemyBullets[l];
if (enemyBullet.lastY === undefined) enemyBullet.lastY = enemyBullet.y;
if (enemyBullet.lastX === undefined) enemyBullet.lastX = enemyBullet.x;
// Destroy bullet if it goes off-screen (top)
if (enemyBullet.lastY >= -20 && enemyBullet.y < -20) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
// Destroy bullet if it goes off-screen (bottom)
if (enemyBullet.lastY < 2732 && enemyBullet.y >= 2732) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
// Destroy bullet if it goes off-screen (left side)
if (enemyBullet.lastX >= 0 && enemyBullet.x < 0) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
// Destroy bullet if it goes off-screen (right side)
if (enemyBullet.lastX <= 2048 && enemyBullet.x > 2048) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
enemyBullet.lastY = enemyBullet.y;
enemyBullet.lastX = enemyBullet.x;
}
// Collision detection - Player bullets vs Spaceships
for (var m = playerBullets.length - 1; m >= 0; m--) {
var pBullet = playerBullets[m];
for (var n = spaceships.length - 1; n >= 0; n--) {
var ship = spaceships[n];
if (pBullet.intersects(ship)) {
LK.setScore(LK.getScore() + 100);
updateScore();
LK.getSound('enemyDestroy').play();
// Spawn 3 enemy bullets when spaceship explodes
for (var explosionBullet = 0; explosionBullet < 3; explosionBullet++) {
var bullet = new EnemyBullet();
bullet.x = ship.x;
bullet.y = ship.y;
// Spread bullets in different directions
var angle = (explosionBullet * 60 - 60) * Math.PI / 180; // -60, 0, 60 degrees
var bulletSpeed = 4;
bullet.setVelocity(Math.sin(angle) * bulletSpeed, Math.cos(angle) * bulletSpeed);
enemyBullets.push(bullet);
game.addChild(bullet);
}
// Create explosion effect
tween(ship, {
scaleX: 2,
scaleY: 2,
alpha: 0,
tint: 0xff4400
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
ship.destroy();
}
});
pBullet.destroy();
playerBullets.splice(m, 1);
spaceships.splice(n, 1);
break;
}
}
}
// Collision detection - Player bullets vs Small UFOs
for (var su2 = playerBullets.length - 1; su2 >= 0; su2--) {
var pBullet4 = playerBullets[su2];
for (var su3 = smallUfos.length - 1; su3 >= 0; su3--) {
var smallUfo2 = smallUfos[su3];
if (pBullet4.intersects(smallUfo2)) {
LK.setScore(LK.getScore() + 75);
updateScore();
LK.getSound('enemyDestroy').play();
// Create explosion effect
tween(smallUfo2, {
scaleX: 0.6,
scaleY: 0.6,
alpha: 0,
tint: 0xff4400
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
smallUfo2.destroy();
}
});
pBullet4.destroy();
playerBullets.splice(su2, 1);
smallUfos.splice(su3, 1);
break;
}
}
}
// Collision detection - Player bullets vs UFOs - single UFO
for (var t = playerBullets.length - 1; t >= 0; t--) {
var pBullet3 = playerBullets[t];
if (ufos.length > 0) {
var ufo2 = ufos[0];
if (pBullet3.intersects(ufo2)) {
var hitResult = ufo2.hit();
if (hitResult === 'destroy') {
// UFO dies - give big score and level up
LK.setScore(LK.getScore() + 1000);
updateScore();
enemiesKilledThisLevel++;
checkLevelProgression();
LK.getSound('enemyDestroy').play();
// Create explosion effect
tween(ufo2, {
scaleX: 3,
scaleY: 3,
alpha: 0,
tint: 0xff4400
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
ufo2.destroy();
clearAllEnemiesAndStartNewLevel();
}
});
ufos.splice(0, 1);
hasActiveUFO = false;
} else {
LK.setScore(LK.getScore() + 10);
updateScore();
LK.getSound('enemyDestroy').play();
}
// Create hit effect
tween(ufo2, {
tint: 0xff0066
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
ufo2.tint = 0xffffff;
}
});
pBullet3.destroy();
playerBullets.splice(t, 1);
break;
}
}
}
// Collision detection - Enemy bullets vs Player
for (var q = enemyBullets.length - 1; q >= 0; q--) {
var eBullet = enemyBullets[q];
if (eBullet.intersects(player)) {
playerLives--;
updateLives();
eBullet.destroy();
enemyBullets.splice(q, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
break;
}
}
// Collision detection - Spaceships vs Player
for (var s = spaceships.length - 1; s >= 0; s--) {
var ship2 = spaceships[s];
if (ship2.intersects(player)) {
playerLives--;
updateLives();
ship2.destroy();
spaceships.splice(s, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
break;
}
}
// Collision detection - Small UFOs vs Player
for (var su4 = smallUfos.length - 1; su4 >= 0; su4--) {
var smallUfo3 = smallUfos[su4];
if (smallUfo3.intersects(player)) {
playerLives--;
updateLives();
smallUfo3.destroy();
smallUfos.splice(su4, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
break;
}
}
// Collision detection - Player bullets vs Enemy bullets
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var playerBullet = playerBullets[pb];
for (var eb = enemyBullets.length - 1; eb >= 0; eb--) {
var enemyBullet = enemyBullets[eb];
if (playerBullet.intersects(enemyBullet)) {
// Destroy both bullets
playerBullet.destroy();
enemyBullet.destroy();
playerBullets.splice(pb, 1);
enemyBullets.splice(eb, 1);
break;
}
}
}
// Collision detection - UFOs vs Player - single UFO
if (ufos.length > 0) {
var ufo3 = ufos[0];
if (ufo3.intersects(player)) {
playerLives--;
updateLives();
ufo3.destroy();
ufos.splice(0, 1);
hasActiveUFO = false;
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
}
}
};
LK.playMusic('battleMusic'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.velocityX = 0;
self.velocityY = 0;
self.setVelocity = function (vx, vy) {
self.velocityX = vx;
self.velocityY = vy;
};
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.speed = 12;
self.update = function () {
self.y -= self.speed;
};
return self;
});
var PlayerTank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('playerTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.fireRate = 15;
self.fireTimer = 0;
self.update = function () {
if (self.fireTimer > 0) {
self.fireTimer--;
}
};
self.canFire = function () {
return self.fireTimer <= 0;
};
self.fire = function () {
if (self.canFire()) {
self.fireTimer = self.fireRate;
return true;
}
return false;
};
return self;
});
var SmallUFO = Container.expand(function () {
var self = Container.call(this);
var smallUfoGraphics = self.attachAsset('ufo', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
self.speed = 3;
self.direction = Math.random() < 0.5 ? -1 : 1;
self.fireTimer = 0;
self.fireRate = 120;
self.update = function () {
self.x += self.speed * self.direction;
if (self.x > 1900 || self.x < 148) {
self.direction *= -1;
}
self.fireTimer++;
if (self.fireTimer >= self.fireRate) {
self.fireTimer = 0;
return true;
}
return false;
};
return self;
});
var Spaceship = Container.expand(function () {
var self = Container.call(this);
var spaceshipGraphics = self.attachAsset('spaceship', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = 1;
self.deployTimer = 0;
self.deployRate = 180;
self.movePattern = Math.random() < 0.5 ? 'horizontal' : 'diagonal';
self.update = function () {
if (self.movePattern === 'horizontal') {
self.x += self.speed * self.direction;
if (self.x > 1900 || self.x < 148) {
self.direction *= -1;
}
} else {
self.x += self.speed * self.direction;
self.y += self.speed * 0.5;
if (self.x > 1900 || self.x < 148) {
self.direction *= -1;
}
}
self.deployTimer++;
if (self.deployTimer >= self.deployRate) {
self.deployTimer = 0;
return true;
}
return false;
};
return self;
});
var UFO = Container.expand(function () {
var self = Container.call(this);
var ufoGraphics = self.attachAsset('ufo', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = 1;
self.verticalSpeed = 0.5;
self.fireTimer = 0;
self.fireRate = 80;
self.isMoving = false;
self.hitCount = 0;
self.maxHits = 30;
self.level = 1;
self.startMovement = function () {
if (!self.isMoving) {
self.isMoving = true;
self.moveLeftRight();
}
};
self.moveLeftRight = function () {
var targetX = self.direction > 0 ? 1600 : 448;
tween(self, {
x: targetX
}, {
duration: 4000,
easing: tween.linear,
onFinish: function onFinish() {
self.direction *= -1;
self.moveLeftRight();
}
});
};
self.update = function () {
if (!self.isMoving) {
self.startMovement();
}
self.fireTimer++;
if (self.fireTimer >= self.fireRate) {
self.fireTimer = 0;
return 'fire';
}
// Deploy spaceship every 240 frames (4 seconds)
if (self.fireTimer % 240 === 0) {
return 'deploy';
}
return false;
};
self.hit = function () {
self.hitCount++;
if (self.hitCount >= self.maxHits) {
// UFO dies after 21 hits
return 'destroy';
}
return false; // UFO not dead yet
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(background);
var player = new PlayerTank();
player.x = 1024;
player.y = 2450;
game.addChild(player);
var playerBullets = [];
var spaceships = [];
var ufos = [];
var smallUfos = [];
var enemyBullets = [];
var spawnTimer = 0;
var spawnRate = 120;
var ufoSpawnTimer = 0;
var ufoSpawnRate = 600;
var hasActiveUFO = false;
var enemyFireTimer = 0;
var enemyFireRate = 90;
var currentLevel = 1;
var maxLevel = 10;
var enemiesKilledThisLevel = 0;
var enemiesToKillForNextLevel = 1;
var playerLives = 3;
var maxLives = 3;
var lastScoreMilestone = 0;
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFF00
});
levelTxt.anchor.set(0.5, 0);
levelTxt.x = 0;
levelTxt.y = 80;
LK.gui.top.addChild(levelTxt);
var lifeHearts = [];
for (var lifeIndex = 0; lifeIndex < maxLives; lifeIndex++) {
var lifeIcon = LK.getAsset('playerTank', {
anchorX: 0,
anchorY: 1,
scaleX: 0.2,
scaleY: 0.2
});
lifeIcon.x = 120 + lifeIndex * 80;
lifeIcon.y = -20;
lifeHearts.push(lifeIcon);
LK.gui.bottomLeft.addChild(lifeIcon);
}
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
}
function updateLevel() {
levelTxt.setText('Level: ' + currentLevel);
}
function updateLives() {
for (var i = 0; i < maxLives; i++) {
if (i < playerLives) {
lifeHearts[i].alpha = 1.0;
} else {
lifeHearts[i].alpha = 0.3;
}
}
}
function checkLevelProgression() {
var shouldLevelUp = false;
// Check if we should level up based on UFO kills only
if (enemiesKilledThisLevel >= enemiesToKillForNextLevel) {
if (currentLevel < maxLevel) {
shouldLevelUp = true;
currentLevel++;
enemiesKilledThisLevel = 0;
enemiesToKillForNextLevel = 1; // Only need 1 UFO kill to advance
}
}
if (shouldLevelUp) {
if (currentLevel >= maxLevel) {
// Player completed all levels
LK.showYouWin();
} else {
updateLevel();
// Increase difficulty based on level
spawnRate = Math.max(30, 120 - (currentLevel - 1) * 10);
enemyFireRate = Math.max(20, 90 - (currentLevel - 1) * 8);
// Flash screen to indicate level up
LK.effects.flashScreen(0x00ffff, 1000); // Cyan flash for level up
}
}
}
function spawnSpaceship() {
var spaceship = new Spaceship();
// If there's an active UFO, spawn from its position
if (hasActiveUFO && ufos.length > 0) {
spaceship.x = ufos[0].x;
spaceship.y = ufos[0].y + 100; // Spawn slightly below UFO
} else {
spaceship.x = Math.random() * 1800 + 124;
spaceship.y = -50;
}
spaceships.push(spaceship);
game.addChild(spaceship);
}
function spawnUFO() {
if (!hasActiveUFO && ufos.length === 0) {
var ufo = new UFO();
ufo.x = 1024;
ufo.y = 200;
// Make subsequent UFOs stronger
if (currentLevel > 1) {
ufo.level = Math.min(currentLevel, 5);
ufo.fireRate = Math.max(20, 80 - (ufo.level - 1) * 15);
var newScale = 1 + (ufo.level - 1) * 0.2;
ufo.scaleX = newScale;
ufo.scaleY = newScale;
}
ufos.push(ufo);
game.addChild(ufo);
hasActiveUFO = true;
}
}
function deploySmallUFO(fromX, fromY) {
var smallUfo = new SmallUFO();
smallUfo.x = fromX;
smallUfo.y = fromY;
smallUfos.push(smallUfo);
game.addChild(smallUfo);
LK.getSound('uavDeploy').play();
}
function clearAllEnemiesAndStartNewLevel() {
// Destroy all spaceships
for (var i = spaceships.length - 1; i >= 0; i--) {
spaceships[i].destroy();
}
spaceships = [];
// Destroy all small UFOs
for (var j = smallUfos.length - 1; j >= 0; j--) {
smallUfos[j].destroy();
}
smallUfos = [];
// Destroy all UFOs
for (var k = ufos.length - 1; k >= 0; k--) {
ufos[k].destroy();
}
ufos = [];
hasActiveUFO = false;
// Destroy all enemy bullets
for (var l = enemyBullets.length - 1; l >= 0; l--) {
enemyBullets[l].destroy();
}
enemyBullets = [];
// Don't automatically advance level - let normal progression handle it
// Just check if we should advance based on current kills
checkLevelProgression();
}
function fireEnemyBullet(fromX, fromY) {
var bullet = new EnemyBullet();
bullet.x = fromX;
bullet.y = fromY;
bullet.setVelocity(0, 6);
enemyBullets.push(bullet);
game.addChild(bullet);
}
game.down = function (x, y, obj) {
// Move player to touch position
player.x = x;
// Keep player within screen boundaries
if (player.x > 1988) {
player.x = 1988;
}
if (player.x < 60) {
player.x = 60;
}
// Shooting now handled by up event for better control
};
game.move = function (x, y, obj) {
// Move player horizontally based on touch/mouse position
player.x = x;
// Keep player within screen boundaries
if (player.x > 1988) {
player.x = 1988;
}
if (player.x < 60) {
player.x = 60;
}
};
game.up = function (x, y, obj) {
// Fire bullet when releasing touch/click
if (player.fire()) {
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y - 40;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('playerShoot').play();
}
};
game.update = function () {
// Check for score milestones to award extra lives
var currentScore = LK.getScore();
var currentMilestone2500 = Math.floor(currentScore / 2500);
var currentMilestone5000 = Math.floor(currentScore / 5000);
if (currentMilestone2500 > lastScoreMilestone) {
// Award extra life for reaching 2500 point milestone
if (playerLives < maxLives) {
playerLives++;
updateLives();
LK.effects.flashScreen(0x00ff00, 1000); // Green flash for life reward
}
lastScoreMilestone = currentMilestone2500;
}
// Check for 5000 point milestones
if (currentMilestone5000 > 0 && currentScore >= currentMilestone5000 * 5000 && currentScore - 5000 < (currentMilestone5000 - 1) * 5000) {
// Award extra life for reaching 5000 point milestone
if (playerLives < maxLives) {
playerLives++;
updateLives();
LK.effects.flashScreen(0x00ff00, 1000); // Green flash for life reward
}
}
// Player movement is now handled by touch/mouse controls
// Spawn spaceships
spawnTimer++;
if (spawnTimer >= spawnRate) {
spawnTimer = 0;
spawnSpaceship();
}
// Spawn UFOs
ufoSpawnTimer++;
if (ufoSpawnTimer >= ufoSpawnRate && !hasActiveUFO) {
ufoSpawnTimer = 0;
spawnUFO();
}
// Difficulty is now controlled by level progression
// Player auto-fire removed - now controlled by touch
// Enemy firing
enemyFireTimer++;
if (enemyFireTimer >= enemyFireRate) {
enemyFireTimer = 0;
if (spaceships.length > 0) {
var randomSpaceship = spaceships[Math.floor(Math.random() * spaceships.length)];
fireEnemyBullet(randomSpaceship.x, randomSpaceship.y);
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
if (bullet.lastY >= -20 && bullet.y < -20) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
bullet.lastY = bullet.y;
}
// Update spaceships
for (var j = spaceships.length - 1; j >= 0; j--) {
var spaceship = spaceships[j];
if (spaceship.lastY === undefined) spaceship.lastY = spaceship.y;
if (spaceship.deployCount === undefined) spaceship.deployCount = 0;
var shouldDeploy = spaceship.update();
if (shouldDeploy) {
deploySmallUFO(spaceship.x, spaceship.y);
}
if (spaceship.lastY < 2732 && spaceship.y >= 2732) {
playerLives--;
updateLives();
spaceship.destroy();
spaceships.splice(j, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
continue;
}
spaceship.lastY = spaceship.y;
}
// Update small UFOs
for (var su = smallUfos.length - 1; su >= 0; su--) {
var smallUfo = smallUfos[su];
if (smallUfo.lastY === undefined) smallUfo.lastY = smallUfo.y;
var shouldFire = smallUfo.update();
if (shouldFire) {
fireEnemyBullet(smallUfo.x, smallUfo.y);
}
if (smallUfo.lastY < 2732 && smallUfo.y >= 2732) {
playerLives--;
updateLives();
smallUfo.destroy();
smallUfos.splice(su, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
continue;
}
smallUfo.lastY = smallUfo.y;
}
// Update UFOs - only one UFO at a time
if (ufos.length > 0) {
var ufo = ufos[0];
if (ufo.lastY === undefined) ufo.lastY = ufo.y;
var action = ufo.update();
if (action === 'fire') {
fireEnemyBullet(ufo.x, ufo.y);
} else if (action === 'deploy') {
spawnSpaceship();
}
if (ufo.lastY < 2732 && ufo.y >= 2732) {
playerLives--;
updateLives();
ufo.destroy();
ufos.splice(0, 1);
hasActiveUFO = false;
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
}
ufo.lastY = ufo.y;
}
// Update enemy bullets
for (var l = enemyBullets.length - 1; l >= 0; l--) {
var enemyBullet = enemyBullets[l];
if (enemyBullet.lastY === undefined) enemyBullet.lastY = enemyBullet.y;
if (enemyBullet.lastX === undefined) enemyBullet.lastX = enemyBullet.x;
// Destroy bullet if it goes off-screen (top)
if (enemyBullet.lastY >= -20 && enemyBullet.y < -20) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
// Destroy bullet if it goes off-screen (bottom)
if (enemyBullet.lastY < 2732 && enemyBullet.y >= 2732) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
// Destroy bullet if it goes off-screen (left side)
if (enemyBullet.lastX >= 0 && enemyBullet.x < 0) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
// Destroy bullet if it goes off-screen (right side)
if (enemyBullet.lastX <= 2048 && enemyBullet.x > 2048) {
enemyBullet.destroy();
enemyBullets.splice(l, 1);
continue;
}
enemyBullet.lastY = enemyBullet.y;
enemyBullet.lastX = enemyBullet.x;
}
// Collision detection - Player bullets vs Spaceships
for (var m = playerBullets.length - 1; m >= 0; m--) {
var pBullet = playerBullets[m];
for (var n = spaceships.length - 1; n >= 0; n--) {
var ship = spaceships[n];
if (pBullet.intersects(ship)) {
LK.setScore(LK.getScore() + 100);
updateScore();
LK.getSound('enemyDestroy').play();
// Spawn 3 enemy bullets when spaceship explodes
for (var explosionBullet = 0; explosionBullet < 3; explosionBullet++) {
var bullet = new EnemyBullet();
bullet.x = ship.x;
bullet.y = ship.y;
// Spread bullets in different directions
var angle = (explosionBullet * 60 - 60) * Math.PI / 180; // -60, 0, 60 degrees
var bulletSpeed = 4;
bullet.setVelocity(Math.sin(angle) * bulletSpeed, Math.cos(angle) * bulletSpeed);
enemyBullets.push(bullet);
game.addChild(bullet);
}
// Create explosion effect
tween(ship, {
scaleX: 2,
scaleY: 2,
alpha: 0,
tint: 0xff4400
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
ship.destroy();
}
});
pBullet.destroy();
playerBullets.splice(m, 1);
spaceships.splice(n, 1);
break;
}
}
}
// Collision detection - Player bullets vs Small UFOs
for (var su2 = playerBullets.length - 1; su2 >= 0; su2--) {
var pBullet4 = playerBullets[su2];
for (var su3 = smallUfos.length - 1; su3 >= 0; su3--) {
var smallUfo2 = smallUfos[su3];
if (pBullet4.intersects(smallUfo2)) {
LK.setScore(LK.getScore() + 75);
updateScore();
LK.getSound('enemyDestroy').play();
// Create explosion effect
tween(smallUfo2, {
scaleX: 0.6,
scaleY: 0.6,
alpha: 0,
tint: 0xff4400
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
smallUfo2.destroy();
}
});
pBullet4.destroy();
playerBullets.splice(su2, 1);
smallUfos.splice(su3, 1);
break;
}
}
}
// Collision detection - Player bullets vs UFOs - single UFO
for (var t = playerBullets.length - 1; t >= 0; t--) {
var pBullet3 = playerBullets[t];
if (ufos.length > 0) {
var ufo2 = ufos[0];
if (pBullet3.intersects(ufo2)) {
var hitResult = ufo2.hit();
if (hitResult === 'destroy') {
// UFO dies - give big score and level up
LK.setScore(LK.getScore() + 1000);
updateScore();
enemiesKilledThisLevel++;
checkLevelProgression();
LK.getSound('enemyDestroy').play();
// Create explosion effect
tween(ufo2, {
scaleX: 3,
scaleY: 3,
alpha: 0,
tint: 0xff4400
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
ufo2.destroy();
clearAllEnemiesAndStartNewLevel();
}
});
ufos.splice(0, 1);
hasActiveUFO = false;
} else {
LK.setScore(LK.getScore() + 10);
updateScore();
LK.getSound('enemyDestroy').play();
}
// Create hit effect
tween(ufo2, {
tint: 0xff0066
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
ufo2.tint = 0xffffff;
}
});
pBullet3.destroy();
playerBullets.splice(t, 1);
break;
}
}
}
// Collision detection - Enemy bullets vs Player
for (var q = enemyBullets.length - 1; q >= 0; q--) {
var eBullet = enemyBullets[q];
if (eBullet.intersects(player)) {
playerLives--;
updateLives();
eBullet.destroy();
enemyBullets.splice(q, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
break;
}
}
// Collision detection - Spaceships vs Player
for (var s = spaceships.length - 1; s >= 0; s--) {
var ship2 = spaceships[s];
if (ship2.intersects(player)) {
playerLives--;
updateLives();
ship2.destroy();
spaceships.splice(s, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
break;
}
}
// Collision detection - Small UFOs vs Player
for (var su4 = smallUfos.length - 1; su4 >= 0; su4--) {
var smallUfo3 = smallUfos[su4];
if (smallUfo3.intersects(player)) {
playerLives--;
updateLives();
smallUfo3.destroy();
smallUfos.splice(su4, 1);
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
break;
}
}
// Collision detection - Player bullets vs Enemy bullets
for (var pb = playerBullets.length - 1; pb >= 0; pb--) {
var playerBullet = playerBullets[pb];
for (var eb = enemyBullets.length - 1; eb >= 0; eb--) {
var enemyBullet = enemyBullets[eb];
if (playerBullet.intersects(enemyBullet)) {
// Destroy both bullets
playerBullet.destroy();
enemyBullet.destroy();
playerBullets.splice(pb, 1);
enemyBullets.splice(eb, 1);
break;
}
}
}
// Collision detection - UFOs vs Player - single UFO
if (ufos.length > 0) {
var ufo3 = ufos[0];
if (ufo3.intersects(player)) {
playerLives--;
updateLives();
ufo3.destroy();
ufos.splice(0, 1);
hasActiveUFO = false;
LK.effects.flashScreen(0xff0000, 1000);
if (playerLives <= 0) {
LK.showGameOver();
return;
}
}
}
};
LK.playMusic('battleMusic');