User prompt
Let my plane move back and forth and I'll fire.
User prompt
Let the enemy bullets pass through the air
User prompt
UFOs explode when they die ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When enemy bullets do not hit me, they will be deleted from the screen.
User prompt
I'll shoot
User prompt
Let them shoot as I destroy
User prompt
If the enemy bullets do not hit me, let it be destroyed.
User prompt
Let the enemy move to the right and left above
Code edit (1 edits merged)
Please save this source code
User prompt
Sky Invasion Defense
Initial prompt
Let the spaceship and the UAVs coming out of it appear above and the war machine fire at the bottom.
/****
* 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');