/****
* 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 = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyPlane = Container.expand(function () {
var self = Container.call(this);
var planeGraphics = self.attachAsset('enemyPlane', {
anchorX: 0.5,
anchorY: 0.5
});
planeGraphics.rotation = Math.PI;
self.speed = 2;
self.lastShot = 0;
self.shotInterval = 120; // 2 seconds at 60fps
self.health = 1;
self.update = function () {
// Move down vertically
self.y += self.speed;
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.shotInterval) {
self.shoot();
self.lastShot = 0;
}
};
self.shoot = function () {
if (self.parent) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
bullet.lastY = bullet.y;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('enemyShoot').play();
}
};
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 PlayerPlane = Container.expand(function () {
var self = Container.call(this);
var planeGraphics = self.attachAsset('playerPlane', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.lastShot = 0;
self.shotCooldown = 10; // shots per second limit
self.shoot = function () {
if (self.lastShot <= 0) {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
bullet.lastY = bullet.y;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
self.lastShot = self.shotCooldown;
}
};
self.dropBomb = function () {
if (specialBombsAvailable > 0) {
// Find nearest enemy plane
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemyPlanes.length; i++) {
var enemy = enemyPlanes[i];
var dx = self.x - enemy.x;
var dy = self.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
// If we found an enemy, destroy it directly
if (nearestEnemy) {
// Award score for bomb kill
LK.setScore(LK.getScore() + 20);
scoreTxt.setText('Score: ' + LK.getScore());
// Track fighter jets hit
fighterJetsHit++;
if (fighterJetsHit >= 5) {
// Award special bomb every 5 hits
specialBombsAvailable++;
bombTxt.setText('Bombs: ' + specialBombsAvailable);
fighterJetsHit = 0; // Reset counter
}
// Destroy enemy with explosion
LK.effects.flashObject(nearestEnemy, 0xff0000, 300);
LK.getSound('explosion').play();
createExplosion(nearestEnemy);
// Remove from enemy planes array
for (var j = enemyPlanes.length - 1; j >= 0; j--) {
if (enemyPlanes[j] === nearestEnemy) {
enemyPlanes.splice(j, 1);
break;
}
}
// Create flash effect to show bomb was used
LK.effects.flashScreen(0xFFFF00, 300);
}
specialBombsAvailable--;
bombTxt.setText('Bombs: ' + specialBombsAvailable);
LK.getSound('shoot').play();
}
};
self.update = function () {
if (self.lastShot > 0) {
self.lastShot--;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var playerPlane;
var enemyPlanes = [];
var playerBullets = [];
var enemyBullets = [];
var specialBombs = [];
var enemySpawnTimer = 0;
var enemySpawnInterval = 180; // 3 seconds at 60fps
var difficultyTimer = 0;
var speedIncreaseTimer = 0;
var baseEnemySpeed = 2;
var dragNode = null;
var enemySpawnCount = 1; // Number of enemy planes to spawn at once
var enemyIncreaseTimer = 0;
var fighterJetsHit = 0; // Track number of fighter jets hit
var specialBombsAvailable = 0; // Track available special bombs
var lastTapTime = 0; // For double-tap detection
// Explosion effect function
function createExplosion(target) {
// Create explosion animation using tween
tween(target, {
scaleX: 2,
scaleY: 2,
alpha: 0,
rotation: target.rotation + Math.PI
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
target.destroy();
}
});
}
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create life bar display
var lifeTxt = new Text2('Lives: 3', {
size: 80,
fill: 0xFF0000
});
lifeTxt.anchor.set(0.5, 0);
lifeTxt.x = 0;
lifeTxt.y = 100;
LK.gui.top.addChild(lifeTxt);
// Create time bar display
var timeTxt = new Text2('Time: 0:00', {
size: 80,
fill: 0xFFFF00
});
timeTxt.anchor.set(0.5, 0);
timeTxt.x = 0;
timeTxt.y = 200;
LK.gui.top.addChild(timeTxt);
// Create special bomb display
var bombTxt = new Text2('Bombs: 0', {
size: 80,
fill: 0x00FF00
});
bombTxt.anchor.set(0.5, 0);
bombTxt.x = 0;
bombTxt.y = 300;
LK.gui.top.addChild(bombTxt);
// Create player plane
playerPlane = game.addChild(new PlayerPlane());
playerPlane.x = 1024;
playerPlane.y = 2400;
// Game event handlers
function handleMove(x, y, obj) {
if (dragNode) {
// Keep player plane within screen bounds
dragNode.x = Math.max(60, Math.min(1988, x));
dragNode.y = Math.max(40, Math.min(2692, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Start dragging player plane
dragNode = playerPlane;
handleMove(x, y, obj);
// Check for double-tap to drop bomb
var currentTime = LK.ticks;
if (currentTime - lastTapTime < 30) {
// 30 ticks = 0.5 seconds
// Double-tap detected - drop bomb
playerPlane.dropBomb();
} else {
// Single tap - shoot bullet
playerPlane.shoot();
}
lastTapTime = currentTime;
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Update timers
enemySpawnTimer++;
difficultyTimer++;
speedIncreaseTimer++;
// Update time display
var gameTimeSeconds = Math.floor(LK.ticks / 60);
var minutes = Math.floor(gameTimeSeconds / 60);
var seconds = gameTimeSeconds % 60;
var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timeTxt.setText('Time: ' + timeString);
// Increase difficulty over time
if (difficultyTimer % 1800 == 0) {
// Every 30 seconds
enemySpawnInterval = Math.max(60, enemySpawnInterval - 20);
}
// Increase enemy plane speed every 30 seconds
if (speedIncreaseTimer % 1800 == 0) {
// Every 30 seconds (1800 ticks at 60fps)
baseEnemySpeed += 0.5;
// Update speed for all existing enemy planes
for (var k = 0; k < enemyPlanes.length; k++) {
enemyPlanes[k].speed = baseEnemySpeed;
}
}
// Increase enemy spawn count every 45 seconds
enemyIncreaseTimer++;
if (enemyIncreaseTimer % 2700 == 0) {
// Every 45 seconds (2700 ticks at 60fps)
enemySpawnCount++;
}
// Spawn enemy planes
if (enemySpawnTimer >= enemySpawnInterval) {
// Spawn multiple enemy planes based on enemySpawnCount
for (var spawnIndex = 0; spawnIndex < enemySpawnCount; spawnIndex++) {
var enemy = new EnemyPlane();
enemy.x = Math.random() * 1800 + 124;
enemy.y = -100 - spawnIndex * 150; // Offset vertically to avoid overlap
enemy.speed = baseEnemySpeed;
enemy.lastY = enemy.y;
enemy.lastIntersecting = false;
enemyPlanes.push(enemy);
game.addChild(enemy);
}
enemySpawnTimer = 0;
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY >= -50 && bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemy planes
var hitEnemy = false;
for (var j = enemyPlanes.length - 1; j >= 0; j--) {
var enemy = enemyPlanes[j];
if (bullet.intersects(enemy)) {
// Hit enemy
LK.setScore(LK.getScore() + 10);
scoreTxt.setText('Score: ' + LK.getScore());
// Track fighter jets hit
fighterJetsHit++;
if (fighterJetsHit >= 5) {
// Award special bomb every 5 hits
specialBombsAvailable++;
bombTxt.setText('Bombs: ' + specialBombsAvailable);
fighterJetsHit = 0; // Reset counter
}
// Destroy enemy with explosion
LK.effects.flashObject(enemy, 0xff0000, 300);
LK.getSound('explosion').play();
createExplosion(enemy);
enemyPlanes.splice(j, 1);
// Destroy bullet
bullet.destroy();
playerBullets.splice(i, 1);
hitEnemy = true;
break;
}
}
if (!hitEnemy) {
bullet.lastY = bullet.y;
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY <= 2782 && bullet.y > 2782) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(playerPlane)) {
// Player hit - reduce life
playerPlane.health--;
lifeTxt.setText('Lives: ' + playerPlane.health);
// Flash player plane red
LK.effects.flashObject(playerPlane, 0xff0000, 500);
LK.getSound('explosion').play();
// Remove the bullet that hit the player
bullet.destroy();
enemyBullets.splice(i, 1);
// Check if player is dead
if (playerPlane.health <= 0) {
createExplosion(playerPlane);
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 300);
return;
}
continue;
}
bullet.lastY = bullet.y;
}
// Update enemy planes
for (var i = enemyPlanes.length - 1; i >= 0; i--) {
var enemy = enemyPlanes[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that go off screen
if (enemy.lastY <= 2782 && enemy.y > 2782) {
enemy.destroy();
enemyPlanes.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(playerPlane)) {
// Player hit by enemy plane - reduce life
playerPlane.health--;
lifeTxt.setText('Lives: ' + playerPlane.health);
// Flash player plane red
LK.effects.flashObject(playerPlane, 0xff0000, 500);
LK.getSound('explosion').play();
// Remove the enemy that hit the player
createExplosion(enemy);
enemyPlanes.splice(i, 1);
// Check if player is dead
if (playerPlane.health <= 0) {
createExplosion(playerPlane);
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 300);
return;
}
continue;
}
enemy.lastY = enemy.y;
}
// Victory condition - survive for high score
if (LK.getScore() >= 500) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('bgmusic'); /****
* 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 = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyPlane = Container.expand(function () {
var self = Container.call(this);
var planeGraphics = self.attachAsset('enemyPlane', {
anchorX: 0.5,
anchorY: 0.5
});
planeGraphics.rotation = Math.PI;
self.speed = 2;
self.lastShot = 0;
self.shotInterval = 120; // 2 seconds at 60fps
self.health = 1;
self.update = function () {
// Move down vertically
self.y += self.speed;
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.shotInterval) {
self.shoot();
self.lastShot = 0;
}
};
self.shoot = function () {
if (self.parent) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
bullet.lastY = bullet.y;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('enemyShoot').play();
}
};
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 PlayerPlane = Container.expand(function () {
var self = Container.call(this);
var planeGraphics = self.attachAsset('playerPlane', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.lastShot = 0;
self.shotCooldown = 10; // shots per second limit
self.shoot = function () {
if (self.lastShot <= 0) {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
bullet.lastY = bullet.y;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
self.lastShot = self.shotCooldown;
}
};
self.dropBomb = function () {
if (specialBombsAvailable > 0) {
// Find nearest enemy plane
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemyPlanes.length; i++) {
var enemy = enemyPlanes[i];
var dx = self.x - enemy.x;
var dy = self.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
// If we found an enemy, destroy it directly
if (nearestEnemy) {
// Award score for bomb kill
LK.setScore(LK.getScore() + 20);
scoreTxt.setText('Score: ' + LK.getScore());
// Track fighter jets hit
fighterJetsHit++;
if (fighterJetsHit >= 5) {
// Award special bomb every 5 hits
specialBombsAvailable++;
bombTxt.setText('Bombs: ' + specialBombsAvailable);
fighterJetsHit = 0; // Reset counter
}
// Destroy enemy with explosion
LK.effects.flashObject(nearestEnemy, 0xff0000, 300);
LK.getSound('explosion').play();
createExplosion(nearestEnemy);
// Remove from enemy planes array
for (var j = enemyPlanes.length - 1; j >= 0; j--) {
if (enemyPlanes[j] === nearestEnemy) {
enemyPlanes.splice(j, 1);
break;
}
}
// Create flash effect to show bomb was used
LK.effects.flashScreen(0xFFFF00, 300);
}
specialBombsAvailable--;
bombTxt.setText('Bombs: ' + specialBombsAvailable);
LK.getSound('shoot').play();
}
};
self.update = function () {
if (self.lastShot > 0) {
self.lastShot--;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var playerPlane;
var enemyPlanes = [];
var playerBullets = [];
var enemyBullets = [];
var specialBombs = [];
var enemySpawnTimer = 0;
var enemySpawnInterval = 180; // 3 seconds at 60fps
var difficultyTimer = 0;
var speedIncreaseTimer = 0;
var baseEnemySpeed = 2;
var dragNode = null;
var enemySpawnCount = 1; // Number of enemy planes to spawn at once
var enemyIncreaseTimer = 0;
var fighterJetsHit = 0; // Track number of fighter jets hit
var specialBombsAvailable = 0; // Track available special bombs
var lastTapTime = 0; // For double-tap detection
// Explosion effect function
function createExplosion(target) {
// Create explosion animation using tween
tween(target, {
scaleX: 2,
scaleY: 2,
alpha: 0,
rotation: target.rotation + Math.PI
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
target.destroy();
}
});
}
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create life bar display
var lifeTxt = new Text2('Lives: 3', {
size: 80,
fill: 0xFF0000
});
lifeTxt.anchor.set(0.5, 0);
lifeTxt.x = 0;
lifeTxt.y = 100;
LK.gui.top.addChild(lifeTxt);
// Create time bar display
var timeTxt = new Text2('Time: 0:00', {
size: 80,
fill: 0xFFFF00
});
timeTxt.anchor.set(0.5, 0);
timeTxt.x = 0;
timeTxt.y = 200;
LK.gui.top.addChild(timeTxt);
// Create special bomb display
var bombTxt = new Text2('Bombs: 0', {
size: 80,
fill: 0x00FF00
});
bombTxt.anchor.set(0.5, 0);
bombTxt.x = 0;
bombTxt.y = 300;
LK.gui.top.addChild(bombTxt);
// Create player plane
playerPlane = game.addChild(new PlayerPlane());
playerPlane.x = 1024;
playerPlane.y = 2400;
// Game event handlers
function handleMove(x, y, obj) {
if (dragNode) {
// Keep player plane within screen bounds
dragNode.x = Math.max(60, Math.min(1988, x));
dragNode.y = Math.max(40, Math.min(2692, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Start dragging player plane
dragNode = playerPlane;
handleMove(x, y, obj);
// Check for double-tap to drop bomb
var currentTime = LK.ticks;
if (currentTime - lastTapTime < 30) {
// 30 ticks = 0.5 seconds
// Double-tap detected - drop bomb
playerPlane.dropBomb();
} else {
// Single tap - shoot bullet
playerPlane.shoot();
}
lastTapTime = currentTime;
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Update timers
enemySpawnTimer++;
difficultyTimer++;
speedIncreaseTimer++;
// Update time display
var gameTimeSeconds = Math.floor(LK.ticks / 60);
var minutes = Math.floor(gameTimeSeconds / 60);
var seconds = gameTimeSeconds % 60;
var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timeTxt.setText('Time: ' + timeString);
// Increase difficulty over time
if (difficultyTimer % 1800 == 0) {
// Every 30 seconds
enemySpawnInterval = Math.max(60, enemySpawnInterval - 20);
}
// Increase enemy plane speed every 30 seconds
if (speedIncreaseTimer % 1800 == 0) {
// Every 30 seconds (1800 ticks at 60fps)
baseEnemySpeed += 0.5;
// Update speed for all existing enemy planes
for (var k = 0; k < enemyPlanes.length; k++) {
enemyPlanes[k].speed = baseEnemySpeed;
}
}
// Increase enemy spawn count every 45 seconds
enemyIncreaseTimer++;
if (enemyIncreaseTimer % 2700 == 0) {
// Every 45 seconds (2700 ticks at 60fps)
enemySpawnCount++;
}
// Spawn enemy planes
if (enemySpawnTimer >= enemySpawnInterval) {
// Spawn multiple enemy planes based on enemySpawnCount
for (var spawnIndex = 0; spawnIndex < enemySpawnCount; spawnIndex++) {
var enemy = new EnemyPlane();
enemy.x = Math.random() * 1800 + 124;
enemy.y = -100 - spawnIndex * 150; // Offset vertically to avoid overlap
enemy.speed = baseEnemySpeed;
enemy.lastY = enemy.y;
enemy.lastIntersecting = false;
enemyPlanes.push(enemy);
game.addChild(enemy);
}
enemySpawnTimer = 0;
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY >= -50 && bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemy planes
var hitEnemy = false;
for (var j = enemyPlanes.length - 1; j >= 0; j--) {
var enemy = enemyPlanes[j];
if (bullet.intersects(enemy)) {
// Hit enemy
LK.setScore(LK.getScore() + 10);
scoreTxt.setText('Score: ' + LK.getScore());
// Track fighter jets hit
fighterJetsHit++;
if (fighterJetsHit >= 5) {
// Award special bomb every 5 hits
specialBombsAvailable++;
bombTxt.setText('Bombs: ' + specialBombsAvailable);
fighterJetsHit = 0; // Reset counter
}
// Destroy enemy with explosion
LK.effects.flashObject(enemy, 0xff0000, 300);
LK.getSound('explosion').play();
createExplosion(enemy);
enemyPlanes.splice(j, 1);
// Destroy bullet
bullet.destroy();
playerBullets.splice(i, 1);
hitEnemy = true;
break;
}
}
if (!hitEnemy) {
bullet.lastY = bullet.y;
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY <= 2782 && bullet.y > 2782) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(playerPlane)) {
// Player hit - reduce life
playerPlane.health--;
lifeTxt.setText('Lives: ' + playerPlane.health);
// Flash player plane red
LK.effects.flashObject(playerPlane, 0xff0000, 500);
LK.getSound('explosion').play();
// Remove the bullet that hit the player
bullet.destroy();
enemyBullets.splice(i, 1);
// Check if player is dead
if (playerPlane.health <= 0) {
createExplosion(playerPlane);
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 300);
return;
}
continue;
}
bullet.lastY = bullet.y;
}
// Update enemy planes
for (var i = enemyPlanes.length - 1; i >= 0; i--) {
var enemy = enemyPlanes[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that go off screen
if (enemy.lastY <= 2782 && enemy.y > 2782) {
enemy.destroy();
enemyPlanes.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(playerPlane)) {
// Player hit by enemy plane - reduce life
playerPlane.health--;
lifeTxt.setText('Lives: ' + playerPlane.health);
// Flash player plane red
LK.effects.flashObject(playerPlane, 0xff0000, 500);
LK.getSound('explosion').play();
// Remove the enemy that hit the player
createExplosion(enemy);
enemyPlanes.splice(i, 1);
// Check if player is dead
if (playerPlane.health <= 0) {
createExplosion(playerPlane);
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 300);
return;
}
continue;
}
enemy.lastY = enemy.y;
}
// Victory condition - survive for high score
if (LK.getScore() >= 500) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('bgmusic');