/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Bomb now uses dark colored shape asset instead of tint
self.speed = 6;
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
cloudGraphics.alpha = 0.6;
self.speed = Math.random() * 1 + 0.5; // Random speed between 0.5-1.5
self.scaleX = self.scaleY = Math.random() * 0.8 + 0.6; // Random scale 0.6-1.4
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyAircraft = Container.expand(function (type) {
var self = Container.call(this);
var assetName = type || 'mig29';
var aircraftGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = assetName;
self.speed = 3;
self.active = true;
// Set point values based on aircraft type
if (self.type === 'mig29') {
self.points = 100;
self.speed = 3;
} else if (self.type === 'su27') {
self.points = 150;
self.speed = 2.5;
} else if (self.type === 'tu95') {
self.points = 200;
self.speed = 2;
} else if (self.type === 'su57') {
self.points = 300;
self.speed = 2.8;
self.hp = 2; // Requires 2 hits to destroy
self.maxHP = 2;
self.stealthMode = false;
self.stealthTimer = 0;
}
self.update = function () {
if (!self.active) return;
self.y += self.speed;
// SU-57 special abilities
if (self.type === 'su57') {
// Stealth mode toggle every 3 seconds
self.stealthTimer++;
if (self.stealthTimer >= 180) {
// 3 seconds at 60fps
self.stealthMode = !self.stealthMode;
self.stealthTimer = 0;
if (self.stealthMode) {
tween(self, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut
});
} else {
tween(self, {
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
}
// Slight evasive maneuvers
if (LK.ticks % 120 === 0) {
// Every 2 seconds
var evasiveMove = (Math.random() - 0.5) * 100; // Random movement -50 to +50
self.x = Math.max(100, Math.min(1948, self.x + evasiveMove));
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.tint = 0xFF4444; // Red tint for enemy bullets
self.speed = 8;
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 20; // frames
self.update = function () {
self.lifetime--;
self.alpha = self.lifetime / 20;
self.scaleX = self.scaleY = (20 - self.lifetime) / 10;
};
return self;
});
var F18Hornet = Container.expand(function () {
var self = Container.call(this);
var hornetGraphics = self.attachAsset('gripen', {
anchorX: 0.5,
anchorY: 0.5
});
// Distinctive blue tint for F-18 Hornet
hornetGraphics.tint = 0x0066FF;
// Scale to make it slightly larger than normal Gripen
hornetGraphics.scaleX = 1.1;
hornetGraphics.scaleY = 1.1;
self.speed = 2.5; // Slightly faster than old friendly
self.active = true;
self.fireTimer = 0;
self.burstCount = 0;
self.burstTimer = 0;
self.targetEnemy = null;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
// Advanced firing system - burst fire
self.fireTimer++;
self.burstTimer++;
// Fire in bursts of 3 missiles every 60 ticks
if (self.fireTimer >= 60 && enemies.length > 0 && self.burstCount < 3) {
// Find closest enemy
var closestEnemy = null;
var closestDistance = 999999;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (!enemy.active) continue;
var distance = Math.abs(enemy.x - self.x) + Math.abs(enemy.y - self.y);
if (distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
if (closestEnemy && closestDistance < 900) {
// Fire with slight spread for burst effect
var missile = new Missile();
missile.x = self.x + (self.burstCount - 1) * 20; // Slight horizontal spread
missile.y = self.y - 50;
missile.isFriendly = true;
friendlyMissiles.push(missile);
game.addChild(missile);
LK.getSound('missile_fire').play();
self.burstCount++;
}
self.fireTimer = 0;
}
// Reset burst after delay
if (self.burstCount >= 3 && self.burstTimer >= 90) {
self.burstCount = 0;
self.burstTimer = 0;
}
};
return self;
});
var GroundExplosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('groundExplosion', {
anchorX: 0.5,
anchorY: 0.5
});
explosionGraphics.alpha = 1;
explosionGraphics.scaleX = 0.2;
explosionGraphics.scaleY = 0.2;
self.active = true;
// Start animation immediately
tween(explosionGraphics, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
self.active = false;
}
});
return self;
});
var Missile = Container.expand(function () {
var self = Container.call(this);
var missileGraphics = self.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
var PlayerGripen = Container.expand(function () {
var self = Container.call(this);
var gripenGraphics = self.attachAsset('gripen', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.active = true;
return self;
});
var Raindrop = Container.expand(function () {
var self = Container.call(this);
var dropGraphics = self.attachAsset('raindrop', {
anchorX: 0.5,
anchorY: 0.5
});
dropGraphics.alpha = 0.6;
self.speed = Math.random() * 8 + 12; // Random speed between 12-20
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Sound effects
// Missiles
// Enemy aircraft types
// Player aircraft - JAS Gripen (distinctive delta wing design)
// Game variables
var player;
var missiles = [];
var enemies = [];
var enemyBullets = [];
var bombs = [];
var explosions = [];
var waveNumber = 1;
var enemiesSpawned = 0;
var enemiesInWave = 5;
var spawnTimer = 0;
var missileTimer = 0;
var enemyFireTimer = 0;
var waveTimer = 0;
var clouds = [];
var cloudSpawnTimer = 0;
var groundExplosions = [];
var raindrops = [];
var rainSpawnTimer = 0;
var weatherIntensity = 0.3; // 0 = no rain, 1 = heavy rain
// Friendly aircraft system
var friendlyAircraft = [];
var friendlyMissiles = [];
var friendlySpawnTimer = 0;
// Day/night cycle variables
var timeOfDay = 0; // 0 = night, 0.5 = dawn/dusk, 1 = day
var dayNightTimer = 0;
var dayNightCycleDuration = 1800; // 30 seconds for full cycle (60fps * 30)
var isTransitioning = false;
// Player health system
var playerHP = 3;
var maxHP = 3;
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var hpTxt = new Text2('HP: 3/3', {
size: 60,
fill: 0xFF0000
});
hpTxt.anchor.set(0, 0);
hpTxt.x = 120;
hpTxt.y = 120;
LK.gui.topLeft.addChild(hpTxt);
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
waveTxt.y = 60; // Move wave text down to make room for pause button
LK.gui.topRight.addChild(waveTxt);
// Add pause button
var pauseTxt = new Text2('PAUSE', {
size: 40,
fill: 0xFFFFFF
});
pauseTxt.anchor.set(1, 0);
pauseTxt.x = -10;
pauseTxt.y = 10;
LK.gui.topRight.addChild(pauseTxt);
// Make pause text clickable
pauseTxt.down = function (x, y, obj) {
LK.pauseGame(); // Trigger the built-in pause functionality
};
// Initialize player
player = new PlayerGripen();
player.x = 1024; // Center horizontally
player.y = 2500; // Near bottom of screen
game.addChild(player);
// Initialize HP display
updateHP();
// Touch/mouse controls for player movement
var isDragging = false;
game.down = function (x, y, obj) {
isDragging = true;
player.x = x;
};
game.move = function (x, y, obj) {
if (isDragging && player.active) {
player.x = Math.max(60, Math.min(1988, x)); // Keep player on screen
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Spawn enemy function
function spawnEnemy() {
var enemyTypes = ['mig29', 'su27', 'tu95'];
// Add SU-57 from wave 3 onwards with lower spawn rate
if (waveNumber >= 3 && Math.random() < 0.2) {
enemyTypes.push('su57');
}
var randomType = enemyTypes[Math.floor(Math.random() * enemyTypes.length)];
var enemy = new EnemyAircraft(randomType);
enemy.x = Math.random() * 1800 + 124; // Random X position across screen
enemy.y = -100; // Start above screen
// Adjust speed based on wave
enemy.speed += (waveNumber - 1) * 0.5;
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
}
// Fire missile function
function fireMissile() {
if (!player.active) return;
var missile = new Missile();
missile.x = player.x;
missile.y = player.y - 70;
missiles.push(missile);
game.addChild(missile);
LK.getSound('missile_fire').play();
}
// Spawn friendly aircraft function
function spawnFriendlyAircraft() {
var friendly = new F18Hornet();
friendly.x = Math.random() * 1800 + 124; // Random X position
friendly.y = 2800; // Start from bottom
// Add entry animation
tween(friendly, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.easeOut
});
friendlyAircraft.push(friendly);
game.addChild(friendly);
}
// Create explosion function
function createExplosion(x, y) {
var explosion = new Explosion();
explosion.x = x;
explosion.y = y;
explosions.push(explosion);
game.addChild(explosion);
LK.getSound('explosion').play();
}
// Create ground explosion function
function createGroundExplosion(x, y) {
var groundExplosion = new GroundExplosion();
groundExplosion.x = x;
groundExplosion.y = y;
groundExplosions.push(groundExplosion);
game.addChild(groundExplosion);
LK.getSound('explosion').play();
}
// Update score display
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
}
// Update wave display
function updateWave() {
waveTxt.setText('Wave: ' + waveNumber);
}
// Update HP display
function updateHP() {
hpTxt.setText('HP: ' + playerHP + '/' + maxHP);
if (playerHP <= 1) {
hpTxt.fill = 0xFF0000; // Red when low HP
} else if (playerHP <= 2) {
hpTxt.fill = 0xFFFF00; // Yellow when medium HP
} else {
hpTxt.fill = 0x00FF00; // Green when full HP
}
}
// Main game update loop
game.update = function () {
if (!player.active) return;
// Fire missiles automatically
missileTimer++;
if (missileTimer >= 20) {
// Fire every 20 ticks (3 times per second)
fireMissile();
missileTimer = 0;
}
// Spawn enemies
spawnTimer++;
var spawnRate = Math.max(60 - waveNumber * 5, 30); // Faster spawning each wave
if (spawnTimer >= spawnRate && enemiesSpawned < enemiesInWave) {
spawnEnemy();
spawnTimer = 0;
}
// Check for missile-enemy collisions
for (var m = missiles.length - 1; m >= 0; m--) {
var missile = missiles[m];
if (!missile.active) continue;
// Remove missiles that go off screen
if (missile.y < -50) {
missile.destroy();
missiles.splice(m, 1);
continue;
}
// Check collision with enemies
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (!enemy.active) continue;
if (missile.intersects(enemy)) {
// Handle SU-57 HP system
if (enemy.type === 'su57' && enemy.hp > 1) {
enemy.hp--;
// Flash red when hit but not destroyed
tween(enemy, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
}
});
createExplosion(enemy.x, enemy.y);
missile.active = false;
missile.destroy();
missiles.splice(m, 1);
break;
} else {
// Create explosion
createExplosion(enemy.x, enemy.y);
// Award points
LK.setScore(LK.getScore() + enemy.points);
updateScore();
// Remove missile and enemy
missile.active = false;
enemy.active = false;
missile.destroy();
enemy.destroy();
missiles.splice(m, 1);
enemies.splice(e, 1);
LK.getSound('enemy_destroyed').play();
break;
}
}
}
}
// Update and check enemy collisions with player
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (!enemy.active) continue;
// Remove enemies that go off screen
if (enemy.y > 2800) {
enemy.destroy();
enemies.splice(e, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
// Take damage
playerHP--;
updateHP();
createExplosion(enemy.x, enemy.y);
enemy.active = false;
enemy.destroy();
enemies.splice(e, 1);
// Check if player is dead
if (playerHP <= 0) {
createExplosion(player.x, player.y);
player.active = false;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
// Enemy firing system
enemyFireTimer++;
if (enemyFireTimer >= 90) {
// Fire every 1.5 seconds
if (enemies.length > 0) {
var randomEnemy = enemies[Math.floor(Math.random() * enemies.length)];
if (randomEnemy.active && randomEnemy.y > 200 && randomEnemy.y < 2000) {
if (randomEnemy.type === 'tu95') {
// Tu-95 drops bombs
var bomb = new Bomb();
bomb.x = randomEnemy.x;
bomb.y = randomEnemy.y + 50;
bombs.push(bomb);
game.addChild(bomb);
} else if (randomEnemy.type === 'su57') {
// SU-57 fires advanced missiles aimed at player
var bullet = new EnemyBullet();
bullet.x = randomEnemy.x;
bullet.y = randomEnemy.y + 50;
// Aim toward player position
var dx = player.x - bullet.x;
var distance = Math.abs(dx);
if (distance > 50) {
// Only adjust if player is not directly below
bullet.x += dx * 0.3; // Adjust firing position toward player
}
bullet.speed = 10; // Faster than normal bullets
enemyBullets.push(bullet);
game.addChild(bullet);
} else {
// Other aircraft fire bullets
var bullet = new EnemyBullet();
bullet.x = randomEnemy.x;
bullet.y = randomEnemy.y + 50;
enemyBullets.push(bullet);
game.addChild(bullet);
}
}
}
enemyFireTimer = 0;
}
// Update and check enemy bullets
for (var eb = enemyBullets.length - 1; eb >= 0; eb--) {
var bullet = enemyBullets[eb];
if (!bullet.active) continue;
// Remove bullets that go off screen
if (bullet.y > 2800) {
bullet.destroy();
enemyBullets.splice(eb, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
// Take damage
playerHP--;
updateHP();
createExplosion(bullet.x, bullet.y);
bullet.destroy();
enemyBullets.splice(eb, 1);
// Check if player is dead
if (playerHP <= 0) {
createExplosion(player.x, player.y);
player.active = false;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
// Update and check bombs
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (!bomb.active) continue;
// Remove bombs that go off screen
if (bomb.y > 2800) {
// Bomb hits ground - create explosion
createExplosion(bomb.x, bomb.y);
createGroundExplosion(bomb.x, bomb.y);
bomb.destroy();
bombs.splice(b, 1);
continue;
}
// Check collision with player
if (bomb.intersects(player)) {
// Take damage
playerHP--;
updateHP();
createExplosion(bomb.x, bomb.y);
bomb.destroy();
bombs.splice(b, 1);
// Check if player is dead
if (playerHP <= 0) {
createExplosion(player.x, player.y);
player.active = false;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
// Update explosions
for (var ex = explosions.length - 1; ex >= 0; ex--) {
var explosion = explosions[ex];
if (explosion.lifetime <= 0) {
explosion.destroy();
explosions.splice(ex, 1);
}
}
// Check if wave is complete
if (enemiesSpawned >= enemiesInWave && enemies.length === 0) {
waveNumber++;
enemiesSpawned = 0;
enemiesInWave += 2; // More enemies each wave
updateWave();
// Brief pause between waves
waveTimer = 120; // 2 second pause
}
// Handle wave timer
if (waveTimer > 0) {
waveTimer--;
}
// Spawn clouds for background atmosphere
cloudSpawnTimer++;
if (cloudSpawnTimer >= 180) {
// Spawn cloud every 3 seconds
var cloud = new Cloud();
cloud.x = Math.random() * 2048; // Random X position across screen
cloud.y = -100; // Start above screen
clouds.push(cloud);
game.addChild(cloud);
cloudSpawnTimer = 0;
}
// Update and remove off-screen clouds
for (var c = clouds.length - 1; c >= 0; c--) {
var cloud = clouds[c];
if (cloud.y > 2800) {
// Remove when off screen
cloud.destroy();
clouds.splice(c, 1);
}
}
// Update and remove finished ground explosions
for (var ge = groundExplosions.length - 1; ge >= 0; ge--) {
var groundExplosion = groundExplosions[ge];
if (!groundExplosion.active) {
groundExplosion.destroy();
groundExplosions.splice(ge, 1);
}
}
// Weather system - spawn raindrops
rainSpawnTimer++;
var rainSpawnRate = Math.max(5 - Math.floor(weatherIntensity * 4), 1); // More frequent with higher intensity
if (rainSpawnTimer >= rainSpawnRate) {
// Spawn multiple raindrops based on intensity
var dropsToSpawn = Math.floor(weatherIntensity * 5) + 1;
for (var rd = 0; rd < dropsToSpawn; rd++) {
var raindrop = new Raindrop();
raindrop.x = Math.random() * 2048; // Random X position across screen
raindrop.y = -20; // Start above screen
raindrops.push(raindrop);
game.addChild(raindrop);
}
rainSpawnTimer = 0;
}
// Update and remove off-screen raindrops
for (var rd = raindrops.length - 1; rd >= 0; rd--) {
var raindrop = raindrops[rd];
if (raindrop.y > 2800) {
// Remove when off screen
raindrop.destroy();
raindrops.splice(rd, 1);
}
}
// Day/night cycle system
dayNightTimer++;
if (dayNightTimer >= dayNightCycleDuration / 4) {
// Update time every quarter cycle
dayNightTimer = 0;
var oldTimeOfDay = timeOfDay;
// Cycle through time: 0 -> 0.25 -> 0.5 -> 0.75 -> 1 -> 0.75 -> 0.5 -> 0.25 -> 0
if (timeOfDay >= 1) {
timeOfDay = 0.75;
} else if (timeOfDay >= 0.75) {
timeOfDay = 0.5;
} else if (timeOfDay >= 0.5) {
timeOfDay = 0.25;
} else if (timeOfDay >= 0.25) {
timeOfDay = 0;
} else {
timeOfDay = 0.25;
}
// Only transition if time changed and not already transitioning
if (oldTimeOfDay !== timeOfDay && !isTransitioning) {
isTransitioning = true;
var targetColor;
var transitionDuration = 3000; // 3 seconds for smooth transition
// Determine base color based on time of day
if (timeOfDay === 0) {
// Night - dark blue
targetColor = 0x191970; // Midnight blue
} else if (timeOfDay === 0.25) {
// Dawn/Early morning - purple-pink
targetColor = 0x4B0082; // Indigo
} else if (timeOfDay === 0.5) {
// Day - bright sky blue
targetColor = 0x87CEEB; // Sky blue
} else if (timeOfDay === 0.75) {
// Dusk/Evening - orange-red
targetColor = 0xFF4500; // Orange red
}
// Apply weather modifications to the base color
if (weatherIntensity > 0.6) {
// Heavy rain - make darker
if (timeOfDay === 0) targetColor = 0x0F0F23; // Darker night
else if (timeOfDay === 0.25) targetColor = 0x2F1B69; // Darker dawn
else if (timeOfDay === 0.5) targetColor = 0x4682B4; // Darker day
else if (timeOfDay === 0.75) targetColor = 0xB8460E; // Darker dusk
} else if (weatherIntensity > 0.4) {
// Medium rain - slightly darker
if (timeOfDay === 0) targetColor = 0x151560; // Slightly darker night
else if (timeOfDay === 0.25) targetColor = 0x3D2376; // Slightly darker dawn
else if (timeOfDay === 0.5) targetColor = 0x6495ED; // Slightly darker day
else if (timeOfDay === 0.75) targetColor = 0xD2691E; // Slightly darker dusk
}
// Smooth transition to new color
tween(game, {
backgroundColor: targetColor
}, {
duration: transitionDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
isTransitioning = false;
}
});
}
}
// Spawn friendly aircraft occasionally
friendlySpawnTimer++;
if (friendlySpawnTimer >= 1800 && friendlyAircraft.length < 2) {
// Every 30 seconds, max 2 friendly
spawnFriendlyAircraft();
friendlySpawnTimer = 0;
}
// Update friendly aircraft
for (var fa = friendlyAircraft.length - 1; fa >= 0; fa--) {
var friendly = friendlyAircraft[fa];
if (!friendly.active) continue;
// Remove if goes off screen
if (friendly.y < -100) {
friendly.destroy();
friendlyAircraft.splice(fa, 1);
continue;
}
}
// Update friendly missiles and check collisions with enemies
for (var fm = friendlyMissiles.length - 1; fm >= 0; fm--) {
var fMissile = friendlyMissiles[fm];
if (!fMissile.active) continue;
// Remove if off screen
if (fMissile.y < -50) {
fMissile.destroy();
friendlyMissiles.splice(fm, 1);
continue;
}
// Check collision with enemies
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (!enemy.active) continue;
if (fMissile.intersects(enemy)) {
// Handle SU-57 HP system
if (enemy.type === 'su57' && enemy.hp > 1) {
enemy.hp--;
// Flash red when hit but not destroyed
tween(enemy, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
}
});
createExplosion(enemy.x, enemy.y);
fMissile.active = false;
fMissile.destroy();
friendlyMissiles.splice(fm, 1);
break;
} else {
// Create explosion
createExplosion(enemy.x, enemy.y);
// Award points (friendly assist gives half points)
LK.setScore(LK.getScore() + Math.floor(enemy.points / 2));
updateScore();
// Remove missile and enemy
fMissile.active = false;
enemy.active = false;
fMissile.destroy();
enemy.destroy();
friendlyMissiles.splice(fm, 1);
enemies.splice(e, 1);
LK.getSound('enemy_destroyed').play();
break;
}
}
}
}
// Change weather intensity over time (less frequent than before)
if (LK.ticks % 900 === 0) {
// Every 15 seconds
weatherIntensity = Math.random() * 0.8 + 0.2; // Random intensity between 0.2-1.0
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Bomb now uses dark colored shape asset instead of tint
self.speed = 6;
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
cloudGraphics.alpha = 0.6;
self.speed = Math.random() * 1 + 0.5; // Random speed between 0.5-1.5
self.scaleX = self.scaleY = Math.random() * 0.8 + 0.6; // Random scale 0.6-1.4
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyAircraft = Container.expand(function (type) {
var self = Container.call(this);
var assetName = type || 'mig29';
var aircraftGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = assetName;
self.speed = 3;
self.active = true;
// Set point values based on aircraft type
if (self.type === 'mig29') {
self.points = 100;
self.speed = 3;
} else if (self.type === 'su27') {
self.points = 150;
self.speed = 2.5;
} else if (self.type === 'tu95') {
self.points = 200;
self.speed = 2;
} else if (self.type === 'su57') {
self.points = 300;
self.speed = 2.8;
self.hp = 2; // Requires 2 hits to destroy
self.maxHP = 2;
self.stealthMode = false;
self.stealthTimer = 0;
}
self.update = function () {
if (!self.active) return;
self.y += self.speed;
// SU-57 special abilities
if (self.type === 'su57') {
// Stealth mode toggle every 3 seconds
self.stealthTimer++;
if (self.stealthTimer >= 180) {
// 3 seconds at 60fps
self.stealthMode = !self.stealthMode;
self.stealthTimer = 0;
if (self.stealthMode) {
tween(self, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut
});
} else {
tween(self, {
alpha: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
}
// Slight evasive maneuvers
if (LK.ticks % 120 === 0) {
// Every 2 seconds
var evasiveMove = (Math.random() - 0.5) * 100; // Random movement -50 to +50
self.x = Math.max(100, Math.min(1948, self.x + evasiveMove));
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.tint = 0xFF4444; // Red tint for enemy bullets
self.speed = 8;
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 20; // frames
self.update = function () {
self.lifetime--;
self.alpha = self.lifetime / 20;
self.scaleX = self.scaleY = (20 - self.lifetime) / 10;
};
return self;
});
var F18Hornet = Container.expand(function () {
var self = Container.call(this);
var hornetGraphics = self.attachAsset('gripen', {
anchorX: 0.5,
anchorY: 0.5
});
// Distinctive blue tint for F-18 Hornet
hornetGraphics.tint = 0x0066FF;
// Scale to make it slightly larger than normal Gripen
hornetGraphics.scaleX = 1.1;
hornetGraphics.scaleY = 1.1;
self.speed = 2.5; // Slightly faster than old friendly
self.active = true;
self.fireTimer = 0;
self.burstCount = 0;
self.burstTimer = 0;
self.targetEnemy = null;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
// Advanced firing system - burst fire
self.fireTimer++;
self.burstTimer++;
// Fire in bursts of 3 missiles every 60 ticks
if (self.fireTimer >= 60 && enemies.length > 0 && self.burstCount < 3) {
// Find closest enemy
var closestEnemy = null;
var closestDistance = 999999;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (!enemy.active) continue;
var distance = Math.abs(enemy.x - self.x) + Math.abs(enemy.y - self.y);
if (distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
if (closestEnemy && closestDistance < 900) {
// Fire with slight spread for burst effect
var missile = new Missile();
missile.x = self.x + (self.burstCount - 1) * 20; // Slight horizontal spread
missile.y = self.y - 50;
missile.isFriendly = true;
friendlyMissiles.push(missile);
game.addChild(missile);
LK.getSound('missile_fire').play();
self.burstCount++;
}
self.fireTimer = 0;
}
// Reset burst after delay
if (self.burstCount >= 3 && self.burstTimer >= 90) {
self.burstCount = 0;
self.burstTimer = 0;
}
};
return self;
});
var GroundExplosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('groundExplosion', {
anchorX: 0.5,
anchorY: 0.5
});
explosionGraphics.alpha = 1;
explosionGraphics.scaleX = 0.2;
explosionGraphics.scaleY = 0.2;
self.active = true;
// Start animation immediately
tween(explosionGraphics, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
self.active = false;
}
});
return self;
});
var Missile = Container.expand(function () {
var self = Container.call(this);
var missileGraphics = self.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
var PlayerGripen = Container.expand(function () {
var self = Container.call(this);
var gripenGraphics = self.attachAsset('gripen', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.active = true;
return self;
});
var Raindrop = Container.expand(function () {
var self = Container.call(this);
var dropGraphics = self.attachAsset('raindrop', {
anchorX: 0.5,
anchorY: 0.5
});
dropGraphics.alpha = 0.6;
self.speed = Math.random() * 8 + 12; // Random speed between 12-20
self.active = true;
self.update = function () {
if (!self.active) return;
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Sound effects
// Missiles
// Enemy aircraft types
// Player aircraft - JAS Gripen (distinctive delta wing design)
// Game variables
var player;
var missiles = [];
var enemies = [];
var enemyBullets = [];
var bombs = [];
var explosions = [];
var waveNumber = 1;
var enemiesSpawned = 0;
var enemiesInWave = 5;
var spawnTimer = 0;
var missileTimer = 0;
var enemyFireTimer = 0;
var waveTimer = 0;
var clouds = [];
var cloudSpawnTimer = 0;
var groundExplosions = [];
var raindrops = [];
var rainSpawnTimer = 0;
var weatherIntensity = 0.3; // 0 = no rain, 1 = heavy rain
// Friendly aircraft system
var friendlyAircraft = [];
var friendlyMissiles = [];
var friendlySpawnTimer = 0;
// Day/night cycle variables
var timeOfDay = 0; // 0 = night, 0.5 = dawn/dusk, 1 = day
var dayNightTimer = 0;
var dayNightCycleDuration = 1800; // 30 seconds for full cycle (60fps * 30)
var isTransitioning = false;
// Player health system
var playerHP = 3;
var maxHP = 3;
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var hpTxt = new Text2('HP: 3/3', {
size: 60,
fill: 0xFF0000
});
hpTxt.anchor.set(0, 0);
hpTxt.x = 120;
hpTxt.y = 120;
LK.gui.topLeft.addChild(hpTxt);
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
waveTxt.y = 60; // Move wave text down to make room for pause button
LK.gui.topRight.addChild(waveTxt);
// Add pause button
var pauseTxt = new Text2('PAUSE', {
size: 40,
fill: 0xFFFFFF
});
pauseTxt.anchor.set(1, 0);
pauseTxt.x = -10;
pauseTxt.y = 10;
LK.gui.topRight.addChild(pauseTxt);
// Make pause text clickable
pauseTxt.down = function (x, y, obj) {
LK.pauseGame(); // Trigger the built-in pause functionality
};
// Initialize player
player = new PlayerGripen();
player.x = 1024; // Center horizontally
player.y = 2500; // Near bottom of screen
game.addChild(player);
// Initialize HP display
updateHP();
// Touch/mouse controls for player movement
var isDragging = false;
game.down = function (x, y, obj) {
isDragging = true;
player.x = x;
};
game.move = function (x, y, obj) {
if (isDragging && player.active) {
player.x = Math.max(60, Math.min(1988, x)); // Keep player on screen
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Spawn enemy function
function spawnEnemy() {
var enemyTypes = ['mig29', 'su27', 'tu95'];
// Add SU-57 from wave 3 onwards with lower spawn rate
if (waveNumber >= 3 && Math.random() < 0.2) {
enemyTypes.push('su57');
}
var randomType = enemyTypes[Math.floor(Math.random() * enemyTypes.length)];
var enemy = new EnemyAircraft(randomType);
enemy.x = Math.random() * 1800 + 124; // Random X position across screen
enemy.y = -100; // Start above screen
// Adjust speed based on wave
enemy.speed += (waveNumber - 1) * 0.5;
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
}
// Fire missile function
function fireMissile() {
if (!player.active) return;
var missile = new Missile();
missile.x = player.x;
missile.y = player.y - 70;
missiles.push(missile);
game.addChild(missile);
LK.getSound('missile_fire').play();
}
// Spawn friendly aircraft function
function spawnFriendlyAircraft() {
var friendly = new F18Hornet();
friendly.x = Math.random() * 1800 + 124; // Random X position
friendly.y = 2800; // Start from bottom
// Add entry animation
tween(friendly, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.easeOut
});
friendlyAircraft.push(friendly);
game.addChild(friendly);
}
// Create explosion function
function createExplosion(x, y) {
var explosion = new Explosion();
explosion.x = x;
explosion.y = y;
explosions.push(explosion);
game.addChild(explosion);
LK.getSound('explosion').play();
}
// Create ground explosion function
function createGroundExplosion(x, y) {
var groundExplosion = new GroundExplosion();
groundExplosion.x = x;
groundExplosion.y = y;
groundExplosions.push(groundExplosion);
game.addChild(groundExplosion);
LK.getSound('explosion').play();
}
// Update score display
function updateScore() {
scoreTxt.setText('Score: ' + LK.getScore());
}
// Update wave display
function updateWave() {
waveTxt.setText('Wave: ' + waveNumber);
}
// Update HP display
function updateHP() {
hpTxt.setText('HP: ' + playerHP + '/' + maxHP);
if (playerHP <= 1) {
hpTxt.fill = 0xFF0000; // Red when low HP
} else if (playerHP <= 2) {
hpTxt.fill = 0xFFFF00; // Yellow when medium HP
} else {
hpTxt.fill = 0x00FF00; // Green when full HP
}
}
// Main game update loop
game.update = function () {
if (!player.active) return;
// Fire missiles automatically
missileTimer++;
if (missileTimer >= 20) {
// Fire every 20 ticks (3 times per second)
fireMissile();
missileTimer = 0;
}
// Spawn enemies
spawnTimer++;
var spawnRate = Math.max(60 - waveNumber * 5, 30); // Faster spawning each wave
if (spawnTimer >= spawnRate && enemiesSpawned < enemiesInWave) {
spawnEnemy();
spawnTimer = 0;
}
// Check for missile-enemy collisions
for (var m = missiles.length - 1; m >= 0; m--) {
var missile = missiles[m];
if (!missile.active) continue;
// Remove missiles that go off screen
if (missile.y < -50) {
missile.destroy();
missiles.splice(m, 1);
continue;
}
// Check collision with enemies
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (!enemy.active) continue;
if (missile.intersects(enemy)) {
// Handle SU-57 HP system
if (enemy.type === 'su57' && enemy.hp > 1) {
enemy.hp--;
// Flash red when hit but not destroyed
tween(enemy, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
}
});
createExplosion(enemy.x, enemy.y);
missile.active = false;
missile.destroy();
missiles.splice(m, 1);
break;
} else {
// Create explosion
createExplosion(enemy.x, enemy.y);
// Award points
LK.setScore(LK.getScore() + enemy.points);
updateScore();
// Remove missile and enemy
missile.active = false;
enemy.active = false;
missile.destroy();
enemy.destroy();
missiles.splice(m, 1);
enemies.splice(e, 1);
LK.getSound('enemy_destroyed').play();
break;
}
}
}
}
// Update and check enemy collisions with player
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (!enemy.active) continue;
// Remove enemies that go off screen
if (enemy.y > 2800) {
enemy.destroy();
enemies.splice(e, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
// Take damage
playerHP--;
updateHP();
createExplosion(enemy.x, enemy.y);
enemy.active = false;
enemy.destroy();
enemies.splice(e, 1);
// Check if player is dead
if (playerHP <= 0) {
createExplosion(player.x, player.y);
player.active = false;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
// Enemy firing system
enemyFireTimer++;
if (enemyFireTimer >= 90) {
// Fire every 1.5 seconds
if (enemies.length > 0) {
var randomEnemy = enemies[Math.floor(Math.random() * enemies.length)];
if (randomEnemy.active && randomEnemy.y > 200 && randomEnemy.y < 2000) {
if (randomEnemy.type === 'tu95') {
// Tu-95 drops bombs
var bomb = new Bomb();
bomb.x = randomEnemy.x;
bomb.y = randomEnemy.y + 50;
bombs.push(bomb);
game.addChild(bomb);
} else if (randomEnemy.type === 'su57') {
// SU-57 fires advanced missiles aimed at player
var bullet = new EnemyBullet();
bullet.x = randomEnemy.x;
bullet.y = randomEnemy.y + 50;
// Aim toward player position
var dx = player.x - bullet.x;
var distance = Math.abs(dx);
if (distance > 50) {
// Only adjust if player is not directly below
bullet.x += dx * 0.3; // Adjust firing position toward player
}
bullet.speed = 10; // Faster than normal bullets
enemyBullets.push(bullet);
game.addChild(bullet);
} else {
// Other aircraft fire bullets
var bullet = new EnemyBullet();
bullet.x = randomEnemy.x;
bullet.y = randomEnemy.y + 50;
enemyBullets.push(bullet);
game.addChild(bullet);
}
}
}
enemyFireTimer = 0;
}
// Update and check enemy bullets
for (var eb = enemyBullets.length - 1; eb >= 0; eb--) {
var bullet = enemyBullets[eb];
if (!bullet.active) continue;
// Remove bullets that go off screen
if (bullet.y > 2800) {
bullet.destroy();
enemyBullets.splice(eb, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
// Take damage
playerHP--;
updateHP();
createExplosion(bullet.x, bullet.y);
bullet.destroy();
enemyBullets.splice(eb, 1);
// Check if player is dead
if (playerHP <= 0) {
createExplosion(player.x, player.y);
player.active = false;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
// Update and check bombs
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (!bomb.active) continue;
// Remove bombs that go off screen
if (bomb.y > 2800) {
// Bomb hits ground - create explosion
createExplosion(bomb.x, bomb.y);
createGroundExplosion(bomb.x, bomb.y);
bomb.destroy();
bombs.splice(b, 1);
continue;
}
// Check collision with player
if (bomb.intersects(player)) {
// Take damage
playerHP--;
updateHP();
createExplosion(bomb.x, bomb.y);
bomb.destroy();
bombs.splice(b, 1);
// Check if player is dead
if (playerHP <= 0) {
createExplosion(player.x, player.y);
player.active = false;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
}
// Update explosions
for (var ex = explosions.length - 1; ex >= 0; ex--) {
var explosion = explosions[ex];
if (explosion.lifetime <= 0) {
explosion.destroy();
explosions.splice(ex, 1);
}
}
// Check if wave is complete
if (enemiesSpawned >= enemiesInWave && enemies.length === 0) {
waveNumber++;
enemiesSpawned = 0;
enemiesInWave += 2; // More enemies each wave
updateWave();
// Brief pause between waves
waveTimer = 120; // 2 second pause
}
// Handle wave timer
if (waveTimer > 0) {
waveTimer--;
}
// Spawn clouds for background atmosphere
cloudSpawnTimer++;
if (cloudSpawnTimer >= 180) {
// Spawn cloud every 3 seconds
var cloud = new Cloud();
cloud.x = Math.random() * 2048; // Random X position across screen
cloud.y = -100; // Start above screen
clouds.push(cloud);
game.addChild(cloud);
cloudSpawnTimer = 0;
}
// Update and remove off-screen clouds
for (var c = clouds.length - 1; c >= 0; c--) {
var cloud = clouds[c];
if (cloud.y > 2800) {
// Remove when off screen
cloud.destroy();
clouds.splice(c, 1);
}
}
// Update and remove finished ground explosions
for (var ge = groundExplosions.length - 1; ge >= 0; ge--) {
var groundExplosion = groundExplosions[ge];
if (!groundExplosion.active) {
groundExplosion.destroy();
groundExplosions.splice(ge, 1);
}
}
// Weather system - spawn raindrops
rainSpawnTimer++;
var rainSpawnRate = Math.max(5 - Math.floor(weatherIntensity * 4), 1); // More frequent with higher intensity
if (rainSpawnTimer >= rainSpawnRate) {
// Spawn multiple raindrops based on intensity
var dropsToSpawn = Math.floor(weatherIntensity * 5) + 1;
for (var rd = 0; rd < dropsToSpawn; rd++) {
var raindrop = new Raindrop();
raindrop.x = Math.random() * 2048; // Random X position across screen
raindrop.y = -20; // Start above screen
raindrops.push(raindrop);
game.addChild(raindrop);
}
rainSpawnTimer = 0;
}
// Update and remove off-screen raindrops
for (var rd = raindrops.length - 1; rd >= 0; rd--) {
var raindrop = raindrops[rd];
if (raindrop.y > 2800) {
// Remove when off screen
raindrop.destroy();
raindrops.splice(rd, 1);
}
}
// Day/night cycle system
dayNightTimer++;
if (dayNightTimer >= dayNightCycleDuration / 4) {
// Update time every quarter cycle
dayNightTimer = 0;
var oldTimeOfDay = timeOfDay;
// Cycle through time: 0 -> 0.25 -> 0.5 -> 0.75 -> 1 -> 0.75 -> 0.5 -> 0.25 -> 0
if (timeOfDay >= 1) {
timeOfDay = 0.75;
} else if (timeOfDay >= 0.75) {
timeOfDay = 0.5;
} else if (timeOfDay >= 0.5) {
timeOfDay = 0.25;
} else if (timeOfDay >= 0.25) {
timeOfDay = 0;
} else {
timeOfDay = 0.25;
}
// Only transition if time changed and not already transitioning
if (oldTimeOfDay !== timeOfDay && !isTransitioning) {
isTransitioning = true;
var targetColor;
var transitionDuration = 3000; // 3 seconds for smooth transition
// Determine base color based on time of day
if (timeOfDay === 0) {
// Night - dark blue
targetColor = 0x191970; // Midnight blue
} else if (timeOfDay === 0.25) {
// Dawn/Early morning - purple-pink
targetColor = 0x4B0082; // Indigo
} else if (timeOfDay === 0.5) {
// Day - bright sky blue
targetColor = 0x87CEEB; // Sky blue
} else if (timeOfDay === 0.75) {
// Dusk/Evening - orange-red
targetColor = 0xFF4500; // Orange red
}
// Apply weather modifications to the base color
if (weatherIntensity > 0.6) {
// Heavy rain - make darker
if (timeOfDay === 0) targetColor = 0x0F0F23; // Darker night
else if (timeOfDay === 0.25) targetColor = 0x2F1B69; // Darker dawn
else if (timeOfDay === 0.5) targetColor = 0x4682B4; // Darker day
else if (timeOfDay === 0.75) targetColor = 0xB8460E; // Darker dusk
} else if (weatherIntensity > 0.4) {
// Medium rain - slightly darker
if (timeOfDay === 0) targetColor = 0x151560; // Slightly darker night
else if (timeOfDay === 0.25) targetColor = 0x3D2376; // Slightly darker dawn
else if (timeOfDay === 0.5) targetColor = 0x6495ED; // Slightly darker day
else if (timeOfDay === 0.75) targetColor = 0xD2691E; // Slightly darker dusk
}
// Smooth transition to new color
tween(game, {
backgroundColor: targetColor
}, {
duration: transitionDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
isTransitioning = false;
}
});
}
}
// Spawn friendly aircraft occasionally
friendlySpawnTimer++;
if (friendlySpawnTimer >= 1800 && friendlyAircraft.length < 2) {
// Every 30 seconds, max 2 friendly
spawnFriendlyAircraft();
friendlySpawnTimer = 0;
}
// Update friendly aircraft
for (var fa = friendlyAircraft.length - 1; fa >= 0; fa--) {
var friendly = friendlyAircraft[fa];
if (!friendly.active) continue;
// Remove if goes off screen
if (friendly.y < -100) {
friendly.destroy();
friendlyAircraft.splice(fa, 1);
continue;
}
}
// Update friendly missiles and check collisions with enemies
for (var fm = friendlyMissiles.length - 1; fm >= 0; fm--) {
var fMissile = friendlyMissiles[fm];
if (!fMissile.active) continue;
// Remove if off screen
if (fMissile.y < -50) {
fMissile.destroy();
friendlyMissiles.splice(fm, 1);
continue;
}
// Check collision with enemies
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (!enemy.active) continue;
if (fMissile.intersects(enemy)) {
// Handle SU-57 HP system
if (enemy.type === 'su57' && enemy.hp > 1) {
enemy.hp--;
// Flash red when hit but not destroyed
tween(enemy, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
}
});
createExplosion(enemy.x, enemy.y);
fMissile.active = false;
fMissile.destroy();
friendlyMissiles.splice(fm, 1);
break;
} else {
// Create explosion
createExplosion(enemy.x, enemy.y);
// Award points (friendly assist gives half points)
LK.setScore(LK.getScore() + Math.floor(enemy.points / 2));
updateScore();
// Remove missile and enemy
fMissile.active = false;
enemy.active = false;
fMissile.destroy();
enemy.destroy();
friendlyMissiles.splice(fm, 1);
enemies.splice(e, 1);
LK.getSound('enemy_destroyed').play();
break;
}
}
}
}
// Change weather intensity over time (less frequent than before)
if (LK.ticks % 900 === 0) {
// Every 15 seconds
weatherIntensity = Math.random() * 0.8 + 0.2; // Random intensity between 0.2-1.0
}
};
Jasgripe 39 riktad upp. In-Game asset. 2d. High contrast. No shadows
Jas Gripen 39 riktad upp. In-Game asset. 2d. High contrast. No shadows
Mig 29. In-Game asset. 2d. High contrast. No shadows
Su 27 uppifrån. In-Game asset. 2d. High contrast. No shadows
Explosion. In-Game asset. 2d. High contrast. No shadows
Tu 95 uppifrån. In-Game asset. 2d. High contrast. No shadows
Moln. In-Game asset. 2d. High contrast. No shadows
Bomb. In-Game asset. 2d. High contrast. No shadows
Regn drope. In-Game asset. 2d. High contrast. No shadows
SU 57. In-Game asset. 2d. High contrast. No shadows