/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var B52 = Container.expand(function () { var self = Container.call(this); var b52Graphics = self.attachAsset('B52', { anchorX: 0.5, anchorY: 0.5 }); // Tint B52 to make it visually distinct (dark gray) b52Graphics.tint = 0x666666; self.speed = 1; // Very slow speed self.health = 5; // 5 hit points - highest health self.reward = 15000; // $15000 reward - highest reward self.targetX = 0; self.targetY = 0; self.moveTimer = 0; self.dodgeTimer = 0; self.dodgeDirection = 1; self.decoyTimer = 0; self.maxDecoyRate = 90; // Can deploy decoy every 1.5 seconds self.update = function () { // B52 moves slowly and steadily towards target with enhanced dodging self.moveTimer++; self.dodgeTimer++; self.decoyTimer++; // Enhanced dodging behavior - check for nearby lasers var shouldDodge = false; for (var i = 0; i < lasers.length; i++) { var laser = lasers[i]; var distanceToLaser = Math.sqrt((laser.x - self.x) * (laser.x - self.x) + (laser.y - self.y) * (laser.y - self.y)); if (distanceToLaser < 150 && laser.y < self.y) { shouldDodge = true; // Deploy decoy if available if (self.decoyTimer >= self.maxDecoyRate) { self.deployDecoy(); } break; } } // Evasive maneuvers when dodging if (shouldDodge) { if (self.dodgeTimer % 30 === 0) { self.dodgeDirection *= -1; } } var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; // Add dodging movement if (shouldDodge) { moveX += Math.sin(self.moveTimer * 0.2) * 3 * self.dodgeDirection; moveY *= 0.5; // Slow down forward movement when dodging } self.x += moveX; self.y += moveY; // Keep within screen bounds self.x = Math.max(60, Math.min(2048 - 60, self.x)); } }; self.deployDecoy = function () { self.decoyTimer = 0; // Create decoy explosive var decoy = new Decoy(); decoy.x = self.x + (Math.random() - 0.5) * 100; // Random offset decoy.y = self.y - 30; decoys.push(decoy); game.addChild(decoy); }; self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; }; self.takeDamage = function () { self.health--; if (self.health <= 0) { return true; // B52 destroyed } return false; }; self.explodeAreaDamage = function () { // Area damage when B52 is destroyed var damageRadius = 200; LK.effects.flashObject(self, 0xFF6600, 600); // Damage nearby enemies (friendly fire) for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy !== self) { var distance = Math.sqrt((enemy.x - self.x) * (enemy.x - self.x) + (enemy.y - self.y) * (enemy.y - self.y)); if (distance < damageRadius) { if (enemy.takeDamage && enemy.takeDamage()) { // Enemy destroyed by area damage LK.effects.flashObject(enemy, 0xFF6600, 400); enemy.destroy(); enemies.splice(i, 1); } } } } // Destroy nearby lasers for (var j = lasers.length - 1; j >= 0; j--) { var laser = lasers[j]; var distance = Math.sqrt((laser.x - self.x) * (laser.x - self.x) + (laser.y - self.y) * (laser.y - self.y)); if (distance < damageRadius) { laser.destroy(); lasers.splice(j, 1); } } }; return self; }); var Cannon = Container.expand(function () { var self = Container.call(this); var cannonGraphics = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 1.0 }); self.fireRate = 0; self.maxFireRate = 2; // Fire every 2 frames at max - 3 shots per second self.update = function () { if (self.fireRate > 0) { self.fireRate--; } }; self.canFire = function () { return self.fireRate <= 0; }; self.fire = function () { if (self.canFire()) { self.fireRate = self.maxFireRate; return true; } return false; }; return self; }); var Decoy = Container.expand(function () { var self = Container.call(this); var decoyGraphics = self.attachAsset('laser', { anchorX: 0.5, anchorY: 0.5 }); // Tint decoy to make it look like a small explosive (red-orange) decoyGraphics.tint = 0xFF4500; decoyGraphics.scaleX = 0.6; decoyGraphics.scaleY = 0.6; self.speed = -8; // Move upward to intercept lasers self.lifeTime = 180; // 3 seconds at 60fps self.update = function () { self.y += self.speed; self.lifeTime--; // Self-destruct after lifetime expires if (self.lifeTime <= 0) { return true; // Mark for destruction } return false; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.health = 1; self.reward = 500; // Default reward for basic enemy - increased reward self.update = function () { self.y += self.speed; }; self.takeDamage = function () { self.health--; if (self.health <= 0) { return true; // Enemy destroyed } return false; }; return self; }); var F35 = Container.expand(function () { var self = Container.call(this); var f35Graphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); // Tint F35 to make it visually distinct (darker blue) f35Graphics.tint = 0x4444FF; self.speed = 2; // Slow speed self.health = 3; // 3 hit points self.reward = 10000; // $10000 reward self.targetX = 0; self.targetY = 0; self.agileTimer = 0; self.agileDirection = 1; self.update = function () { // Agile movement - add evasive maneuvers self.agileTimer++; if (self.agileTimer % 60 === 0) { self.agileDirection *= -1; } // Move towards target with agile zigzag pattern var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed + Math.sin(self.agileTimer * 0.1) * 2 * self.agileDirection; self.y += dy / distance * self.speed; } }; self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; }; self.takeDamage = function () { self.health--; if (self.health <= 0) { return true; // F35 destroyed } return false; }; return self; }); var Laser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('laser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -12; self.update = function () { self.y += self.speed; }; return self; }); var Rocket = Container.expand(function () { var self = Container.call(this); var rocketGraphics = self.attachAsset('Rockets', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; // Fast speed self.health = 1; // 1 hit point self.reward = 1000; // $1000 reward self.targetX = 0; self.targetY = 0; self.update = function () { // Move directly towards the cannon with higher speed var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; }; self.takeDamage = function () { self.health--; if (self.health <= 0) { return true; // Rocket destroyed } return false; }; return self; }); var UAV = Container.expand(function () { var self = Container.call(this); var uavGraphics = self.attachAsset('UAV', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4; // Medium speed self.health = 2; // 2 hit points self.reward = 2500; // $2500 reward self.targetX = 0; self.targetY = 0; self.update = function () { // Move directly towards the cannon var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; }; self.takeDamage = function () { self.health--; if (self.health <= 0) { return true; // UAV destroyed } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x001122 }); /**** * Game Code ****/ // Create gradient background from sky blue at top to green-brown at bottom var backgroundGradient = LK.getAsset('background', { width: 2048, height: 2732, color: 0x87CEEB, // Sky blue shape: 'box' }); game.addChild(backgroundGradient); // Create multiple horizontal strips for gradient effect var gradientStrips = []; var stripHeight = 60; var totalStrips = Math.ceil(2732 / stripHeight); for (var i = 0; i < totalStrips; i++) { var strip = LK.getAsset('gradientStrip_' + i, { width: 2048, height: stripHeight, color: 0x87CEEB, // Will be tinted for gradient shape: 'box' }); strip.y = i * stripHeight; // Calculate gradient progression from sky blue to green to brown var progress = i / totalStrips; var r, g, b; if (progress < 0.6) { // Sky blue to green transition (top 60% of screen) var skyProgress = progress / 0.6; r = Math.floor(135 + (34 - 135) * skyProgress); // 135 -> 34 g = Math.floor(206 + (139 - 206) * skyProgress); // 206 -> 139 b = Math.floor(235 + (34 - 235) * skyProgress); // 235 -> 34 } else { // Green to brown transition (bottom 40% of screen) var groundProgress = (progress - 0.6) / 0.4; r = Math.floor(34 + (139 - 34) * groundProgress); // 34 -> 139 g = Math.floor(139 + (69 - 139) * groundProgress); // 139 -> 69 b = Math.floor(34 + (19 - 34) * groundProgress); // 34 -> 19 } var color = r << 16 | g << 8 | b; strip.tint = color; game.addChild(strip); gradientStrips.push(strip); } // Game variables var cannon; var lasers = []; var enemies = []; var decoys = []; var enemySpawnTimer = 0; var enemySpawnRate = 120; // Spawn enemy every 2 seconds initially var gameSpeed = 1; var waveNumber = 1; var currentLevel = 1; var enemiesKilledThisLevel = 0; var requiredKills = { 1: 10, 2: 20, 3: 30 }; // Total enemies per level var scoreToAdvance = { 1: 10000, 2: 25000, 3: 50000 }; var levelComplete = false; // UI Elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var waveTxt = new Text2('Wave: 1', { size: 50, fill: 0xFFFF00 }); waveTxt.anchor.set(1, 0); LK.gui.topRight.addChild(waveTxt); var levelTxt = new Text2('Level: 1', { size: 50, fill: 0x00FFFF }); levelTxt.anchor.set(0, 0); levelTxt.x = 120; // Offset from left edge to avoid menu icon LK.gui.topLeft.addChild(levelTxt); // Initialize cannon cannon = game.addChild(new Cannon()); cannon.x = 2048 / 2; cannon.y = 2732 - 100; // Set initial cannon stats for level 1 function updateCannonStats() { if (currentLevel === 1) { cannon.maxFireRate = 2; // 3 shots per second cannonSpeed = 24; // Normal movement } else if (currentLevel === 2) { cannon.maxFireRate = 1; // 6 shots per second - faster cannonSpeed = 32; // Faster movement } else if (currentLevel === 3) { cannon.maxFireRate = 1; // Keep high fire rate cannonSpeed = 40; // Fastest movement } } updateCannonStats(); // Touch controls var isDragging = false; var cannonSpeed = 24; game.down = function (x, y, obj) { // Check if touch is in the cannon control area for dragging if (y > 2732 - 300) { isDragging = true; cannon.x = Math.max(60, Math.min(2048 - 60, x)); } // Fire laser on any tap/touch - gun sound plays when player pushes laser if (cannon.fire()) { if (currentLevel === 3) { // Double laser beams for level 3 var laser1 = new Laser(); laser1.x = cannon.x - 30; laser1.y = cannon.y - 50; lasers.push(laser1); game.addChild(laser1); var laser2 = new Laser(); laser2.x = cannon.x + 30; laser2.y = cannon.y - 50; lasers.push(laser2); game.addChild(laser2); } else { // Single laser beam for levels 1 and 2 var laser = new Laser(); laser.x = cannon.x; laser.y = cannon.y - 50; lasers.push(laser); game.addChild(laser); } LK.getSound('shoot').play(); } }; game.move = function (x, y, obj) { if (isDragging) { cannon.x = Math.max(60, Math.min(2048 - 60, x)); } }; game.up = function (x, y, obj) { isDragging = false; }; // Spawn enemy function function spawnEnemy() { // Level-based enemy spawning var levelSpawnQueue = []; if (currentLevel === 1) { // Level 1: 5 Rockets, 3 Drones, 1 F-35, 1 B52 for (var i = 0; i < 5; i++) levelSpawnQueue.push('rocket'); for (var i = 0; i < 3; i++) levelSpawnQueue.push('uav'); for (var i = 0; i < 1; i++) levelSpawnQueue.push('f35'); for (var i = 0; i < 1; i++) levelSpawnQueue.push('b52'); } else if (currentLevel === 2) { // Level 2: 10 Rockets, 6 Drones, 2 F-35s, 2 B52s for (var i = 0; i < 10; i++) levelSpawnQueue.push('rocket'); for (var i = 0; i < 6; i++) levelSpawnQueue.push('uav'); for (var i = 0; i < 2; i++) levelSpawnQueue.push('f35'); for (var i = 0; i < 2; i++) levelSpawnQueue.push('b52'); } else if (currentLevel === 3) { // Level 3: 15 Rockets, 9 Drones, 3 F-35s, 3 B52s for (var i = 0; i < 15; i++) levelSpawnQueue.push('rocket'); for (var i = 0; i < 9; i++) levelSpawnQueue.push('uav'); for (var i = 0; i < 3; i++) levelSpawnQueue.push('f35'); for (var i = 0; i < 3; i++) levelSpawnQueue.push('b52'); } // Don't spawn if we've reached the level limit if (enemiesKilledThisLevel >= requiredKills[currentLevel]) { return; } // Randomly pick from the queue var enemyType = levelSpawnQueue[Math.floor(Math.random() * levelSpawnQueue.length)]; // Level multipliers for stats var speedMultiplier = currentLevel === 1 ? 1 : currentLevel === 2 ? 1.5 : 2; var healthMultiplier = currentLevel === 1 ? 1 : currentLevel === 2 ? 1.5 : 2; if (enemyType === 'rocket') { var rocket = new Rocket(); rocket.x = Math.random() * (2048 - 160) + 80; rocket.y = -100; rocket.speed = (6 + Math.random() * 1.5) * speedMultiplier; rocket.health = Math.floor(1 * healthMultiplier); // Update rewards based on level if (currentLevel === 1) rocket.reward = 1000;else if (currentLevel === 2) rocket.reward = 1200;else if (currentLevel === 3) rocket.reward = 1500; rocket.setTarget(cannon.x, cannon.y); enemies.push(rocket); game.addChild(rocket); } else if (enemyType === 'uav') { var uav = new UAV(); uav.x = Math.random() * (2048 - 160) + 80; uav.y = -100; uav.speed = (4 + Math.random() * 1.5) * speedMultiplier; uav.health = Math.floor(2 * healthMultiplier); // Update rewards based on level if (currentLevel === 1) uav.reward = 2500;else if (currentLevel === 2) uav.reward = 3000;else if (currentLevel === 3) uav.reward = 4000; uav.setTarget(cannon.x, cannon.y); enemies.push(uav); game.addChild(uav); } else if (enemyType === 'f35') { var f35 = new F35(); f35.x = Math.random() * (2048 - 160) + 80; f35.y = -100; f35.speed = (2 + Math.random() * 0.5) * speedMultiplier; f35.health = Math.floor(3 * healthMultiplier); // Update rewards based on level if (currentLevel === 1) f35.reward = 5000;else if (currentLevel === 2) f35.reward = 6000;else if (currentLevel === 3) f35.reward = 8000; f35.setTarget(cannon.x, cannon.y); enemies.push(f35); game.addChild(f35); } else if (enemyType === 'b52') { var b52 = new B52(); b52.x = Math.random() * (2048 - 160) + 80; b52.y = -100; b52.speed = (1 + Math.random() * 0.5) * speedMultiplier; b52.health = Math.floor(5 * healthMultiplier); // Update rewards based on level if (currentLevel === 1) b52.reward = 15000;else if (currentLevel === 2) b52.reward = 18000;else if (currentLevel === 3) b52.reward = 22000; b52.setTarget(cannon.x, cannon.y); enemies.push(b52); game.addChild(b52); } } // Update wave difficulty function updateWave() { waveNumber++; enemySpawnRate = Math.max(30, enemySpawnRate - 10); waveTxt.setText('Wave: ' + waveNumber); // Flash effect for new wave LK.effects.flashScreen(0x00FF00, 500); } // Main game loop game.update = function () { // Player-controlled laser firing - only when player touches/taps // No automatic firing - gun sound only plays when player pushes laser // Update enemy spawn timer enemySpawnTimer++; if (enemySpawnTimer >= enemySpawnRate) { spawnEnemy(); enemySpawnTimer = 0; } // Update lasers for (var i = lasers.length - 1; i >= 0; i--) { var laser = lasers[i]; if (laser.lastY === undefined) laser.lastY = laser.y; // Remove laser if off screen if (laser.lastY >= -50 && laser.y < -50) { laser.destroy(); lasers.splice(i, 1); continue; } // Check collision with enemies var hitEnemy = false; for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (laser.intersects(enemy)) { // Hit enemy LK.getSound('enemyHit').play(); // Different laser effects based on enemy type var effectColor = 0xFFFFFF; var effectDuration = 200; if (enemy.constructor.name === 'Rocket') { effectColor = 0xFF6600; // Orange effect for rockets effectDuration = 150; } else if (enemy.constructor.name === 'UAV') { effectColor = 0x00FFFF; // Cyan effect for UAVs effectDuration = 250; } else if (enemy.constructor.name === 'F35') { effectColor = 0xFF00FF; // Magenta effect for F35s effectDuration = 300; } else if (enemy.constructor.name === 'B52') { effectColor = 0xFFFF00; // Yellow effect for B52s effectDuration = 400; } LK.effects.flashObject(laser, effectColor, effectDuration); if (enemy.takeDamage()) { // Enemy destroyed - use enemy's reward value var reward = enemy.reward || 100; LK.setScore(LK.getScore() + reward); scoreTxt.setText('Score: ' + LK.getScore()); LK.getSound('enemyDestroy').play(); // Flash effect LK.effects.flashObject(enemy, effectColor, effectDuration); // Special area damage for B52 if (enemy.constructor.name === 'B52' && enemy.explodeAreaDamage) { enemy.explodeAreaDamage(); } enemy.destroy(); enemies.splice(j, 1); enemiesKilledThisLevel++; // Check for level progression if (LK.getScore() >= scoreToAdvance[currentLevel] && enemiesKilledThisLevel >= requiredKills[currentLevel] && currentLevel < 3) { currentLevel++; enemiesKilledThisLevel = 0; levelComplete = false; levelTxt.setText('Level: ' + currentLevel); updateCannonStats(); LK.effects.flashScreen(0x00FF00, 1000); } } else { // Enemy damaged but not destroyed LK.effects.flashObject(enemy, 0xFF0000, 300); } laser.destroy(); lasers.splice(i, 1); hitEnemy = true; break; } } // Check collision with decoys if (!hitEnemy) { for (var d = decoys.length - 1; d >= 0; d--) { var decoy = decoys[d]; if (laser.intersects(decoy)) { // Laser intercepted by decoy LK.effects.flashObject(decoy, 0xFF4500, 200); LK.effects.flashObject(laser, 0xFF4500, 200); laser.destroy(); lasers.splice(i, 1); decoy.destroy(); decoys.splice(d, 1); hitEnemy = true; break; } } } if (!hitEnemy) { laser.lastY = laser.y; } } // Update decoys for (var d = decoys.length - 1; d >= 0; d--) { var decoy = decoys[d]; if (decoy.update && decoy.update()) { // Decoy expired decoy.destroy(); decoys.splice(d, 1); continue; } // Remove decoy if off screen if (decoy.y < -50) { decoy.destroy(); decoys.splice(d, 1); continue; } } // Update enemies for (var k = enemies.length - 1; k >= 0; k--) { var enemy = enemies[k]; if (enemy.lastY === undefined) enemy.lastY = enemy.y; // Update UAV and Rocket targets to track cannon if (enemy.setTarget) { enemy.setTarget(cannon.x, cannon.y); } // Check if enemy reached bottom if (enemy.y > 2732 + 100) { enemy.destroy(); enemies.splice(k, 1); continue; } // Check collision with cannon if (enemy.intersects(cannon)) { // Game over LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); return; } enemy.lastY = enemy.y; } // Check for wave completion and increase difficulty if (LK.ticks % 1800 === 0) { // Every 30 seconds updateWave(); } // Victory condition - complete level 3 if (currentLevel === 3 && LK.getScore() >= scoreToAdvance[3] && enemiesKilledThisLevel >= requiredKills[3]) { LK.showYouWin(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var B52 = Container.expand(function () {
var self = Container.call(this);
var b52Graphics = self.attachAsset('B52', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint B52 to make it visually distinct (dark gray)
b52Graphics.tint = 0x666666;
self.speed = 1; // Very slow speed
self.health = 5; // 5 hit points - highest health
self.reward = 15000; // $15000 reward - highest reward
self.targetX = 0;
self.targetY = 0;
self.moveTimer = 0;
self.dodgeTimer = 0;
self.dodgeDirection = 1;
self.decoyTimer = 0;
self.maxDecoyRate = 90; // Can deploy decoy every 1.5 seconds
self.update = function () {
// B52 moves slowly and steadily towards target with enhanced dodging
self.moveTimer++;
self.dodgeTimer++;
self.decoyTimer++;
// Enhanced dodging behavior - check for nearby lasers
var shouldDodge = false;
for (var i = 0; i < lasers.length; i++) {
var laser = lasers[i];
var distanceToLaser = Math.sqrt((laser.x - self.x) * (laser.x - self.x) + (laser.y - self.y) * (laser.y - self.y));
if (distanceToLaser < 150 && laser.y < self.y) {
shouldDodge = true;
// Deploy decoy if available
if (self.decoyTimer >= self.maxDecoyRate) {
self.deployDecoy();
}
break;
}
}
// Evasive maneuvers when dodging
if (shouldDodge) {
if (self.dodgeTimer % 30 === 0) {
self.dodgeDirection *= -1;
}
}
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
// Add dodging movement
if (shouldDodge) {
moveX += Math.sin(self.moveTimer * 0.2) * 3 * self.dodgeDirection;
moveY *= 0.5; // Slow down forward movement when dodging
}
self.x += moveX;
self.y += moveY;
// Keep within screen bounds
self.x = Math.max(60, Math.min(2048 - 60, self.x));
}
};
self.deployDecoy = function () {
self.decoyTimer = 0;
// Create decoy explosive
var decoy = new Decoy();
decoy.x = self.x + (Math.random() - 0.5) * 100; // Random offset
decoy.y = self.y - 30;
decoys.push(decoy);
game.addChild(decoy);
};
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
return true; // B52 destroyed
}
return false;
};
self.explodeAreaDamage = function () {
// Area damage when B52 is destroyed
var damageRadius = 200;
LK.effects.flashObject(self, 0xFF6600, 600);
// Damage nearby enemies (friendly fire)
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy !== self) {
var distance = Math.sqrt((enemy.x - self.x) * (enemy.x - self.x) + (enemy.y - self.y) * (enemy.y - self.y));
if (distance < damageRadius) {
if (enemy.takeDamage && enemy.takeDamage()) {
// Enemy destroyed by area damage
LK.effects.flashObject(enemy, 0xFF6600, 400);
enemy.destroy();
enemies.splice(i, 1);
}
}
}
}
// Destroy nearby lasers
for (var j = lasers.length - 1; j >= 0; j--) {
var laser = lasers[j];
var distance = Math.sqrt((laser.x - self.x) * (laser.x - self.x) + (laser.y - self.y) * (laser.y - self.y));
if (distance < damageRadius) {
laser.destroy();
lasers.splice(j, 1);
}
}
};
return self;
});
var Cannon = Container.expand(function () {
var self = Container.call(this);
var cannonGraphics = self.attachAsset('cannon', {
anchorX: 0.5,
anchorY: 1.0
});
self.fireRate = 0;
self.maxFireRate = 2; // Fire every 2 frames at max - 3 shots per second
self.update = function () {
if (self.fireRate > 0) {
self.fireRate--;
}
};
self.canFire = function () {
return self.fireRate <= 0;
};
self.fire = function () {
if (self.canFire()) {
self.fireRate = self.maxFireRate;
return true;
}
return false;
};
return self;
});
var Decoy = Container.expand(function () {
var self = Container.call(this);
var decoyGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint decoy to make it look like a small explosive (red-orange)
decoyGraphics.tint = 0xFF4500;
decoyGraphics.scaleX = 0.6;
decoyGraphics.scaleY = 0.6;
self.speed = -8; // Move upward to intercept lasers
self.lifeTime = 180; // 3 seconds at 60fps
self.update = function () {
self.y += self.speed;
self.lifeTime--;
// Self-destruct after lifetime expires
if (self.lifeTime <= 0) {
return true; // Mark for destruction
}
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.health = 1;
self.reward = 500; // Default reward for basic enemy - increased reward
self.update = function () {
self.y += self.speed;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
return true; // Enemy destroyed
}
return false;
};
return self;
});
var F35 = Container.expand(function () {
var self = Container.call(this);
var f35Graphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint F35 to make it visually distinct (darker blue)
f35Graphics.tint = 0x4444FF;
self.speed = 2; // Slow speed
self.health = 3; // 3 hit points
self.reward = 10000; // $10000 reward
self.targetX = 0;
self.targetY = 0;
self.agileTimer = 0;
self.agileDirection = 1;
self.update = function () {
// Agile movement - add evasive maneuvers
self.agileTimer++;
if (self.agileTimer % 60 === 0) {
self.agileDirection *= -1;
}
// Move towards target with agile zigzag pattern
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed + Math.sin(self.agileTimer * 0.1) * 2 * self.agileDirection;
self.y += dy / distance * self.speed;
}
};
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
return true; // F35 destroyed
}
return false;
};
return self;
});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Rocket = Container.expand(function () {
var self = Container.call(this);
var rocketGraphics = self.attachAsset('Rockets', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6; // Fast speed
self.health = 1; // 1 hit point
self.reward = 1000; // $1000 reward
self.targetX = 0;
self.targetY = 0;
self.update = function () {
// Move directly towards the cannon with higher speed
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
return true; // Rocket destroyed
}
return false;
};
return self;
});
var UAV = Container.expand(function () {
var self = Container.call(this);
var uavGraphics = self.attachAsset('UAV', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4; // Medium speed
self.health = 2; // 2 hit points
self.reward = 2500; // $2500 reward
self.targetX = 0;
self.targetY = 0;
self.update = function () {
// Move directly towards the cannon
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
return true; // UAV destroyed
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Create gradient background from sky blue at top to green-brown at bottom
var backgroundGradient = LK.getAsset('background', {
width: 2048,
height: 2732,
color: 0x87CEEB,
// Sky blue
shape: 'box'
});
game.addChild(backgroundGradient);
// Create multiple horizontal strips for gradient effect
var gradientStrips = [];
var stripHeight = 60;
var totalStrips = Math.ceil(2732 / stripHeight);
for (var i = 0; i < totalStrips; i++) {
var strip = LK.getAsset('gradientStrip_' + i, {
width: 2048,
height: stripHeight,
color: 0x87CEEB,
// Will be tinted for gradient
shape: 'box'
});
strip.y = i * stripHeight;
// Calculate gradient progression from sky blue to green to brown
var progress = i / totalStrips;
var r, g, b;
if (progress < 0.6) {
// Sky blue to green transition (top 60% of screen)
var skyProgress = progress / 0.6;
r = Math.floor(135 + (34 - 135) * skyProgress); // 135 -> 34
g = Math.floor(206 + (139 - 206) * skyProgress); // 206 -> 139
b = Math.floor(235 + (34 - 235) * skyProgress); // 235 -> 34
} else {
// Green to brown transition (bottom 40% of screen)
var groundProgress = (progress - 0.6) / 0.4;
r = Math.floor(34 + (139 - 34) * groundProgress); // 34 -> 139
g = Math.floor(139 + (69 - 139) * groundProgress); // 139 -> 69
b = Math.floor(34 + (19 - 34) * groundProgress); // 34 -> 19
}
var color = r << 16 | g << 8 | b;
strip.tint = color;
game.addChild(strip);
gradientStrips.push(strip);
}
// Game variables
var cannon;
var lasers = [];
var enemies = [];
var decoys = [];
var enemySpawnTimer = 0;
var enemySpawnRate = 120; // Spawn enemy every 2 seconds initially
var gameSpeed = 1;
var waveNumber = 1;
var currentLevel = 1;
var enemiesKilledThisLevel = 0;
var requiredKills = {
1: 10,
2: 20,
3: 30
}; // Total enemies per level
var scoreToAdvance = {
1: 10000,
2: 25000,
3: 50000
};
var levelComplete = false;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFF00
});
waveTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(waveTxt);
var levelTxt = new Text2('Level: 1', {
size: 50,
fill: 0x00FFFF
});
levelTxt.anchor.set(0, 0);
levelTxt.x = 120; // Offset from left edge to avoid menu icon
LK.gui.topLeft.addChild(levelTxt);
// Initialize cannon
cannon = game.addChild(new Cannon());
cannon.x = 2048 / 2;
cannon.y = 2732 - 100;
// Set initial cannon stats for level 1
function updateCannonStats() {
if (currentLevel === 1) {
cannon.maxFireRate = 2; // 3 shots per second
cannonSpeed = 24; // Normal movement
} else if (currentLevel === 2) {
cannon.maxFireRate = 1; // 6 shots per second - faster
cannonSpeed = 32; // Faster movement
} else if (currentLevel === 3) {
cannon.maxFireRate = 1; // Keep high fire rate
cannonSpeed = 40; // Fastest movement
}
}
updateCannonStats();
// Touch controls
var isDragging = false;
var cannonSpeed = 24;
game.down = function (x, y, obj) {
// Check if touch is in the cannon control area for dragging
if (y > 2732 - 300) {
isDragging = true;
cannon.x = Math.max(60, Math.min(2048 - 60, x));
}
// Fire laser on any tap/touch - gun sound plays when player pushes laser
if (cannon.fire()) {
if (currentLevel === 3) {
// Double laser beams for level 3
var laser1 = new Laser();
laser1.x = cannon.x - 30;
laser1.y = cannon.y - 50;
lasers.push(laser1);
game.addChild(laser1);
var laser2 = new Laser();
laser2.x = cannon.x + 30;
laser2.y = cannon.y - 50;
lasers.push(laser2);
game.addChild(laser2);
} else {
// Single laser beam for levels 1 and 2
var laser = new Laser();
laser.x = cannon.x;
laser.y = cannon.y - 50;
lasers.push(laser);
game.addChild(laser);
}
LK.getSound('shoot').play();
}
};
game.move = function (x, y, obj) {
if (isDragging) {
cannon.x = Math.max(60, Math.min(2048 - 60, x));
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Spawn enemy function
function spawnEnemy() {
// Level-based enemy spawning
var levelSpawnQueue = [];
if (currentLevel === 1) {
// Level 1: 5 Rockets, 3 Drones, 1 F-35, 1 B52
for (var i = 0; i < 5; i++) levelSpawnQueue.push('rocket');
for (var i = 0; i < 3; i++) levelSpawnQueue.push('uav');
for (var i = 0; i < 1; i++) levelSpawnQueue.push('f35');
for (var i = 0; i < 1; i++) levelSpawnQueue.push('b52');
} else if (currentLevel === 2) {
// Level 2: 10 Rockets, 6 Drones, 2 F-35s, 2 B52s
for (var i = 0; i < 10; i++) levelSpawnQueue.push('rocket');
for (var i = 0; i < 6; i++) levelSpawnQueue.push('uav');
for (var i = 0; i < 2; i++) levelSpawnQueue.push('f35');
for (var i = 0; i < 2; i++) levelSpawnQueue.push('b52');
} else if (currentLevel === 3) {
// Level 3: 15 Rockets, 9 Drones, 3 F-35s, 3 B52s
for (var i = 0; i < 15; i++) levelSpawnQueue.push('rocket');
for (var i = 0; i < 9; i++) levelSpawnQueue.push('uav');
for (var i = 0; i < 3; i++) levelSpawnQueue.push('f35');
for (var i = 0; i < 3; i++) levelSpawnQueue.push('b52');
}
// Don't spawn if we've reached the level limit
if (enemiesKilledThisLevel >= requiredKills[currentLevel]) {
return;
}
// Randomly pick from the queue
var enemyType = levelSpawnQueue[Math.floor(Math.random() * levelSpawnQueue.length)];
// Level multipliers for stats
var speedMultiplier = currentLevel === 1 ? 1 : currentLevel === 2 ? 1.5 : 2;
var healthMultiplier = currentLevel === 1 ? 1 : currentLevel === 2 ? 1.5 : 2;
if (enemyType === 'rocket') {
var rocket = new Rocket();
rocket.x = Math.random() * (2048 - 160) + 80;
rocket.y = -100;
rocket.speed = (6 + Math.random() * 1.5) * speedMultiplier;
rocket.health = Math.floor(1 * healthMultiplier);
// Update rewards based on level
if (currentLevel === 1) rocket.reward = 1000;else if (currentLevel === 2) rocket.reward = 1200;else if (currentLevel === 3) rocket.reward = 1500;
rocket.setTarget(cannon.x, cannon.y);
enemies.push(rocket);
game.addChild(rocket);
} else if (enemyType === 'uav') {
var uav = new UAV();
uav.x = Math.random() * (2048 - 160) + 80;
uav.y = -100;
uav.speed = (4 + Math.random() * 1.5) * speedMultiplier;
uav.health = Math.floor(2 * healthMultiplier);
// Update rewards based on level
if (currentLevel === 1) uav.reward = 2500;else if (currentLevel === 2) uav.reward = 3000;else if (currentLevel === 3) uav.reward = 4000;
uav.setTarget(cannon.x, cannon.y);
enemies.push(uav);
game.addChild(uav);
} else if (enemyType === 'f35') {
var f35 = new F35();
f35.x = Math.random() * (2048 - 160) + 80;
f35.y = -100;
f35.speed = (2 + Math.random() * 0.5) * speedMultiplier;
f35.health = Math.floor(3 * healthMultiplier);
// Update rewards based on level
if (currentLevel === 1) f35.reward = 5000;else if (currentLevel === 2) f35.reward = 6000;else if (currentLevel === 3) f35.reward = 8000;
f35.setTarget(cannon.x, cannon.y);
enemies.push(f35);
game.addChild(f35);
} else if (enemyType === 'b52') {
var b52 = new B52();
b52.x = Math.random() * (2048 - 160) + 80;
b52.y = -100;
b52.speed = (1 + Math.random() * 0.5) * speedMultiplier;
b52.health = Math.floor(5 * healthMultiplier);
// Update rewards based on level
if (currentLevel === 1) b52.reward = 15000;else if (currentLevel === 2) b52.reward = 18000;else if (currentLevel === 3) b52.reward = 22000;
b52.setTarget(cannon.x, cannon.y);
enemies.push(b52);
game.addChild(b52);
}
}
// Update wave difficulty
function updateWave() {
waveNumber++;
enemySpawnRate = Math.max(30, enemySpawnRate - 10);
waveTxt.setText('Wave: ' + waveNumber);
// Flash effect for new wave
LK.effects.flashScreen(0x00FF00, 500);
}
// Main game loop
game.update = function () {
// Player-controlled laser firing - only when player touches/taps
// No automatic firing - gun sound only plays when player pushes laser
// Update enemy spawn timer
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnRate) {
spawnEnemy();
enemySpawnTimer = 0;
}
// Update lasers
for (var i = lasers.length - 1; i >= 0; i--) {
var laser = lasers[i];
if (laser.lastY === undefined) laser.lastY = laser.y;
// Remove laser if off screen
if (laser.lastY >= -50 && laser.y < -50) {
laser.destroy();
lasers.splice(i, 1);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (laser.intersects(enemy)) {
// Hit enemy
LK.getSound('enemyHit').play();
// Different laser effects based on enemy type
var effectColor = 0xFFFFFF;
var effectDuration = 200;
if (enemy.constructor.name === 'Rocket') {
effectColor = 0xFF6600; // Orange effect for rockets
effectDuration = 150;
} else if (enemy.constructor.name === 'UAV') {
effectColor = 0x00FFFF; // Cyan effect for UAVs
effectDuration = 250;
} else if (enemy.constructor.name === 'F35') {
effectColor = 0xFF00FF; // Magenta effect for F35s
effectDuration = 300;
} else if (enemy.constructor.name === 'B52') {
effectColor = 0xFFFF00; // Yellow effect for B52s
effectDuration = 400;
}
LK.effects.flashObject(laser, effectColor, effectDuration);
if (enemy.takeDamage()) {
// Enemy destroyed - use enemy's reward value
var reward = enemy.reward || 100;
LK.setScore(LK.getScore() + reward);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('enemyDestroy').play();
// Flash effect
LK.effects.flashObject(enemy, effectColor, effectDuration);
// Special area damage for B52
if (enemy.constructor.name === 'B52' && enemy.explodeAreaDamage) {
enemy.explodeAreaDamage();
}
enemy.destroy();
enemies.splice(j, 1);
enemiesKilledThisLevel++;
// Check for level progression
if (LK.getScore() >= scoreToAdvance[currentLevel] && enemiesKilledThisLevel >= requiredKills[currentLevel] && currentLevel < 3) {
currentLevel++;
enemiesKilledThisLevel = 0;
levelComplete = false;
levelTxt.setText('Level: ' + currentLevel);
updateCannonStats();
LK.effects.flashScreen(0x00FF00, 1000);
}
} else {
// Enemy damaged but not destroyed
LK.effects.flashObject(enemy, 0xFF0000, 300);
}
laser.destroy();
lasers.splice(i, 1);
hitEnemy = true;
break;
}
}
// Check collision with decoys
if (!hitEnemy) {
for (var d = decoys.length - 1; d >= 0; d--) {
var decoy = decoys[d];
if (laser.intersects(decoy)) {
// Laser intercepted by decoy
LK.effects.flashObject(decoy, 0xFF4500, 200);
LK.effects.flashObject(laser, 0xFF4500, 200);
laser.destroy();
lasers.splice(i, 1);
decoy.destroy();
decoys.splice(d, 1);
hitEnemy = true;
break;
}
}
}
if (!hitEnemy) {
laser.lastY = laser.y;
}
}
// Update decoys
for (var d = decoys.length - 1; d >= 0; d--) {
var decoy = decoys[d];
if (decoy.update && decoy.update()) {
// Decoy expired
decoy.destroy();
decoys.splice(d, 1);
continue;
}
// Remove decoy if off screen
if (decoy.y < -50) {
decoy.destroy();
decoys.splice(d, 1);
continue;
}
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Update UAV and Rocket targets to track cannon
if (enemy.setTarget) {
enemy.setTarget(cannon.x, cannon.y);
}
// Check if enemy reached bottom
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(k, 1);
continue;
}
// Check collision with cannon
if (enemy.intersects(cannon)) {
// Game over
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
enemy.lastY = enemy.y;
}
// Check for wave completion and increase difficulty
if (LK.ticks % 1800 === 0) {
// Every 30 seconds
updateWave();
}
// Victory condition - complete level 3
if (currentLevel === 3 && LK.getScore() >= scoreToAdvance[3] && enemiesKilledThisLevel >= requiredKills[3]) {
LK.showYouWin();
}
};
F35 like fighter jet. In-Game asset. 2d. High contrast. No shadows
Overwiev of unmanned aircraft coming to us. 2d. High contrast. No shadows
Looking like real rocket. Rocket picture. In-Game asset. 2d. High contrast. No shadows
Imagine that a Big laser machine you see from upside. Stands from back to the forward. Tries to hit enemy's.. In-Game asset. 2d. High contrast. No shadows