/**** 
* 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();
});
:quality(85)/https://cdn.frvr.ai/684257048e9021f9d409f30a.png%3F3) 
 tank with vertical cannon. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/684257ae8e9021f9d409f31d.png%3F3) 
 horizontal sharp ufo battle plane. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68425d328e9021f9d409f35a.png%3F3) 
 elips vertical fire light. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6846db78e8c68a0d58b5244a.png%3F3) 
 anime image style battlefield plains. on this distance as lost angeles burning city at night In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68765b033a5d13c11cd5db25.png%3F3) 
 cluster rocket. In-Game asset. 2d. High contrast. No shadows