User prompt
the speed of the enemy missiles increase by %75 if there is one base left
User prompt
keep the bottom of the muzzle flash effect fixed
User prompt
Make the muzzle fire effect align with the launched missile
User prompt
remove the muzzle flashs scale anim
User prompt
make the muzzle flash effect solid not like a blink
User prompt
make the muzzle flash effect appear a bit higher
User prompt
make the muzzle flash effect appear a little bit higher
User prompt
make the muzzle flash effect last longer
/**** * Classes ****/ // City class: represents a city to defend var City = Container.expand(function () { var self = Container.call(this); var cityAsset = self.attachAsset('city', { anchorX: 0.5, anchorY: 1.0 }); self.width = cityAsset.width; self.height = cityAsset.height; self.destroyed = false; self.destroyCity = function () { self.destroyed = true; self.visible = false; }; return self; }); // --- Game Variables --- // CounterMissile class: player's missile var CounterMissile = Container.expand(function () { var self = Container.call(this); var missileAsset = self.attachAsset('counterMissile', { anchorX: 0.5, anchorY: 1.0 }); self.speed = 24; self.targetX = 0; self.targetY = 0; self.lastX = self.x; self.lastY = self.y; self.setTarget = function (x, y) { self.targetX = x; self.targetY = y; var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); self.vx = dx / dist * self.speed; self.vy = dy / dist * self.speed; // Rotate missile to face direction of travel if (dist > 0) { // The missile asset points up (anchorY: 1.0), so angle is atan2(dx, -dy) // But for standard missile, use atan2(dx, -dy) or atan2(-dy, dx) depending on asset orientation // Here, asset points up, so rotation = Math.atan2(dx, -dy) // But in PIXI, rotation 0 is to the right, so to point up, use Math.atan2(dx, -dy) // Actually, to point the missile in the direction of travel, use Math.atan2(dx, -dy) // But in practice, for a missile pointing up, rotation = Math.atan2(dx, -dy) // Let's use Math.atan2(dx, -dy) self.rotation = Math.atan2(dx, -dy); } }; self.update = function () { self.x += self.vx; self.y += self.vy; // Continuously update rotation to face direction of travel if (self.vx !== 0 || self.vy !== 0) { self.rotation = Math.atan2(self.vx, -self.vy); } }; return self; }); // EnemyMissile class: descending enemy missile var EnemyMissile = Container.expand(function () { var self = Container.call(this); var missileAsset = self.attachAsset('enemyMissile', { anchorX: 0.5, anchorY: 0.0 }); self.speed = 6; // Default, will be overridden on spawn self.targetX = 200 + Math.random() * (2048 - 400); self.targetY = 2200 + Math.random() * 400; self.lastY = self.y; self.update = function () { // Move towards target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); // Explosion class: visual effect for missile hit var Explosion = Container.expand(function () { var self = Container.call(this); // Use a simple ellipse shape for explosion var explosionAsset = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1, alpha: 0.7 }); self.life = 18; // frames (0.3s at 60fps) self.age = 0; self.update = function () { self.age++; // Animate: grow and fade out explosionAsset.scaleX = explosionAsset.scaleY = 1 + self.age * 0.15; explosionAsset.alpha = Math.max(0, 0.7 * (1 - self.age / self.life)); if (self.age >= self.life) { self.destroy(); } }; return self; }); // MuzzleFlash class: bigger and longer-lived flash at the muzzle when firing var MuzzleFlash = Container.expand(function () { var self = Container.call(this); // Use the new muzzleFlash asset, centered var flashAsset = self.attachAsset('muzzleFlash', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 0.6, alpha: 0.85 }); self.life = 28; // frames (~0.47s at 60fps), even longer self.age = 0; self.update = function () { self.age++; // Animate: fade out only (no scale animation) flashAsset.scaleX = 1.2; flashAsset.scaleY = 0.6; flashAsset.alpha = Math.max(0, 0.85 * (1 - self.age / self.life)); if (self.age >= self.life) { self.destroy(); } }; return self; }); // Player class: controls the anti-missile battery var Player = Container.expand(function () { var self = Container.call(this); var playerAsset = self.attachAsset('playerBattery', { anchorX: 0.5, anchorY: 0.5 }); self.width = playerAsset.width; self.height = playerAsset.height; self.update = function () {}; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // --- Game Variables --- var player; var cities = []; var enemyMissiles = []; var counterMissiles = []; var scoreText; var spawnTimer; var gameOver = false; // Cooldown for counter missile firing var canFire = true; var fireCooldownTimer = null; // --- Add background image --- var background = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); game.addChildAt(background, 0); // --- Setup Game Elements --- function setupGame() { // Add player battery at bottom center player = new Player(); player.x = 2048 / 2; player.y = 2350; game.addChild(player); // Add cities to defend var cityCount = 5; var spacing = 2048 / (cityCount + 1); for (var i = 0; i < cityCount; i++) { var city = new City(); city.x = spacing * (i + 1); city.y = 2650; game.addChild(city); cities.push(city); } ; // --- Update explosions --- if (typeof explosions === "undefined") { explosions = []; } // Find all explosions in game.children and update them, remove if destroyed for (var i = game.children.length - 1; i >= 0; i--) { var obj = game.children[i]; if (obj && obj.update && obj.constructor && obj.constructor.name === "Explosion") { obj.update(); if (obj.destroyed) { game.removeChild(obj); } } } // Score text scoreText = new Text2('0', { size: 120, fill: "#fff" }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Start enemy missile spawn timer spawnTimer = LK.setInterval(spawnEnemyMissile, 60 * 8); } // --- Calculate enemy missile speed based on score --- function getEnemyMissileSpeed() { // Base speed is 6, increases up to +10 as score increases, capped at 16 var base = 6; var max = 16; var score = LK.getScore(); var speed = base + Math.min(10, Math.floor(score / 500)); return Math.min(speed, max); } // --- Enemy Missile Spawner --- function spawnEnemyMissile() { if (gameOver) return; var missile = new EnemyMissile(); missile.x = 200 + Math.random() * (2048 - 400); missile.y = -80; missile.speed = getEnemyMissileSpeed(); // Target a random city that is not destroyed var aliveCities = cities.filter(function (c) { return !c.destroyed; }); if (aliveCities.length === 0) return; var targetCity = aliveCities[Math.floor(Math.random() * aliveCities.length)]; missile.targetX = targetCity.x; missile.targetY = targetCity.y - 40; // Set missile initial rotation to face the target var dx = missile.targetX - missile.x; var dy = missile.targetY - missile.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { missile.vx = dx / dist * missile.speed; missile.vy = dy / dist * missile.speed; missile.rotation = Math.atan2(missile.vx, -missile.vy); } enemyMissiles.push(missile); game.addChild(missile); } // --- Game Touch: Launch CounterMissile or Start Drag --- game.down = function (x, y, obj) { if (gameOver) return; // If touch/click is on the player battery, start dragging // Use bounding box for touch area var px = player.x, py = player.y; var halfW = player.width / 2, halfH = player.height / 2; if (x >= px - halfW && x <= px + halfW && y >= py - halfH && y <= py + halfH) { // Start dragging playerDragging = true; player.dragTargetX = x; return; } if (!canFire) return; // Only allow firing from above the player if (y < player.y - 100) { var missile = new CounterMissile(); missile.x = player.x; missile.y = player.y - 60; missile.setTarget(x, y); counterMissiles.push(missile); game.addChild(missile); // --- Muzzle flash effect at missile launch position and direction --- var muzzleFlash = new MuzzleFlash(); // Place muzzle flash at the missile's initial position muzzleFlash.x = missile.x; muzzleFlash.y = missile.y; // Align muzzle flash rotation to match the missile's rotation muzzleFlash.rotation = missile.rotation; game.addChild(muzzleFlash); // Start cooldown canFire = false; if (fireCooldownTimer !== null) { LK.clearTimeout(fireCooldownTimer); } fireCooldownTimer = LK.setTimeout(function () { canFire = true; fireCooldownTimer = null; }, 300); } }; // --- Game Move: Drag Counter Battery if dragging --- game.move = function (x, y, obj) { if (gameOver) return; if (typeof playerDragging !== "undefined" && playerDragging) { player.dragTargetX = x; } }; // --- Game Up: End Drag --- game.up = function (x, y, obj) { if (typeof playerDragging !== "undefined" && playerDragging) { playerDragging = false; } }; // --- Game Update Loop --- game.update = function () { if (gameOver) return; // --- Moveable Counter Battery (Player) --- if (typeof playerDragging !== "undefined" && playerDragging) { // Clamp player.x to within game bounds (leave some margin for battery width) var minX = player.width / 2; var maxX = 2048 - player.width / 2; if (player.dragTargetX < minX) player.x = minX;else if (player.dragTargetX > maxX) player.x = maxX;else player.x = player.dragTargetX; } // --- Update and remove muzzle flashes --- for (var i = game.children.length - 1; i >= 0; i--) { var obj = game.children[i]; if (obj && obj.update && obj.constructor && obj.constructor.name === "MuzzleFlash") { obj.update(); if (obj.destroyed) { game.removeChild(obj); } } } // Update enemy missiles for (var i = enemyMissiles.length - 1; i >= 0; i--) { var em = enemyMissiles[i]; em.update(); // Check if hit a city for (var j = 0; j < cities.length; j++) { var city = cities[j]; if (!city.destroyed && em.intersects(city)) { // Spawn explosion at city location var explosion = new Explosion(); explosion.x = city.x; explosion.y = city.y - city.height / 2; game.addChild(explosion); city.destroyCity(); // Deduct score based on how many cities have been destroyed var destroyedCount = 0; for (var d = 0; d < cities.length; d++) { if (cities[d].destroyed) destroyedCount++; } var penalty = 0; if (destroyedCount === 1) penalty = 500;else if (destroyedCount === 2) penalty = 750;else if (destroyedCount === 3) penalty = 1000;else if (destroyedCount === 4) penalty = 1250; // Do not lose any points if the last base is destroyed (destroyedCount === 5) if (penalty > 0) { LK.setScore(Math.max(0, LK.getScore() - penalty)); scoreText.setText(LK.getScore()); } em.destroy(); enemyMissiles.splice(i, 1); // Check for game over if (cities.filter(function (c) { return !c.destroyed; }).length === 0) { gameOver = true; LK.showGameOver(); } break; } } // Remove if off screen or landed on empty space or destroyed base if (em.y > 2732) { // Check if landed on a destroyed base var landedOnDestroyedBase = false; for (var j = 0; j < cities.length; j++) { var city = cities[j]; if (city.destroyed && em.intersects(city)) { landedOnDestroyedBase = true; break; } } // Spawn explosion at missile's last position if it didn't hit a city or landed on destroyed base var explosion = new Explosion(); explosion.x = em.x; explosion.y = em.y; game.addChild(explosion); em.destroy(); enemyMissiles.splice(i, 1); } } // Update counter missiles for (var i = counterMissiles.length - 1; i >= 0; i--) { var cm = counterMissiles[i]; cm.update(); // Remove if off screen if (cm.x < 0 || cm.x > 2048 || cm.y < 0 || cm.y > 2732) { cm.destroy(); counterMissiles.splice(i, 1); continue; } // Check for collision with enemy missiles for (var j = enemyMissiles.length - 1; j >= 0; j--) { var em = enemyMissiles[j]; if (cm.intersects(em)) { // Spawn explosion at collision point var explosion = new Explosion(); explosion.x = em.x; explosion.y = em.y; game.addChild(explosion); // Destroy both cm.destroy(); em.destroy(); counterMissiles.splice(i, 1); enemyMissiles.splice(j, 1); // Score LK.setScore(LK.getScore() + 100); scoreText.setText(LK.getScore()); break; } } } }; // --- Start Game --- setupGame();
===================================================================
--- original.js
+++ change.js
@@ -277,12 +277,15 @@
missile.y = player.y - 60;
missile.setTarget(x, y);
counterMissiles.push(missile);
game.addChild(missile);
- // --- Muzzle flash effect at muzzle position ---
+ // --- Muzzle flash effect at missile launch position and direction ---
var muzzleFlash = new MuzzleFlash();
- muzzleFlash.x = player.x;
- muzzleFlash.y = player.y - 160; // Raise the muzzle flash even higher above the battery
+ // Place muzzle flash at the missile's initial position
+ muzzleFlash.x = missile.x;
+ muzzleFlash.y = missile.y;
+ // Align muzzle flash rotation to match the missile's rotation
+ muzzleFlash.rotation = missile.rotation;
game.addChild(muzzleFlash);
// Start cooldown
canFire = false;
if (fireCooldownTimer !== null) {
a 2d pixel art missile. In-Game asset. 2d. High contrast. No shadows
2d pixel art explosion. In-Game asset. 2d. High contrast. No shadows
2d pixel art military base. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
make the gray concrete shorter. make the clouds smaller, more realistic and less frequent.
a 2d pixel art anti-air battery. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat