User prompt
add cluster rocket assets to explode and spread fire fragments ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kurangi kecepatan player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kurangi kecepatan pegerakkan player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat karakter musuh terpecah saat tertembak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat ledakkan saat peluru mengenai musuh ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kurangi lebih pergerakkan peluru ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat pergerakkan player agak lambat ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat pergerakkan player lebih halus ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
fix a background
User prompt
fix a music
User prompt
make background not blur
User prompt
make background not blur
User prompt
add background function
User prompt
add background asset
User prompt
add background
User prompt
disable horizontal shoot change to vertical shoot
Code edit (1 edits merged)
Please save this source code
User prompt
LCD Blaster: Monochrome Horizontal Shooter
Initial prompt
lcd monocrom style. horizontal shooter game
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGfx = self.attachAsset('lcd_bullet', { anchorX: 0.5, anchorY: 0.5 }); self.width = bulletGfx.width; self.height = bulletGfx.height; self.speed = 20; // px per frame self.update = function () { self.y -= self.speed; }; return self; }); // Cluster Rocket var ClusterRocket = Container.expand(function () { var self = Container.call(this); var rocketGfx = self.attachAsset('cluster_rocket', { anchorX: 0.5, anchorY: 0.5 }); self.width = rocketGfx.width; self.height = rocketGfx.height; self.speed = 12; self.hasExploded = false; self.update = function () { self.x -= self.speed; // Explode when reaching center of screen if (self.x <= GAME_W / 2 && !self.hasExploded) { self.explode(); } }; self.explode = function () { self.hasExploded = true; // Create fire fragments var fragmentCount = 8 + Math.floor(Math.random() * 4); for (var i = 0; i < fragmentCount; i++) { var fragment = new FireFragment(); fragment.x = self.x; fragment.y = self.y; var angle = Math.PI * 2 * i / fragmentCount + (Math.random() - 0.5) * 0.5; var speed = 8 + Math.random() * 6; fragment.velocityX = Math.cos(angle) * speed; fragment.velocityY = Math.sin(angle) * speed; fragment.rotationSpeed = (Math.random() - 0.5) * 0.4; fireFragments.push(fragment); game.addChild(fragment); } // Flash screen for explosion effect LK.effects.flashScreen(0xFFFF00, 200); }; return self; }); // Enemy var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGfx = self.attachAsset('lcd_enemy', { anchorX: 0.5, anchorY: 0.5 }); self.width = enemyGfx.width; self.height = enemyGfx.height; self.speed = 7 + Math.random() * 3; // px per frame self.direction = 0; // 0: straight, -1: up, 1: down self.amplitude = 0; // for sine movement self.phase = Math.random() * Math.PI * 2; self.update = function () { self.x -= self.speed; if (self.amplitude) { self.y += Math.sin(LK.ticks / 12 + self.phase) * self.amplitude; } }; return self; }); // Enemy Fragment var EnemyFragment = Container.expand(function () { var self = Container.call(this); var fragmentGfx = self.attachAsset('lcd_enemy', { anchorX: 0.5, anchorY: 0.5 }); self.width = fragmentGfx.width; self.height = fragmentGfx.height; self.velocityX = 0; self.velocityY = 0; self.rotationSpeed = 0; self.gravity = 0.5; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.velocityY += self.gravity; self.rotation += self.rotationSpeed; self.alpha -= 0.02; }; return self; }); // Fire Fragment var FireFragment = Container.expand(function () { var self = Container.call(this); var fragmentGfx = self.attachAsset('fire_fragment', { anchorX: 0.5, anchorY: 0.5 }); self.width = fragmentGfx.width; self.height = fragmentGfx.height; self.velocityX = 0; self.velocityY = 0; self.rotationSpeed = 0; self.lifetime = 180; // frames self.maxLifetime = 180; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.rotation += self.rotationSpeed; self.lifetime--; // Fade out over time self.alpha = self.lifetime / self.maxLifetime; // Change color from yellow to red over time var t = 1 - self.lifetime / self.maxLifetime; var red = Math.floor(255); var green = Math.floor(255 * (1 - t)); var blue = 0; self.tint = red << 16 | green << 8 | blue; }; return self; }); // Player Ship var Ship = Container.expand(function () { var self = Container.call(this); var shipGfx = self.attachAsset('lcd_ship', { anchorX: 0.5, anchorY: 0.5 }); self.width = shipGfx.width; self.height = shipGfx.height; self.canShoot = true; self.shootCooldown = 18; // frames between shots // Ship flash effect on hit self.flash = function () { tween(self, { alpha: 0.2 }, { duration: 80, easing: tween.linear, onFinish: function onFinish() { tween(self, { alpha: 1 }, { duration: 120, easing: tween.linear }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Ship: white box, Enemy: white ellipse, Bullet: white box, Background: black, Accent: #A3FFB2 (LCD green). // LCD-style monochrome: use only black, white, and one accent color (e.g. greenish for LCD). // --- LCD color accent for UI --- var LCD_ACCENT = 0xA3FFB2; // --- Game constants --- var GAME_W = 2048, GAME_H = 2732; var SHIP_Y = GAME_H - 220; var ENEMY_SPAWN_Y_MIN = 220, ENEMY_SPAWN_Y_MAX = GAME_H - 600; var ENEMY_SPAWN_X = GAME_W + 120; var ENEMY_SPAWN_INTERVAL = 48; // frames var MAX_LIVES = 3; // --- Game state --- var ship; var bullets = []; var enemies = []; var fragments = []; var clusterRockets = []; var fireFragments = []; var lives = MAX_LIVES; var score = 0; var canMove = true; var lastTouchX = null; // --- UI --- var scoreTxt = new Text2('0', { size: 120, fill: 0xA3FFB2 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var livesContainer = new Container(); LK.gui.topRight.addChild(livesContainer); // --- Helper: update lives UI --- function updateLivesUI() { livesContainer.removeChildren(); for (var i = 0; i < lives; i++) { var life = LK.getAsset('lcd_life', { anchorX: 0.5, anchorY: 0.5 }); life.x = -i * 60 - 60; life.y = 60; livesContainer.addChild(life); } } updateLivesUI(); // --- Helper: reset game state --- function resetGame() { // Remove all bullets/enemies/fragments for (var i = 0; i < bullets.length; i++) bullets[i].destroy(); for (var i = 0; i < enemies.length; i++) enemies[i].destroy(); for (var i = 0; i < fragments.length; i++) fragments[i].destroy(); for (var i = 0; i < clusterRockets.length; i++) clusterRockets[i].destroy(); for (var i = 0; i < fireFragments.length; i++) fireFragments[i].destroy(); bullets = []; enemies = []; fragments = []; clusterRockets = []; fireFragments = []; lives = MAX_LIVES; score = 0; scoreTxt.setText(score); updateLivesUI(); canMove = true; // Place ship if (ship) ship.destroy(); ship = new Ship(); ship.x = 320; ship.y = SHIP_Y; game.addChild(ship); } resetGame(); // --- Touch controls: drag ship horizontally --- game.down = function (x, y, obj) { if (!canMove) return; // Only allow drag if touch is in lower 1/3 of screen if (y > GAME_H * 0.6) { lastTouchX = x; } }; game.move = function (x, y, obj) { if (!canMove) return; if (lastTouchX !== null) { // Clamp ship to screen var newX = Math.max(ship.width / 2, Math.min(GAME_W - ship.width / 2, x)); // Stop any existing tween on ship position tween.stop(ship, { x: true }); // Smoothly tween ship to new position tween(ship, { x: newX }, { duration: 800, easing: tween.easeOut }); } }; game.up = function (x, y, obj) { lastTouchX = null; }; // --- Ship auto-fire --- var shootTimer = 0; function tryShoot() { if (!canMove) return; if (shootTimer > 0) { shootTimer--; return; } // Fire bullet var bullet = new Bullet(); bullet.x = ship.x; bullet.y = ship.y - ship.height / 2 - bullet.height / 2 - 10; bullets.push(bullet); game.addChild(bullet); shootTimer = ship.shootCooldown; } // --- Enemy spawn --- var enemySpawnTimer = 0; function spawnEnemy() { var enemy = new Enemy(); enemy.x = ENEMY_SPAWN_X; // Random Y within play area enemy.y = ENEMY_SPAWN_Y_MIN + Math.random() * (ENEMY_SPAWN_Y_MAX - ENEMY_SPAWN_Y_MIN); // Some enemies move in sine wave if (Math.random() < 0.4) { enemy.amplitude = 6 + Math.random() * 18; } enemies.push(enemy); game.addChild(enemy); } // --- Cluster rocket spawn --- var rocketSpawnTimer = 0; function spawnClusterRocket() { var rocket = new ClusterRocket(); rocket.x = ENEMY_SPAWN_X; rocket.y = ENEMY_SPAWN_Y_MIN + Math.random() * (ENEMY_SPAWN_Y_MAX - ENEMY_SPAWN_Y_MIN); clusterRockets.push(rocket); game.addChild(rocket); } // --- Main update loop --- game.update = function () { // --- Ship auto-fire --- tryShoot(); // --- Bullets update --- for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); // Remove if off screen if (b.y < -b.height) { b.destroy(); bullets.splice(i, 1); continue; } // Check collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; if (b.intersects(e)) { // Create enemy fragments var fragmentCount = 4 + Math.floor(Math.random() * 3); for (var f = 0; f < fragmentCount; f++) { var fragment = new EnemyFragment(); fragment.x = e.x + (Math.random() - 0.5) * e.width; fragment.y = e.y + (Math.random() - 0.5) * e.height; fragment.scaleX = 0.3 + Math.random() * 0.4; fragment.scaleY = 0.3 + Math.random() * 0.4; fragment.velocityX = (Math.random() - 0.5) * 15; fragment.velocityY = (Math.random() - 0.5) * 10 - 5; fragment.rotationSpeed = (Math.random() - 0.5) * 0.3; fragment.alpha = 0.8; fragments.push(fragment); game.addChild(fragment); } // Flash screen briefly for explosion effect LK.effects.flashScreen(0xFFFFFF, 100); // Play hit sound LK.getSound('123bullethitenemy').play(); // Destroy enemy and bullet e.destroy(); b.destroy(); bullets.splice(i, 1); enemies.splice(j, 1); // Score score += 1; scoreTxt.setText(score); // Small flash effect on ship LK.effects.flashObject(ship, LCD_ACCENT, 120); break; } } } // --- Fragments update --- for (var i = fragments.length - 1; i >= 0; i--) { var f = fragments[i]; f.update(); // Remove if off screen or fully transparent if (f.y > GAME_H + 100 || f.x < -100 || f.x > GAME_W + 100 || f.alpha <= 0) { f.destroy(); fragments.splice(i, 1); } } // --- Enemies update --- for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.update(); // Remove if off screen if (e.x < -e.width) { e.destroy(); enemies.splice(i, 1); continue; } // Check collision with ship if (e.intersects(ship)) { // Ship hit! e.destroy(); enemies.splice(i, 1); lives--; updateLivesUI(); ship.flash(); canMove = false; // Flash screen LK.effects.flashScreen(0xffffff, 200); // After short delay, allow movement again or game over LK.setTimeout(function () { if (lives <= 0) { // Game over LK.showGameOver(); } else { canMove = true; } }, 600); break; } } // --- Cluster rockets update --- for (var i = clusterRockets.length - 1; i >= 0; i--) { var r = clusterRockets[i]; r.update(); // Remove if off screen or exploded if (r.x < -r.width || r.hasExploded) { r.destroy(); clusterRockets.splice(i, 1); continue; } // Check collision with ship if (r.intersects(ship)) { r.explode(); lives--; updateLivesUI(); ship.flash(); canMove = false; // Flash screen LK.effects.flashScreen(0xFFFF00, 300); // After short delay, allow movement again or game over LK.setTimeout(function () { if (lives <= 0) { // Game over LK.showGameOver(); } else { canMove = true; } }, 600); break; } } // --- Fire fragments update --- for (var i = fireFragments.length - 1; i >= 0; i--) { var f = fireFragments[i]; f.update(); // Remove if lifetime expired or off screen if (f.lifetime <= 0 || f.y > GAME_H + 100 || f.x < -100 || f.x > GAME_W + 100) { f.destroy(); fireFragments.splice(i, 1); continue; } // Check collision with ship if (f.intersects(ship)) { f.destroy(); fireFragments.splice(i, 1); lives--; updateLivesUI(); ship.flash(); canMove = false; // Flash screen LK.effects.flashScreen(0xFF4500, 200); // After short delay, allow movement again or game over LK.setTimeout(function () { if (lives <= 0) { // Game over LK.showGameOver(); } else { canMove = true; } }, 600); break; } } // --- Enemy spawn --- enemySpawnTimer--; if (enemySpawnTimer <= 0) { spawnEnemy(); // Faster spawn as score increases var minInterval = 18; var interval = Math.max(minInterval, ENEMY_SPAWN_INTERVAL - Math.floor(score / 8) * 4); enemySpawnTimer = interval + Math.floor(Math.random() * 12); } // --- Cluster rocket spawn --- rocketSpawnTimer--; if (rocketSpawnTimer <= 0) { spawnClusterRocket(); // Spawn rockets less frequently than enemies rocketSpawnTimer = 300 + Math.floor(Math.random() * 200); } }; // --- Center score text --- scoreTxt.setText(score); scoreTxt.anchor.set(0.5, 0); scoreTxt.x = 0; // LK.gui.top is centered horizontally // --- LCD-style background (monochrome rectangle) --- function addBackground() { // Use the background asset at its native resolution, then scale up to fit the game area to avoid blur var bg = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: GAME_W / 2, y: GAME_H / 2 }); // Calculate scale factors to fit the game area var scaleX = GAME_W / bg.width; var scaleY = GAME_H / bg.height; bg.scaleX = scaleX; bg.scaleY = scaleY; game.addChildAt(bg, 0); // Ensure background is at the bottom layer // LCD accent border (use a shape asset for a crisp border) var border = LK.getAsset('lcd_life', { width: GAME_W - 120, height: GAME_H - 120, color: LCD_ACCENT, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); border.alpha = 0.08; border.x = GAME_W / 2; border.y = GAME_H / 2; game.addChildAt(border, 1); } addBackground(); // --- Play background music --- LK.playMusic('1alarmofwar'); // --- On game over, reset state --- LK.on('gameover', function () { LK.stopMusic(); resetGame(); }); // --- On you win (not used, but for completeness) --- LK.on('youwin', function () { LK.stopMusic(); resetGame(); });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bullet
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('lcd_bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bulletGfx.width;
self.height = bulletGfx.height;
self.speed = 20; // px per frame
self.update = function () {
self.y -= self.speed;
};
return self;
});
// Cluster Rocket
var ClusterRocket = Container.expand(function () {
var self = Container.call(this);
var rocketGfx = self.attachAsset('cluster_rocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = rocketGfx.width;
self.height = rocketGfx.height;
self.speed = 12;
self.hasExploded = false;
self.update = function () {
self.x -= self.speed;
// Explode when reaching center of screen
if (self.x <= GAME_W / 2 && !self.hasExploded) {
self.explode();
}
};
self.explode = function () {
self.hasExploded = true;
// Create fire fragments
var fragmentCount = 8 + Math.floor(Math.random() * 4);
for (var i = 0; i < fragmentCount; i++) {
var fragment = new FireFragment();
fragment.x = self.x;
fragment.y = self.y;
var angle = Math.PI * 2 * i / fragmentCount + (Math.random() - 0.5) * 0.5;
var speed = 8 + Math.random() * 6;
fragment.velocityX = Math.cos(angle) * speed;
fragment.velocityY = Math.sin(angle) * speed;
fragment.rotationSpeed = (Math.random() - 0.5) * 0.4;
fireFragments.push(fragment);
game.addChild(fragment);
}
// Flash screen for explosion effect
LK.effects.flashScreen(0xFFFF00, 200);
};
return self;
});
// Enemy
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('lcd_enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = enemyGfx.width;
self.height = enemyGfx.height;
self.speed = 7 + Math.random() * 3; // px per frame
self.direction = 0; // 0: straight, -1: up, 1: down
self.amplitude = 0; // for sine movement
self.phase = Math.random() * Math.PI * 2;
self.update = function () {
self.x -= self.speed;
if (self.amplitude) {
self.y += Math.sin(LK.ticks / 12 + self.phase) * self.amplitude;
}
};
return self;
});
// Enemy Fragment
var EnemyFragment = Container.expand(function () {
var self = Container.call(this);
var fragmentGfx = self.attachAsset('lcd_enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = fragmentGfx.width;
self.height = fragmentGfx.height;
self.velocityX = 0;
self.velocityY = 0;
self.rotationSpeed = 0;
self.gravity = 0.5;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
self.rotation += self.rotationSpeed;
self.alpha -= 0.02;
};
return self;
});
// Fire Fragment
var FireFragment = Container.expand(function () {
var self = Container.call(this);
var fragmentGfx = self.attachAsset('fire_fragment', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = fragmentGfx.width;
self.height = fragmentGfx.height;
self.velocityX = 0;
self.velocityY = 0;
self.rotationSpeed = 0;
self.lifetime = 180; // frames
self.maxLifetime = 180;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.rotation += self.rotationSpeed;
self.lifetime--;
// Fade out over time
self.alpha = self.lifetime / self.maxLifetime;
// Change color from yellow to red over time
var t = 1 - self.lifetime / self.maxLifetime;
var red = Math.floor(255);
var green = Math.floor(255 * (1 - t));
var blue = 0;
self.tint = red << 16 | green << 8 | blue;
};
return self;
});
// Player Ship
var Ship = Container.expand(function () {
var self = Container.call(this);
var shipGfx = self.attachAsset('lcd_ship', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = shipGfx.width;
self.height = shipGfx.height;
self.canShoot = true;
self.shootCooldown = 18; // frames between shots
// Ship flash effect on hit
self.flash = function () {
tween(self, {
alpha: 0.2
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
alpha: 1
}, {
duration: 120,
easing: tween.linear
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Ship: white box, Enemy: white ellipse, Bullet: white box, Background: black, Accent: #A3FFB2 (LCD green).
// LCD-style monochrome: use only black, white, and one accent color (e.g. greenish for LCD).
// --- LCD color accent for UI ---
var LCD_ACCENT = 0xA3FFB2;
// --- Game constants ---
var GAME_W = 2048,
GAME_H = 2732;
var SHIP_Y = GAME_H - 220;
var ENEMY_SPAWN_Y_MIN = 220,
ENEMY_SPAWN_Y_MAX = GAME_H - 600;
var ENEMY_SPAWN_X = GAME_W + 120;
var ENEMY_SPAWN_INTERVAL = 48; // frames
var MAX_LIVES = 3;
// --- Game state ---
var ship;
var bullets = [];
var enemies = [];
var fragments = [];
var clusterRockets = [];
var fireFragments = [];
var lives = MAX_LIVES;
var score = 0;
var canMove = true;
var lastTouchX = null;
// --- UI ---
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xA3FFB2
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var livesContainer = new Container();
LK.gui.topRight.addChild(livesContainer);
// --- Helper: update lives UI ---
function updateLivesUI() {
livesContainer.removeChildren();
for (var i = 0; i < lives; i++) {
var life = LK.getAsset('lcd_life', {
anchorX: 0.5,
anchorY: 0.5
});
life.x = -i * 60 - 60;
life.y = 60;
livesContainer.addChild(life);
}
}
updateLivesUI();
// --- Helper: reset game state ---
function resetGame() {
// Remove all bullets/enemies/fragments
for (var i = 0; i < bullets.length; i++) bullets[i].destroy();
for (var i = 0; i < enemies.length; i++) enemies[i].destroy();
for (var i = 0; i < fragments.length; i++) fragments[i].destroy();
for (var i = 0; i < clusterRockets.length; i++) clusterRockets[i].destroy();
for (var i = 0; i < fireFragments.length; i++) fireFragments[i].destroy();
bullets = [];
enemies = [];
fragments = [];
clusterRockets = [];
fireFragments = [];
lives = MAX_LIVES;
score = 0;
scoreTxt.setText(score);
updateLivesUI();
canMove = true;
// Place ship
if (ship) ship.destroy();
ship = new Ship();
ship.x = 320;
ship.y = SHIP_Y;
game.addChild(ship);
}
resetGame();
// --- Touch controls: drag ship horizontally ---
game.down = function (x, y, obj) {
if (!canMove) return;
// Only allow drag if touch is in lower 1/3 of screen
if (y > GAME_H * 0.6) {
lastTouchX = x;
}
};
game.move = function (x, y, obj) {
if (!canMove) return;
if (lastTouchX !== null) {
// Clamp ship to screen
var newX = Math.max(ship.width / 2, Math.min(GAME_W - ship.width / 2, x));
// Stop any existing tween on ship position
tween.stop(ship, {
x: true
});
// Smoothly tween ship to new position
tween(ship, {
x: newX
}, {
duration: 800,
easing: tween.easeOut
});
}
};
game.up = function (x, y, obj) {
lastTouchX = null;
};
// --- Ship auto-fire ---
var shootTimer = 0;
function tryShoot() {
if (!canMove) return;
if (shootTimer > 0) {
shootTimer--;
return;
}
// Fire bullet
var bullet = new Bullet();
bullet.x = ship.x;
bullet.y = ship.y - ship.height / 2 - bullet.height / 2 - 10;
bullets.push(bullet);
game.addChild(bullet);
shootTimer = ship.shootCooldown;
}
// --- Enemy spawn ---
var enemySpawnTimer = 0;
function spawnEnemy() {
var enemy = new Enemy();
enemy.x = ENEMY_SPAWN_X;
// Random Y within play area
enemy.y = ENEMY_SPAWN_Y_MIN + Math.random() * (ENEMY_SPAWN_Y_MAX - ENEMY_SPAWN_Y_MIN);
// Some enemies move in sine wave
if (Math.random() < 0.4) {
enemy.amplitude = 6 + Math.random() * 18;
}
enemies.push(enemy);
game.addChild(enemy);
}
// --- Cluster rocket spawn ---
var rocketSpawnTimer = 0;
function spawnClusterRocket() {
var rocket = new ClusterRocket();
rocket.x = ENEMY_SPAWN_X;
rocket.y = ENEMY_SPAWN_Y_MIN + Math.random() * (ENEMY_SPAWN_Y_MAX - ENEMY_SPAWN_Y_MIN);
clusterRockets.push(rocket);
game.addChild(rocket);
}
// --- Main update loop ---
game.update = function () {
// --- Ship auto-fire ---
tryShoot();
// --- Bullets update ---
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
// Remove if off screen
if (b.y < -b.height) {
b.destroy();
bullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (b.intersects(e)) {
// Create enemy fragments
var fragmentCount = 4 + Math.floor(Math.random() * 3);
for (var f = 0; f < fragmentCount; f++) {
var fragment = new EnemyFragment();
fragment.x = e.x + (Math.random() - 0.5) * e.width;
fragment.y = e.y + (Math.random() - 0.5) * e.height;
fragment.scaleX = 0.3 + Math.random() * 0.4;
fragment.scaleY = 0.3 + Math.random() * 0.4;
fragment.velocityX = (Math.random() - 0.5) * 15;
fragment.velocityY = (Math.random() - 0.5) * 10 - 5;
fragment.rotationSpeed = (Math.random() - 0.5) * 0.3;
fragment.alpha = 0.8;
fragments.push(fragment);
game.addChild(fragment);
}
// Flash screen briefly for explosion effect
LK.effects.flashScreen(0xFFFFFF, 100);
// Play hit sound
LK.getSound('123bullethitenemy').play();
// Destroy enemy and bullet
e.destroy();
b.destroy();
bullets.splice(i, 1);
enemies.splice(j, 1);
// Score
score += 1;
scoreTxt.setText(score);
// Small flash effect on ship
LK.effects.flashObject(ship, LCD_ACCENT, 120);
break;
}
}
}
// --- Fragments update ---
for (var i = fragments.length - 1; i >= 0; i--) {
var f = fragments[i];
f.update();
// Remove if off screen or fully transparent
if (f.y > GAME_H + 100 || f.x < -100 || f.x > GAME_W + 100 || f.alpha <= 0) {
f.destroy();
fragments.splice(i, 1);
}
}
// --- Enemies update ---
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// Remove if off screen
if (e.x < -e.width) {
e.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with ship
if (e.intersects(ship)) {
// Ship hit!
e.destroy();
enemies.splice(i, 1);
lives--;
updateLivesUI();
ship.flash();
canMove = false;
// Flash screen
LK.effects.flashScreen(0xffffff, 200);
// After short delay, allow movement again or game over
LK.setTimeout(function () {
if (lives <= 0) {
// Game over
LK.showGameOver();
} else {
canMove = true;
}
}, 600);
break;
}
}
// --- Cluster rockets update ---
for (var i = clusterRockets.length - 1; i >= 0; i--) {
var r = clusterRockets[i];
r.update();
// Remove if off screen or exploded
if (r.x < -r.width || r.hasExploded) {
r.destroy();
clusterRockets.splice(i, 1);
continue;
}
// Check collision with ship
if (r.intersects(ship)) {
r.explode();
lives--;
updateLivesUI();
ship.flash();
canMove = false;
// Flash screen
LK.effects.flashScreen(0xFFFF00, 300);
// After short delay, allow movement again or game over
LK.setTimeout(function () {
if (lives <= 0) {
// Game over
LK.showGameOver();
} else {
canMove = true;
}
}, 600);
break;
}
}
// --- Fire fragments update ---
for (var i = fireFragments.length - 1; i >= 0; i--) {
var f = fireFragments[i];
f.update();
// Remove if lifetime expired or off screen
if (f.lifetime <= 0 || f.y > GAME_H + 100 || f.x < -100 || f.x > GAME_W + 100) {
f.destroy();
fireFragments.splice(i, 1);
continue;
}
// Check collision with ship
if (f.intersects(ship)) {
f.destroy();
fireFragments.splice(i, 1);
lives--;
updateLivesUI();
ship.flash();
canMove = false;
// Flash screen
LK.effects.flashScreen(0xFF4500, 200);
// After short delay, allow movement again or game over
LK.setTimeout(function () {
if (lives <= 0) {
// Game over
LK.showGameOver();
} else {
canMove = true;
}
}, 600);
break;
}
}
// --- Enemy spawn ---
enemySpawnTimer--;
if (enemySpawnTimer <= 0) {
spawnEnemy();
// Faster spawn as score increases
var minInterval = 18;
var interval = Math.max(minInterval, ENEMY_SPAWN_INTERVAL - Math.floor(score / 8) * 4);
enemySpawnTimer = interval + Math.floor(Math.random() * 12);
}
// --- Cluster rocket spawn ---
rocketSpawnTimer--;
if (rocketSpawnTimer <= 0) {
spawnClusterRocket();
// Spawn rockets less frequently than enemies
rocketSpawnTimer = 300 + Math.floor(Math.random() * 200);
}
};
// --- Center score text ---
scoreTxt.setText(score);
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = 0; // LK.gui.top is centered horizontally
// --- LCD-style background (monochrome rectangle) ---
function addBackground() {
// Use the background asset at its native resolution, then scale up to fit the game area to avoid blur
var bg = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_W / 2,
y: GAME_H / 2
});
// Calculate scale factors to fit the game area
var scaleX = GAME_W / bg.width;
var scaleY = GAME_H / bg.height;
bg.scaleX = scaleX;
bg.scaleY = scaleY;
game.addChildAt(bg, 0); // Ensure background is at the bottom layer
// LCD accent border (use a shape asset for a crisp border)
var border = LK.getAsset('lcd_life', {
width: GAME_W - 120,
height: GAME_H - 120,
color: LCD_ACCENT,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
border.alpha = 0.08;
border.x = GAME_W / 2;
border.y = GAME_H / 2;
game.addChildAt(border, 1);
}
addBackground();
// --- Play background music ---
LK.playMusic('1alarmofwar');
// --- On game over, reset state ---
LK.on('gameover', function () {
LK.stopMusic();
resetGame();
});
// --- On you win (not used, but for completeness) ---
LK.on('youwin', function () {
LK.stopMusic();
resetGame();
});
tank with vertical cannon. In-Game asset. 2d. High contrast. No shadows
horizontal sharp ufo battle plane. In-Game asset. 2d. High contrast. No shadows
elips vertical fire light. In-Game asset. 2d. High contrast. No shadows
anime image style battlefield plains. on this distance as lost angeles burning city at night In-Game asset. 2d. High contrast. No shadows
cluster rocket. In-Game asset. 2d. High contrast. No shadows