Code edit (1 edits merged)
Please save this source code
User prompt
move the glaud sign down a little bit.
User prompt
move the glaud sign down a little bit.
User prompt
Add a small “Glaud” inscription in the upper right corner, orange color
User prompt
we must be able to hit enemies.
Code edit (1 edits merged)
Please save this source code
User prompt
Rocket Blast Defense
User prompt
Please continue polishing my design document.
Initial prompt
Idea 3: Melody of Shadows (Stealth / Puzzle Platformer) Concept: The player controls an agile character who can manipulate light and shadow. Shadows can become both hiding places and physical platforms. Mechanics: The player can move, block or destroy light sources. Created shadows can be walked on, climbed or hidden in. Different types of light (e.g. moonlight, firelight, magic light) can create shadows with different properties (e.g. slippery, sticky, damaging). Sound mechanics can also be added: Enemies become sensitive to sound, the player can make noises as a distraction. Maybe some puzzles are based on rhythm or melody. Stealth-oriented; avoiding enemies and reaching objectives undetected is essential. Story Potential: A noir story set in a city plunged into darkness could be the story of a character who wants to become a shadow master in a magical world. Why It's Great: High potential to be atmospheric and visually appealing. Allows for creative puzzle designs. Encourages the player to think cleverly.
/**** * 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