/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, level: 1 }); /**** * Classes ****/ var CounterRocket = Container.expand(function () { var self = Container.call(this); var rocketGraphic = self.attachAsset('counter_rocket', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 12; self.active = true; self.blastRadius = 100; self.init = function (startX, startY, targetX, targetY) { self.x = startX; self.y = startY; self.targetX = targetX; self.targetY = targetY; // Calculate direction vector var dx = targetX - startX; var dy = targetY - startY; var dist = Math.sqrt(dx * dx + dy * dy); self.vx = dx / dist * self.speed; self.vy = dy / dist * self.speed; // Set rotation self.rotation = Math.atan2(dx, -dy); }; self.update = function () { if (!self.active) { return; } // Move along trajectory self.x += self.vx; self.y += self.vy; // Check if reached target area var distToTarget = Math.sqrt(Math.pow(self.x - self.targetX, 2) + Math.pow(self.y - self.targetY, 2)); if (distToTarget < 10) { self.explode(); } // Check for missile hits if (self.active) { // Track if we hit any missiles directly var hitMissile = false; // Check all missiles for direct hits for (var i = 0; i < missiles.length; i++) { var missile = missiles[i]; if (missile.active) { var dist = Math.sqrt(Math.pow(self.x - missile.x, 2) + Math.pow(self.y - missile.y, 2)); // Direct hit if within 30px if (dist < 30) { missile.explode(); self.explode(); hitMissile = true; // Award points and increase combo score += 20 * (1 + level * 0.1); comboCount++; if (comboCount > 1) { // Bonus points for combos score += 5 * comboCount; } updateUI(); break; } } } // Check if level should advance if (score >= level * 1000) { advanceLevel(); } } // Check if off screen if (self.y < -100 || self.y > 2832 || self.x < -100 || self.x > 2148) { self.destroy(); // Remove from counter rockets array var index = counterRockets.indexOf(self); if (index !== -1) { counterRockets.splice(index, 1); } } }; self.explode = function () { self.active = false; // Create explosion var explosion = new Explosion(); explosion.x = self.x; explosion.y = self.y; explosion.init(self.blastRadius); game.addChild(explosion); // Check for missile hits game.checkMissileHits(self.x, self.y, self.blastRadius); // Play sound LK.getSound('explosion_sound').play(); // Remove rocket self.destroy(); // Remove from counter rockets array var index = counterRockets.indexOf(self); if (index !== -1) { counterRockets.splice(index, 1); } }; return self; }); var DefenseStation = Container.expand(function () { var self = Container.call(this); var stationGraphic = self.attachAsset('defense_station', { anchorX: 0.5, anchorY: 0.5 }); var aimLine = self.attachAsset('aim_line', { anchorX: 0.5, anchorY: 1, alpha: 0.7 }); self.init = function () { self.x = 2048 / 2; self.y = 2732 - 60 - 100; // Just above ground aimLine.visible = false; aimLine.rotation = -Math.PI / 2; // Pointing upward }; self.startAiming = function (x, y) { aimLine.visible = true; self.updateAimLine(x, y); }; self.updateAimLine = function (x, y) { if (!aimLine.visible) { return; } // Calculate angle for aim line var dx = x - self.x; var dy = y - self.y; var angle = Math.atan2(dx, -dy); // Negative dy because y is inverted // Restrict angle (can't aim below horizon) if (angle > Math.PI / 2) { angle = Math.PI / 2; } if (angle < -Math.PI / 2) { angle = -Math.PI / 2; } aimLine.rotation = angle; }; self.stopAiming = function () { aimLine.visible = false; }; self.fire = function (x, y) { // Calculate direction and target position var dx = x - self.x; var dy = y - self.y; var angle = Math.atan2(dx, -dy); // Restrict angle (can't fire below horizon) if (angle > Math.PI / 2) { angle = Math.PI / 2; } if (angle < -Math.PI / 2) { angle = -Math.PI / 2; } // Calculate target point var reach = 2000; var targetX = self.x + Math.sin(angle) * reach; var targetY = self.y - Math.cos(angle) * reach; // Fire main rocket var rocket = new CounterRocket(); rocket.init(self.x, self.y, targetX, targetY); counterRockets.push(rocket); game.addChild(rocket); // Fire additional rockets if multishot is active if (game.multishotActive) { var spread = Math.PI / 12; // 15 degrees // Left rocket var leftRocket = new CounterRocket(); var leftAngle = angle - spread; var leftTargetX = self.x + Math.sin(leftAngle) * reach; var leftTargetY = self.y - Math.cos(leftAngle) * reach; leftRocket.init(self.x, self.y, leftTargetX, leftTargetY); counterRockets.push(leftRocket); game.addChild(leftRocket); // Right rocket var rightRocket = new CounterRocket(); var rightAngle = angle + spread; var rightTargetX = self.x + Math.sin(rightAngle) * reach; var rightTargetY = self.y - Math.cos(rightAngle) * reach; rightRocket.init(self.x, self.y, rightTargetX, rightTargetY); counterRockets.push(rightRocket); game.addChild(rightRocket); } // Play sound LK.getSound('rocket_launch').play(); }; return self; }); var Explosion = Container.expand(function () { var self = Container.call(this); var explosionGraphic = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); self.init = function (radius) { self.radius = radius || 75; explosionGraphic.width = self.radius * 2; explosionGraphic.height = self.radius * 2; // Start animation explosionGraphic.alpha = 0.9; tween(explosionGraphic, { alpha: 0, width: self.radius * 3, height: self.radius * 3 }, { duration: 600, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var Missile = Container.expand(function () { var self = Container.call(this); var missileGraphic = self.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5 }); // Default properties self.speed = 3; self.targetX = 0; self.active = true; self.init = function (startX, speed, targetX) { self.x = startX; self.y = -100; self.speed = speed || 3; self.targetX = targetX || self.x; // Calculate angle based on trajectory var dx = self.targetX - self.x; var dy = 2732 - self.y; self.rotation = Math.atan2(dx, dy); }; self.update = function () { if (!self.active) { return; } // Move towards target var dx = self.targetX - self.x; var groundY = 2732 - 60; // Ground level var percentComplete = self.y / groundY; self.x += dx * 0.005; self.y += self.speed; // Check if hit ground if (self.y >= groundY - 40) { self.explode(); game.missileHitGround(self.x); } }; self.explode = function () { self.active = false; // Create explosion var explosion = new Explosion(); explosion.x = self.x; explosion.y = self.y; explosion.init(75); game.addChild(explosion); // Play sound LK.getSound('explosion_sound').play(); // Remove missile self.destroy(); // Remove from missiles array var index = missiles.indexOf(self); if (index !== -1) { missiles.splice(index, 1); } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphic = self.attachAsset('power_up', { anchorX: 0.5, anchorY: 0.5 }); self.type = "multishot"; self.fallSpeed = 2; self.active = true; self.init = function (type) { self.type = type || (Math.random() < 0.5 ? "multishot" : "nuke"); // Set color based on type if (self.type === "multishot") { powerUpGraphic.tint = 0x9b59b6; // Purple } else { powerUpGraphic.tint = 0xe74c3c; // Red } // Position self.x = 100 + Math.random() * (2048 - 200); self.y = -100; // Animation tween(self, { rotation: Math.PI * 2 }, { duration: 3000, onFinish: function onFinish() { if (self.active) { self.rotation = 0; tween(self, { rotation: Math.PI * 2 }, { duration: 3000 }); } } }); }; self.update = function () { if (!self.active) { return; } // Fall down self.y += self.fallSpeed; // Check if hit ground if (self.y >= 2732 - 60 - 40) { self.destroy(); var index = powerUps.indexOf(self); if (index !== -1) { powerUps.splice(index, 1); } } // Check if near defense station var distToStation = Math.sqrt(Math.pow(self.x - defenseStation.x, 2) + Math.pow(self.y - defenseStation.y, 2)); if (distToStation < 150) { self.collect(); } }; self.collect = function () { self.active = false; // Apply power up effect if (self.type === "multishot") { game.activateMultishot(); } else { game.activateNuke(); } // Play sound LK.getSound('power_up_collect').play(); // Remove power up self.destroy(); // Remove from powerUps array var index = powerUps.indexOf(self); if (index !== -1) { powerUps.splice(index, 1); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x121f2a }); /**** * Game Code ****/ // Game variables var score = 0; var level = 1; var lives = 3; var isAiming = false; var aimStartX = 0; var aimStartY = 0; var missiles = []; var counterRockets = []; var powerUps = []; var defenseStation; var ground; var gameActive = true; var missileSpawnRate = 3000; // Time in ms between missile spawns var missileSpawnTimer = null; var powerUpSpawnTimer = null; var multishotTimeoutId = null; var comboCount = 0; var comboTimer = null; // UI elements var scoreTxt; var livesTxt; var levelTxt; var comboTxt; // Initialize game objects function initGame() { // Set background game.setBackgroundColor(0x121f2a); // Play background music LK.playMusic('game_music'); // Create ground ground = LK.getAsset('ground', { anchorX: 0.5, anchorY: 0.5 }); ground.x = 2048 / 2; ground.y = 2732 - 30; // Bottom of screen game.addChild(ground); // Create defense station defenseStation = new DefenseStation(); defenseStation.init(); game.addChild(defenseStation); // Setup UI setupUI(); // Start missile spawning startMissileSpawner(); // Start power-up spawning startPowerUpSpawner(); // Reset game state score = 0; level = storage.level || 1; lives = 3; gameActive = true; game.multishotActive = false; comboCount = 0; // Update UI updateUI(); } function setupUI() { // Glaud inscription var glaudTxt = new Text2('Glaud', { size: 40, fill: 0xFF8C00 }); glaudTxt.anchor.set(1, 0); LK.gui.topRight.addChild(glaudTxt); glaudTxt.x = -20; glaudTxt.y = 80; // Score text scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -280; scoreTxt.y = 20; // Lives text livesTxt = new Text2('Lives: 3', { size: 60, fill: 0xFFFFFF }); livesTxt.anchor.set(0, 0); LK.gui.top.addChild(livesTxt); livesTxt.y = 20; // Level text levelTxt = new Text2('Level: 1', { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(levelTxt); levelTxt.x = 120; // Avoid the top-left 100x100 reserved area levelTxt.y = 20; // Combo text comboTxt = new Text2('', { size: 80, fill: 0xF1C40F }); comboTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(comboTxt); comboTxt.visible = false; } function updateUI() { scoreTxt.setText('Score: ' + score); livesTxt.setText('Lives: ' + lives); levelTxt.setText('Level: ' + level); if (comboCount > 1) { comboTxt.setText('COMBO x' + comboCount + '!'); comboTxt.visible = true; // Reset combo timer if (comboTimer) { LK.clearTimeout(comboTimer); } comboTimer = LK.setTimeout(function () { comboTxt.visible = false; comboCount = 0; }, 2000); } } function startMissileSpawner() { // Clear any existing timer if (missileSpawnTimer) { LK.clearInterval(missileSpawnTimer); } // Calculate spawn rate based on level var rate = Math.max(3000 - level * 200, 500); missileSpawnTimer = LK.setInterval(function () { if (!gameActive) { return; } spawnMissile(); }, rate); } function spawnMissile() { // Create a new missile var missile = new Missile(); // Randomize starting position var startX = Math.random() * 2048; // Randomize target position var targetX = Math.random() * 2048; // Calculate speed based on level var speed = 3 + level * 0.5; // Initialize missile missile.init(startX, speed, targetX); // Add to game missiles.push(missile); game.addChild(missile); } function startPowerUpSpawner() { // Clear any existing timer if (powerUpSpawnTimer) { LK.clearInterval(powerUpSpawnTimer); } powerUpSpawnTimer = LK.setInterval(function () { if (!gameActive) { return; } // 10% chance to spawn a power-up if (Math.random() < 0.1) { spawnPowerUp(); } }, 5000); } function spawnPowerUp() { // Create a new power-up var powerUp = new PowerUp(); // Initialize power-up powerUp.init(); // Add to game powerUps.push(powerUp); game.addChild(powerUp); } // Game mechanics game.checkMissileHits = function (x, y, radius) { var hitCount = 0; // Check all missiles for (var i = missiles.length - 1; i >= 0; i--) { var missile = missiles[i]; if (!missile.active) { continue; } // Calculate distance var dist = Math.sqrt(Math.pow(missile.x - x, 2) + Math.pow(missile.y - y, 2)); // If missile is within blast radius if (dist <= radius) { missile.explode(); hitCount++; // Award points score += 10 * (1 + level * 0.1); // Increment combo comboCount++; if (comboCount > 1) { // Bonus points for combos score += 5 * comboCount; } } } // Check if level should advance if (score >= level * 1000) { advanceLevel(); } // Update UI updateUI(); return hitCount; }; game.missileHitGround = function (x) { // Visual effect var groundExplosion = new Explosion(); groundExplosion.x = x; groundExplosion.y = 2732 - 60; groundExplosion.init(100); game.addChild(groundExplosion); // Reduce lives lives--; // Reset combo comboCount = 0; if (comboTimer) { LK.clearTimeout(comboTimer); } comboTxt.visible = false; // Update UI updateUI(); // Check for game over if (lives <= 0) { gameOver(); } }; function gameOver() { gameActive = false; // Stop spawners if (missileSpawnTimer) { LK.clearInterval(missileSpawnTimer); } if (powerUpSpawnTimer) { LK.clearInterval(powerUpSpawnTimer); } // Update high score if (score > storage.highScore) { storage.highScore = score; } // Set final score LK.setScore(score); // Show game over screen LK.showGameOver(); } function advanceLevel() { level++; storage.level = level; // Update UI updateUI(); // Flash level indicator tween(levelTxt, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { tween(levelTxt, { alpha: 1 }, { duration: 200 }); } }); // Restart missile spawner with new rate startMissileSpawner(); } game.activateMultishot = function () { game.multishotActive = true; // Create visual indicator defenseStation.attachAsset('power_up', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -50, tint: 0x9b59b6, alpha: 0.7, scale: 0.5 }); // Clear previous timeout if exists if (multishotTimeoutId) { LK.clearTimeout(multishotTimeoutId); } // Set timeout to disable multishot multishotTimeoutId = LK.setTimeout(function () { game.multishotActive = false; // Remove all power-up indicators from defense station for (var i = 0; i < defenseStation.children.length; i++) { var child = defenseStation.children[i]; if (child.color && child.color === 0x9b59b6) { defenseStation.removeChild(child); child.destroy(); } } }, 10000); // 10 seconds }; game.activateNuke = function () { // Create large explosion at center var nukeExplosion = new Explosion(); nukeExplosion.x = 2048 / 2; nukeExplosion.y = 2732 / 2; nukeExplosion.init(1500); // Large radius game.addChild(nukeExplosion); // Destroy all missiles var destroyedCount = 0; for (var i = missiles.length - 1; i >= 0; i--) { var missile = missiles[i]; if (missile.active) { missile.explode(); destroyedCount++; } } // Award points if (destroyedCount > 0) { score += destroyedCount * 15; updateUI(); } }; // Input handling game.down = function (x, y, obj) { if (!gameActive) { return; } isAiming = true; aimStartX = x; aimStartY = y; // Start aiming defenseStation.startAiming(x, y); }; game.move = function (x, y, obj) { if (!isAiming || !gameActive) { return; } // Update aim line defenseStation.updateAimLine(x, y); }; game.up = function (x, y, obj) { if (!isAiming || !gameActive) { return; } // Fire rocket defenseStation.fire(x, y); // Reset aiming isAiming = false; defenseStation.stopAiming(); }; // Game loop game.update = function () { if (!gameActive) { return; } // Update missiles for (var i = missiles.length - 1; i >= 0; i--) { missiles[i].update(); } // Update counter rockets for (var i = counterRockets.length - 1; i >= 0; i--) { counterRockets[i].update(); } // Update power-ups for (var i = powerUps.length - 1; i >= 0; i--) { powerUps[i].update(); } }; // Initialize the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
/****
* Classes
****/
var CounterRocket = Container.expand(function () {
var self = Container.call(this);
var rocketGraphic = self.attachAsset('counter_rocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.active = true;
self.blastRadius = 100;
self.init = function (startX, startY, targetX, targetY) {
self.x = startX;
self.y = startY;
self.targetX = targetX;
self.targetY = targetY;
// Calculate direction vector
var dx = targetX - startX;
var dy = targetY - startY;
var dist = Math.sqrt(dx * dx + dy * dy);
self.vx = dx / dist * self.speed;
self.vy = dy / dist * self.speed;
// Set rotation
self.rotation = Math.atan2(dx, -dy);
};
self.update = function () {
if (!self.active) {
return;
}
// Move along trajectory
self.x += self.vx;
self.y += self.vy;
// Check if reached target area
var distToTarget = Math.sqrt(Math.pow(self.x - self.targetX, 2) + Math.pow(self.y - self.targetY, 2));
if (distToTarget < 10) {
self.explode();
}
// Check for missile hits
if (self.active) {
// Track if we hit any missiles directly
var hitMissile = false;
// Check all missiles for direct hits
for (var i = 0; i < missiles.length; i++) {
var missile = missiles[i];
if (missile.active) {
var dist = Math.sqrt(Math.pow(self.x - missile.x, 2) + Math.pow(self.y - missile.y, 2));
// Direct hit if within 30px
if (dist < 30) {
missile.explode();
self.explode();
hitMissile = true;
// Award points and increase combo
score += 20 * (1 + level * 0.1);
comboCount++;
if (comboCount > 1) {
// Bonus points for combos
score += 5 * comboCount;
}
updateUI();
break;
}
}
}
// Check if level should advance
if (score >= level * 1000) {
advanceLevel();
}
}
// Check if off screen
if (self.y < -100 || self.y > 2832 || self.x < -100 || self.x > 2148) {
self.destroy();
// Remove from counter rockets array
var index = counterRockets.indexOf(self);
if (index !== -1) {
counterRockets.splice(index, 1);
}
}
};
self.explode = function () {
self.active = false;
// Create explosion
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
explosion.init(self.blastRadius);
game.addChild(explosion);
// Check for missile hits
game.checkMissileHits(self.x, self.y, self.blastRadius);
// Play sound
LK.getSound('explosion_sound').play();
// Remove rocket
self.destroy();
// Remove from counter rockets array
var index = counterRockets.indexOf(self);
if (index !== -1) {
counterRockets.splice(index, 1);
}
};
return self;
});
var DefenseStation = Container.expand(function () {
var self = Container.call(this);
var stationGraphic = self.attachAsset('defense_station', {
anchorX: 0.5,
anchorY: 0.5
});
var aimLine = self.attachAsset('aim_line', {
anchorX: 0.5,
anchorY: 1,
alpha: 0.7
});
self.init = function () {
self.x = 2048 / 2;
self.y = 2732 - 60 - 100; // Just above ground
aimLine.visible = false;
aimLine.rotation = -Math.PI / 2; // Pointing upward
};
self.startAiming = function (x, y) {
aimLine.visible = true;
self.updateAimLine(x, y);
};
self.updateAimLine = function (x, y) {
if (!aimLine.visible) {
return;
}
// Calculate angle for aim line
var dx = x - self.x;
var dy = y - self.y;
var angle = Math.atan2(dx, -dy); // Negative dy because y is inverted
// Restrict angle (can't aim below horizon)
if (angle > Math.PI / 2) {
angle = Math.PI / 2;
}
if (angle < -Math.PI / 2) {
angle = -Math.PI / 2;
}
aimLine.rotation = angle;
};
self.stopAiming = function () {
aimLine.visible = false;
};
self.fire = function (x, y) {
// Calculate direction and target position
var dx = x - self.x;
var dy = y - self.y;
var angle = Math.atan2(dx, -dy);
// Restrict angle (can't fire below horizon)
if (angle > Math.PI / 2) {
angle = Math.PI / 2;
}
if (angle < -Math.PI / 2) {
angle = -Math.PI / 2;
}
// Calculate target point
var reach = 2000;
var targetX = self.x + Math.sin(angle) * reach;
var targetY = self.y - Math.cos(angle) * reach;
// Fire main rocket
var rocket = new CounterRocket();
rocket.init(self.x, self.y, targetX, targetY);
counterRockets.push(rocket);
game.addChild(rocket);
// Fire additional rockets if multishot is active
if (game.multishotActive) {
var spread = Math.PI / 12; // 15 degrees
// Left rocket
var leftRocket = new CounterRocket();
var leftAngle = angle - spread;
var leftTargetX = self.x + Math.sin(leftAngle) * reach;
var leftTargetY = self.y - Math.cos(leftAngle) * reach;
leftRocket.init(self.x, self.y, leftTargetX, leftTargetY);
counterRockets.push(leftRocket);
game.addChild(leftRocket);
// Right rocket
var rightRocket = new CounterRocket();
var rightAngle = angle + spread;
var rightTargetX = self.x + Math.sin(rightAngle) * reach;
var rightTargetY = self.y - Math.cos(rightAngle) * reach;
rightRocket.init(self.x, self.y, rightTargetX, rightTargetY);
counterRockets.push(rightRocket);
game.addChild(rightRocket);
}
// Play sound
LK.getSound('rocket_launch').play();
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphic = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.init = function (radius) {
self.radius = radius || 75;
explosionGraphic.width = self.radius * 2;
explosionGraphic.height = self.radius * 2;
// Start animation
explosionGraphic.alpha = 0.9;
tween(explosionGraphic, {
alpha: 0,
width: self.radius * 3,
height: self.radius * 3
}, {
duration: 600,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Missile = Container.expand(function () {
var self = Container.call(this);
var missileGraphic = self.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5
});
// Default properties
self.speed = 3;
self.targetX = 0;
self.active = true;
self.init = function (startX, speed, targetX) {
self.x = startX;
self.y = -100;
self.speed = speed || 3;
self.targetX = targetX || self.x;
// Calculate angle based on trajectory
var dx = self.targetX - self.x;
var dy = 2732 - self.y;
self.rotation = Math.atan2(dx, dy);
};
self.update = function () {
if (!self.active) {
return;
}
// Move towards target
var dx = self.targetX - self.x;
var groundY = 2732 - 60; // Ground level
var percentComplete = self.y / groundY;
self.x += dx * 0.005;
self.y += self.speed;
// Check if hit ground
if (self.y >= groundY - 40) {
self.explode();
game.missileHitGround(self.x);
}
};
self.explode = function () {
self.active = false;
// Create explosion
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
explosion.init(75);
game.addChild(explosion);
// Play sound
LK.getSound('explosion_sound').play();
// Remove missile
self.destroy();
// Remove from missiles array
var index = missiles.indexOf(self);
if (index !== -1) {
missiles.splice(index, 1);
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphic = self.attachAsset('power_up', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = "multishot";
self.fallSpeed = 2;
self.active = true;
self.init = function (type) {
self.type = type || (Math.random() < 0.5 ? "multishot" : "nuke");
// Set color based on type
if (self.type === "multishot") {
powerUpGraphic.tint = 0x9b59b6; // Purple
} else {
powerUpGraphic.tint = 0xe74c3c; // Red
}
// Position
self.x = 100 + Math.random() * (2048 - 200);
self.y = -100;
// Animation
tween(self, {
rotation: Math.PI * 2
}, {
duration: 3000,
onFinish: function onFinish() {
if (self.active) {
self.rotation = 0;
tween(self, {
rotation: Math.PI * 2
}, {
duration: 3000
});
}
}
});
};
self.update = function () {
if (!self.active) {
return;
}
// Fall down
self.y += self.fallSpeed;
// Check if hit ground
if (self.y >= 2732 - 60 - 40) {
self.destroy();
var index = powerUps.indexOf(self);
if (index !== -1) {
powerUps.splice(index, 1);
}
}
// Check if near defense station
var distToStation = Math.sqrt(Math.pow(self.x - defenseStation.x, 2) + Math.pow(self.y - defenseStation.y, 2));
if (distToStation < 150) {
self.collect();
}
};
self.collect = function () {
self.active = false;
// Apply power up effect
if (self.type === "multishot") {
game.activateMultishot();
} else {
game.activateNuke();
}
// Play sound
LK.getSound('power_up_collect').play();
// Remove power up
self.destroy();
// Remove from powerUps array
var index = powerUps.indexOf(self);
if (index !== -1) {
powerUps.splice(index, 1);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x121f2a
});
/****
* Game Code
****/
// Game variables
var score = 0;
var level = 1;
var lives = 3;
var isAiming = false;
var aimStartX = 0;
var aimStartY = 0;
var missiles = [];
var counterRockets = [];
var powerUps = [];
var defenseStation;
var ground;
var gameActive = true;
var missileSpawnRate = 3000; // Time in ms between missile spawns
var missileSpawnTimer = null;
var powerUpSpawnTimer = null;
var multishotTimeoutId = null;
var comboCount = 0;
var comboTimer = null;
// UI elements
var scoreTxt;
var livesTxt;
var levelTxt;
var comboTxt;
// Initialize game objects
function initGame() {
// Set background
game.setBackgroundColor(0x121f2a);
// Play background music
LK.playMusic('game_music');
// Create ground
ground = LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 0.5
});
ground.x = 2048 / 2;
ground.y = 2732 - 30; // Bottom of screen
game.addChild(ground);
// Create defense station
defenseStation = new DefenseStation();
defenseStation.init();
game.addChild(defenseStation);
// Setup UI
setupUI();
// Start missile spawning
startMissileSpawner();
// Start power-up spawning
startPowerUpSpawner();
// Reset game state
score = 0;
level = storage.level || 1;
lives = 3;
gameActive = true;
game.multishotActive = false;
comboCount = 0;
// Update UI
updateUI();
}
function setupUI() {
// Glaud inscription
var glaudTxt = new Text2('Glaud', {
size: 40,
fill: 0xFF8C00
});
glaudTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(glaudTxt);
glaudTxt.x = -20;
glaudTxt.y = 80;
// Score text
scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -280;
scoreTxt.y = 20;
// Lives text
livesTxt = new Text2('Lives: 3', {
size: 60,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0, 0);
LK.gui.top.addChild(livesTxt);
livesTxt.y = 20;
// Level text
levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(levelTxt);
levelTxt.x = 120; // Avoid the top-left 100x100 reserved area
levelTxt.y = 20;
// Combo text
comboTxt = new Text2('', {
size: 80,
fill: 0xF1C40F
});
comboTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(comboTxt);
comboTxt.visible = false;
}
function updateUI() {
scoreTxt.setText('Score: ' + score);
livesTxt.setText('Lives: ' + lives);
levelTxt.setText('Level: ' + level);
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + '!');
comboTxt.visible = true;
// Reset combo timer
if (comboTimer) {
LK.clearTimeout(comboTimer);
}
comboTimer = LK.setTimeout(function () {
comboTxt.visible = false;
comboCount = 0;
}, 2000);
}
}
function startMissileSpawner() {
// Clear any existing timer
if (missileSpawnTimer) {
LK.clearInterval(missileSpawnTimer);
}
// Calculate spawn rate based on level
var rate = Math.max(3000 - level * 200, 500);
missileSpawnTimer = LK.setInterval(function () {
if (!gameActive) {
return;
}
spawnMissile();
}, rate);
}
function spawnMissile() {
// Create a new missile
var missile = new Missile();
// Randomize starting position
var startX = Math.random() * 2048;
// Randomize target position
var targetX = Math.random() * 2048;
// Calculate speed based on level
var speed = 3 + level * 0.5;
// Initialize missile
missile.init(startX, speed, targetX);
// Add to game
missiles.push(missile);
game.addChild(missile);
}
function startPowerUpSpawner() {
// Clear any existing timer
if (powerUpSpawnTimer) {
LK.clearInterval(powerUpSpawnTimer);
}
powerUpSpawnTimer = LK.setInterval(function () {
if (!gameActive) {
return;
}
// 10% chance to spawn a power-up
if (Math.random() < 0.1) {
spawnPowerUp();
}
}, 5000);
}
function spawnPowerUp() {
// Create a new power-up
var powerUp = new PowerUp();
// Initialize power-up
powerUp.init();
// Add to game
powerUps.push(powerUp);
game.addChild(powerUp);
}
// Game mechanics
game.checkMissileHits = function (x, y, radius) {
var hitCount = 0;
// Check all missiles
for (var i = missiles.length - 1; i >= 0; i--) {
var missile = missiles[i];
if (!missile.active) {
continue;
}
// Calculate distance
var dist = Math.sqrt(Math.pow(missile.x - x, 2) + Math.pow(missile.y - y, 2));
// If missile is within blast radius
if (dist <= radius) {
missile.explode();
hitCount++;
// Award points
score += 10 * (1 + level * 0.1);
// Increment combo
comboCount++;
if (comboCount > 1) {
// Bonus points for combos
score += 5 * comboCount;
}
}
}
// Check if level should advance
if (score >= level * 1000) {
advanceLevel();
}
// Update UI
updateUI();
return hitCount;
};
game.missileHitGround = function (x) {
// Visual effect
var groundExplosion = new Explosion();
groundExplosion.x = x;
groundExplosion.y = 2732 - 60;
groundExplosion.init(100);
game.addChild(groundExplosion);
// Reduce lives
lives--;
// Reset combo
comboCount = 0;
if (comboTimer) {
LK.clearTimeout(comboTimer);
}
comboTxt.visible = false;
// Update UI
updateUI();
// Check for game over
if (lives <= 0) {
gameOver();
}
};
function gameOver() {
gameActive = false;
// Stop spawners
if (missileSpawnTimer) {
LK.clearInterval(missileSpawnTimer);
}
if (powerUpSpawnTimer) {
LK.clearInterval(powerUpSpawnTimer);
}
// Update high score
if (score > storage.highScore) {
storage.highScore = score;
}
// Set final score
LK.setScore(score);
// Show game over screen
LK.showGameOver();
}
function advanceLevel() {
level++;
storage.level = level;
// Update UI
updateUI();
// Flash level indicator
tween(levelTxt, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
tween(levelTxt, {
alpha: 1
}, {
duration: 200
});
}
});
// Restart missile spawner with new rate
startMissileSpawner();
}
game.activateMultishot = function () {
game.multishotActive = true;
// Create visual indicator
defenseStation.attachAsset('power_up', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -50,
tint: 0x9b59b6,
alpha: 0.7,
scale: 0.5
});
// Clear previous timeout if exists
if (multishotTimeoutId) {
LK.clearTimeout(multishotTimeoutId);
}
// Set timeout to disable multishot
multishotTimeoutId = LK.setTimeout(function () {
game.multishotActive = false;
// Remove all power-up indicators from defense station
for (var i = 0; i < defenseStation.children.length; i++) {
var child = defenseStation.children[i];
if (child.color && child.color === 0x9b59b6) {
defenseStation.removeChild(child);
child.destroy();
}
}
}, 10000); // 10 seconds
};
game.activateNuke = function () {
// Create large explosion at center
var nukeExplosion = new Explosion();
nukeExplosion.x = 2048 / 2;
nukeExplosion.y = 2732 / 2;
nukeExplosion.init(1500); // Large radius
game.addChild(nukeExplosion);
// Destroy all missiles
var destroyedCount = 0;
for (var i = missiles.length - 1; i >= 0; i--) {
var missile = missiles[i];
if (missile.active) {
missile.explode();
destroyedCount++;
}
}
// Award points
if (destroyedCount > 0) {
score += destroyedCount * 15;
updateUI();
}
};
// Input handling
game.down = function (x, y, obj) {
if (!gameActive) {
return;
}
isAiming = true;
aimStartX = x;
aimStartY = y;
// Start aiming
defenseStation.startAiming(x, y);
};
game.move = function (x, y, obj) {
if (!isAiming || !gameActive) {
return;
}
// Update aim line
defenseStation.updateAimLine(x, y);
};
game.up = function (x, y, obj) {
if (!isAiming || !gameActive) {
return;
}
// Fire rocket
defenseStation.fire(x, y);
// Reset aiming
isAiming = false;
defenseStation.stopAiming();
};
// Game loop
game.update = function () {
if (!gameActive) {
return;
}
// Update missiles
for (var i = missiles.length - 1; i >= 0; i--) {
missiles[i].update();
}
// Update counter rockets
for (var i = counterRockets.length - 1; i >= 0; i--) {
counterRockets[i].update();
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
powerUps[i].update();
}
};
// Initialize the game
initGame();
defense_station. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
counter rocket. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
power up. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
explosion. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
missile. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
aim line. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
graund. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows