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 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() {
// 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(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,693 @@
-/****
+/****
+* 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 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: 0x000000
-});
\ No newline at end of file
+ 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() {
+ // 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();
\ No newline at end of file
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